Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Jan 2013 20:37:41 +0000 (UTC)
From:      Tim Kientzle <kientzle@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r245070 - head/sys/arm/ti/cpsw
Message-ID:  <201301052037.r05KbfXW053879@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kientzle
Date: Sat Jan  5 20:37:40 2013
New Revision: 245070
URL: http://svnweb.freebsd.org/changeset/base/245070

Log:
  Shuffle the TX underrun to work the same way as the RX underrun,
  as suggested by YongHyeon PYUN.

Modified:
  head/sys/arm/ti/cpsw/if_cpsw.c

Modified: head/sys/arm/ti/cpsw/if_cpsw.c
==============================================================================
--- head/sys/arm/ti/cpsw/if_cpsw.c	Sat Jan  5 20:37:14 2013	(r245069)
+++ head/sys/arm/ti/cpsw/if_cpsw.c	Sat Jan  5 20:37:40 2013	(r245070)
@@ -716,26 +716,22 @@ cpsw_start_locked(struct ifnet *ifp)
 	if (STAILQ_EMPTY(&newslots))
 		return;
 
-	/* Attach new segments to the hardware TX queue. */
+	/* Attach the list of new buffers to the hardware TX queue. */
 	prev_slot = STAILQ_LAST(&sc->tx_active, cpsw_slot, next);
 	first_new_slot = STAILQ_FIRST(&newslots);
 	STAILQ_CONCAT(&sc->tx_active, &newslots);
 	if (prev_slot == NULL) {
 		/* Start the TX queue fresh. */
 		cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
-			     cpsw_cpdma_txbd_paddr(first_new_slot->index));
+		    cpsw_cpdma_txbd_paddr(first_new_slot->index));
 	} else {
-		/* Add packets to current queue. */
-		/* Race: The hardware might have sent the last packet
-		 * on the queue and stopped the transmitter just
-		 * before we got here.  In that case, this is a no-op,
-		 * but it also means there's a TX interrupt waiting
-		 * to be processed as soon as we release the lock here.
-		 * That TX interrupt can detect and recover from this
-		 * situation; see cpsw_intr_tx_locked.
-		 */
+		/* Add buffers to end of current queue. */
 		cpsw_cpdma_write_txbd_next(prev_slot->index,
 		   cpsw_cpdma_txbd_paddr(first_new_slot->index));
+		/* If underrun, restart queue. */
+		if (cpsw_cpdma_read_txbd_flags(prev_slot->index) & CPDMA_BD_EOQ)
+			cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
+			    cpsw_cpdma_txbd_paddr(first_new_slot->index));
 	}
 	sc->tx_enqueues += enqueued;
 	sc->tx_queued += enqueued;
@@ -1091,14 +1087,10 @@ cpsw_fill_rx_queue_locked(struct cpsw_so
 		cpsw_write_4(CPSW_CPDMA_RX_HDP(0),
 		    cpsw_cpdma_rxbd_paddr(next_slot->index));
 	} else {
-		/* Extend an existing RX queue. */
+		/* Add buffers to end of current queue. */
 		cpsw_cpdma_write_rxbd_next(prev_slot->index,
 		    cpsw_cpdma_rxbd_paddr(next_slot->index));
-		/* XXX Order matters: Previous write must complete
-		   before next read begins in order to avoid an
-		   end-of-queue race.  I think bus_write and bus_read have
-		   sufficient barriers built-in to ensure this. XXX */
-		/* If old RX queue was stopped, restart it. */
+		/* If underrun, restart queue. */
 		if (cpsw_cpdma_read_rxbd_flags(prev_slot->index) & CPDMA_BD_EOQ) {
 			cpsw_write_4(CPSW_CPDMA_RX_HDP(0),
 			    cpsw_cpdma_rxbd_paddr(next_slot->index));
@@ -1170,12 +1162,6 @@ cpsw_intr_tx_locked(void *arg)
 		/* Tell hardware the last item we dequeued. */
 		cpsw_write_4(CPSW_CPDMA_TX_CP(0),
 		     cpsw_cpdma_txbd_paddr(last_slot->index));
-		/* If transmitter stopped and there's more, restart it. */
-		/* This resolves the race described in tx_start above. */
-		if ((last_flags & CPDMA_BD_EOQ) && (slot != NULL)) {
-			cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
-			     cpsw_cpdma_txbd_paddr(slot->index));
-		}
 		sc->tx_retires += retires;
 		sc->tx_queued -= retires;
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201301052037.r05KbfXW053879>