summaryrefslogtreecommitdiff
path: root/drivers/dahdi/dahdi-base.c
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2010-09-20 20:34:32 +0000
committerShaun Ruffell <sruffell@digium.com>2010-09-20 20:34:32 +0000
commite03b1046e736a3d8002ca864d393406570d9a93d (patch)
tree3a8200e852d36f82a6f431a87c4d0d8a53b07846 /drivers/dahdi/dahdi-base.c
parentfb19e75fc2e04496e51fcb4e2894ecf1a3dd2ec6 (diff)
dahdi: Keep psuedo channels on pseudo_chan_list.
Since pseudo channels are without spans and we would like to use the span list to enumerate through all the channels, keeping the psuedo channels on their own list is required. I believe this is a more natural choice than making a dummy spans for pseudos since pseudo channels should *really* just be an implementation detail that the user shouldn't care about. Review: https://reviewboard.asterisk.org/r/905/ Signed-off-by: Shaun Ruffell <sruffell@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9383 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/dahdi-base.c')
-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)