[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