[dahdi-commits] sruffell: linux/trunk r5367 - /linux/trunk/drivers/dahdi/wcb4xxp/

SVN commits to the DAHDI project dahdi-commits at lists.digium.com
Sun Nov 23 22:09:58 CST 2008


Author: sruffell
Date: Sun Nov 23 22:09:56 2008
New Revision: 5367

URL: http://svn.digium.com/view/dahdi?view=rev&rev=5367
Log:
Do not make assumptions about the number of ready HDLC frames on HDLC RX
interrupt.  This prevents libpri from becoming confused when many HDLC frames
arrive before the driver can service them or a false RX interrupt is received.

Patch provided by akolsmith. Issue DAHDI-173.

Modified:
    linux/trunk/drivers/dahdi/wcb4xxp/base.c
    linux/trunk/drivers/dahdi/wcb4xxp/wcb4xxp.h

Modified: linux/trunk/drivers/dahdi/wcb4xxp/base.c
URL: http://svn.digium.com/view/dahdi/linux/trunk/drivers/dahdi/wcb4xxp/base.c?view=diff&rev=5367&r1=5366&r2=5367
==============================================================================
--- linux/trunk/drivers/dahdi/wcb4xxp/base.c (original)
+++ linux/trunk/drivers/dahdi/wcb4xxp/base.c Sun Nov 23 22:09:56 2008
@@ -1522,32 +1522,44 @@
 /*
  * Inner loop for D-channel receive function.
  * Retrieves a full HDLC frame from the hardware.
- * If the hardware indicates that the frame is complete, checks the FCS and updates
- * DAHDI as needed.
- * Returns 1 if an HDLC frame was correctly received, 0 otherwise.
+ * If the hardware indicates that the frame is complete,
+ * we check the HDLC engine's STAT byte and update DAHDI as needed.
+ *
+ * Returns the number of HDLC frames left in the FIFO.
  */
 static int hdlc_rx_frame(struct b4xxp_span *bspan)
 {
-	int fifo, i, j, zlen, zleft, z1, z2, ret;
-	unsigned char buf[32];		/* arbitrary */
+	int fifo, i, j, zleft;
+	int z1, z2, zlen, f1, f2, flen;
+	unsigned char buf[WCB4XXP_HDLC_BUF_LEN];
 	unsigned long irq_flags;
 	struct b4xxp *b4 = bspan->parent;
 
-	ret = 0;
 	fifo = bspan->fifos[2];
 	++bspan->frames_in;
 
 	spin_lock_irqsave(&b4->fifolock, irq_flags);
 	hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR);
+	get_F(f1, f2, flen);
 	get_Z(z1, z2, zlen);
 	spin_unlock_irqrestore(&b4->fifolock, irq_flags);
 
+/* first check to make sure we really do have HDLC frames available to retrieve */
+	if (flen == 0) {
+		if (DBG_HDLC) {
+			dev_info(b4->dev, "hdlc_rx_frame(span %d): no frames available?\n",
+				bspan->port + 1);
+		}
+
+		return flen;
+	}
+
 	zlen++;		/* include STAT byte that the HFC injects after FCS */
 	zleft = zlen;
 
 	do {
-		if (zleft > 32)
-			j = 32;
+		if (zleft > WCB4XXP_HDLC_BUF_LEN)
+			j = WCB4XXP_HDLC_BUF_LEN;
 		else
 			j = zleft;
 
@@ -1558,7 +1570,7 @@
 		spin_unlock_irqrestore(&b4->fifolock, irq_flags);
 
 /* don't send STAT byte to DAHDI */
-		dahdi_hdlc_putbuf(bspan->sigchan, buf, (j == 32) ? j : j - 1);
+		dahdi_hdlc_putbuf(bspan->sigchan, buf, (j == WCB4XXP_HDLC_BUF_LEN) ? j : j - 1);
 
 		zleft -= j;
 		if (DBG_HDLC) {
@@ -1568,8 +1580,10 @@
 		}
 	} while (zleft > 0);
 
+/* Frame received, increment F2 and get an updated count of frames left */
 	spin_lock_irqsave(&b4->fifolock, irq_flags);
 	hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_INC_F);
+	get_F(f1, f2, flen);
 	spin_unlock_irqrestore(&b4->fifolock, irq_flags);
 
 	if (zlen < 3) {
@@ -1597,11 +1611,10 @@
 			if (DBG_HDLC)
 				dev_info(b4->dev, "(span %d) Frame %d is good!\n", bspan->port + 1, bspan->frames_in);
 			dahdi_hdlc_finish(bspan->sigchan);
-			ret = 1;
-		}
-	}
-
-	return ret;
+		}
+	}
+
+	return flen;
 }
 
 
@@ -1615,9 +1628,9 @@
 {
 	struct b4xxp *b4 = bspan->parent;
 	int res, i, fifo;
-	unsigned int size = 32;
 	int z1, z2, zlen;
-	unsigned char buf[32];
+	unsigned char buf[WCB4XXP_HDLC_BUF_LEN];
+	unsigned int size = sizeof(buf) / sizeof(buf[0]);
 	unsigned long irq_flags;
 
 /* if we're ignoring TE red alarms and we are in alarm, restart the S/T state machine */
@@ -2269,7 +2282,15 @@
 
 			if (b & V_IRQ_FIFOx_RX) {
 				if (fifo >=8 && fifo <= 11) {
-					hdlc_rx_frame(&b4->spans[fifo - 8]);
+/*
+ * I have to loop here until hdlc_rx_frame says there are no more frames waiting.
+ * for whatever reason, the HFC will not generate another interrupt if there are
+ * still HDLC frames waiting to be received.
+ * i.e. I get an int when F1 changes, not when F1 != F2.
+ */
+					do {
+						k = hdlc_rx_frame(&b4->spans[fifo - 8]);
+					} while (k);
 				} else {
 					if (printk_ratelimit())
 						dev_warn(b4->dev, "Got FIFO RX int from non-d-chan FIFO %d??\n", fifo);

Modified: linux/trunk/drivers/dahdi/wcb4xxp/wcb4xxp.h
URL: http://svn.digium.com/view/dahdi/linux/trunk/drivers/dahdi/wcb4xxp/wcb4xxp.h?view=diff&rev=5367&r1=5366&r2=5367
==============================================================================
--- linux/trunk/drivers/dahdi/wcb4xxp/wcb4xxp.h (original)
+++ linux/trunk/drivers/dahdi/wcb4xxp/wcb4xxp.h Sun Nov 23 22:09:56 2008
@@ -381,6 +381,7 @@
 #define MAX_SPANS_PER_CARD			4
 
 #define WCB4XXP_CHANNELS_PER_SPAN		3	/* 2 B-channels and 1 D-Channel for each BRI span */
+#define WCB4XXP_HDLC_BUF_LEN			32	/* arbitrary, just the max # of byts we will send to DAHDI per call */
 
 struct b4xxp_span {
 	struct b4xxp *parent;
@@ -508,3 +509,4 @@
 
 #endif	/* __KERNEL__ */
 #endif	/* _B4XX_H_ */
+




More information about the dahdi-commits mailing list