From 8080751796851bae724ce85b5525ae47b6245be7 Mon Sep 17 00:00:00 2001 From: markster Date: Mon, 26 Sep 2005 20:11:36 +0000 Subject: Fix issue with CPU spiking git-svn-id: http://svn.digium.com/svn/zaptel/trunk@777 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- wctdm.c | 90 ++++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 32 deletions(-) diff --git a/wctdm.c b/wctdm.c index 7dcb9f7..6e35189 100755 --- a/wctdm.c +++ b/wctdm.c @@ -255,9 +255,9 @@ static struct fxo_mode { (the interrupt cycles around the four modules), so the periods are specified in _4 millisecond_ increments */ -#define RING_DEBOUNCE 16 /* Ringer Debounce (64 ms) */ -#define DEFAULT_BATT_DEBOUNCE 16 /* Battery debounce (64 ms) */ -#define POLARITY_DEBOUNCE 16 /* Polarity debounce (64 ms) */ +#define RING_DEBOUNCE 4 /* Ringer Debounce (64 ms) */ +#define DEFAULT_BATT_DEBOUNCE 4 /* Battery debounce (64 ms) */ +#define POLARITY_DEBOUNCE 4 /* Polarity debounce (64 ms) */ #define DEFAULT_BATT_THRESH 3 /* Anything under this is "no battery" */ #define OHT_TIMER 6000 /* How long after RING to retain OHT */ @@ -338,6 +338,8 @@ struct wctdm { /* Receive hook state and debouncing */ int modtype[NUM_CARDS]; + unsigned char reg0shadow[NUM_CARDS]; + unsigned char reg1shadow[NUM_CARDS]; unsigned long ioaddr; dma_addr_t readdma; @@ -803,13 +805,13 @@ static inline void wctdm_proslic_recheck_sanity(struct wctdm *wc, int card) { int res; /* Check loopback */ - res = wctdm_getreg(wc, card, 8); - if (res) { - printk("Ouch, part reset, quickly restoring reality (%d)\n", card); - wctdm_init_proslic(wc, card, 1, 0, 1); - } else { - res = wctdm_getreg(wc, card, 64); - if (!res && (res != wc->mod[card].fxs.lasttxhook)) { + res = wc->reg1shadow[card]; + if (!res && (res != wc->mod[card].fxs.lasttxhook)) { + res = wctdm_getreg(wc, card, 8); + if (res) { + printk("Ouch, part reset, quickly restoring reality (%d)\n", card); + wctdm_init_proslic(wc, card, 1, 0, 1); + } else { if (wc->mod[card].fxs.palarms++ < MAX_ALARMS) { printk("Power alarm on module %d, resetting!\n", card + 1); if (wc->mod[card].fxs.lasttxhook == 4) @@ -831,7 +833,7 @@ static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card) signed char b; int poopy = 0; /* Try to track issues that plague slot one FXO's */ - b = wctdm_getreg(wc, card, 5); + b = wc->reg0shadow[card]; if ((b & 0x2) || !(b & 0x8)) { /* Not good -- don't look at anything else */ if (debug) @@ -850,9 +852,9 @@ static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card) return; #ifndef AUDIO_RINGCHECK if (!wc->mod[card].fxo.offhook) { - res = wctdm_getreg(wc, card, 5); + res = wc->reg0shadow[card]; if ((res & 0x60) && wc->mod[card].fxo.battery) { - wc->mod[card].fxo.ringdebounce += (ZT_CHUNKSIZE * 4); + wc->mod[card].fxo.ringdebounce += (ZT_CHUNKSIZE * 16); if (wc->mod[card].fxo.ringdebounce >= ZT_CHUNKSIZE * 64) { if (!wc->mod[card].fxo.wasringing) { wc->mod[card].fxo.wasringing = 1; @@ -863,10 +865,10 @@ static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card) wc->mod[card].fxo.ringdebounce = ZT_CHUNKSIZE * 64; } } else { - wc->mod[card].fxo.ringdebounce -= ZT_CHUNKSIZE; + wc->mod[card].fxo.ringdebounce -= ZT_CHUNKSIZE * 4; if (wc->mod[card].fxo.ringdebounce <= 0) { if (wc->mod[card].fxo.wasringing) { - wc->mod[card].fxo.wasringing =0; + wc->mod[card].fxo.wasringing = 0; zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); if (debug) printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); @@ -877,7 +879,7 @@ static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card) } } #endif - b = wctdm_getreg(wc, card, 29); + b = wc->reg1shadow[card]; #if 0 { static int count = 0; @@ -955,13 +957,13 @@ static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card) wc->mod[card].fxo.polaritydebounce--; if (wc->mod[card].fxo.polaritydebounce < 1) { if (wc->mod[card].fxo.lastpol != wc->mod[card].fxo.polarity) { - if (debug) - printk("%lu Polarity reversed (%d -> %d)\n", jiffies, - wc->mod[card].fxo.polarity, - wc->mod[card].fxo.lastpol); - if (wc->mod[card].fxo.polarity) - zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY); - wc->mod[card].fxo.polarity = wc->mod[card].fxo.lastpol; + if (debug) + printk("%lu Polarity reversed (%d -> %d)\n", jiffies, + wc->mod[card].fxo.polarity, + wc->mod[card].fxo.lastpol); + if (wc->mod[card].fxo.polarity) + zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY); + wc->mod[card].fxo.polarity = wc->mod[card].fxo.lastpol; } } } @@ -975,7 +977,7 @@ static inline void wctdm_proslic_check_hook(struct wctdm *wc, int card) /* For some reason we have to debounce the hook detector. */ - res = wctdm_getreg(wc, card, 68); + res = wc->reg0shadow[card]; hook = (res & 1); if (hook != wc->mod[card].fxs.lastrxhook) { /* Reset the debounce (must be multiple of 4ms) */ @@ -985,7 +987,7 @@ static inline void wctdm_proslic_check_hook(struct wctdm *wc, int card) #endif } else { if (wc->mod[card].fxs.debounce > 0) { - wc->mod[card].fxs.debounce-= 4 * ZT_CHUNKSIZE; + wc->mod[card].fxs.debounce-= 16 * ZT_CHUNKSIZE; #if 0 printk("Sustaining hook %d, %d\n", hook, wc->mod[card].fxs.debounce); #endif @@ -1029,6 +1031,7 @@ static void wctdm_interrupt(int irq, void *dev_id, struct pt_regs *regs) struct wctdm *wc = dev_id; unsigned char ints; int x; + int mode; ints = inb(wc->ioaddr + WC_INTSTAT); outb(ints, wc->ioaddr + WC_INTSTAT); @@ -1094,14 +1097,37 @@ static void wctdm_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (ints & 0x0f) { wc->intcount++; - x = wc->intcount % 4; + x = wc->intcount & 0x3; + mode = wc->intcount & 0xc; if (wc->cardflag & (1 << x)) { - if (wc->modtype[x] == MOD_TYPE_FXS) { - wctdm_proslic_check_hook(wc, x); - if (!(wc->intcount & 0xfc)) - wctdm_proslic_recheck_sanity(wc, x); - } else if (wc->modtype[x] == MOD_TYPE_FXO) { - wctdm_voicedaa_check_hook(wc, x); + switch(mode) { + case 0: + /* Rest */ + break; + case 4: + /* Read first shadow reg */ + if (wc->modtype[x] == MOD_TYPE_FXS) + wc->reg0shadow[x] = wctdm_getreg(wc, x, 68); + else if (wc->modtype[x] == MOD_TYPE_FXO) + wc->reg0shadow[x] = wctdm_getreg(wc, x, 5); + break; + case 8: + /* Read second shadow reg */ + if (wc->modtype[x] == MOD_TYPE_FXS) + wc->reg1shadow[x] = wctdm_getreg(wc, x, 64); + else if (wc->modtype[x] == MOD_TYPE_FXO) + wc->reg1shadow[x] = wctdm_getreg(wc, x, 29); + break; + case 12: + /* Perform processing */ + if (wc->modtype[x] == MOD_TYPE_FXS) { + wctdm_proslic_check_hook(wc, x); + if (!(wc->intcount & 0xf0)) + wctdm_proslic_recheck_sanity(wc, x); + } else if (wc->modtype[x] == MOD_TYPE_FXO) { + wctdm_voicedaa_check_hook(wc, x); + } + break; } } if (!(wc->intcount % 10000)) { -- cgit v1.2.3