Date: Fri, 4 Aug 2006 14:43:33 GMT From: Paolo Pisati <piso@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 103172 for review Message-ID: <200608041443.k74EhXDD096852@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=103172 Change 103172 by piso@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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608041443.k74EhXDD096852>