summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/dahdi/dahdi-base.c61
1 files changed, 46 insertions, 15 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c
index 5dface3..d05add0 100644
--- a/drivers/dahdi/dahdi-base.c
+++ b/drivers/dahdi/dahdi-base.c
@@ -409,6 +409,19 @@ static rwlock_t zone_lock = RW_LOCK_UNLOCKED;
static rwlock_t chan_lock = RW_LOCK_UNLOCKED;
#endif
+struct pseudo_chan {
+ struct dahdi_chan chan;
+ struct list_head node;
+};
+
+static inline struct pseudo_chan *chan_to_pseudo(struct dahdi_chan *chan)
+{
+ return container_of(chan, struct pseudo_chan, chan);
+}
+
+/* This is protected by the chan_lock. */
+static LIST_HEAD(pseudo_chans);
+
/**
* is_pseudo_chan() - By definition psuedo channels are not on a span.
*/
@@ -2867,7 +2880,8 @@ static int can_open_timer(void)
static struct dahdi_chan *dahdi_alloc_pseudo(void)
{
- struct dahdi_chan *pseudo;
+ struct pseudo_chan *pseudo;
+ unsigned long flags;
/* Don't allow /dev/dahdi/pseudo to open if there is not a timing
* source. */
@@ -2877,27 +2891,44 @@ static struct dahdi_chan *dahdi_alloc_pseudo(void)
if (!(pseudo = kzalloc(sizeof(*pseudo), GFP_KERNEL)))
return NULL;
- pseudo->sig = DAHDI_SIG_CLEAR;
- pseudo->sigcap = DAHDI_SIG_CLEAR;
- pseudo->flags = DAHDI_FLAG_AUDIO;
- pseudo->span = NULL; /* No span == psuedo channel */
+ INIT_LIST_HEAD(&pseudo->node);
- if (dahdi_chan_reg(pseudo)) {
+ pseudo->chan.sig = DAHDI_SIG_CLEAR;
+ pseudo->chan.sigcap = DAHDI_SIG_CLEAR;
+ pseudo->chan.flags = DAHDI_FLAG_AUDIO;
+ pseudo->chan.span = NULL; /* No span == psuedo channel */
+
+ if (dahdi_chan_reg(&pseudo->chan)) {
kfree(pseudo);
- pseudo = NULL;
- } else {
- snprintf(pseudo->name, sizeof(pseudo->name)-1,"Pseudo/%d", pseudo->channo);
+ return NULL;
}
- return pseudo;
+ write_lock_irqsave(&chan_lock, flags);
+ list_add_tail(&pseudo->node, &pseudo_chans);
+ write_unlock_irqrestore(&chan_lock, flags);
+
+ snprintf(pseudo->chan.name, sizeof(pseudo->chan.name)-1,
+ "Pseudo/%d", pseudo->chan.channo);
+
+ return &pseudo->chan;
}
-static void dahdi_free_pseudo(struct dahdi_chan *pseudo)
+static void dahdi_free_pseudo(struct dahdi_chan *chan)
{
- if (pseudo) {
- dahdi_chan_unreg(pseudo);
- kfree(pseudo);
- }
+ struct pseudo_chan *pseudo;
+ unsigned long flags;
+
+ if (!chan)
+ return;
+
+ pseudo = chan_to_pseudo(chan);
+
+ write_lock_irqsave(&chan_lock, flags);
+ list_del(&pseudo->node);
+ write_unlock_irqrestore(&chan_lock, flags);
+
+ dahdi_chan_unreg(chan);
+ kfree(pseudo);
}
static int dahdi_open(struct inode *inode, struct file *file)