diff options
author | attilio <attilio@FreeBSD.org> | 2009-05-30 15:14:44 +0000 |
---|---|---|
committer | attilio <attilio@FreeBSD.org> | 2009-05-30 15:14:44 +0000 |
commit | b523608331b881784ac18a7dfcb65c7a679130b0 (patch) | |
tree | 073ce0f089e7f642e36b12a238c6d66778db53f5 /sys/dev/dc | |
parent | d03ca3acc6b07da900f12523e3d2560f84b538c4 (diff) | |
download | FreeBSD-src-b523608331b881784ac18a7dfcb65c7a679130b0.zip FreeBSD-src-b523608331b881784ac18a7dfcb65c7a679130b0.tar.gz |
When user_frac in the polling subsystem is low it is going to busy the
CPU for too long period than necessary. Additively, interfaces are kept
polled (in the tick) even if no more packets are available.
In order to avoid such situations a new generic mechanism can be
implemented in proactive way, keeping track of the time spent on any
packet and fragmenting the time for any tick, stopping the processing
as soon as possible.
In order to implement such mechanism, the polling handler needs to
change, returning the number of packets processed.
While the intended logic is not part of this patch, the polling KPI is
broken by this commit, adding an int return value and the new flag
IFCAP_POLLING_NOCOUNT (which will signal that the return value is
meaningless for the installed handler and checking should be skipped).
Bump __FreeBSD_version in order to signal such situation.
Reviewed by: emaste
Sponsored by: Sandvine Incorporated
Diffstat (limited to 'sys/dev/dc')
-rw-r--r-- | sys/dev/dc/if_dc.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c index e29ff18..d1f51ac 100644 --- a/sys/dev/dc/if_dc.c +++ b/sys/dev/dc/if_dc.c @@ -236,7 +236,7 @@ static int dc_newbuf(struct dc_softc *, int, int); static int dc_encap(struct dc_softc *, struct mbuf **); static void dc_pnic_rx_bug_war(struct dc_softc *, int); static int dc_rx_resync(struct dc_softc *); -static void dc_rxeof(struct dc_softc *); +static int dc_rxeof(struct dc_softc *); static void dc_txeof(struct dc_softc *); static void dc_tick(void *); static void dc_tx_underrun(struct dc_softc *); @@ -2640,19 +2640,21 @@ dc_rx_resync(struct dc_softc *sc) * A frame has been uploaded: pass the resulting mbuf chain up to * the higher level protocols. */ -static void +static int dc_rxeof(struct dc_softc *sc) { struct mbuf *m, *m0; struct ifnet *ifp; struct dc_desc *cur_rx; - int i, total_len = 0; + int i, total_len, rx_npkts; u_int32_t rxstat; DC_LOCK_ASSERT(sc); ifp = sc->dc_ifp; i = sc->dc_cdata.dc_rx_prod; + total_len = 0; + rx_npkts = 0; bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap, BUS_DMASYNC_POSTREAD); while (!(le32toh(sc->dc_ldata->dc_rx_list[i].dc_status) & @@ -2706,7 +2708,7 @@ dc_rxeof(struct dc_softc *sc) continue; } else { dc_init_locked(sc); - return; + return (rx_npkts); } } } @@ -2745,9 +2747,11 @@ dc_rxeof(struct dc_softc *sc) DC_UNLOCK(sc); (*ifp->if_input)(ifp, m); DC_LOCK(sc); + rx_npkts++; } sc->dc_cdata.dc_rx_prod = i; + return (rx_npkts); } /* @@ -2989,20 +2993,21 @@ dc_tx_underrun(struct dc_softc *sc) #ifdef DEVICE_POLLING static poll_handler_t dc_poll; -static void +static int dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) { struct dc_softc *sc = ifp->if_softc; + int rx_npkts = 0; DC_LOCK(sc); if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { DC_UNLOCK(sc); - return; + return (rx_npkts); } sc->rxcycles = count; - dc_rxeof(sc); + rx_npkts = dc_rxeof(sc); dc_txeof(sc); if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_drv_flags & IFF_DRV_OACTIVE)) @@ -3017,7 +3022,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) DC_ISR_BUS_ERR); if (!status) { DC_UNLOCK(sc); - return; + return (rx_npkts); } /* ack what we have */ CSR_WRITE_4(sc, DC_ISR, status); @@ -3043,6 +3048,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) } } DC_UNLOCK(sc); + return (rx_npkts); } #endif /* DEVICE_POLLING */ |