Author: mattf
Date: Sat Apr 28 16:07:35 2007
New Revision: 2469
URL: http://svn.digium.com/view/zaptel?view=rev&rev=2469
a>
Log:
Fix for potential deadlock in wct4xxp driver
Modified:
branches/1.2/wct4xxp/base.c
Modified: branches/1.2/wct4xxp/base.c
URL: http
://svn.digium.com/view/zaptel/branches/1.2/wct4xxp/base.c?vi
ew=diff&rev=2469&r1=2468&r2=2469
============================================================
==================
--- branches/1.2/wct4xxp/base.c (original)
+++ branches/1.2/wct4xxp/base.c Sat Apr 28 16:07:35 2007
 -360,8
+360,8 
static void t4_tsi_assign(struct t4 *wc, int fromspan, int
fromchan, int tospan, int tochan);
static void t4_tsi_unassign(struct t4 *wc, int tospan, int
tochan);
static void __t4_set_timing_source(struct t4 *wc, int
unit);
-static void __t4_check_alarms(struct t4 *wc, int span);
-static void __t4_check_sigbits(struct t4 *wc, int span);
+static void t4_check_alarms(struct t4 *wc, int span);
+static void t4_check_sigbits(struct t4 *wc, int span);
#define WC_RDADDR 0
#define WC_WRADDR 1
 -747,7
+747,7 
}
}
-static void __t4_check_vpm400(struct t4 *wc, unsigned int
newio)
+static void t4_check_vpm400(struct t4 *wc, unsigned int
newio)
{
unsigned int digit, regval = 0;
unsigned int regbyte;
 -755,12
+755,14 
short energy=0;
static unsigned int lastio = 0;
struct t4_span *ts;
+ unsigned long flags;
if (debug && (newio != lastio))
printk("Last was %08x, new is %08xn", lastio,
newio);
lastio = newio;
+ spin_lock_irqsave(&wc->reglock, flags);
for(x = 0; x < 8; x++) {
if (newio & (1 << (7 - x)))
continue;
 -789,23
+791,33 
}
ts->dtmfactive |= (1 << base);
if (ts->dtmfdigit[base]) {
- if (ts->dtmfmask & (1 << base))
+ if (ts->dtmfmask & (1 << base)) {
+ spin_unlock_irqrestore(&wc->reglock, flags);
zt_qevent_lock(&ts->span.chans[base],
(ZT_EVENT_DTMFUP | ts->dtmfdigit[base]));
+ spin_lock_irqsave(&wc->reglock, flags);
+ }
}
ts->dtmfdigit[base] = digit;
- if (ts->dtmfmask & (1 << base))
+ if (ts->dtmfmask & (1 << base)) {
+ spin_unlock_irqrestore(&wc->reglock, flags);
zt_qevent_lock(&ts->span.chans[base],
(ZT_EVENT_DTMFDOWN | digit));
+ spin_lock_irqsave(&wc->reglock, flags);
+ }
if (ts->dtmfmutemask & (1 << base)) {
/* Mute active receive buffer*/
- unsigned long flags;
+ unsigned long flags2;
struct zt_chan *chan = &ts->span.chans[base];
int y;
- spin_lock_irqsave(&chan->lock, flags);
+ /* We can't hold the reglock and the channel lock at
the same time. If we do so,
+ * we can cause a deadlock scenario */
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ spin_lock_irqsave(&chan->lock, flags2);
for (y=0;y<chan->numbufs;y++) {
if ((chan->inreadbuf > -1) &&
(chan->readidx[y]))
memset(chan->readbuf[chan->inreadbuf],
ZT_XLAW(0, chan), chan->readidx[y]);
}
- spin_unlock_irqrestore(&chan->lock, flags);
+ spin_unlock_irqrestore(&chan->lock, flags2);
+ spin_lock_irqsave(&wc->reglock, flags);
}
if (debug)
printk("Digit Seen: %d, Span: %d, channel: %d,
energy: %02x, 'channel %d' chip %dn", digit, x % 4,
base + 1, energy, channel, x);
 -833,8
+845,11 
base -= 4;
ts->dtmfactive &= ~(1 << base);
if (ts->dtmfdigit[base]) {
- if (ts->dtmfmask & (1 << base))
+ if (ts->dtmfmask & (1 << base)) {
+ spin_unlock_irqrestore(&wc->reglock, flags);
zt_qevent_lock(&ts->span.chans[base],
(ZT_EVENT_DTMFUP | ts->dtmfdigit[base]));
+ spin_lock_irqsave(&wc->reglock, flags);
+ }
}
digit = ts->dtmfdigit[base];
ts->dtmfdigit[base] = 0;
 -846,6
+861,7 
}
}
+ spin_unlock_irqrestore(&wc->reglock, flags);
}
#endif
 -1545,11
