PERFORCE change 103172 for review

Paolo Pisati piso at FreeBSD.org
Fri Aug 4 14:43:41 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=103172

Change 103172 by piso at piso_newluxor on 2006/08/04 14:43:24

	Modify again bfe: this time use a combination of 
	ithread handler (transmission path) and taskqueue (errors
	and link handling).
	
	The advantage of this approach is that we don't have
	to introduce any mutex to synchronize the filter and 
	the thread/tasks, but on the other hand every driver 
	will grow its own taskqueue+tasks, and it will result
	in some code duplication.

Affected files ...

.. //depot/projects/soc2006/intr_filter/dev/bfe/if_bfe.c#5 edit
.. //depot/projects/soc2006/intr_filter/dev/bfe/if_bfereg.h#3 edit

Differences ...

==== //depot/projects/soc2006/intr_filter/dev/bfe/if_bfe.c#5 (text+ko) ====

@@ -37,6 +37,7 @@
 #include <sys/module.h>
 #include <sys/socket.h>
 #include <sys/queue.h>
+#include <sys/taskqueue.h>
 
 #include <net/if.h>
 #include <net/if_arp.h>
@@ -93,6 +94,8 @@
 #endif
 static int  bfe_filter				(void *);
 static void bfe_handler				(void *);
+static void bfe_errors                          (void *, int);
+static void bfe_stops                           (void *, int);
 static void bfe_start				(struct ifnet *);
 static void bfe_start_locked			(struct ifnet *);
 static int  bfe_ioctl				(struct ifnet *, u_long, caddr_t);
@@ -419,6 +422,14 @@
 	ifp->if_capabilities |= IFCAP_VLAN_MTU;
 	ifp->if_capenable |= IFCAP_VLAN_MTU;
 
+	sc->sc_tq = taskqueue_create("bfe_taskq", M_NOWAIT,
+				     taskqueue_thread_enqueue, &sc->sc_tq);
+	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
+				"%s taskq", ifp->if_xname);
+
+	TASK_INIT(&sc->sc_errorstask, 0, bfe_errors, sc);
+	TASK_INIT(&sc->sc_stoptask, 0, bfe_stops, sc);
+
 	/*
 	 * Hook interrupt last to avoid having to lock softc
 	 */
@@ -464,6 +475,9 @@
 		device_delete_child(dev, sc->bfe_miibus);
 
 	bfe_release_resources(sc);
+	taskqueue_drain(sc->sc_tq, &sc->sc_stoptask);
+	taskqueue_drain(sc->sc_tq, &sc->sc_errorstask);
+	taskqueue_free(sc->sc_tq);
 	BFE_UNLOCK(sc);
 	mtx_destroy(&sc->bfe_mtx);
 
