From 2485ad582edc4bd70f6bc532491fd5da47fb690f Mon Sep 17 00:00:00 2001 From: mattf Date: Wed, 25 Apr 2007 16:49:50 +0000 Subject: Fix potential deadlock in driver-zaptel interaction git-svn-id: http://svn.digium.com/svn/zaptel/trunk@2453 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- wct1xxp.c | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) (limited to 'wct1xxp.c') diff --git a/wct1xxp.c b/wct1xxp.c index 81e428e..43215fc 100644 --- a/wct1xxp.c +++ b/wct1xxp.c @@ -959,10 +959,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++) { @@ -970,13 +972,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 { @@ -990,18 +998,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); @@ -1105,11 +1120,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); @@ -1121,9 +1141,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) @@ -1161,8 +1184,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 */; @@ -1170,17 +1195,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"); -- cgit v1.2.3