diff options
author | mattf <mattf@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-04-25 16:26:18 +0000 |
---|---|---|
committer | mattf <mattf@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-04-25 16:26:18 +0000 |
commit | fa410634b9156b926619cd41025df536af14dfb5 (patch) | |
tree | 7780a631c5c883192de6e55318c8bc6d150a1818 /wct1xxp.c | |
parent | bfbb86dec39366f1990a6d949f0aad467b8b1531 (diff) |
Start fixing potential deadlock between device driver and zaptel
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@2451 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wct1xxp.c')
-rw-r--r-- | wct1xxp.c | 45 |
1 files changed, 34 insertions, 11 deletions
@@ -957,10 +957,12 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints) zt_receive(&wc->span); } -static void __t1xxp_check_sigbits(struct t1xxp *wc, int x) +static void t1xxp_check_sigbits(struct t1xxp *wc, int x) { int a,b,i,y,rxs; + unsigned long flags; + spin_lock_irqsave(&wc->lock, flags); if (wc->ise1) { /* Read 5 registers at a time, loading 10 channels at a time */ for (i = (x * 5); i < (x * 5) + 5; i++) { @@ -968,13 +970,19 @@ static void __t1xxp_check_sigbits(struct t1xxp *wc, int x) /* Get high channel in low bits */ rxs = (a & 0xf); if (!(wc->chans[i+16].sig & ZT_SIG_CLEAR)) { - if (wc->chans[i+16].rxsig != rxs) + if (wc->chans[i+16].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); zt_rbsbits(&wc->chans[i+16], rxs); + spin_lock_irqsave(&wc->lock, flags); + } } rxs = (a >> 4) & 0xf; if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->chans[i].rxsig != rxs) + if (wc->chans[i].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); zt_rbsbits(&wc->chans[i], rxs); + spin_lock_irqsave(&wc->lock, flags); + } } } } else { @@ -988,18 +996,25 @@ static void __t1xxp_check_sigbits(struct t1xxp *wc, int x) if (b & (1 << y)) rxs |= ZT_BBIT; if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->chans[i].rxsig != rxs) + if (wc->chans[i].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); zt_rbsbits(&wc->chans[i], rxs); + spin_lock_irqsave(&wc->lock, flags); + } } } } + spin_unlock_irqrestore(&wc->lock, flags); } -static void __t1xxp_check_alarms(struct t1xxp *wc) +static void t1xxp_check_alarms(struct t1xxp *wc) { unsigned char c,d; int alarms; int x,j; + unsigned long flags; + + spin_lock_irqsave(&wc->lock, flags); if (wc->ise1) { __t1_set_reg(wc, 0x06, 0xff); @@ -1103,11 +1118,16 @@ static void __t1xxp_check_alarms(struct t1xxp *wc) wc->span.alarms = alarms; + spin_unlock_irqrestore(&wc->lock, flags); + zt_alarm_notify(&wc->span); } -static void __t1xxp_do_counters(struct t1xxp *wc) +static void t1xxp_do_counters(struct t1xxp *wc) { + unsigned long flags; + + spin_lock_irqsave(&wc->lock, flags); if (wc->alarmtimer) { if (!--wc->alarmtimer) { wc->span.alarms &= ~(ZT_ALARM_RECOVER); @@ -1119,9 +1139,12 @@ static void __t1xxp_do_counters(struct t1xxp *wc) __t1_set_reg(wc, 0x21, 0x5f); else __t1_set_reg(wc, 0x35, 0x10); + spin_unlock_irqrestore(&wc->lock, flags); zt_alarm_notify(&wc->span); + spin_lock_irqsave(&wc->lock, flags); } } + spin_unlock_irqrestore(&wc->lock, flags); } ZAP_IRQ_HANDLER(t1xxp_interrupt) @@ -1159,8 +1182,10 @@ ZAP_IRQ_HANDLER(t1xxp_interrupt) __handle_leds(wc); #endif + spin_unlock_irqrestore(&wc->lock, flags); + /* Count down timers */ - __t1xxp_do_counters(wc); + t1xxp_do_counters(wc); /* Do some things that we don't have to do very often */ x = wc->intcount & 15 /* 63 */; @@ -1168,17 +1193,15 @@ ZAP_IRQ_HANDLER(t1xxp_interrupt) case 0: case 1: case 2: - __t1xxp_check_sigbits(wc, x); + t1xxp_check_sigbits(wc, x); break; case 4: /* Check alarms 1/4 as frequently */ if (!(wc->intcount & 0x30)) - __t1xxp_check_alarms(wc); + t1xxp_check_alarms(wc); break; } - spin_unlock_irqrestore(&wc->lock, flags); - if (ints & 0x10) printk("PCI Master abort\n"); |