[svn-commits] sruffell: branch linux/sruffell/chan_list r9346 - /linux/team/sruffell/chan_l...

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


Author: sruffell
Date: Fri Sep 17 14:11:43 2010
New Revision: 9346

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=9346
Log:
dahdi: Remove 'chans' array from reg/unreg. Now completely removed.

This change removes the remaining locations the 'chans' array was
referenced, but keeps the observable behavior to the way it was when the
chans array. Namely, channels are numbered in registration order.  Only
now it's possible to renumber channels easily since their number isn't
also their implied location in any arrays.

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

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=9346&r1=9345&r2=9346
==============================================================================
--- 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:43 2010
@@ -420,7 +420,7 @@
 	return container_of(chan, struct pseudo_chan, chan);
 }
 
-/* This is protected by the chan_lock. */
+/* This list is protected by the chan_lock. */
 static LIST_HEAD(pseudo_chans);
 
 /**
@@ -433,13 +433,10 @@
 
 static bool valid_channo(const int channo)
 {
-	return ((channo >= DAHDI_MAX_CHANNELS) || (channo < 1)) ?
-			false : true;
+	return (channo < 1) ?  false : true;
 }
 
 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,
@@ -539,7 +536,6 @@
 	return count;
 }
 
-static int maxchans = 0;
 static int maxconfs = 0;
 static int maxlinks = 0;
 
@@ -1439,9 +1435,10 @@
  * close_channel - close the channel, resetting any channel variables
  * @chan: the dahdi_chan to close
  *
- * This function might be called before the channel is placed on the global
- * array of channels, (chans), and therefore, neither this function nor it's
- * children should depend on the dahdi_chan.channo member which is not set yet.
+ * This function is called before either the parent span is linked into the
+ * span list, or for pseudos, place on the psuedo_list.  Therefore, this
+ * function nor it's callers should depend on the channel being findable
+ * via those methods.
  */
 static void close_channel(struct dahdi_chan *chan)
 {
@@ -1754,11 +1751,8 @@
 	}
 }
 
-static int dahdi_chan_reg(struct dahdi_chan *chan)
-{
-	int x;
-	unsigned long flags;
-
+static void dahdi_chan_reg(struct dahdi_chan *chan)
+{
 	might_sleep();
 
 	spin_lock_init(&chan->lock);
@@ -1773,27 +1767,9 @@
 	dahdi_set_law(chan, 0);
 	close_channel(chan);
 
-	write_lock_irqsave(&chan_lock, flags);
-	for (x = 1; x < DAHDI_MAX_CHANNELS; x++) {
-		if (chans[x])
-			continue;
-
-		chans[x] = chan;
-		if (maxchans < x + 1)
-			maxchans = x + 1;
-		chan->channo = x;
-		/* set this AFTER running close_channel() so that
-		   HDLC channels wont cause hangage */
-		set_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags);
-		break;
-	}
-	write_unlock_irqrestore(&chan_lock, flags);
-	if (DAHDI_MAX_CHANNELS == x) {
-		module_printk(KERN_ERR, "No more channels available\n");
-		return -ENOMEM;
-	}
-
-	return 0;
+	/* set this AFTER running close_channel() so that
+	   HDLC channels wont cause hangage */
+	set_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags);
 }
 
 char *dahdi_lboname(int x)
@@ -2170,9 +2146,6 @@
 {
 	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)
@@ -2224,11 +2197,7 @@
 		chan->hdlcnetdev = NULL;
 	}
 #endif
