[svn-commits] mattf: branch 1.4 r2470 - in /branches/1.4: ./
wct4xxp/base.c
svn-commits at lists.digium.com
svn-commits at lists.digium.com
Sat Apr 28 14:29:07 MST 2007
Author: mattf
Date: Sat Apr 28 16:29:06 2007
New Revision: 2470
URL: http://svn.digium.com/view/zaptel?view=rev&rev=2470
Log:
Merged revisions 2469 via svnmerge from
https://origsvn.digium.com/svn/zaptel/branches/1.2
........
r2469 | mattf | 2007-04-28 16:07:35 -0500 (Sat, 28 Apr 2007) | 1 line
Fix for potential deadlock in wct4xxp driver
........
Modified:
branches/1.4/ (props changed)
branches/1.4/wct4xxp/base.c
Propchange: branches/1.4/
------------------------------------------------------------------------------
Binary property 'branch-1.2-merged' - no diff available.
Modified: branches/1.4/wct4xxp/base.c
URL: http://svn.digium.com/view/zaptel/branches/1.4/wct4xxp/base.c?view=diff&rev=2470&r1=2469&r2=2470
==============================================================================
--- branches/1.4/wct4xxp/base.c (original)
+++ branches/1.4/wct4xxp/base.c Sat Apr 28 16:29:06 2007
@@ -369,8 +369,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, int master, int slave);
-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
@@ -765,7 +765,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;
@@ -773,12 +773,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 %08x\n", lastio, newio);
lastio = newio;
+ spin_lock_irqsave(&wc->reglock, flags);
for(x = 0; x < 8; x++) {
if (newio & (1 << (7 - x)))
continue;
@@ -807,23 +809,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 %d\n", digit, x % 4, base + 1, energy, channel, x);
@@ -851,8 +863,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;
@@ -864,6 +879,7 @@
}
}
+ spin_unlock_irqrestore(&wc->reglock, flags);
}
#endif
@@ -1186,12 +1202,16 @@
return 0;
}
-static void inline __t4_hdlc_xmit_fifo(struct t4 *wc, unsigned int span, struct t4_span *ts)
+static void inline t4_hdlc_xmit_fifo(struct t4 *wc, unsigned int span, struct t4_span *ts)
{
int res, i, size = 32;
unsigned char buf[32];
+ unsigned long flags;
res = zt_hdlc_getbuf(ts->sigchan, buf, &size);
+
+ spin_lock_irqsave(&wc->reglock, flags);
+
if (debug & DEBUG_FRAMER) printk("Got buffer sized %d and res %d for %d\n", size, res, span);
if (size > 0) {
ts->sigactive = 1;
@@ -1222,6 +1242,8 @@
}
else if (res < 0)
ts->sigactive = 0;
+
+ spin_unlock_irqrestore(&wc->reglock, flags);
}
static void t4_hdlc_hard_xmit(struct zt_chan *chan)
@@ -1238,9 +1260,11 @@
return;
}
if (debug & DEBUG_FRAMER) printk("t4_hdlc_hard_xmit on channel %s (sigchan %s), sigactive=%d\n", chan->name, ts->sigchan->name, ts->sigactive);
- if ((ts->sigchan == chan) && !ts->sigactive)
- __t4_hdlc_xmit_fifo(wc, span, ts);
- spin_unlock_irqrestore(&wc->reglock, flags);
+ if ((ts->sigchan == chan) && !ts->sigactive) {
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ t4_hdlc_xmit_fifo(wc, span, ts);
+ } else
+ spin_unlock_irqrestore(&wc->reglock, flags);
}
static int t4_maint(struct zt_span *span, int cmd)
@@ -1868,11 +1892,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/%s\n", wc->numspans, unit + 1, framing, line);
}
@@ -1956,10 +1975,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%s\n", wc->numspans, unit + 1, framing, line, crc4);
}
@@ -2024,10 +2039,6 @@
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);
- }
/* Startup HDLC controller too */
if (ts->sigchan) {
if (__hdlc_start(wc, span->offset, ts->sigchan, ts->sigmode)) {
@@ -2040,6 +2051,10 @@
}
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 Source\n",span->spanno);
if (wc->tspans[1]->sync == span->spanno) printk("SPAN %d: Secondary Sync Source\n",span->spanno);
if (wc->numspans == 4) {
@@ -2297,7 +2312,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];
@@ -2307,9 +2322,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)) {
@@ -2324,7 +2340,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)) {
@@ -2349,7 +2365,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)) {
@@ -2369,15 +2385,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);
@@ -2488,15 +2507,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) {
@@ -2505,9 +2530,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);
}
}
@@ -2575,38 +2601,39 @@
#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, isr1, isr2, isr3, isr4;
int readsize = -1;
struct t4_span *ts = wc->tspans[span];
+ unsigned long flags;
if (debug & DEBUG_FRAMER)
printk("framer interrupt span %d:%d!\n", wc->num, span + 1);
/* 1st gen cards isn't used interrupts */
- gis = __t4_framer_in(wc, span, FRMR_GIS);
- isr0 = (gis & FRMR_GIS_ISR0) ? __t4_framer_in(wc, span, FRMR_ISR0) : 0;
- isr1 = (gis & FRMR_GIS_ISR1) ? __t4_framer_in(wc, span, FRMR_ISR1) : 0;
- isr2 = (gis & FRMR_GIS_ISR2) ? __t4_framer_in(wc, span, FRMR_ISR2) : 0;
- isr3 = (gis & FRMR_GIS_ISR3) ? __t4_framer_in(wc, span, FRMR_ISR3) : 0;
- isr4 = (gis & FRMR_GIS_ISR4) ? __t4_framer_in(wc, span, FRMR_ISR4) : 0;
+ gis = t4_framer_in(wc, span, FRMR_GIS);
+ isr0 = (gis & FRMR_GIS_ISR0) ? t4_framer_in(wc, span, FRMR_ISR0) : 0;
+ isr1 = (gis & FRMR_GIS_ISR1) ? t4_framer_in(wc, span, FRMR_ISR1) : 0;
+ isr2 = (gis & FRMR_GIS_ISR2) ? t4_framer_in(wc, span, FRMR_ISR2) : 0;
+ isr3 = (gis & FRMR_GIS_ISR3) ? t4_framer_in(wc, span, FRMR_ISR3) : 0;
+ isr4 = (gis & FRMR_GIS_ISR4) ? t4_framer_in(wc, span, FRMR_ISR4) : 0;
if (debug & DEBUG_FRAMER)
printk("gis: %02x, isr0: %02x, isr1: %02x, isr2: %02x, isr3: %02x, isr4: %02x\n", gis, isr0, isr1, isr2, isr3, isr4);
if (isr0)
- __t4_check_sigbits(wc, span);
+ t4_check_sigbits(wc, span);
if (ts->spantype == TYPE_E1) {
/* E1 checks */
if ((isr3 & 0x38) || isr2 || isr1)
- __t4_check_alarms(wc, span);
+ t4_check_alarms(wc, span);
} else {
/* T1 checks */
if (isr2 || (isr3 & 0x08))
- __t4_check_alarms(wc, span);
+ t4_check_alarms(wc, span);
}
if (debugslips && !ts->span.alarms) {
if (isr3 & 0x02)
@@ -2619,9 +2646,12 @@
printk("TE%d10P: TRANSMIT slip NEGATIVE on span %d\n", wc->numspans, span + 1);
}
+ spin_lock_irqsave(&wc->reglock, flags);
/* HDLC controller checks - receive side */
- if (!ts->sigchan)
+ if (!ts->sigchan) {
+ spin_unlock_irqrestore(&wc->reglock, flags);
return;
+ }
if (isr0 & FRMR_ISR0_RME) {
readsize = (__t4_framer_in(wc, span, FRMR_RBCH) << 8) | __t4_framer_in(wc, span, FRMR_RBCL);
@@ -2664,6 +2694,7 @@
#endif
++ts->frames_in;
+ spin_unlock_irqrestore(&wc->reglock, flags);
if ((debug & DEBUG_FRAMER) && !(ts->frames_in & 0x0f))
printk("Received %d frames on span %d\n", ts->frames_in, span);
if (debug & DEBUG_FRAMER) printk("Received HDLC frame %d. RSIS = 0x%x (%x)\n", ts->frames_in, rsis, rsis_reg);
@@ -2684,9 +2715,13 @@
zt_hdlc_finish(sigchan);
if (debug & DEBUG_FRAMER) printk("Received valid HDLC frame on span %d\n", span);
}
+ spin_lock_irqsave(&wc->reglock, flags);
debug = olddebug;
- } else if (isr0 & FRMR_ISR0_RPF)
+ } else if (isr0 & FRMR_ISR0_RPF) {
+ spin_unlock_irqrestore(&wc->reglock, flags);
zt_hdlc_putbuf(sigchan, readbuf, readsize);
+ spin_lock_irqsave(&wc->reglock, flags);
+ }
}
/* Transmit side */
@@ -2700,12 +2735,16 @@
printk("Sigchan %d is %p\n", sigchan->chanpos, sigchan);
if (debug & DEBUG_FRAMER) printk("Framer %d: Got XPR!\n", sigchan->span->offset);
- __t4_hdlc_xmit_fifo(wc, span, ts);
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ t4_hdlc_xmit_fifo(wc, span, ts);
+ spin_lock_irqsave(&wc->reglock, flags);
}
if (isr1 & FRMR_ISR1_ALLS) {
if (debug & DEBUG_FRAMER) printk("ALLS received\n");
}
+
+ spin_unlock_irqrestore(&wc->reglock, flags);
}
@@ -2730,12 +2769,10 @@
/* Process framer interrupts */
status2 = t4_framer_in(wc, 0, FRMR_CIS);
if (status2 & 0x0f) {
- spin_lock_irqsave(&wc->reglock, flags);
for (x = 0; x < wc->numspans; ++x) {
if (status2 & (1 << x))
- __t4_framer_interrupt(wc, x);
- }
- spin_unlock_irqrestore(&wc->reglock, flags);
+ t4_framer_interrupt(wc, x);
+ }
}
/* Ignore if it's not for us */
@@ -2778,11 +2815,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) {
@@ -2790,25 +2823,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;
}
+
+ 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);
#endif
}
#endif
-
ZAP_IRQ_HANDLER(t4_interrupt_gen2)
{
@@ -2858,7 +2895,7 @@
#if 1
if ((wc->intcount < 20) && debug)
- printk("2G: Got interrupt, status = %08x, CIS = %04x\n", status, __t4_framer_in(wc, 0, FRMR_CIS));
+ printk("2G: Got interrupt, status = %08x, CIS = %04x\n", status, t4_framer_in(wc, 0, FRMR_CIS));
#endif
if (status & 0x2) {
@@ -2888,10 +2925,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 */;
@@ -2900,26 +2935,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, FRMR_CIS);
+ cis = t4_framer_in(wc, 0, FRMR_CIS);
if (cis & FRMR_CIS_GIS1)
- __t4_framer_interrupt(wc, 0);
+ t4_framer_interrupt(wc, 0);
if (cis & FRMR_CIS_GIS2)
- __t4_framer_interrupt(wc, 1);
+ t4_framer_interrupt(wc, 1);
if (cis & FRMR_CIS_GIS3)
- __t4_framer_interrupt(wc, 2);
+ t4_framer_interrupt(wc, 2);
if (cis & FRMR_CIS_GIS4)
- __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)) {
@@ -2946,8 +2984,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 %d\n", 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);
@@ -2967,8 +3008,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
More information about the svn-commits
mailing list