[svn-commits] sruffell: linux/trunk r10231 - /linux/trunk/drivers/dahdi/wct4xxp/base.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Oct 20 15:52:09 CDT 2011


Author: sruffell
Date: Thu Oct 20 15:52:06 2011
New Revision: 10231

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=10231
Log:
wct4xxp: Slow down the rate we poll the framers in alarm.

The overhead of reading the framer registers is significant and can
result in latency bumps / data drops on heavily loaded systems.
Instead of checking all spans every millisecond when they are in
alarm we will instead only check every 100 ms.

On one test system, dropped the % CPU time spent in hard interrupt
context from 10% per TDM4XX when all four spans are in alarm to
closer to 2%.

Signed-off-by: Shaun Ruffell <sruffell at digium.com>
Acked-by: Michael Spiceland <mspiceland at digium.com>
Acked-by: Russ Meyerriecks <rmeyerriecks at digium.com>

Modified:
    linux/trunk/drivers/dahdi/wct4xxp/base.c

Modified: linux/trunk/drivers/dahdi/wct4xxp/base.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/wct4xxp/base.c?view=diff&rev=10231&r1=10230&r2=10231
==============================================================================
--- linux/trunk/drivers/dahdi/wct4xxp/base.c (original)
+++ linux/trunk/drivers/dahdi/wct4xxp/base.c Thu Oct 20 15:52:06 2011
@@ -291,10 +291,11 @@
 	int sync;
 	int alarmtimer;
 	int notclear;
-	int alarmcount;
-	int losalarmcount;
-	int aisalarmcount;
-	int yelalarmcount;
+	unsigned long alarm_time;
+	unsigned long losalarm_time;
+	unsigned long aisalarm_time;
+	unsigned long yelalarm_time;
+	unsigned long alarmcheck_time;
 	int spanflags;
 	int syncpos;
 #ifdef SUPPORT_GEN1
@@ -2112,6 +2113,7 @@
 	gen2 = (wc->tspans[0]->spanflags & FLAG_2NDGEN);
 	for (x = 0; x < wc->numspans; x++) {
 		ts = wc->tspans[x];
+
 		sprintf(ts->span.name, "TE%d/%d/%d", wc->numspans, wc->num, x + 1);
 		snprintf(ts->span.desc, sizeof(ts->span.desc) - 1,
 			 "T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num, x+1);
@@ -2174,6 +2176,9 @@
 			mychans->pvt = wc;
 			mychans->chanpos = y + 1;
 		}
+
+		/* Start checking for alarms in 250 ms */
+		ts->alarmcheck_time = jiffies + msecs_to_jiffies(250);
 
 		/* Enable 1sec timer interrupt */
 		reg = t4_framer_in(wc, x, FMR1_T);
@@ -2758,8 +2763,10 @@
 
 	spin_unlock_irqrestore(&wc->reglock, flags);
 
+	local_irq_save(flags);
 	t4_check_alarms(wc, span->offset);
 	t4_check_sigbits(wc, span->offset);
+	local_irq_restore(flags);
 
 	if (wc->tspans[0]->sync == span->spanno)
 		dev_info(&wc->dev->dev, "SPAN %d: Primary Sync Source\n",
@@ -3106,18 +3113,21 @@
 	}
 }
 
