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
This commit is contained in:
Shaun Ruffell 2011-01-03 18:28:11 +00:00
parent 6f8b5cefe5
commit b3aa15a793

View File

@ -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;
/* skip if not in this conf */
if (pos->confna != i)
continue;
if (!c) {
module_printk(KERN_NOTICE,
"Conf #%d:\n", i);
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 (pseudo->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",
k, pos->confmode);
pseudo->chan.channo, pseudo->chan.confmode);
}
spin_unlock_irqrestore(&chan_lock, flags);
rv = 0;
if (c)
module_printk(KERN_NOTICE, "\n");