svn commit: r235334 - head/sys/dev/vr

Rui Paulo rpaulo at FreeBSD.org
Sat May 12 14:37:26 UTC 2012


Author: rpaulo
Date: Sat May 12 14:37:25 2012
New Revision: 235334
URL: http://svn.freebsd.org/changeset/base/235334

Log:
  Convert the if_vr(4) driver model to the interrupt filter model and use
  a taskqueue.
  
  This gives a 16% performance improvement under high load on slow systems,
  especially when vr shares an interrupt with another device, which is
  common with the Alix x86 boards.
  Contrary to the other devices, I left the interrupt processing for loop
  in because there was no significant difference in performance and this
  should avoid enqueuing more taskqueues unnecessarily.
  We also decided to move the vr_start_locked() call inside the for loop
  because we found out that it helps performance since TCP ACKs now have a
  chance to go out quicker.
  
  Reviewed by:	yongari (older version, same idea)
  Discussed with:	yongari, jhb

Modified:
  head/sys/dev/vr/if_vr.c
  head/sys/dev/vr/if_vrreg.h

Modified: head/sys/dev/vr/if_vr.c
==============================================================================
--- head/sys/dev/vr/if_vr.c	Sat May 12 13:55:36 2012	(r235333)
+++ head/sys/dev/vr/if_vr.c	Sat May 12 14:37:25 2012	(r235334)
@@ -165,7 +165,8 @@ static void vr_txeof(struct vr_softc *);
 static void vr_tick(void *);
 static int vr_error(struct vr_softc *, uint16_t);
 static void vr_tx_underrun(struct vr_softc *);
-static void vr_intr(void *);
+static int vr_intr(void *);
+static void vr_int_task(void *, int);
 static void vr_start(struct ifnet *);
 static void vr_start_locked(struct ifnet *);
 static int vr_encap(struct vr_softc *, struct mbuf **);
@@ -658,6 +659,8 @@ vr_attach(device_t dev)
 	ifp->if_snd.ifq_maxlen = VR_TX_RING_CNT - 1;
 	IFQ_SET_READY(&ifp->if_snd);
 
+	TASK_INIT(&sc->vr_inttask, 0, vr_int_task, sc);
+
 	/* Configure Tx FIFO threshold. */
 	sc->vr_txthresh = VR_TXTHRESH_MIN;
 	if (sc->vr_revid < REV_ID_VT6105_A0) {
@@ -784,7 +787,7 @@ vr_attach(device_t dev)
 
 	/* Hook interrupt last to avoid having to lock softc. */
 	error = bus_setup_intr(dev, sc->vr_irq, INTR_TYPE_NET | INTR_MPSAFE,
-	    NULL, vr_intr, sc, &sc->vr_intrhand);
+	    vr_intr, NULL, sc, &sc->vr_intrhand);
 
 	if (error) {
 		device_printf(dev, "couldn't set up irq\n");
@@ -826,6 +829,7 @@ vr_detach(device_t dev)
 		vr_stop(sc);
 		VR_UNLOCK(sc);
 		callout_drain(&sc->vr_stat_callout);
+		taskqueue_drain(taskqueue_fast, &sc->vr_inttask);
 		ether_ifdetach(ifp);
 	}
 	if (sc->vr_miibus)
@@ -1653,10 +1657,30 @@ vr_tx_underrun(struct vr_softc *sc)
 	vr_tx_start(sc);
 }
 
-static void
+static int
 vr_intr(void *arg)
 {
 	struct vr_softc		*sc;
+	uint16_t		status;
+
+	sc = (struct vr_softc *)arg;
+
+	status = CSR_READ_2(sc, VR_ISR);
+	if (status == 0 || status == 0xffff || (status & VR_INTRS) == 0)
+		return (FILTER_STRAY);
+
+	/* Disable interrupts. */
+	CSR_WRITE_2(sc, VR_IMR, 0x0000);
+
+	taskqueue_enqueue_fast(taskqueue_fast, &sc->vr_inttask);
+
+	return (FILTER_HANDLED);
+}
+
+static void
+vr_int_task(void *arg, int npending)
+{
+	struct vr_softc		*sc;
 	struct ifnet		*ifp;
 	uint16_t		status;
 
@@ -1668,9 +1692,6 @@ vr_intr(void *arg)
 		goto done_locked;
 
 	status = CSR_READ_2(sc, VR_ISR);
-	if (status == 0 || status == 0xffff || (status & VR_INTRS) == 0)
-		goto done_locked;
-
 	ifp = sc->vr_ifp;
 #ifdef DEVICE_POLLING
 	if ((ifp->if_capenable & IFCAP_POLLING) != 0)
@@ -1685,9 +1706,6 @@ vr_intr(void *arg)
 		goto done_locked;
 	}
 
-	/* Disable interrupts. */
-	CSR_WRITE_2(sc, VR_IMR, 0x0000);
-
 	for (; (status & VR_INTRS) != 0;) {
 		CSR_WRITE_2(sc, VR_ISR, status);
 		if ((status & (VR_ISR_BUSERR | VR_ISR_LINKSTAT2 |
@@ -1707,15 +1725,16 @@ vr_intr(void *arg)
 			vr_rx_start(sc);
 		}
 		vr_txeof(sc);
+
+		if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+			vr_start_locked(ifp);
+
 		status = CSR_READ_2(sc, VR_ISR);
 	}
 
 	/* Re-enable interrupts. */
 	CSR_WRITE_2(sc, VR_IMR, VR_INTRS);
 
-	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
-		vr_start_locked(ifp);
-
 done_locked:
 	VR_UNLOCK(sc);
 }

Modified: head/sys/dev/vr/if_vrreg.h
==============================================================================
--- head/sys/dev/vr/if_vrreg.h	Sat May 12 13:55:36 2012	(r235333)
+++ head/sys/dev/vr/if_vrreg.h	Sat May 12 14:37:25 2012	(r235334)
@@ -738,6 +738,7 @@ struct vr_softc {
 #ifdef DEVICE_POLLING
 	int			rxcycles;
 #endif
+	struct task		vr_inttask;
 };
 
 #define	VR_LOCK(_sc)		mtx_lock(&(_sc)->vr_mtx)


More information about the svn-src-head mailing list