[svn-commits] alecdavis: linux/trunk r9063 - /linux/trunk/drivers/dahdi/wctdm24xxp/
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Thu Jul 29 18:48:27 CDT 2010
Author: alecdavis
Date: Thu Jul 29 18:48:16 2010
New Revision: 9063
URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=9063
Log:
SLIC_LF_OPPENDING confict between wctdm_proslic_recheck_sanity() and set_lasttxhook_interruptible()
Problem:
'wctdm_proslic_recheck_sanity()' is executed (4 times??) every ~256ms which monitors and clears the SLIC_LF_OPPENDING on fxs->lasttxhook when the LF state has been reached.
'set_lasttxhook_interruptible()' times out after 100ms waiting from the previous write to the SLIC_LF register, by waiting for SLIC_LF_OPPENDING to be cleared, thus the write will fail.
Solution:
adds wctdm_proslic_check_oppending which does the monitoring and clearing of SLIC_LF_OPPENDING, which is execute every 1ms. It also if the correct state is not reached within 100ms, resends the lasttxhook state.
(closes issue #17724)
Reported by: alecdavis
Patches:
wctdm24xxp_fxs_answer.diff4.txt uploaded by alecdavis (license 585)
Tested by: alecdavis, sruffell
Modified:
linux/trunk/drivers/dahdi/wctdm24xxp/base.c
linux/trunk/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
Modified: linux/trunk/drivers/dahdi/wctdm24xxp/base.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/wctdm24xxp/base.c?view=diff&rev=9063&r1=9062&r2=9063
==============================================================================
--- linux/trunk/drivers/dahdi/wctdm24xxp/base.c (original)
+++ linux/trunk/drivers/dahdi/wctdm24xxp/base.c Thu Jul 29 18:48:16 2010
@@ -1349,6 +1349,44 @@
return 0;
}
+/* 1ms interrupt */
+static inline void wctdm_proslic_check_oppending(struct wctdm *wc, int card)
+{
+ struct fxs *const fxs = &wc->mods[card].fxs;
+ int res;
+
+ /* Monitor the Pending LF state change, for the next 100ms */
+ if (fxs->lasttxhook & SLIC_LF_OPPENDING) {
+ spin_lock(&fxs->lasttxhooklock);
+
+ if (!(fxs->lasttxhook & SLIC_LF_OPPENDING)) {
+ spin_unlock(&fxs->lasttxhooklock);
+ return;
+ }
+
+ res = wc->cmdq[card].isrshadow[1];
+ if ((res & SLIC_LF_SETMASK) == (fxs->lasttxhook & SLIC_LF_SETMASK)) {
+ fxs->lasttxhook &= SLIC_LF_SETMASK;
+ fxs->oppending_ms = 0;
+ if (debug & DEBUG_CARD) {
+ dev_info(&wc->vb.pdev->dev, "SLIC_LF OK: card=%d shadow=%02x lasttxhook=%02x intcount=%d \n", card, res, fxs->lasttxhook, wc->intcount);
+ }
+ } else if (fxs->oppending_ms) { /* if timing out */
+ if (--fxs->oppending_ms == 0) {
+ /* Timed out, resend the linestate */
+ wc->sethook[card] = CMD_WR(LINE_STATE, fxs->lasttxhook);
+ if (debug & DEBUG_CARD) {
+ dev_info(&wc->vb.pdev->dev, "SLIC_LF RETRY: card=%d shadow=%02x lasttxhook=%02x intcount=%d \n", card, res, fxs->lasttxhook, wc->intcount);
+ }
+ }
+ } else { /* Start 100ms Timeout */
+ fxs->oppending_ms = 100;
+ }
+ spin_unlock(&fxs->lasttxhooklock);
+ }
+}
+
+/* 256ms interrupt */
static inline void wctdm_proslic_recheck_sanity(struct wctdm *wc, int card)
{
struct fxs *const fxs = &wc->mods[card].fxs;
@@ -1373,9 +1411,28 @@
#else
spin_lock_irqsave(&fxs->lasttxhooklock, flags);
res = wc->cmdq[card].isrshadow[1];
+
+#if 0
/* This makes sure the lasthook was put in reg 64 the linefeed reg */
- if (((res & SLIC_LF_SETMASK) | SLIC_LF_OPPENDING) == fxs->lasttxhook)
- fxs->lasttxhook &= SLIC_LF_SETMASK;
+ if (fxs->lasttxhook & SLIC_LF_OPPENDING) {
+ if ((res & SLIC_LF_SETMASK) == (fxs->lasttxhook & SLIC_LF_SETMASK)) {
+ fxs->lasttxhook &= SLIC_LF_SETMASK;
+ if (debug & DEBUG_CARD) {
+ dev_info(&wc->vb.pdev->dev, "SLIC_LF OK: intcount=%d channel=%d shadow=%02x lasttxhook=%02x\n", wc->intcount, card, res, fxs->lasttxhook);
+ }
+ } else if (!(wc->intcount & 0x03)) {
+ wc->sethook[card] = CMD_WR(LINE_STATE, fxs->lasttxhook);
+ if (debug & DEBUG_CARD) {
+ dev_info(&wc->vb.pdev->dev, "SLIC_LF RETRY: intcount=%d channel=%d shadow=%02x lasttxhook=%02x\n", wc->intcount, card, res, fxs->lasttxhook);
+ }
+ }
+ }
+ if (debug & DEBUG_CARD) {
+ if (!(wc->intcount % 100)) {
+ dev_info(&wc->vb.pdev->dev, "SLIC_LF DEBUG: intcount=%d channel=%d shadow=%02x lasttxhook=%02x\n", wc->intcount, card, res, fxs->lasttxhook);
+ }
+ }
+#endif
res = !res && /* reg 64 has to be zero at last isr read */
!(fxs->lasttxhook & SLIC_LF_OPPENDING) && /* not a transition */
@@ -1927,6 +1984,7 @@
}
}
+/* 1ms interrupt */
static void wctdm_isr_misc_fxs(struct wctdm *wc, int card)
{
struct fxs *const fxs = &wc->mods[card].fxs;
@@ -1938,7 +1996,10 @@
fxs->palarms--;
}
wctdm_proslic_check_hook(wc, card);
- if (!(wc->intcount & 0xfc))
+
+ wctdm_proslic_check_oppending(wc, card);
+
+ if (!(wc->intcount & 0xfc)) /* every 256ms */
wctdm_proslic_recheck_sanity(wc, card);
if (SLIC_LF_RINGING == fxs->lasttxhook) {
/* RINGing, prepare for OHT */
@@ -1947,29 +2008,53 @@
fxs->idletxhookstate = POLARITY_XOR(card) ? SLIC_LF_OHTRAN_REV :
SLIC_LF_OHTRAN_FWD;
} else if (fxs->ohttimer) {
- fxs->ohttimer -= DAHDI_CHUNKSIZE;
- if (fxs->ohttimer)
- return;
-
- /* Switch to active */
- fxs->idletxhookstate = POLARITY_XOR(card) ? SLIC_LF_ACTIVE_REV :
- SLIC_LF_ACTIVE_FWD;
- spin_lock_irqsave(&fxs->lasttxhooklock, flags);
- if (SLIC_LF_OHTRAN_FWD == fxs->lasttxhook) {
- /* Apply the change if appropriate */
- fxs->lasttxhook = SLIC_LF_OPPENDING | SLIC_LF_ACTIVE_FWD;
- /* Data enqueued here */
- wc->sethook[card] = CMD_WR(LINE_STATE, fxs->lasttxhook);
- } else if (SLIC_LF_OHTRAN_REV == fxs->lasttxhook) {
- /* Apply the change if appropriate */
- fxs->lasttxhook = SLIC_LF_OPPENDING | SLIC_LF_ACTIVE_REV;
- /* Data enqueued here */
- wc->sethook[card] = CMD_WR(LINE_STATE, fxs->lasttxhook);
- }
- spin_unlock_irqrestore(&fxs->lasttxhooklock, flags);
- }
-}
-
+ /* check if still OnHook */
+ if (!fxs->oldrxhook) {
+ fxs->ohttimer -= DAHDI_CHUNKSIZE;
+ if (fxs->ohttimer)
+ return;
+
+ /* Switch to active */
+ fxs->idletxhookstate = POLARITY_XOR(card) ? SLIC_LF_ACTIVE_REV :
+ SLIC_LF_ACTIVE_FWD;
+ spin_lock_irqsave(&fxs->lasttxhooklock, flags);
+ if (SLIC_LF_OHTRAN_FWD == fxs->lasttxhook) {
+ /* Apply the change if appropriate */
+ fxs->lasttxhook = SLIC_LF_OPPENDING | SLIC_LF_ACTIVE_FWD;
+ /* Data enqueued here */
+ wc->sethook[card] = CMD_WR(LINE_STATE, fxs->lasttxhook);
+ if (debug & DEBUG_CARD) {
+ dev_info(&wc->vb.pdev->dev,
+ "Channel %d OnHookTransfer "
+ "stop\n", card);
+ }
+ } else if (SLIC_LF_OHTRAN_REV == fxs->lasttxhook) {
+ /* Apply the change if appropriate */
+ fxs->lasttxhook = SLIC_LF_OPPENDING | SLIC_LF_ACTIVE_REV;
+ /* Data enqueued here */
+ wc->sethook[card] = CMD_WR(LINE_STATE, fxs->lasttxhook);
+ if (debug & DEBUG_CARD) {
+ dev_info(&wc->vb.pdev->dev,
+ "Channel %d OnHookTransfer "
+ "stop\n", card);
+ }
+ }
+ spin_unlock_irqrestore(&fxs->lasttxhooklock, flags);
+ } else {
+ fxs->ohttimer = 0;
+ /* Switch to active */
+ fxs->idletxhookstate = POLARITY_XOR(card) ? SLIC_LF_ACTIVE_REV : SLIC_LF_ACTIVE_FWD;
+ if (debug & DEBUG_CARD) {
+ dev_info(&wc->vb.pdev->dev,
+ "Channel %d OnHookTransfer abort\n",
+ card);
+ }
+ }
+
+ }
+}
+
+/* 1ms interrupt */
static inline void wctdm_isr_misc(struct wctdm *wc)
{
int x;
@@ -3000,9 +3085,24 @@
if (((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_ACTIVE_FWD) ||
((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_ACTIVE_REV)) {
- set_lasttxhook_interruptible(fxs, POLARITY_XOR(chan->chanpos - 1)
- ? SLIC_LF_OHTRAN_REV : SLIC_LF_OHTRAN_FWD ,
- &wc->sethook[chan->chanpos - 1]);
+ x = set_lasttxhook_interruptible(fxs,
+ (POLARITY_XOR(chan->chanpos - 1) ?
+ SLIC_LF_OHTRAN_REV : SLIC_LF_OHTRAN_FWD),
+ &wc->sethook[chan->chanpos - 1]);
+
+ if (debug & DEBUG_CARD) {
+ if (x) {
+ dev_info(&wc->vb.pdev->dev,
+ "Channel %d TIMEOUT: "
+ "OnHookTransfer start\n",
+ chan->chanpos - 1);
+ } else {
+ dev_info(&wc->vb.pdev->dev,
+ "Channel %d OnHookTransfer "
+ "start\n", chan->chanpos - 1);
+ }
+ }
+
}
break;
case DAHDI_VMWI_CONFIG:
@@ -3123,21 +3223,44 @@
return -EINVAL;
/* Can't change polarity while ringing or when open */
if (((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_RINGING) ||
- ((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_OPEN))
+ ((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_OPEN)) {
+ if (debug & DEBUG_CARD) {
+ dev_info(&wc->vb.pdev->dev,
+ "Channel %d Unable to Set Polarity\n", chan->chanpos - 1);
+ }
return -EINVAL;
+ }
fxs->reversepolarity = (x) ? 1 : 0;
- if (POLARITY_XOR(chan->chanpos -1)) {
+ if (POLARITY_XOR(chan->chanpos - 1)) {
fxs->idletxhookstate |= SLIC_LF_REVMASK;
- x = fxs->lasttxhook;
+ x = fxs->lasttxhook & SLIC_LF_SETMASK;
x |= SLIC_LF_REVMASK;
- set_lasttxhook_interruptible(fxs, x, &wc->sethook[chan->chanpos - 1]);
+ x = set_lasttxhook_interruptible(fxs, x, &wc->sethook[chan->chanpos - 1]);
+ if ((debug & DEBUG_CARD) && x) {
+ dev_info(&wc->vb.pdev->dev,
+ "Channel %d TIMEOUT: Set Reverse "
+ "Polarity\n", chan->chanpos - 1);
+ } else if (debug & DEBUG_CARD) {
+ dev_info(&wc->vb.pdev->dev,
+ "Channel %d Set Reverse Polarity\n",
+ chan->chanpos - 1);
+ }
} else {
fxs->idletxhookstate &= ~SLIC_LF_REVMASK;
- x = fxs->lasttxhook;
+ x = fxs->lasttxhook & SLIC_LF_SETMASK;
x &= ~SLIC_LF_REVMASK;
- set_lasttxhook_interruptible(fxs, x, &wc->sethook[chan->chanpos - 1]);
+ x = set_lasttxhook_interruptible(fxs, x, &wc->sethook[chan->chanpos - 1]);
+ if ((debug & DEBUG_CARD) & x) {
+ dev_info(&wc->vb.pdev->dev,
+ "Channel %d TIMEOUT: Set Normal "
+ "Polarity\n", chan->chanpos - 1);
+ } else if (debug & DEBUG_CARD) {
+ dev_info(&wc->vb.pdev->dev,
+ "Channel %d Set Normal Polarity\n",
+ chan->chanpos - 1);
+ }
}
break;
case DAHDI_RADIO_GETPARAM:
@@ -3404,6 +3527,7 @@
dev_notice(&wc->vb.pdev->dev, "wctdm24xxp: Can't set tx state to %d\n", txsig);
}
} else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
+ int x = 0;
unsigned long flags;
struct fxs *const fxs = &wc->mods[chan->chanpos - 1].fxs;
spin_lock_irqsave(&fxs->lasttxhooklock, flags);
@@ -3413,16 +3537,13 @@
case DAHDI_SIG_EM:
case DAHDI_SIG_FXOKS:
case DAHDI_SIG_FXOLS:
- fxs->lasttxhook = SLIC_LF_OPPENDING |
- fxs->idletxhookstate;
+ x = fxs->idletxhookstate;
break;
case DAHDI_SIG_FXOGS:
if (POLARITY_XOR(chan->chanpos -1)) {
- fxs->lasttxhook = SLIC_LF_OPPENDING |
- SLIC_LF_RING_OPEN;
+ x = SLIC_LF_RING_OPEN;
} else {
- fxs->lasttxhook = SLIC_LF_OPPENDING |
- SLIC_LF_TIP_OPEN;
+ x = SLIC_LF_TIP_OPEN;
}
break;
}
@@ -3430,33 +3551,35 @@
case DAHDI_TXSIG_OFFHOOK:
switch(chan->sig) {
case DAHDI_SIG_EM:
- if (POLARITY_XOR(chan->chanpos -1)) {
- fxs->lasttxhook = SLIC_LF_OPPENDING |
- SLIC_LF_ACTIVE_FWD;
- } else {
- fxs->lasttxhook = SLIC_LF_OPPENDING |
+ x = (POLARITY_XOR(chan->chanpos - 1)) ?
+ SLIC_LF_ACTIVE_FWD :
SLIC_LF_ACTIVE_REV;
- }
break;
default:
- fxs->lasttxhook = SLIC_LF_OPPENDING |
- fxs->idletxhookstate;
+ x = fxs->idletxhookstate;
break;
}
break;
case DAHDI_TXSIG_START:
- fxs->lasttxhook = SLIC_LF_OPPENDING | SLIC_LF_RINGING;
+ x = SLIC_LF_RINGING;
break;
case DAHDI_TXSIG_KEWL:
- fxs->lasttxhook = SLIC_LF_OPPENDING | SLIC_LF_OPEN;
+ x = SLIC_LF_OPEN;
break;
default:
+ spin_unlock_irqrestore(&fxs->lasttxhooklock, flags);
dev_notice(&wc->vb.pdev->dev, "wctdm24xxp: Can't set tx state to %d\n", txsig);
- }
+ return 0;
+ }
+
+ fxs->lasttxhook = x | SLIC_LF_OPPENDING;
wc->sethook[chan->chanpos - 1] = CMD_WR(LINE_STATE, fxs->lasttxhook);
spin_unlock_irqrestore(&fxs->lasttxhooklock, flags);
- if (debug & DEBUG_CARD)
- dev_info(&wc->vb.pdev->dev, "Setting FXS hook state to %d (%02x)\n", txsig, reg);
+ if (debug & DEBUG_CARD) {
+ dev_info(&wc->vb.pdev->dev, "Setting FXS hook state "
+ "to %d (%02x) intcount=%d\n", txsig, x,
+ wc->intcount);
+ }
} else {
}
return 0;
Modified: linux/trunk/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/wctdm24xxp/wctdm24xxp.h?view=diff&rev=9063&r1=9062&r2=9063
==============================================================================
--- linux/trunk/drivers/dahdi/wctdm24xxp/wctdm24xxp.h (original)
+++ linux/trunk/drivers/dahdi/wctdm24xxp/wctdm24xxp.h Thu Jul 29 18:48:16 2010
@@ -240,6 +240,7 @@
* voicebus ISR.
*/
int lasttxhook;
+ int oppending_ms;
spinlock_t lasttxhooklock;
int palarms;
struct dahdi_vmwi_info vmwisetting;
More information about the svn-commits
mailing list