@@ -1194,9 +1208,10 @@
 bfe_filter(void *xsc)
 {
 	struct bfe_softc *sc = xsc;
-	u_int32_t imask;
+	struct ifnet *ifp;
+	u_int32_t imask, istat, flag;
 
-	sc->bfe_istat = CSR_READ_4(sc, BFE_ISTAT);
+	istat = CSR_READ_4(sc, BFE_ISTAT);
 	imask = CSR_READ_4(sc, BFE_IMASK);
 
 	/*
@@ -1204,49 +1219,28 @@
 	 * chips interrupt mask register to 0 doesn't actually stop the
 	 * interrupts
 	 */
-	sc->bfe_istat &= imask;
-	CSR_WRITE_4(sc, BFE_ISTAT, sc->bfe_istat);
+	istat &= imask;
+	CSR_WRITE_4(sc, BFE_ISTAT, istat);
 	CSR_READ_4(sc, BFE_ISTAT);
 
 	/* not expecting this interrupt, disregard it */
-	if(sc->bfe_istat == 0)
+	if(istat == 0)
 		return (FILTER_STRAY);
 
-	/* disable interrupts - not that it actually does..*/
-	CSR_WRITE_4(sc, BFE_IMASK, 0);
-	CSR_READ_4(sc, BFE_IMASK);
-
-	return (FILTER_HANDLED | FILTER_SCHEDULE_THREAD);
-}
-
-static void
-bfe_handler(void *xsc)
-{
-	struct bfe_softc *sc = xsc;
-	struct ifnet *ifp;
-	u_int32_t istat, flag;
-
-	ifp = sc->bfe_ifp;
-
-	BFE_LOCK(sc);
-
-	istat = sc->bfe_istat;
 	if(istat & BFE_ISTAT_ERRORS) {
-
 		if (istat & BFE_ISTAT_DSCE) {
 			printf("if_bfe Descriptor Error\n");
-			bfe_stop(sc);
-			BFE_UNLOCK(sc);
-			return;
+			taskqueue_enqueue(sc->sc_tq, &sc->sc_stoptask);
+			return (FILTER_HANDLED);
 		}
 
 		if (istat & BFE_ISTAT_DPE) {
 			printf("if_bfe Descriptor Protocol Error\n");
-			bfe_stop(sc);
-			BFE_UNLOCK(sc);
-			return;
+			taskqueue_enqueue(sc->sc_tq, &sc->sc_stoptask);
+			return (FILTER_HANDLED);
 		}
 		
+		ifp = sc->bfe_ifp;
 		flag = CSR_READ_4(sc, BFE_DMATX_STAT);
 		if(flag & BFE_STAT_EMASK)
 			ifp->if_oerrors++;
@@ -1254,28 +1248,61 @@
 		flag = CSR_READ_4(sc, BFE_DMARX_STAT);
 		if(flag & BFE_RX_FLAG_ERRORS)
 			ifp->if_ierrors++;
+		
+		taskqueue_enqueue(sc->sc_tq, &sc->sc_errorstask);
+		return (FILTER_HANDLED);
+	}
+
+	/* disable interrupts - not that it actually does..*/
+	CSR_WRITE_4(sc, BFE_IMASK, 0);
+	CSR_READ_4(sc, BFE_IMASK);
+
+	return (FILTER_HANDLED | FILTER_SCHEDULE_THREAD);
+}
+
+static void
+bfe_stops(void *context, int p __unused) {
+	struct bfe_softc *sc = context;
+
+	BFE_LOCK(sc);
+	bfe_stop(sc);
+	BFE_UNLOCK(sc);			
+}
+
+static void
+bfe_errors(void *context, int p __unused) {
+	struct bfe_softc *sc = context;
+	struct ifnet *ifp;
+
+	BFE_LOCK(sc);
+	ifp = sc->bfe_ifp;
+	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+	bfe_init_locked(sc);
+	BFE_UNLOCK(sc);
+}
+
+static void
+bfe_handler(void *xsc) {
+	struct bfe_softc *sc = xsc;
+	struct ifnet *ifp;
 
-		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-		bfe_init_locked(sc);
-	}
+	BFE_LOCK(sc);
+	ifp = sc->bfe_ifp;
 
-	/* A packet was received */
-	if(istat & BFE_ISTAT_RX)
-		bfe_rxeof(sc);
+	/* A packet was received */	
+	bfe_rxeof(sc);
 
 	/* A packet was sent */
-	if(istat & BFE_ISTAT_TX)
-		bfe_txeof(sc);
+	bfe_txeof(sc);
 
 	/* We have packets pending, fire them out */
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
 	    !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
 		bfe_start_locked(ifp);
 
-	BFE_UNLOCK(sc);	
-
 	/* Enable interrupts */
 	CSR_WRITE_4(sc, BFE_IMASK, BFE_IMASK_DEF);
+	BFE_UNLOCK(sc);	
 }
 
 #if 0

==== //depot/projects/soc2006/intr_filter/dev/bfe/if_bfereg.h#3 (text+ko) ====

@@ -510,7 +510,9 @@
     struct bfe_data         bfe_tx_ring[BFE_TX_LIST_CNT]; /* XXX */
     struct bfe_data         bfe_rx_ring[BFE_RX_LIST_CNT]; /* XXX */
     struct mtx              bfe_mtx;
-    u_int32_t               bfe_istat;
+    struct taskqueue	    *sc_tq;	/* private task queue */
+    struct task		    sc_stoptask;	
+    struct task		    sc_errorstask;	
     u_int32_t               bfe_flags;
     u_int32_t               bfe_imask;
     u_int32_t               bfe_dma_offset;


More information about the p4-projects mailing list