summaryrefslogtreecommitdiff
path: root/drivers/dahdi/wct4xxp
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2011-10-20 20:52:06 +0000
committerShaun Ruffell <sruffell@digium.com>2011-10-20 20:52:06 +0000
commitc85dbd6db92c190328f1ff1b1ae19e11b0ffdd36 (patch)
treeb25e5ad02a02f93bba89ad0208176b8aea077657 /drivers/dahdi/wct4xxp
parent03e4048ff20e3416ac369ce3551e916d90771c5a (diff)
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@digium.com> Acked-by: Michael Spiceland <mspiceland@digium.com> Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10231 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/wct4xxp')
-rw-r--r--drivers/dahdi/wct4xxp/base.c135
1 files changed, 74 insertions, 61 deletions
diff --git a/drivers/dahdi/wct4xxp/base.c b/drivers/dahdi/wct4xxp/base.c
index 5040c66..02b4c85 100644
--- a/drivers/dahdi/wct4xxp/base.c
+++ b/drivers/dahdi/wct4xxp/base.c
@@ -291,10 +291,11 @@ struct t4_span {
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 @@ static void init_spans(struct t4 *wc)
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);
@@ -2175,6 +2177,9 @@ static void init_spans(struct t4 *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);
t4_framer_out(wc, x, FMR1_T, (reg | FMR1_ECM));
@@ -2758,8 +2763,10 @@ static int t4_startup(struct file *file, struct dahdi_span *span)
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 @@ static void t4_check_sigbits(struct t4 *wc, int span)
}
}
+/* 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 @@ static void t4_check_alarms(struct t4 *wc, int span)
/* 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++;
+ 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->losalarmcount = 0;
+ } 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++;
+ ts->aisalarm_time = jiffies +
+ msecs_to_jiffies(aisalarmdebounce);
+ } else if (time_after(jiffies, ts->aisalarm_time)) {
+ alarms |= DAHDI_ALARM_BLUE;
}
- } else
- ts->aisalarmcount = 0;
+ } else {
+ ts->aisalarm_time = 0;
+ }
/* Add detailed alarm status information to a red alarm state */
if (alarms & DAHDI_ALARM_RED) {
@@ -3307,10 +3322,8 @@ static void t4_check_alarms(struct t4 *wc, int span)
/* 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 @@ static void t4_check_alarms(struct t4 *wc, int span)
wc->numspans, span + 1,
yelalarmdebounce);
}
- ts->yelalarmcount++;
+ ts->yelalarm_time = jiffies +
+ msecs_to_jiffies(yelalarmdebounce);
+ } else if (time_after(jiffies, ts->yelalarm_time)) {
+ alarms |= DAHDI_ALARM_YELLOW;
}
- } else
- ts->yelalarmcount = 0;
+ } 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 @@ static inline void __handle_leds(struct t4 *wc)
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);