[svn-commits] sruffell: linux/trunk r9598 - in /linux/trunk: drivers/dahdi/ include/dahdi/
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Mon Jan 3 18:27:31 UTC 2011
Author: sruffell
Date: Mon Jan 3 12:27:27 2011
New Revision: 9598
URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=9598
Log:
dahdi: Remove arbitrary limit on number of spans in the kernel.
Spans are no longer added to a static array, but they are chained
together in a list. DAHDI_MAX_SPANS, while no longer used in the
kernel, is still in include/dahdi/user.h since dahdi tools is currently
using it.
Signed-off-by: Shaun Ruffell <sruffell at digium.com>
Acked-by: Kinsey Moore <kmoore at digium.com>
Modified:
linux/trunk/drivers/dahdi/dahdi-base.c
linux/trunk/include/dahdi/kernel.h
Modified: linux/trunk/drivers/dahdi/dahdi-base.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/dahdi-base.c?view=diff&rev=9598&r1=9597&r2=9598
==============================================================================
--- linux/trunk/drivers/dahdi/dahdi-base.c (original)
+++ linux/trunk/drivers/dahdi/dahdi-base.c Mon Jan 3 12:27:27 2011
@@ -471,11 +471,10 @@
false : true;
}
-/* Protected by chan_lock. */
-static struct dahdi_span *spans[DAHDI_MAX_SPANS];
+static DEFINE_MUTEX(registration_mutex);
+static LIST_HEAD(span_list);
+
static struct dahdi_chan *chans[DAHDI_MAX_CHANNELS];
-
-static int maxspans = 0;
static inline struct dahdi_chan *chan_from_num(unsigned int channo)
{
@@ -488,6 +487,22 @@
file->private_data : chan_from_num(UNIT(file));
}
+/**
+ * _find_span() - Find a span by span number.
+ *
+ * Must be called with registration_lock held.
+ *
+ */
+static struct dahdi_span *_find_span(int spanno)
+{
+ struct dahdi_span *s;
+ list_for_each_entry(s, &span_list, node) {
+ if (s->spanno == spanno) {
+ return s;
+ }
+ }
+ return NULL;
+}
/**
* span_find_and_get() - Search for the span by number, and if found take out
* a reference on it.
@@ -498,25 +513,31 @@
*/
static struct dahdi_span *span_find_and_get(int spanno)
{
+ struct dahdi_span *found;
+
+ mutex_lock(®istration_mutex);
+ found = _find_span(spanno);
+ if (found && !try_module_get(found->ops->owner))
+ found = NULL;
+ mutex_unlock(®istration_mutex);
+ return found;
+}
+
+static void put_span(struct dahdi_span *span)
+{
+ module_put(span->ops->owner);
+}
+
+static unsigned int span_count(void)
+{
+ unsigned int count = 0;
+ struct dahdi_span *s;
unsigned long flags;
- struct dahdi_span *span;
-
spin_lock_irqsave(&chan_lock, flags);
- span = (spanno > 0 && spanno < DAHDI_MAX_SPANS) ? spans[spanno] : NULL;
- if (likely(span && !try_module_get(span->ops->owner)))
- span = NULL;
+ list_for_each_entry(s, &span_list, node)
+ ++count;
spin_unlock_irqrestore(&chan_lock, flags);
- return span;
-}
-
-static void put_span(struct dahdi_span *span)
-{
- module_put(span->ops->owner);
-}
-
-static inline unsigned int span_count(void)
-{
- return maxspans;
+ return count;
}
static inline bool can_provide_timing(const struct dahdi_span *const s)
@@ -2905,7 +2926,7 @@
#ifdef CONFIG_DAHDI_CORE_TIMER
return 1;
#else
- return maxspans > 0;
+ return (list_empty(&span_list)) ? 0 : 1;
#endif
}
@@ -3551,6 +3572,7 @@
void dahdi_alarm_notify(struct dahdi_span *span)
{
int x;
+ unsigned long flags;
span->alarms &= ~DAHDI_ALARM_LOOPBACK;
/* Determine maint status */
@@ -3561,15 +3583,14 @@
as ((!a) != (!b)) */
/* if change in general state */
if ((!span->alarms) != (!span->lastalarms)) {
+ struct dahdi_span *s;
span->lastalarms = span->alarms;
for (x = 0; x < span->channels; x++)
dahdi_alarm_channel(span->chans[x], span->alarms);
/* Switch to other master if current master in alarm */
- for (x=1; x<maxspans; x++) {
- struct dahdi_span *const s = spans[x];
- if (!s)
- continue;
+ spin_lock_irqsave(&chan_lock, flags);
+ list_for_each_entry(s, &span_list, node) {
if (s->alarms)
continue;
if (!test_bit(DAHDI_FLAGBIT_RUNNING, &s->flags))
@@ -3587,6 +3608,7 @@
master = s;
break;
}
+ spin_unlock_irqrestore(&chan_lock, flags);
/* Report more detailed alarms */
if (debug & DEBUG_MAIN) {
@@ -6220,6 +6242,97 @@
}
#endif
+static int _dahdi_register(struct dahdi_span *span, int prefmaster)
+{
+ unsigned int spanno;
+ unsigned int x;
+ int res = 0;
+ struct list_head *loc = &span_list;
+ unsigned long flags;
+
+ if (!span || !span->ops || !span->ops->owner)
+ return -EINVAL;
+
+ if (!span->deflaw) {
+ module_printk(KERN_NOTICE, "Span %s didn't specify default law. "
+ "Assuming mulaw, please fix driver!\n", span->name);
+ span->deflaw = DAHDI_LAW_MULAW;
+ }
+
+
+ spin_lock_init(&span->lock);
+
+ spanno = 1;
+
+ /* Look through the span list to find the first available span number.
+ * The spans are kept on this list in sorted order. */
+ if (!list_empty(&span_list)) {
+ struct dahdi_span *pos;
+ list_for_each_entry(pos, &span_list, node) {
+ loc = &pos->node;
+ if (pos->spanno == spanno) {
+ ++spanno;
+ continue;
+ }
+ break;
+ }
+ }
+
+ span->spanno = spanno;
+ for (x = 0; x < span->channels; x++) {
+ span->chans[x]->span = span;
+ res = dahdi_chan_reg(span->chans[x]);
+ if (res) {
+ for (x--; x >= 0; x--)
+ dahdi_chan_unreg(span->chans[x]);
+ goto unreg_channels;
+ }
+ }
+
+#ifdef CONFIG_PROC_FS
+ {
+ char tempfile[17];
+ snprintf(tempfile, sizeof(tempfile), "%d", span->spanno);
+ span->proc_entry = create_proc_read_entry(tempfile, 0444,
+ root_proc_entry, dahdi_proc_read,
+ (int *) (long) span->spanno);
+ }
+#endif
+
+ for (x = 0; x < span->channels; x++) {
+ if (span->chans[x]->channo < 250) {
+ char chan_name[32];
+ snprintf(chan_name, sizeof(chan_name), "dahdi!%d",
+ span->chans[x]->channo);
+ CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR,
+ span->chans[x]->channo), NULL, chan_name);
+ }
+ }
+
+ if (debug & DEBUG_MAIN) {
+ module_printk(KERN_NOTICE, "Registered Span %d ('%s') with "
+ "%d channels\n", span->spanno, span->name, span->channels);
+ }
+
+ if (!master && can_provide_timing(span)) {
+ master = span;
+ if (debug & DEBUG_MAIN) {
+ module_printk(KERN_NOTICE, "Span ('%s') is new master\n",
+ span->name);
+ }
+ }
+
+ spin_lock_irqsave(&chan_lock, flags);
+ list_add(&span->node, loc);
+ spin_unlock_irqrestore(&chan_lock, flags);
+ set_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
+
+ return 0;
+
+unreg_channels:
+ return res;
+}
+
/**
* dahdi_register() - unregister a new DAHDI span
* @span: the DAHDI span
@@ -6232,115 +6345,73 @@
* master DAHDI span at registration time. If 0: it will only become
* master if no other span is currently the master (i.e.: it is the
* first one).
+ *
*/
int dahdi_register(struct dahdi_span *span, int prefmaster)
{
+ int ret;
+ mutex_lock(®istration_mutex);
+ ret = _dahdi_register(span, prefmaster);
+ mutex_unlock(®istration_mutex);
+ return ret;
+}
+
+static int _dahdi_unregister(struct dahdi_span *span)
+{
int x;
- int res = 0;
- int spanno;
+ struct dahdi_span *new_master, *s;
unsigned long flags;
- if (!span)
- return -EINVAL;
-
- if (!span->ops)
- return -EINVAL;
-
- if (!span->ops->owner)
- return -EINVAL;
-
-
- if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) {
- module_printk(KERN_ERR, "Span %s already appears to be registered\n", span->name);
- return -EBUSY;
- }
-
- for (x = 1; x < maxspans; x++) {
- if (spans[x] == span) {
- module_printk(KERN_ERR, "Span %s already in list\n", span->name);
- return -EBUSY;
- }
- }
-
- for (x = 1; x < DAHDI_MAX_SPANS; x++) {
- if (!spans[x])
- break;
- }
-
- if (x < DAHDI_MAX_SPANS) {
- spanno = x;
- } else {
- module_printk(KERN_ERR, "Too many DAHDI spans registered\n");
- return -EBUSY;
- }
-
- span->spanno = x;
-
- spin_lock_init(&span->lock);
-
- if (!span->deflaw) {
- module_printk(KERN_NOTICE, "Span %s didn't specify default law. "
- "Assuming mulaw, please fix driver!\n", span->name);
- span->deflaw = DAHDI_LAW_MULAW;
- }
+ if (span != _find_span(span->spanno)) {
+ module_printk(KERN_ERR, "Span %s does not appear to be registered\n", span->name);
+ return -1;
+ }
+
+ spin_lock_irqsave(&chan_lock, flags);
+ list_del_init(&span->node);
+ spin_unlock_irqrestore(&chan_lock, flags);
+ span->spanno = 0;
+ clear_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
+
+ /* Shutdown the span if it's running */
+ if ((span->flags & DAHDI_FLAG_RUNNING) && span->ops->shutdown)
+ span->ops->shutdown(span);
+
+ if (debug & DEBUG_MAIN)
+ module_printk(KERN_NOTICE, "Unregistering Span '%s' with %d channels\n", span->name, span->channels);
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry(span->proc_entry->name, root_proc_entry);
+#endif /* CONFIG_PROC_FS */
for (x = 0; x < span->channels; x++) {
- span->chans[x]->span = span;
- res = dahdi_chan_reg(span->chans[x]);
- if (res) {
- for (x--; x >= 0; x--)
- dahdi_chan_unreg(span->chans[x]);
- goto unreg_channels;
- }
- }
-
-#ifdef CONFIG_PROC_FS
- {
- char tempfile[17];
- snprintf(tempfile, sizeof(tempfile), "dahdi/%d", span->spanno);
- span->proc_entry = create_proc_read_entry(tempfile, 0444,
- NULL, dahdi_proc_read,
- (int *) (long) span->spanno);
- }
-#endif
-
- for (x = 0; x < span->channels; x++) {
- if (span->chans[x]->channo < 250) {
- char chan_name[32];
- snprintf(chan_name, sizeof(chan_name), "dahdi!%d",
- span->chans[x]->channo);
- CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR,
- span->chans[x]->channo), NULL, chan_name);
- }
- }
-
- if (debug & DEBUG_MAIN) {
- module_printk(KERN_NOTICE, "Registered Span %d ('%s') with "
- "%d channels\n", span->spanno, span->name, span->channels);
- }
-
- if (!master && can_provide_timing(span)) {
- master = span;
+ if (span->chans[x]->channo < 250)
+ CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, span->chans[x]->channo));
+ }
+
+ for (x=0;x<span->channels;x++)
+ dahdi_chan_unreg(span->chans[x]);
+
+ new_master = master; /* FIXME: locking */
+ if (master == span)
+ new_master = NULL;
+
+ spin_lock_irqsave(&chan_lock, flags);
+ list_for_each_entry(s, &span_list, node) {
+ if ((s == new_master) || !can_provide_timing(s))
+ continue;
+ new_master = s;
+ break;
+ }
+ spin_unlock_irqrestore(&chan_lock, flags);
+ if (master != new_master) {
if (debug & DEBUG_MAIN) {
- module_printk(KERN_NOTICE, "Span ('%s') is new master\n",
- span->name);
- }
- }
-
- spin_lock_irqsave(&chan_lock, flags);
- spans[spanno] = span;
- if (maxspans < x + 1)
- maxspans = x + 1;
- spin_unlock_irqrestore(&chan_lock, flags);
- set_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
-
+ module_printk(KERN_NOTICE, "%s: Span ('%s') is new master\n", __FUNCTION__,
+ (new_master)? new_master->name: "no master");
+ }
+ }
+ master = new_master;
return 0;
-
-unreg_channels:
- spans[span->spanno] = NULL;
- return res;
-}
-
+}
/**
* dahdi_unregister() - unregister a DAHDI span
@@ -6351,77 +6422,11 @@
*/
int dahdi_unregister(struct dahdi_span *span)
{
- int x;
- unsigned long flags;
-
-#ifdef CONFIG_PROC_FS
- char tempfile[17];
-#endif /* CONFIG_PROC_FS */
-
- if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) {
- module_printk(KERN_ERR, "Span %s does not appear to be registered\n", span->name);
- return -1;
- }
-
- /* Shutdown the span if it's running */
- if (span->flags & DAHDI_FLAG_RUNNING)
- if (span->ops->shutdown)
- span->ops->shutdown(span);
-
- if (spans[span->spanno] != span) {
- module_printk(KERN_ERR, "Span %s has spanno %d which is something else\n", span->name, span->spanno);
- return -1;
- }
-
- clear_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
- spin_lock_irqsave(&chan_lock, flags);
- spans[span->spanno] = NULL;
- spin_unlock_irqrestore(&chan_lock, flags);
-
- if (debug & DEBUG_MAIN)
- module_printk(KERN_NOTICE, "Unregistering Span '%s' with %d channels\n", span->name, span->channels);
-#ifdef CONFIG_PROC_FS
- snprintf(tempfile, sizeof(tempfile)-1, "dahdi/%d", span->spanno);
- remove_proc_entry(tempfile, NULL);
-#endif /* CONFIG_PROC_FS */
-
- for (x = 0; x < span->channels; x++) {
- if (span->chans[x]->channo < 250)
- CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, span->chans[x]->channo));
- }
-
- for (x=0;x<span->channels;x++)
- dahdi_chan_unreg(span->chans[x]);
-
- if (master == span) {
- struct dahdi_span *new_master = NULL;
- int new_maxspans = 0;
-
- spin_lock_irqsave(&chan_lock, flags);
- for (x = 1; x < DAHDI_MAX_SPANS; x++) {
- struct dahdi_span *const cur = spans[x];
- if (!cur)
- continue;
-
- new_maxspans = x;
- if (can_provide_timing(cur)) {
- new_master = cur;
- break;
- }
- }
- maxspans = new_maxspans;
- spin_unlock_irqrestore(&chan_lock, flags);
-
- if (debug & DEBUG_MAIN) {
- module_printk(KERN_NOTICE, "%s: Span ('%s') is new "
- "master\n", __func__,
- (new_master) ? new_master->name :
- "no master");
- }
- master = new_master;
- }
- span->spanno = 0;
- return 0;
+ int ret;
+ mutex_lock(®istration_mutex);
+ ret = _dahdi_unregister(span);
+ mutex_unlock(®istration_mutex);
+ return ret;
}
/*
@@ -8631,8 +8636,7 @@
static void process_masterspan(void)
{
unsigned long flags;
- int x, y;
- struct dahdi_chan *chan;
+ int x;
struct pseudo_chan *pseudo;
struct dahdi_span *s;
u_char *data;
@@ -8651,12 +8655,9 @@
/* Process any timers */
process_timers();
- for (y = 1; y < maxspans; ++y) {
- s = spans[y];
- if (!s)
- continue;
- for (x = 0; x < s->channels; x++) {
- chan = s->chans[x];
+ list_for_each_entry(s, &span_list, node) {
+ for (x = 0; x < s->channels; ++x) {
+ struct dahdi_chan *const chan = s->chans[x];
if (!chan->confmode)
continue;
spin_lock(&chan->lock);
@@ -8684,12 +8685,9 @@
pseudo_rx_audio(&pseudo->chan);
}
- for (y = 1; y < maxspans; ++y) {
- s = spans[y];
- if (!s)
- continue;
+ list_for_each_entry(s, &span_list, node) {
for (x = 0; x < s->channels; x++) {
- chan = s->chans[x];
+ struct dahdi_chan *const chan = s->chans[x];
if (!chan->confmode)
continue;
spin_lock(&chan->lock);
@@ -8979,14 +8977,13 @@
static void watchdog_check(unsigned long ignored)
{
- int x;
unsigned long flags;
static int wdcheck=0;
-
- local_irq_save(flags);
- for (x=0;x<maxspans;x++) {
- s = spans[x];
- if (s && (s->flags & DAHDI_FLAG_RUNNING)) {
+ struct dahdi_span *s;
+
+ spin_lock_irqsave(&span_list_lock, flags);
+ list_for_each_entry(s, &span_list, node) {
+ if (s->flags & DAHDI_FLAG_RUNNING) {
if (s->watchcounter == DAHDI_WATCHDOG_INIT) {
/* Whoops, dead card */
if ((s->watchstate == DAHDI_WATCHSTATE_OK) ||
@@ -9009,7 +9006,7 @@
s->watchcounter = DAHDI_WATCHDOG_INIT;
}
}
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&span_list_lock, flags);
if (!wdcheck) {
module_printk(KERN_NOTICE, "watchdog on duty!\n");
wdcheck=1;
@@ -9137,7 +9134,7 @@
unregister_chrdev(DAHDI_MAJOR, "dahdi");
#ifdef CONFIG_PROC_FS
- remove_proc_entry("dahdi", NULL);
+ remove_proc_entry(root_proc_entry->name, NULL);
#endif
module_printk(KERN_INFO, "Telephony Interface Unloaded\n");
Modified: linux/trunk/include/dahdi/kernel.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/include/dahdi/kernel.h?view=diff&rev=9598&r1=9597&r2=9598
==============================================================================
--- linux/trunk/include/dahdi/kernel.h (original)
+++ linux/trunk/include/dahdi/kernel.h Mon Jan 3 12:27:27 2011
@@ -898,6 +898,7 @@
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
#endif
+ struct list_head node;
};
struct dahdi_transcoder_channel {
More information about the svn-commits
mailing list