[svn-commits] sruffell: branch linux/sruffell/chan_list r9335 - in /linux/team/sruffell/cha...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Sep 17 14:11:40 CDT 2010


Author: sruffell
Date: Fri Sep 17 14:11:36 2010
New Revision: 9335

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=9335
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>

Modified:
    linux/team/sruffell/chan_list/drivers/dahdi/dahdi-base.c
    linux/team/sruffell/chan_list/include/dahdi/kernel.h

Modified: linux/team/sruffell/chan_list/drivers/dahdi/dahdi-base.c
URL: http://svnview.digium.com/svn/dahdi/linux/team/sruffell/chan_list/drivers/dahdi/dahdi-base.c?view=diff&rev=9335&r1=9334&r2=9335
==============================================================================
--- linux/team/sruffell/chan_list/drivers/dahdi/dahdi-base.c (original)
+++ linux/team/sruffell/chan_list/drivers/dahdi/dahdi-base.c Fri Sep 17 14:11:36 2010
@@ -437,11 +437,9 @@
 			false : true;
 }
 
-/* Protected by chan_lock. */
-static struct dahdi_span *spans[DAHDI_MAX_SPANS];
+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)
 {
@@ -456,12 +454,30 @@
 
 static struct dahdi_span *find_span(int spanno)
 {
-	return (spanno > 0 && spanno < DAHDI_MAX_SPANS) ? spans[spanno] : NULL;
-}
-
-static inline unsigned int span_count(void)
-{
-	return maxspans;
+	struct dahdi_span *found = NULL;
+	struct dahdi_span *s;
+	unsigned long flags;
+	read_lock_irqsave(&chan_lock, flags);
+	list_for_each_entry(s, &span_list, node) {
+		if (s->spanno == spanno) {
+			found = s;
+			break;
+		}
+	}
+	read_unlock_irqrestore(&chan_lock, flags);
+	return found;
+}
+
+static unsigned int span_count(void)
+{
+	unsigned int count = 0;
+	struct dahdi_span *s;
+	unsigned long flags;
+	read_lock_irqsave(&chan_lock, flags);
+	list_for_each_entry(s, &span_list, node)
+		++count;
+	read_unlock_irqrestore(&chan_lock, flags);
+	return count;
 }
 
 static int maxchans = 0;
@@ -737,8 +753,6 @@
 		return 0;
 
 	s = find_span(spanno);
-	if (!s)
-		return -ENODEV;
 
 	if (s->name)
 		len += snprintf(page + len, count - len, "Span %d: %s ",
@@ -2918,9 +2932,11 @@
 #ifdef CONFIG_DAHDI_CORE_TIMER
 	return 1;
 #else
-	return maxspans > 0;
-#endif
-}
+	return (list_empty(&span_list)) ? 0 : 1;
+#endif
+}
+
+static DECLARE_MUTEX(registration_lock);
 
 static struct dahdi_chan *dahdi_alloc_pseudo(void)
 {
@@ -3569,6 +3585,7 @@
 void dahdi_alarm_notify(struct dahdi_span *span)
 {
 	int x;
+	unsigned long flags;
 
 	span->alarms &= ~DAHDI_ALARM_LOOPBACK;
 	/* Determine maint status */
@@ -3579,23 +3596,28 @@
 	   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 && !s->alarms && (s->flags & DAHDI_FLAG_RUNNING)) {
-				if (master != s) {
-					module_printk(KERN_NOTICE,
-						"Master changed to %s\n",
-						s->name);
-				}
-				master = s;
-				break;
-			}
-		}
+		read_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))
+				continue;
+			if (master == s)
+				continue;
+
+			module_printk(KERN_NOTICE,
+				      "Master changed to %s\n", s->name);
+			master = s;
+			break;
+		}
+		read_unlock_irqrestore(&chan_lock, flags);
+
 		/* Report more detailed alarms */
 		if (debug) {
 			if (span->alarms & DAHDI_ALARM_LOS) {
@@ -6144,6 +6166,24 @@
 }
 #endif
 
+static bool is_span_registered(const struct dahdi_span *const span)
+{
+	unsigned long flags;
+	struct dahdi_span *pos;
+	bool registered = false;
+
+	read_lock_irqsave(&chan_lock, flags);
+	list_for_each_entry(pos, &span_list, node) {
+		if (likely(pos != span))
+			continue;
+
+		registered =  true;
+		break;
+	}
+	read_unlock_irqrestore(&chan_lock, flags);
+	return registered;
+}
+
 /**
  * dahdi_register() - unregister a new DAHDI span
  * @span:	the DAHDI span
@@ -6156,52 +6196,18 @@
  * 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 x;
+	unsigned int spanno;
+	unsigned int x;
 	int res = 0;
-
-	if (!span)
+	struct list_head *loc = &span_list;
+	unsigned long flags;
+
+	if (!span || !span->ops || !span->ops->owner)
 		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) {
-		spans[x] = span;
-		if (maxspans < x + 1)
-			maxspans = x + 1;
-	} else {
-		module_printk(KERN_ERR, "Too many DAHDI spans registered\n");
-		return -EBUSY;
-	}
-
-	set_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
-	span->spanno = x;
-
-	spin_lock_init(&span->lock);
 
 	if (!span->deflaw) {
 		module_printk(KERN_NOTICE, "Span %s didn't specify default law.  "
@@ -6209,6 +6215,37 @@
 		span->deflaw = DAHDI_LAW_MULAW;
 	}
 
+	down(&registration_lock);
+
+	if (unlikely(is_span_registered(span))) {
+		module_printk(KERN_ERR, "Span %s already registered.\n",
+			      span->name);
+		up(&registration_lock);
+		return -EBUSY;
+	}
+
+	INIT_LIST_HEAD(&span->node);
+	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. */
+	read_lock_irqsave(&chan_lock, flags);
+	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;
+		}
+	}
+	read_unlock_irqrestore(&chan_lock, flags);
+
+	span->spanno = spanno;
 	for (x = 0; x < span->channels; x++) {
 		span->chans[x]->span = span;
 		res = dahdi_chan_reg(span->chans[x]);
@@ -6252,10 +6289,16 @@
 		}
 	}
 
