From e938a478184e67088fc89ce03838929f4112e40b Mon Sep 17 00:00:00 2001 From: mattf Date: Sat, 28 Apr 2007 19:13:00 +0000 Subject: Merged revisions 2465 via svnmerge from https://origsvn.digium.com/svn/zaptel/branches/1.4 ................ r2465 | mattf | 2007-04-28 14:11:20 -0500 (Sat, 28 Apr 2007) | 10 lines Merged revisions 2464 via svnmerge from https://origsvn.digium.com/svn/zaptel/branches/1.2 ........ r2464 | mattf | 2007-04-28 14:04:50 -0500 (Sat, 28 Apr 2007) | 2 lines Fix for potential deadlock in drivers ........ ................ git-svn-id: http://svn.digium.com/svn/zaptel/trunk@2466 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- wcte11xp.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 16 deletions(-) diff --git a/wcte11xp.c b/wcte11xp.c index 78537ed..e417be7 100644 --- a/wcte11xp.c +++ b/wcte11xp.c @@ -561,24 +561,35 @@ static int t1xxp_rbsbits(struct zt_chan *chan, int bits) return 0; } -static void __t1_check_sigbits(struct t1 *wc) +static void t1_check_sigbits(struct t1 *wc) { int a,i,rxs; + unsigned long flags; + if (!(wc->span.flags & ZT_FLAG_RUNNING)) return; + + spin_lock_irqsave(&wc->lock, flags); + if (wc->spantype == TYPE_E1) { for (i = 0; i < 15; i++) { a = __t1_framer_in(wc, 0x71 + i); /* Get high channel in low bits */ rxs = (a & 0xf); if (!(wc->span.chans[i+16].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+16].rxsig != rxs) + if (wc->span.chans[i+16].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); zt_rbsbits(&wc->span.chans[i+16], rxs); + spin_lock_irqsave(&wc->lock, flags); + } } rxs = (a >> 4) & 0xf; if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i].rxsig != rxs) + if (wc->span.chans[i].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); zt_rbsbits(&wc->span.chans[i], rxs); + spin_lock_irqsave(&wc->lock, flags); + } } } } else if (wc->span.lineconfig & ZT_CONFIG_D4) { @@ -587,23 +598,35 @@ static void __t1_check_sigbits(struct t1 *wc) /* Get high channel in low bits */ rxs = (a & 0x3) << 2; if (!(wc->span.chans[i+3].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+3].rxsig != rxs) + if (wc->span.chans[i+3].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); zt_rbsbits(&wc->span.chans[i+3], rxs); + spin_lock_irqsave(&wc->lock, flags); + } } rxs = (a & 0xc); if (!(wc->span.chans[i+2].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+2].rxsig != rxs) + if (wc->span.chans[i+2].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); zt_rbsbits(&wc->span.chans[i+2], rxs); + spin_lock_irqsave(&wc->lock, flags); + } } rxs = (a >> 2) & 0xc; if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+1].rxsig != rxs) + if (wc->span.chans[i+1].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); zt_rbsbits(&wc->span.chans[i+1], rxs); + spin_lock_irqsave(&wc->lock, flags); + } } rxs = (a >> 4) & 0xc; if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i].rxsig != rxs) + if (wc->span.chans[i].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); zt_rbsbits(&wc->span.chans[i], rxs); + spin_lock_irqsave(&wc->lock, flags); + } } } } else { @@ -612,16 +635,23 @@ static void __t1_check_sigbits(struct t1 *wc) /* Get high channel in low bits */ rxs = (a & 0xf); if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+1].rxsig != rxs) + if (wc->span.chans[i+1].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); zt_rbsbits(&wc->span.chans[i+1], rxs); + spin_lock_irqsave(&wc->lock, flags); + } } rxs = (a >> 4) & 0xf; if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i].rxsig != rxs) + if (wc->span.chans[i].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); zt_rbsbits(&wc->span.chans[i], rxs); + spin_lock_irqsave(&wc->lock, flags); + } } } } + spin_unlock_irqrestore(&wc->lock, flags); } static void t4_serial_setup(struct t1 *wc) @@ -1145,15 +1175,18 @@ static void t1xxp_receiveprep(struct t1 *wc, int ints) zt_receive(&wc->span); } -static void __t1_check_alarms(struct t1 *wc) +static void t1_check_alarms(struct t1 *wc) { unsigned char c,d; int alarms; int x,j; + unsigned long flags; if (!(wc->span.flags & ZT_FLAG_RUNNING)) return; + spin_lock_irqsave(&wc->lock, flags); + c = __t1_framer_in(wc, 0x4c); if (wc->spanflags & FLAG_FALC12) d = __t1_framer_in(wc, 0x4f); @@ -1267,18 +1300,25 @@ static void __t1_check_alarms(struct t1 *wc) if (wc->span.mainttimer || wc->span.maintstat) alarms |= ZT_ALARM_LOOPBACK; wc->span.alarms = alarms; + spin_unlock_irqrestore(&wc->lock, flags); zt_alarm_notify(&wc->span); } -static void __t1_do_counters(struct t1 *wc) +static void t1_do_counters(struct t1 *wc) { + unsigned long flags; + + spin_lock_irqsave(&wc->lock, flags); if (wc->alarmtimer) { if (!--wc->alarmtimer) { wc->span.alarms &= ~(ZT_ALARM_RECOVER); + 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) @@ -1316,8 +1356,10 @@ ZAP_IRQ_HANDLER(t1xxp_interrupt) __handle_leds(wc); #endif + spin_unlock_irqrestore(&wc->lock, flags); + /* Count down timers */ - __t1_do_counters(wc); + t1_do_counters(wc); /* Do some things that we don't have to do very often */ x = wc->intcount & 15 /* 63 */; @@ -1326,17 +1368,15 @@ ZAP_IRQ_HANDLER(t1xxp_interrupt) case 1: break; case 2: - __t1_check_sigbits(wc); + t1_check_sigbits(wc); break; case 4: /* Check alarms 1/4 as frequently */ if (!(wc->intcount & 0x30)) - __t1_check_alarms(wc); + t1_check_alarms(wc); break; } - spin_unlock_irqrestore(&wc->lock, flags); - if (ints & 0x10) printk("PCI Master abort\n"); -- cgit v1.2.3