+1561,6 
__t4_framer_out(wc, unit, 0x18, 0xff); /* IMR4: We don't
care about slips on transmit */
}
- if (!polling) {
- __t4_check_alarms(wc, unit);
- __t4_check_sigbits(wc, unit);
- }
-
printk("TE%dXXP: Span %d configured for
%s/%sn", wc->numspans, unit + 1, framing, line);
}
 -1632,10
+1643,6 
__t4_framer_out(wc, unit, 0x17, 0xc7 | imr3extra); /*
IMR3: We care about AIS and friends */
__t4_framer_out(wc, unit, 0x18, 0xff); /* IMR4: We don't
care about slips on transmit */
}
- if (!polling) {
- __t4_check_alarms(wc, unit);
- __t4_check_sigbits(wc, unit);
- }
printk("TE%dXXP: Span %d configured for
%s/%s%sn", wc->numspans, unit + 1, framing, line,
crc4);
}
 -1700,13
+1707,13 
if (noburst)
wc->dmactrl |= (1 << 26);
__t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
- if (!polling) {
- __t4_check_alarms(wc, span->offset);
- __t4_check_sigbits(wc, span->offset);
- }
}
spin_unlock_irqrestore(&wc->reglock, flags);
+
+ t4_check_alarms(wc, span->offset);
+ t4_check_sigbits(wc, span->offset);
+
if (wc->tspans[0]->sync == span->spanno)
printk("SPAN %d: Primary Sync
Sourcen",span->spanno);
if (wc->tspans[1]->sync == span->spanno)
printk("SPAN %d: Secondary Sync
Sourcen",span->spanno);
if (wc->numspans == 4) {
 -1963,7
+1970,7 
}
#endif
-static void __t4_check_sigbits(struct t4 *wc, int span)
+static void t4_check_sigbits(struct t4 *wc, int span)
{
int a,i,rxs;
struct t4_span *ts = wc->tspans[span];
 -1973,9
+1980,10 
if (!(ts->span.flags & ZT_FLAG_RUNNING))
return;
+
if (ts->spantype == TYPE_E1) {
for (i = 0; i < 15; i++) {
- a = __t4_framer_in(wc, span, 0x71 + i);
+ a = t4_framer_in(wc, span, 0x71 + i);
/* Get high channel in low bits */
rxs = (a & 0xf);
if (!(ts->span.chans[i+16].sig & ZT_SIG_CLEAR))
{
 -1990,7
+1998,7 
}
} else if (ts->span.lineconfig & ZT_CONFIG_D4) {
for (i = 0; i < 24; i+=4) {
- a = __t4_framer_in(wc, span, 0x70 + (i>>2));
+ a = t4_framer_in(wc, span, 0x70 + (i>>2));
/* Get high channel in low bits */
rxs = (a & 0x3) << 2;
if (!(ts->span.chans[i+3].sig & ZT_SIG_CLEAR)) {
 -2015,7
+2023,7 
}
} else {
for (i = 0; i < 24; i+=2) {
- a = __t4_framer_in(wc, span, 0x70 + (i>>1));
+ a = t4_framer_in(wc, span, 0x70 + (i>>1));
/* Get high channel in low bits */
rxs = (a & 0xf);
if (!(ts->span.chans[i+1].sig & ZT_SIG_CLEAR)) {
 -2035,15
+2043,18 
}
}
-static void __t4_check_alarms(struct t4 *wc, int span)
+static void t4_check_alarms(struct t4 *wc, int span)
{
unsigned char c,d;
int alarms;
int x,j;
struct t4_span *ts = wc->tspans[span];
+ unsigned long flags;
if (!(ts->span.flags & ZT_FLAG_RUNNING))
return;
+
+ spin_lock_irqsave(&wc->reglock, flags);
c = __t4_framer_in(wc, span, 0x4c);
d = __t4_framer_in(wc, span, 0x4d);
 -2154,15
+2165,21 
if (ts->span.mainttimer || ts->span.maintstat)
alarms |= ZT_ALARM_LOOPBACK;
ts->span.alarms = alarms;
+
+ spin_unlock_irqrestore(&wc->reglock, flags);
+
zt_alarm_notify(&ts->span);
}
-static void __t4_do_counters(struct t4 *wc)
+static void t4_do_counters(struct t4 *wc)
{
int span;
+ unsigned long flags;
+
for (span=0;span<wc->numspans;span++) {
struct t4_span *ts = wc->tspans[span];
int docheck=0;
+ spin_lock_irqsave(&wc->reglock, flags);
if (ts->loopupcnt || ts->loopdowncnt)
docheck++;
if (ts->alarmtimer) {
 -2171,9
+2188,10 
ts->span.alarms &= ~(ZT_ALARM_RECOVER);
}
}
+ spin_unlock_irqrestore(&wc->reglock, flags);
if (docheck) {
if (!polling)
- __t4_check_alarms(wc, span);
+ t4_check_alarms(wc, span);
zt_alarm_notify(&ts->span);
}
}
 -2301,11
+2319,7 
}
}
#endif
- spin_lock_irqsave(&wc->reglock, flags);
-
- __handle_leds(wc);
-
- __t4_do_counters(wc);
+ t4_do_counters(wc);
x = wc->intcount & 15 /* 63 */;
switch(x) {
 -2313,18
+2327,23 
case 1:
case 2:
case 3:
- __t4_check_sigbits(wc, x);
+ t4_check_sigbits(wc, x);
break;
case 4:
case 5:
case 6:
case 7:
- __t4_check_alarms(wc, x - 4);
+ t4_check_alarms(wc, x - 4);
break;
}
+
+ spin_lock_irqsave(&wc->reglock, flags);
+
+ __handle_leds(wc);
if (wc->checktiming > 0)
__t4_set_timing_source_auto(wc);
+
spin_unlock_irqrestore(&wc->reglock, flags);
#ifdef LINUX26
return IRQ_RETVAL(1);
 -2332,7
+2351,7 
}
#endif
-static inline void __t4_framer_interrupt(struct t4 *wc, int
span)
+static inline void t4_framer_interrupt(struct t4 *wc, int
span)
{
/* Check interrupts for a given span */
unsigned char gis, isr0=0, isr1=0, isr2=0, isr3=0, isr4;
 -2342,40
+2361,40 
printk("framer interrupt span %d:%d!n",
wc->num, span + 1);
ts = wc->tspans[span];
- gis = __t4_framer_in(wc, span, 0x6e);
+ gis = t4_framer_in(wc, span, 0x6e);
if (ts->spantype == TYPE_E1) {
/* E1 checks */
if (gis & 0x1)
- isr0 = __t4_framer_in(wc, span, 0x68);
+ isr0 = t4_framer_in(wc, span, 0x68);
if (gis & 0x2)
- isr1 = __t4_framer_in(wc, span, 0x69);
+ isr1 = t4_framer_in(wc, span, 0x69);
if (gis & 0x4)
- isr2 = __t4_framer_in(wc, span, 0x6a);
+ isr2 = t4_framer_in(wc, span, 0x6a);
if (gis & 0x8)
- isr3 = __t4_framer_in(wc, span, 0x6b);
+ isr3 = t4_framer_in(wc, span, 0x6b);
if (isr0)
- __t4_check_sigbits(wc, span);
+ t4_check_sigbits(wc, span);
if ((isr3 & 0x38) || isr2 || isr1)
- __t4_check_alarms(wc, span);
+ t4_check_alarms(wc, span);
if (debug & DEBUG_FRAMER)
printk("gis: %02x, isr0: %02x, isr1: %02x, isr2:
%02x, isr3: %02xn", gis, isr0, isr1, isr2, isr3);
} else {
/* T1 checks */
if (gis & 0x1)
- isr0 = __t4_framer_in(wc, span, 0x68);
+ isr0 = t4_framer_in(wc, span, 0x68);
if (gis & 0x4)
- isr2 = __t4_framer_in(wc, span, 0x6a);
+ isr2 = t4_framer_in(wc, span, 0x6a);
if (gis & 0x8)
- isr3 = __t4_framer_in(wc, span, 0x6b);
+ isr3 = t4_framer_in(wc, span, 0x6b);
if (isr0)
- __t4_check_sigbits(wc, span);
+ t4_check_sigbits(wc, span);
if (isr2 || (isr3 & 0x08))
- __t4_check_alarms(wc, span);
+ t4_check_alarms(wc, span);
if (debug & DEBUG_FRAMER)
printk("gis: %02x, isr0: %02x, isr1: %02x, irs2:
%02x, isr3: %02xn", gis, isr0, isr1, isr2, isr3);
}
 -2385,7
+2404,7 
if (isr3 & 0x01)
printk("TE%d10P: RECEIVE slip POSITIVE on span
%dn", wc->numspans, span + 1);
if (gis & 0x10)
- isr4 = __t4_framer_in(wc, span, 0x6c);
+ isr4 = t4_framer_in(wc, span, 0x6c);
else
isr4 = 0;
if (isr4 & 0x80)
 -2472,10
+2491,8 
#endif
}
- spin_lock_irqsave(&wc->reglock, flags);
-
if (status & 0x2)
- __t4_do_counters(wc);
+ t4_do_counters(wc);
if (polling && (status & 0x2)) {
x = wc->intcount & 15 /* 63 */;
 -2484,26
+2501,29 
case 1:
case 2:
case 3:
- __t4_check_sigbits(wc, x);
+ t4_check_sigbits(wc, x);
break;
case 4:
case 5:
case 6:
case 7:
- __t4_check_alarms(wc, x - 4);
+ t4_check_alarms(wc, x - 4);
break;
}
} else if (status & 0x1) {
- cis = __t4_framer_in(wc, 0, 0x6f);
+ cis = t4_framer_in(wc, 0, 0x6f);
if (cis & 0x1)
- __t4_framer_interrupt(wc, 0);
+ t4_framer_interrupt(wc, 0);
if (cis & 0x2)
- __t4_framer_interrupt(wc, 1);
+ t4_framer_interrupt(wc, 1);
if (cis & 0x4)
- __t4_framer_interrupt(wc, 2);
+ t4_framer_interrupt(wc, 2);
if (cis & 0x8)
- __t4_framer_interrupt(wc, 3);
- }
+ t4_framer_interrupt(wc, 3);
+ }
+
+ spin_lock_irqsave(&wc->reglock, flags);
+
#ifdef VPM_SUPPORT
if (wc->vpm) {
if (!wc->vpm450m && !(wc->intcount % 16)
&& !(wc->tspans[0]->spanflags &
FLAG_VPM2GEN)) {
 -2530,8
+2550,11 
printk("Finished digit on span %d, channel %d
(energy = %02x < %02x) 'channel' %d, chip %d!n",
span, y + 1, energy, ts->dtmfenergy[y], channel, chip);
if (debug & DEBUG_DTMF)
printk("Finished digit '%c' on channel %d of
span %dn", ts->dtmfdigit[y], y + 1, span);
- if (ts->dtmfmask & (1 << y))
+ if (ts->dtmfmask & (1 << y)) {
+ spin_unlock_irqrestore(&wc->reglock,
flags);
zt_qevent_lock(&ts->span.chans[y],
(ZT_EVENT_DTMFUP | ts->dtmfdigit[y]));
+ spin_lock_irqsave(&wc->reglock, flags);
+ }
ts->dtmfenergy[y] = 0;
ts->dtmfdigit[y] = 0;
ts->dtmfactive &= ~(1 << y);
 -2549,8
+2572,11 
if (!(wc->intcount & 0xf)) {
needcheckvpm450 = 1;
}
- } else if ((status & 0xff00) != 0xff00)
- __t4_check_vpm400(wc, (status & 0xff00) >>
8);
+ } else if ((status & 0xff00) != 0xff00) {
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ t4_check_vpm400(wc, (status & 0xff00) >> 8);
+ spin_lock_irqsave(&wc->reglock, flags);
+ }
}
#endif
_______________________________________________
--Bandwidth and Colocation provided by Easynews.com --
zaptel-commits mailing list
To UNSUBSCRIBE or update options visit:
http://lists.digium.com/mailman/listinfo/zaptel-commits
a>
|