summaryrefslogtreecommitdiff
path: root/drivers/dahdi/dahdi-base.c
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2011-01-03 18:28:11 +0000
committerShaun Ruffell <sruffell@digium.com>2011-01-03 18:28:11 +0000
commit9128a66f9a6ee5169be0ef9fe0f96531ee25bb2c (patch)
treeb13fce82eb4d8e029f76a1416e1afaf0515f7602 /drivers/dahdi/dahdi-base.c
parent3b4aebbbc28ccb8a154a4d5c700b124448bdd6cc (diff)
dahdi: Remove three maxchans/DAHDI_MAX_CHANNELS references.
In dahdi_chec_conf, dahdi_chan_unreg, and dahdi_ioctl_confdiag maxchans and DAHDI_MAX_CHANNELS was used to scan through all the channels. Since the channels are stored on the list of spans and list of pseudo channels, we can directly iterate through those lists. This also paves the way for removing the arbitrary limit on the number of channels in the driver. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Acked-by: Kinsey Moore <kmoore@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9608 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/dahdi-base.c')
-rw-r--r--drivers/dahdi/dahdi-base.c161
1 files changed, 103 insertions, 58 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c
index 608da1b..a03f4a9 100644
--- a/drivers/dahdi/dahdi-base.c
+++ b/drivers/dahdi/dahdi-base.c
@@ -476,6 +476,33 @@ static LIST_HEAD(span_list);
static struct dahdi_chan *chans[DAHDI_MAX_CHANNELS];
+static unsigned long
+__for_each_channel(unsigned long (*func)(struct dahdi_chan *chan,
+ unsigned long data),
+ unsigned long data)
+{
+ int res;
+ struct dahdi_span *s;
+ struct pseudo_chan *pseudo;
+
+ list_for_each_entry(s, &span_list, node) {
+ unsigned long x;
+ for (x = 0; x < s->channels; x++) {
+ struct dahdi_chan *const chan = s->chans[x];
+ res = func(chan, data);
+ if (res)
+ return res;
+ }
+ }
+
+ list_for_each_entry(pseudo, &pseudo_chans, node) {
+ res = func(&pseudo->chan, data);
+ if (res)
+ return res;
+ }
+ return 0;
+}
+
static struct dahdi_chan *chan_from_num(unsigned int channo)
{
struct dahdi_span *s;
@@ -1046,9 +1073,21 @@ static int dahdi_get_conf_alias(int x)
return a;
}
+static unsigned long _chan_in_conf(struct dahdi_chan *chan, unsigned long x)
+{
+ const int confmode = chan->confmode & DAHDI_CONF_MODE_MASK;
+ return (chan && (chan->confna == x) &&
+ (confmode == DAHDI_CONF_CONF ||
+ confmode == DAHDI_CONF_CONFANN ||
+ confmode == DAHDI_CONF_CONFMON ||
+ confmode == DAHDI_CONF_CONFANNMON ||
+ confmode == DAHDI_CONF_REALANDPSEUDO)) ? 1 : 0;
+}
+
static void dahdi_check_conf(int x)
{
- int y;
+ unsigned long res;
+ unsigned long flags;
/* return if no valid conf number */
if (x <= 0)
@@ -1058,21 +1097,11 @@ static void dahdi_check_conf(int x)
if (!confalias[x])
return;
- for (y = 0; y < maxchans; y++) {
- struct dahdi_chan *const chan = chan_from_num(y);
- int confmode;
- if (!chan)
- continue;
- confmode = chan->confmode & DAHDI_CONF_MODE_MASK;
- if ((chan->confna == x) &&
- (confmode == DAHDI_CONF_CONF ||
- confmode == DAHDI_CONF_CONFANN ||
- confmode == DAHDI_CONF_CONFMON ||
- confmode == DAHDI_CONF_CONFANNMON ||
- confmode == DAHDI_CONF_REALANDPSEUDO)) {
- return;
- }
- }
+ spin_lock_irqsave(&chan_lock, flags);
+ res = __for_each_channel(_chan_in_conf, x);
+ spin_unlock_irqrestore(&chan_lock, flags);
+ if (res)
+ return;
/* If we get here, nobody is in the conference anymore. Clear it out
both forward and reverse */
@@ -2100,10 +2129,41 @@ static bool is_monitor_mode(int confmode)
}
}
+static unsigned long _chan_cleanup(struct dahdi_chan *pos, unsigned long data)
+{
+ unsigned long flags;
+ struct dahdi_chan *const chan = (struct dahdi_chan *)data;
+
+ ++maxchans;
+
+ /* Remove anyone pointing to us as master
+ and make them their own thing */
+ if (pos->master == chan)
+ pos->master = pos;
+
+ if (((pos->confna == chan->channo) &&
+ is_monitor_mode(pos->confmode)) ||
+ (pos->dacs_chan == chan)) {
+ /* Take them out of conference with us */
+ /* release conference resource if any */
+ if (pos->confna)
+ dahdi_check_conf(pos->confna);
+
+ dahdi_disable_dacs(pos);
+ spin_lock_irqsave(&pos->lock, flags);
+ pos->confna = 0;
+ pos->_confn = 0;
+ pos->confmode = 0;
+ pos->conf_chan = NULL;
+ pos->dacs_chan = NULL;
+ spin_unlock_irqrestore(&pos->lock, flags);
+ }
+
+ return 0;
+}
static void dahdi_chan_unreg(struct dahdi_chan *chan)
{
- int x;
unsigned long flags;
might_sleep();
@@ -2137,36 +2197,10 @@ static void dahdi_chan_unreg(struct dahdi_chan *chan)
module_printk(KERN_NOTICE, "HUH??? PPP still attached??\n");
}
#endif
- maxchans = 0;
- for (x = 1; x < DAHDI_MAX_CHANNELS; x++) {
- struct dahdi_chan *const pos = chan_from_num(x);
- if (!pos)
- continue;
- maxchans = x + 1;
- /* Remove anyone pointing to us as master
- and make them their own thing */
- if (pos->master == chan)
- pos->master = pos;
-
- if ((pos->confna == chan->channo) &&
- (is_monitor_mode(pos->confmode) ||
- ((pos->confmode & DAHDI_CONF_MODE_MASK) ==
- DAHDI_CONF_DIGITALMON))) {
- /* Take them out of conference with us */
- /* release conference resource if any */
- if (pos->confna)
- dahdi_check_conf(pos->confna);
-
- dahdi_disable_dacs(pos);
- pos->confna = 0;
- pos->_confn = 0;
- pos->confmode = 0;
- pos->dacs_chan = NULL;
- pos->conf_chan = NULL;
- }
- }
- chan->channo = -1;
+ __for_each_channel(_chan_cleanup, (unsigned long)chan);
spin_unlock_irqrestore(&chan_lock, flags);
+
+ chan->channo = -1;
}
static ssize_t dahdi_chan_read(struct file *file, char __user *usrbuf,
@@ -5127,11 +5161,11 @@ static int dahdi_ioctl_setconf(struct file *file, unsigned long data)
static int dahdi_ioctl_confdiag(struct file *file, unsigned long data)
{
struct dahdi_chan *chan;
+ unsigned long flags;
int rv;
int i;
int j;
int c;
- int k;
chan = chan_from_file(file);
if (!chan)
@@ -5144,23 +5178,34 @@ static int dahdi_ioctl_confdiag(struct file *file, unsigned long data)
/* loop thru the interesting ones */
for (i = ((j) ? j : 1); i <= ((j) ? j : DAHDI_MAX_CONF); i++) {
+ struct dahdi_span *s;
+ struct pseudo_chan *pseudo;
c = 0;
- for (k = 1; k < DAHDI_MAX_CHANNELS; k++) {
- struct dahdi_chan *const pos = chan_from_num(k);
- /* skip if no pointer */
- if (!pos)
- continue;
+ spin_lock_irqsave(&chan_lock, flags);
+ list_for_each_entry(s, &span_list, node) {
+ int k;
+ for (k = 0; k < s->channels; k++) {
+ chan = s->chans[k];
+ if (chan->confna != i)
+ continue;
+ if (!c)
+ module_printk(KERN_NOTICE, "Conf #%d:\n", i);
+ c = 1;
+ module_printk(KERN_NOTICE, "chan %d, mode %x\n",
+ chan->channo, chan->confmode);
+ }
+ }
+ list_for_each_entry(pseudo, &pseudo_chans, node) {
/* skip if not in this conf */
- if (pos->confna != i)
+ if (pseudo->chan.confna != i)
continue;
- if (!c) {
- module_printk(KERN_NOTICE,
- "Conf #%d:\n", i);
- }
+ if (!c)
+ module_printk(KERN_NOTICE, "Conf #%d:\n", i);
c = 1;
module_printk(KERN_NOTICE, "chan %d, mode %x\n",
- k, pos->confmode);
+ pseudo->chan.channo, pseudo->chan.confmode);
}
+ spin_unlock_irqrestore(&chan_lock, flags);
rv = 0;
if (c)
module_printk(KERN_NOTICE, "\n");