summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2011-01-03 18:28:06 +0000
committerShaun Ruffell <sruffell@digium.com>2011-01-03 18:28:06 +0000
commit889ab7e2ab312aeeb481c460504314b1a95769d0 (patch)
tree206e993d9eac512b95ad793a36cceb9e104f8038 /drivers
parent31effc77bf36289ea97159ceba6d2e1d47aeb571 (diff)
dahdi: Drop 'chans' reference in chan_from_num.
Part of getting rid of global chans array. We need to search the list of spans and the list of pseudo channels. While this is slower than a direct index into a 'chans' array, the places where this function is called are not in the 'hot' path but instead part of channel configuration and conferencing setup. 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@9607 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dahdi/dahdi-base.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c
index 50116fb..608da1b 100644
--- a/drivers/dahdi/dahdi-base.c
+++ b/drivers/dahdi/dahdi-base.c
@@ -476,9 +476,54 @@ static LIST_HEAD(span_list);
static struct dahdi_chan *chans[DAHDI_MAX_CHANNELS];
-static inline struct dahdi_chan *chan_from_num(unsigned int channo)
+static struct dahdi_chan *chan_from_num(unsigned int channo)
{
- return valid_channo(channo) ? chans[channo] : NULL;
+ struct dahdi_span *s;
+ struct pseudo_chan *pseudo;
+
+ if (!unlikely(valid_channo(channo)))
+ return NULL;
+
+ mutex_lock(&registration_mutex);
+
+ /* When searching for the channel amongst the spans, we can use the
+ * fact that channels on a span must be numbered consecutively to skip
+ * checking each individual channel. */
+ list_for_each_entry(s, &span_list, node) {
+ unsigned int basechan;
+ struct dahdi_chan *chan;
+
+ if (unlikely(!s->channels))
+ continue;
+
+ basechan = s->chans[0]->channo;
+ if (channo >= (basechan + s->channels))
+ continue;
+
+ if (unlikely(channo < basechan)) {
+ /* Looks like they are asking for a channel that has
+ * already been removed. */
+ mutex_unlock(&registration_mutex);
+ return NULL;
+ }
+
+ chan = s->chans[channo - basechan];
+ WARN_ON(chan->channo != channo);
+ mutex_unlock(&registration_mutex);
+ return chan;
+ }
+
+ /* If we didn't find the channel on the list of real channels, then
+ * it's most likely a pseudo channel. */
+ list_for_each_entry(pseudo, &pseudo_chans, node) {
+ if (pseudo->chan.channo == channo) {
+ mutex_unlock(&registration_mutex);
+ return &pseudo->chan;
+ }
+ }
+
+ mutex_unlock(&registration_mutex);
+ return NULL;
}
static inline struct dahdi_chan *chan_from_file(struct file *file)