-	write_lock_irqsave(&chan_lock, flags);
-	if (test_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags)) {
-		chans[chan->channo] = NULL;
-		clear_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags);
-	}
+	clear_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags);
 #ifdef CONFIG_DAHDI_PPP
 	if (chan->ppp) {
 		module_printk(KERN_NOTICE, "HUH???  PPP still attached??\n");
@@ -2236,7 +2205,6 @@
 #endif
 
 	write_lock_irqsave(&chan_lock, flags);
-	maxchans = 0;
 	__for_each_channel(_chan_cleanup, (unsigned long)chan);
 	write_unlock_irqrestore(&chan_lock, flags);
 
@@ -3026,33 +2994,67 @@
 {
 	struct pseudo_chan *pseudo;
 	unsigned long flags;
+	unsigned int channo;
+	struct list_head *pos = &pseudo_chans;
+	static unsigned int first_pseudo_channo;
 
 	/* Don't allow /dev/dahdi/pseudo to open if there is not a timing
 	 * source. */
 	if (!can_open_timer())
 		return NULL;
 
-	if (!(pseudo = kzalloc(sizeof(*pseudo), GFP_KERNEL)))
+	pseudo = kzalloc(sizeof(*pseudo), GFP_KERNEL);
+	if (NULL == pseudo)
 		return NULL;
-
-	INIT_LIST_HEAD(&pseudo->node);
 
 	pseudo->chan.sig = DAHDI_SIG_CLEAR;
 	pseudo->chan.sigcap = DAHDI_SIG_CLEAR;
 	pseudo->chan.flags = DAHDI_FLAG_AUDIO;
 	pseudo->chan.span = NULL; /* No span == psuedo channel */
 
-	if (dahdi_chan_reg(&pseudo->chan)) {
-		kfree(pseudo);
-		return NULL;
-	}
-
-	write_lock_irqsave(&chan_lock, flags);
-	list_add_tail(&pseudo->node, &pseudo_chans);
-	write_unlock_irqrestore(&chan_lock, flags);
+	down(&registration_lock);
+
+	read_lock_irqsave(&chan_lock, flags);
+	if (list_empty(&pseudo_chans)) {
+		/* If there aren't any pseudo channels allocated, we need to
+		 * take the next channel number after all the 'real' channels
+		 * on the spans. */
+		struct dahdi_span *span;
+		channo = 1;
+		list_for_each_entry_reverse(span, &span_list, node) {
+			if (unlikely(!span->channels))
+				continue;
+			channo = span->chans[0]->channo + span->channels;
+			break;
+		}
+		first_pseudo_channo = channo;
+	} else {
+		struct pseudo_chan *p;
+		/* Otherwise, we'll find the first available channo in the list
+		 * of pseudo chans. */
+		channo = first_pseudo_channo;
+		list_for_each_entry(p, &pseudo_chans, node) {
+			if (channo != p->chan.channo)
+				break;
+			pos = &p->node;
+			++channo;
+		}
+	}
+	read_unlock_irqrestore(&chan_lock, flags);
+
+	pseudo->chan.channo = channo;
+	dahdi_chan_reg(&pseudo->chan);
 
 	snprintf(pseudo->chan.name, sizeof(pseudo->chan.name)-1,
 		 "Pseudo/%d", pseudo->chan.channo); 
+
+	/* Once we place the pseudo chan on the list...it's registered and
+	 * live. */
+	write_lock_irqsave(&chan_lock, flags);
+	list_add(&pseudo->node, pos);
+	write_unlock_irqrestore(&chan_lock, flags);
+
+	up(&registration_lock);
 
 	return &pseudo->chan;
 }
@@ -6305,9 +6307,9 @@
 {
 	unsigned int spanno;
 	unsigned int x;
-	int res = 0;
 	struct list_head *loc = &span_list;
 	unsigned long flags;
+	unsigned int next_channo = 1;
 
 	if (!span || !span->ops || !span->ops->owner)
 		return -EINVAL;
@@ -6333,7 +6335,8 @@
 	spanno = 1;
 
 	/* Look through the span list to find the first available span number.
-	 * The spans are kept on this list in sorted order. */
+	 * The spans are kept on this list in sorted order. We'll also save
+	 * off the next available channel number to use. */
 	read_lock_irqsave(&chan_lock, flags);
 	if (!list_empty(&span_list)) {
 		struct dahdi_span *pos;
@@ -6341,6 +6344,10 @@
 			loc = &pos->node;
 			if (pos->spanno == spanno) {
 				++spanno;
+				if (pos->channels) {
+					next_channo = pos->chans[0]->channo +
+							pos->channels;
+				}
 				continue;
 			}
 			break;
@@ -6351,12 +6358,8 @@
 	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;
-		}
+		span->chans[x]->channo = next_channo + x;
+		dahdi_chan_reg(span->chans[x]);
 	}
 
 #ifdef CONFIG_PROC_FS
@@ -6399,10 +6402,6 @@
 	up(&registration_lock);
 
 	return 0;
-
-unreg_channels:
-	up(&registration_lock);
-	return res;
 }
 
 




More information about the svn-commits mailing list