svn commit: r186214 - in head/sys: dev/re pci

Pyun YongHyeon yongari at FreeBSD.org
Wed Dec 17 08:18:12 UTC 2008


Author: yongari
Date: Wed Dec 17 08:18:11 2008
New Revision: 186214
URL: http://svn.freebsd.org/changeset/base/186214

Log:
  It seems that RealTek PCIe controllers require an explicit Tx poll
  command whenever Tx completion interrupt is raised. The Tx poll
  bit is cleared when all packets waiting to be transferred have been
  processed. This means the second Tx poll command can be silently
  ignored as the Tx poll bit could be still active while processing
  of previous Tx poll command is in progress.
  To address the issue re(4) used to invoke the Tx poll command in Tx
  completion handler whenever it detects there are pending packets in
  TxQ. However that still does not seem to completely eliminate
  watchdog timeouts seen on RealTek PCIe controllers. To fix the
  issue kick Tx poll command only after Tx completion interrupt is
  raised as this would indicate Tx is now idle state such that it can
  accept new Tx poll command again. While here apply this workaround
  for PCIe based controllers as other controllers does not seem to
  have this limitation.
  
  Tested by:	Victor Balada Diaz < victor <> bsdes DOT net >

Modified:
  head/sys/dev/re/if_re.c
  head/sys/pci/if_rlreg.h

Modified: head/sys/dev/re/if_re.c
==============================================================================
--- head/sys/dev/re/if_re.c	Wed Dec 17 08:12:50 2008	(r186213)
+++ head/sys/dev/re/if_re.c	Wed Dec 17 08:18:11 2008	(r186214)
@@ -1157,6 +1157,7 @@ re_attach(device_t dev)
 
 	msic = 0;
 	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
+		sc->rl_flags |= RL_FLAG_PCIE;
 		msic = pci_msi_count(dev);
 		if (bootverbose)
 			device_printf(dev, "MSI count : %d\n", msic);
@@ -2042,16 +2043,6 @@ re_txeof(struct rl_softc *sc)
 	/* No changes made to the TX ring, so no flush needed */
 
 	if (sc->rl_ldata.rl_tx_free != sc->rl_ldata.rl_tx_desc_cnt) {
-		/*
-		 * Some chips will ignore a second TX request issued
-		 * while an existing transmission is in progress. If
-		 * the transmitter goes idle but there are still
-		 * packets waiting to be sent, we need to restart the
-		 * channel here to flush them out. This only seems to
-		 * be required with the PCIe devices.
-		 */
-		CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
-
 #ifdef RE_TX_MODERATION
 		/*
 		 * If not all descriptors have been reaped yet, reload
@@ -2115,6 +2106,9 @@ re_poll_locked(struct ifnet *ifp, enum p
 			return;
 		if (status)
 			CSR_WRITE_2(sc, RL_ISR, status);
+		if ((status & (RL_ISR_TX_OK | RL_ISR_TX_DESC_UNAVAIL)) &&
+		    (sc->rl_flags & RL_FLAG_PCIE))
+			CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
 
 		/*
 		 * XXX check behaviour on receiver stalls.
@@ -2176,6 +2170,17 @@ re_int_task(void *arg, int npending)
 	if (status & (RL_ISR_RX_OK|RL_ISR_RX_ERR|RL_ISR_FIFO_OFLOW))
 		rval = re_rxeof(sc);
 
+	/*
+	 * Some chips will ignore a second TX request issued
+	 * while an existing transmission is in progress. If
+	 * the transmitter goes idle but there are still
+	 * packets waiting to be sent, we need to restart the
+	 * channel here to flush them out. This only seems to
+	 * be required with the PCIe devices.
+	 */
+	if ((status & (RL_ISR_TX_OK | RL_ISR_TX_DESC_UNAVAIL)) &&
+	    (sc->rl_flags & RL_FLAG_PCIE))
+		CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
 	if (status & (
 #ifdef RE_TX_MODERATION
 	    RL_ISR_TIMEOUT_EXPIRED|

Modified: head/sys/pci/if_rlreg.h
==============================================================================
--- head/sys/pci/if_rlreg.h	Wed Dec 17 08:12:50 2008	(r186213)
+++ head/sys/pci/if_rlreg.h	Wed Dec 17 08:18:11 2008	(r186214)
@@ -891,6 +891,7 @@ struct rl_softc {
 #define	RL_FLAG_PHY8110S	0x0800
 #define	RL_FLAG_WOLRXENB	0x1000
 #define	RL_FLAG_MACSLEEP	0x2000
+#define	RL_FLAG_PCIE		0x4000
 #define	RL_FLAG_LINK		0x8000
 };
 


More information about the svn-src-all mailing list