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

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


Author: sruffell
Date: Sun Nov 23 22:14:37 2008
New Revision: 5368

URL: http://svn.digium.com/view/dahdi?view=rev&rev=5368
Log:
Use counter of pending HDLC frames in order to eliminate the need to send a
zero-byte frame to kick start the transmission process.

Patch provided by akohlsmith. 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=5368&r1=5367&r2=5368
==============================================================================
--- linux/trunk/drivers/dahdi/wcb4xxp/base.c (original)
+++ linux/trunk/drivers/dahdi/wcb4xxp/base.c Sun Nov 23 22:14:37 2008
@@ -1654,13 +1654,18 @@
 		for (i=0; i < size; i++)
 			b4xxp_setreg8(b4, A_FIFO_DATA0, buf[i]);
 
-/* increment F and kick-start the FIFO if we have a complete frame to send. */
+/*
+ * If we got a full frame from DAHDI, increment F and decrement our HDLC pending counter.
+ * Otherwise, select the FIFO again (to start transmission) and make sure the
+ * TX IRQ is enabled so we will get called again to finish off the data
+ */
 		if (res != 0) {
 			++bspan->frames_out;
 			bspan->sigactive = 0;
 			hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_INC_F);
+			atomic_dec(&bspan->hdlc_pending);
+		} else {
 			hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT));
-		} else {
 			b4xxp_setreg8(b4, A_IRQ_MSK, V_IRQ);
 		}
 	}
@@ -2011,6 +2016,7 @@
 
 		bspan->sigchan = (sigtype == DAHDI_SIG_HARDHDLC) ? chan : NULL;
 		bspan->sigactive = 0;
+		atomic_set(&bspan->hdlc_pending, 0);
 	} else {
 /* FIXME: shouldn't I be returning an error? */
 	}
@@ -2055,45 +2061,17 @@
 	struct b4xxp *b4 = chan->pvt;
 	int span = chan->span->offset;
 	struct b4xxp_span *bspan = &b4->spans[span];
-	int fifo, f1, f2, flen;
-	unsigned long irq_flags;
 
 	if (DBG_FOPS || DBG_HDLC)
 		dev_info(b4->dev, "hdlc_hard_xmit on chan %s (%i/%i), span=%i\n",
 			chan->name, chan->channo, chan->chanpos, span + 1);
 
-	if ((bspan->sigchan == chan) && !bspan->sigactive) {
-		fifo = bspan->fifos[2];
-
-		spin_lock_irqsave(&b4->fifolock, irq_flags);
-		hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT));
-		get_F(f1, f2, flen);
-
-/* check flen, etc. */
-
-/*
- * WOW, more HFC suckage.
- * If the TX FIFO is empty and interrupts are enabled, I do not get an IRQ. (??)
- * If I increment F without writing any bytes (a zero-length HDLC frame),
- * I will get an interrupt immediately.
- * I can't just send it here, because I can't guarantee I'm not talking to another HFC
- * on the other side.  The HDLC controller is not supposed to give me an interrupt until
- * the entire frame is received, but it interrupts me anyway.
- *
- * SO: enable interrupts and increment F with 0 data to actually GET an IRQ.
- * Inside the interrupt bottom half, loop until all HDLC frame data is in the FIFO,
- * then increment F again to add on CRC and send it.
- * I can do it this way because I'm guaranteed not to process any RX interrupt
- * until my TX is done (by virtue of how the bottom half is written).
- * If I do it outside of interrupt context, I either have to hold the FIFO lock while
- * calling DAHDI (much wailing and gnashing of teeth) or I have to have a long enough
- * intermediate buffer so that I can do it all in one shot.
- *
- * Way to make FIFOs easy, Cologne Chip AG.
- */
-		b4xxp_setreg8(b4, A_IRQ_MSK, V_IRQ);
-		hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_INC_F);
-		spin_unlock_irqrestore(&b4->fifolock, irq_flags);
+/*
+ * increment the hdlc_pending counter and trigger the bottom-half so it
+ * will be picked up and sent.
+ */
+	if (bspan->sigchan == chan) {
+		atomic_inc(&bspan->hdlc_pending);
 	}
 }
 
@@ -2337,6 +2315,24 @@
 /* clear the timer interrupt flag. */
 		b4->misc_irqstatus &= ~V_TI_IRQ;
 	}
+
+/*
+ * Check for outgoing HDLC frame requests
+ * The HFC does not generate TX interrupts when there is room to send, so
+ * I use an atomic counter that is incremented every time DAHDI wants to send
+ * a frame, and decremented every time I send a frame.  It'd be better if I could
+ * just use the interrupt handler, but the HFC seems to trigger a FIFO TX IRQ 
+ * only when it has finished sending a frame, not when one can be sent.
+ */
+	for (i=0; i < b4->numspans; i++) {
+		struct b4xxp_span *bspan = &b4->spans[i];
+
+		if (atomic_read(&bspan->hdlc_pending)) {
+			do {
+				k = hdlc_tx_frame(bspan);
+			}  while (k);
+                }
+        }
 }
 
 

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=5368&r1=5367&r2=5368
==============================================================================
--- linux/trunk/drivers/dahdi/wcb4xxp/wcb4xxp.h (original)
+++ linux/trunk/drivers/dahdi/wcb4xxp/wcb4xxp.h Sun Nov 23 22:14:37 2008
@@ -405,6 +405,7 @@
 	/* HDLC controller fields */
 	struct dahdi_chan *sigchan;		/* pointer to the signalling channel for this span */
 	int sigactive;				/* nonzero means we're in the middle of sending an HDLC frame */
+	atomic_t hdlc_pending;			/* hdlc_hard_xmit() increments, hdlc_tx_frame() decrements */
 	int frames_out;
 	int frames_in;
 




More information about the dahdi-commits mailing list