+	write_lock_irqsave(&chan_lock, flags);
+	list_add(&span->node, loc);
+	write_unlock_irqrestore(&chan_lock, flags);
+	set_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
+	up(&registration_lock);
+
 	return 0;
 
 unreg_channels:
-	spans[span->spanno] = NULL;
+	up(&registration_lock);
 	return res;
 }
 
@@ -6270,26 +6313,25 @@
 int dahdi_unregister(struct dahdi_span *span)
 {
 	int x;
-	int new_maxspans;
 	static struct dahdi_span *new_master;
+	unsigned long flags;
 
 #ifdef CONFIG_PROC_FS
 	char tempfile[17];
 #endif /* CONFIG_PROC_FS */
 
-	if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) {
+	if (span != find_span(span->spanno)) {
 		module_printk(KERN_ERR, "Span %s does not appear to be registered\n", span->name);
 		return -1;
 	}
+
+	down(&registration_lock);
+
 	/* 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;
-	}
 	if (debug)
 		module_printk(KERN_NOTICE, "Unregistering Span '%s' with %d channels\n", span->name, span->channels);
 #ifdef CONFIG_PROC_FS
@@ -6302,29 +6344,31 @@
 			CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, span->chans[x]->channo));
 	}
 
-	spans[span->spanno] = NULL;
+	write_lock_irqsave(&chan_lock, flags);
+	list_del_init(&span->node);
+	write_unlock_irqrestore(&chan_lock, flags);
 	span->spanno = 0;
 	clear_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
+
 	for (x=0;x<span->channels;x++)
 		dahdi_chan_unreg(span->chans[x]);
-	new_maxspans = 0;
 	new_master = master; /* FIXME: locking */
 	if (master == span)
 		new_master = NULL;
-	for (x=1;x<DAHDI_MAX_SPANS;x++) {
-		if (spans[x]) {
-			new_maxspans = x+1;
-			if (!new_master)
-				new_master = spans[x];
-		}
-	}
-	maxspans = new_maxspans;
+
+	read_lock_irqsave(&chan_lock, flags);
+	if (!list_empty(&span_list)) {
+		new_master = list_entry(span_list.next,
+					struct dahdi_span, node);
+	}
+	read_unlock_irqrestore(&chan_lock, flags);
 	if (master != new_master)
 		if (debug)
 			module_printk(KERN_NOTICE, "%s: Span ('%s') is new master\n", __FUNCTION__,
 				      (new_master)? new_master->name: "no master");
 	master = new_master;
 
+	up(&registration_lock);
 	return 0;
 }
 
@@ -8497,7 +8541,6 @@
 {
 	unsigned long flags;
 	int x, y, z;
-	struct dahdi_chan *chan;
 	struct pseudo_chan *pseudo;
 	struct dahdi_span *s;
 	u_char *data;
@@ -8520,12 +8563,9 @@
 	if (dahdi_dynamic_ioctl)
 		dahdi_dynamic_ioctl(0, 0);
 
-	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);
@@ -8577,12 +8617,9 @@
 		spin_unlock(&pseudo->chan.lock);
 	}
 
-	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);
@@ -8857,14 +8894,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) ||
@@ -8887,7 +8923,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;

Modified: linux/team/sruffell/chan_list/include/dahdi/kernel.h
URL: http://svnview.digium.com/svn/dahdi/linux/team/sruffell/chan_list/include/dahdi/kernel.h?view=diff&rev=9335&r1=9334&r2=9335
==============================================================================
--- linux/team/sruffell/chan_list/include/dahdi/kernel.h (original)
+++ linux/team/sruffell/chan_list/include/dahdi/kernel.h Fri Sep 17 14:11:36 2010
@@ -870,6 +870,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