[Midnightbsd-cvs] src: if_nve.c: Improve reliability of nforce4 adapters: - When setting

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Wed Sep 3 22:55:23 EDT 2008


Log Message:
-----------
Improve reliability of nforce4 adapters:
  - When setting up a packet for transmit, if we the tx ring is over half
    full, kick the binary blob to force it to complete any pending tx
    completions.
  - In the watchdog routine, poke the binary blob to force it to flush any
    pending tx completions and only reset the chip if the blob doesn't
    complete any of them.
  
Altqify nve(4).

Obtained from FreeBSD.

Modified Files:
--------------
    src/sys/dev/nve:
        if_nve.c (r1.1.1.2 -> r1.2)

-------------- next part --------------
Index: if_nve.c
===================================================================
RCS file: /home/cvs/src/sys/dev/nve/if_nve.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/dev/nve/if_nve.c -L sys/dev/nve/if_nve.c -u -r1.1.1.2 -r1.2
--- sys/dev/nve/if_nve.c
+++ sys/dev/nve/if_nve.c
@@ -521,7 +521,9 @@
 	ifp->if_init = nve_init;
 	ifp->if_mtu = ETHERMTU;
 	ifp->if_baudrate = IF_Mbps(100);
-	ifp->if_snd.ifq_maxlen = TX_RING_SIZE - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, TX_RING_SIZE - 1);
+	ifp->if_snd.ifq_drv_maxlen = TX_RING_SIZE - 1;
+	IFQ_SET_READY(&ifp->if_snd);
 	ifp->if_capabilities |= IFCAP_VLAN_MTU;
 
 	/* Attach to OS's managers. */
@@ -861,12 +863,23 @@
 		buf = &desc->buf;
 
 		/* Get next packet to send. */
-		IF_DEQUEUE(&ifp->if_snd, m0);
+		IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
 
 		/* If nothing to send, return. */
 		if (m0 == NULL)
 			return;
 
+		/*
+		 * On nForce4, the chip doesn't interrupt on transmit,
+		 * so try to flush transmitted packets from the queue
+		 * if it's getting large (see note in nve_watchdog).
+		 */
+		if (sc->pending_txs > TX_RING_SIZE/2) {
+			sc->hwapi->pfnDisableInterrupts(sc->hwapi->pADCX);
+			sc->hwapi->pfnHandleInterrupt(sc->hwapi->pADCX);
+			sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX);
+		}
+
 		/* Map MBUF for DMA access */
 		error = bus_dmamap_load_mbuf(sc->mtag, buf->map, m0,
 		    nve_dmamap_tx_cb, desc, BUS_DMA_NOWAIT);
@@ -929,7 +942,7 @@
 			    "nve_ifstart: transmit queue is full\n");
 			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 			bus_dmamap_unload(sc->mtag, buf->map);
-			IF_PREPEND(&ifp->if_snd, buf->mbuf);
+			IFQ_DRV_PREPEND(&ifp->if_snd, buf->mbuf);
 			buf->mbuf = NULL;
 			return;
 
@@ -1270,10 +1283,31 @@
 nve_watchdog(struct ifnet *ifp)
 {
 	struct nve_softc *sc = ifp->if_softc;
+	int pending_txs_start;
+
+	NVE_LOCK(sc);
+
+	/*
+	 * The nvidia driver blob defers tx completion notifications.
+	 * Thus, sometimes the watchdog timer will go off when the
+	 * tx engine is fine, but the tx completions are just deferred.
+	 * Try kicking the driver blob to clear out any pending tx
+	 * completions.  If that clears up any of the pending tx
+	 * operations, then just return without printing the warning
+	 * message or resetting the adapter, as we can then conclude
+	 * the chip hasn't actually crashed (it's still sending packets).
+	 */
+	pending_txs_start = sc->pending_txs;
+	sc->hwapi->pfnDisableInterrupts(sc->hwapi->pADCX);
+	sc->hwapi->pfnHandleInterrupt(sc->hwapi->pADCX);
+	sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX);
+	if (sc->pending_txs < pending_txs_start) {
+		NVE_UNLOCK(sc);
+		return;
+	}
 
 	device_printf(sc->dev, "device timeout (%d)\n", sc->pending_txs);
 
-	NVE_LOCK(sc);
 	sc->tx_errors++;
 
 	nve_stop(sc);


More information about the Midnightbsd-cvs mailing list