+/* Must be called from within hardirq context. */
 static void t4_check_alarms(struct t4 *wc, int span)
 {
 	unsigned char c, d, e;
 	int alarms;
 	int x,j;
 	struct t4_span *ts = wc->tspans[span];
-	unsigned long flags;
+
+	if (time_before(jiffies, ts->alarmcheck_time))
+		return;
 
 	if (!(ts->span.flags & DAHDI_FLAG_RUNNING))
 		return;
 
-	spin_lock_irqsave(&wc->reglock, flags);
+	spin_lock(&wc->reglock);
 
 	c = __t4_framer_in(wc, span, 0x4c);
 	d = __t4_framer_in(wc, span, 0x4d);
@@ -3192,63 +3202,68 @@
 
 	/* Loss of Frame Alignment */
 	if (c & 0x20) {
-		if (ts->alarmcount >= alarmdebounce) {
-
-			/* Disable Slip Interrupts */
-			e = __t4_framer_in(wc, span, 0x17);
-			__t4_framer_out(wc, span, 0x17, (e|0x03));
-
-			alarms |= DAHDI_ALARM_RED;
-		} else {
-			if (unlikely(debug && !ts->alarmcount)) {
+		if (!ts->alarm_time) {
+			if (unlikely(debug)) {
 				/* starting to debounce LOF/LFA */
 				dev_info(&wc->dev->dev, "wct%dxxp: LOF/LFA "
 					"detected on span %d but debouncing "
 					"for %d ms\n", wc->numspans, span + 1,
 					alarmdebounce);
 			}
-			ts->alarmcount++;
-		}
-	} else
-		ts->alarmcount = 0;
-
-	/* Loss of Signal */
-	if (c & 0x80) {
-		if (ts->losalarmcount >= losalarmdebounce) {
+			ts->alarm_time = jiffies +
+					  msecs_to_jiffies(alarmdebounce);
+		} else if (time_after(jiffies, ts->alarm_time)) {
 			/* Disable Slip Interrupts */
 			e = __t4_framer_in(wc, span, 0x17);
 			__t4_framer_out(wc, span, 0x17, (e|0x03));
 
 			alarms |= DAHDI_ALARM_RED;
-		} else {
-			if (unlikely(debug && !ts->losalarmcount)) {
+		}
+	} else {
+		ts->alarm_time = 0;
+	}
+
+	/* Loss of Signal */
+	if (c & 0x80) {
+		if (!ts->losalarm_time) {
+			if (unlikely(debug)) {
 				/* starting to debounce LOS */
 				dev_info(&wc->dev->dev, "wct%dxxp: LOS "
 					"detected on span %d but debouncing "
 					"for %d ms\n", wc->numspans,
 					span + 1, losalarmdebounce);
 			}
-			ts->losalarmcount++;
-		}
-	} else
-		ts->losalarmcount = 0;
+			ts->losalarm_time = jiffies +
+					     msecs_to_jiffies(losalarmdebounce);
+		} else if (time_after(jiffies, ts->losalarm_time)) {
+			/* Disable Slip Interrupts */
+			e = __t4_framer_in(wc, span, 0x17);
+			__t4_framer_out(wc, span, 0x17, (e|0x03));
+
+			alarms |= DAHDI_ALARM_RED;
+		}
+	} else {
+		ts->losalarm_time = 0;
+	}
 
 	/* Alarm Indication Signal */
 	if (c & 0x40) {
-		if (ts->aisalarmcount >= aisalarmdebounce)
-			alarms |= DAHDI_ALARM_BLUE;
-		else {
-			if (unlikely(debug && !ts->aisalarmcount)) {
+		if (!ts->aisalarm_time) {
+			if (unlikely(debug)) {
 				/* starting to debounce AIS */
 				dev_info(&wc->dev->dev, "wct%dxxp: AIS "
 					"detected on span %d but debouncing "
 					"for %d ms\n", wc->numspans,
 					span + 1, aisalarmdebounce);
 			}
-			ts->aisalarmcount++;
-		}
-	} else
-		ts->aisalarmcount = 0;
+			ts->aisalarm_time = jiffies +
+					     msecs_to_jiffies(aisalarmdebounce);
+		} else if (time_after(jiffies, ts->aisalarm_time)) {
+			alarms |= DAHDI_ALARM_BLUE;
+		}
+	} else {
+		ts->aisalarm_time = 0;
+	}
 
 	/* Add detailed alarm status information to a red alarm state */
 	if (alarms & DAHDI_ALARM_RED) {
@@ -3307,10 +3322,8 @@
 	/* Re-check the timing source when we enter/leave alarm, not withstanding
 	   yellow alarm */
 	if (c & 0x10) { /* receiving yellow (RAI) */
-		if (ts->yelalarmcount >= yelalarmdebounce)
-			alarms |= DAHDI_ALARM_YELLOW;
-		else {
-			if (unlikely(debug && !ts->yelalarmcount)) {
+		if (!ts->yelalarm_time) {
+			if (unlikely(debug)) {
 				/* starting to debounce AIS */
 				dev_info(&wc->dev->dev, "wct%dxxp: yellow "
 					"(RAI) detected on span %d but "
@@ -3318,42 +3331,40 @@
 					wc->numspans, span + 1,
 					yelalarmdebounce);
 			}
-			ts->yelalarmcount++;
-		}
-	} else
-		ts->yelalarmcount = 0;
+			ts->yelalarm_time = jiffies +
+					     msecs_to_jiffies(yelalarmdebounce);
+		} else if (time_after(jiffies, ts->yelalarm_time)) {
+			alarms |= DAHDI_ALARM_YELLOW;
+		}
+	} else {
+		ts->yelalarm_time = 0;
+	}
+
+	if (alarms)
+		ts->alarmcheck_time = jiffies + msecs_to_jiffies(100);
+	else
+		ts->alarmcheck_time = jiffies + msecs_to_jiffies(50);
 
 	if (ts->span.mainttimer || ts->span.maintstat) 
 		alarms |= DAHDI_ALARM_LOOPBACK;
 	ts->span.alarms = alarms;
-	spin_unlock_irqrestore(&wc->reglock, flags);
+
+	spin_unlock(&wc->reglock);
 	dahdi_alarm_notify(&ts->span);
 }
 
 static void t4_do_counters(struct t4 *wc)
 {
 	int span;
-	for (span=0;span<wc->numspans;span++) {
+	for (span = 0; span < wc->numspans; span++) {
 		struct t4_span *ts = wc->tspans[span];
-		int docheck=0;
 
 		spin_lock(&wc->reglock);
-		if (ts->loopupcnt || ts->loopdowncnt || ts->alarmcount
-			|| ts->losalarmcount || ts->aisalarmcount
-			|| ts->yelalarmcount)
-			docheck++;
-
-		if (ts->alarmtimer) {
-			if (!--ts->alarmtimer) {
-				docheck++;
-				ts->span.alarms &= ~(DAHDI_ALARM_RECOVER);
-			}
-		}
+		if (ts->alarmtimer && (0 == (--ts->alarmtimer)))
+			ts->span.alarms &= ~(DAHDI_ALARM_RECOVER);
 		spin_unlock(&wc->reglock);
-		if (docheck) {
-			t4_check_alarms(wc, span);
-			dahdi_alarm_notify(&ts->span);
-		}
+
+		t4_check_alarms(wc, span);
 	}
 }
 
@@ -3365,7 +3376,9 @@
 	for (x=0;x<wc->numspans;x++) {
 		struct t4_span *ts = wc->tspans[x];
 		if (ts->span.flags & DAHDI_FLAG_RUNNING) {
-			if ((ts->span.alarms & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE)) || ts->losalarmcount) {
+			if ((ts->span.alarms & (DAHDI_ALARM_RED |
+						DAHDI_ALARM_BLUE)) ||
+			     ts->losalarm_time) {
 #ifdef FANCY_ALARM
 				if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) {
 					__t4_set_led(wc, x, WC_RED);




More information about the svn-commits mailing list