Date: Mon, 26 Mar 2012 03:48:21 +0000 (UTC) From: Pyun YongHyeon <yongari@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r233487 - in stable/8/sys: dev/sf i386/conf Message-ID: <201203260348.q2Q3mLVf012977@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: yongari Date: Mon Mar 26 03:48:21 2012 New Revision: 233487 URL: http://svn.freebsd.org/changeset/base/233487 Log: MFC r232019,232021,232025,232027,232029,232040: r232019: Give hardware chance to drain active DMA cycles. r232021: If there are not enough RX buffers, release partially allocated RX buffers. r232025: Introduce sf_ifmedia_upd_locked() and have driver reset PHY before switching to selected media. While here, set if_drv_flags before switching to selected media. r232027: No need to reprogram hardware RX filter when driver is not running. r232029: Remove taskqueue based MII stat change handler. Driver does not need deferred link state change processing. While I'm here, do not report current link status if interface is not UP. r232040: Add check for IFF_DRV_RUNNING flag after serving an interrupt and don't give RX path more priority than TX path. Also remove infinite loop in interrupt handler and limit number of iteration to 32. This change addresses system load fluctuations under high network load. Modified: stable/8/sys/dev/sf/if_sf.c stable/8/sys/dev/sf/if_sfreg.h Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/boot/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/e1000/ (props changed) stable/8/sys/i386/conf/XENHVM (props changed) Modified: stable/8/sys/dev/sf/if_sf.c ============================================================================== --- stable/8/sys/dev/sf/if_sf.c Mon Mar 26 03:45:46 2012 (r233486) +++ stable/8/sys/dev/sf/if_sf.c Mon Mar 26 03:48:21 2012 (r233487) @@ -96,7 +96,6 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <sys/sockio.h> #include <sys/sysctl.h> -#include <sys/taskqueue.h> #include <net/bpf.h> #include <net/if.h> @@ -172,6 +171,7 @@ static void sf_init_locked(struct sf_sof static void sf_stop(struct sf_softc *); static void sf_watchdog(struct sf_softc *); static int sf_ifmedia_upd(struct ifnet *); +static int sf_ifmedia_upd_locked(struct ifnet *); static void sf_ifmedia_sts(struct ifnet *, struct ifmediareq *); static void sf_reset(struct sf_softc *); static int sf_dma_alloc(struct sf_softc *); @@ -191,7 +191,6 @@ static uint8_t sf_read_eeprom(struct sf_ static int sf_miibus_readreg(device_t, int, int); static int sf_miibus_writereg(device_t, int, int, int); static void sf_miibus_statchg(device_t); -static void sf_link_task(void *, int); #ifdef DEVICE_POLLING static int sf_poll(struct ifnet *ifp, enum poll_cmd cmd, int count); #endif @@ -393,30 +392,16 @@ static void sf_miibus_statchg(device_t dev) { struct sf_softc *sc; - - sc = device_get_softc(dev); - taskqueue_enqueue(taskqueue_swi, &sc->sf_link_task); -} - -static void -sf_link_task(void *arg, int pending) -{ - struct sf_softc *sc; struct mii_data *mii; struct ifnet *ifp; uint32_t val; - sc = (struct sf_softc *)arg; - - SF_LOCK(sc); - + sc = device_get_softc(dev); mii = device_get_softc(sc->sf_miibus); ifp = sc->sf_ifp; if (mii == NULL || ifp == NULL || - (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - SF_UNLOCK(sc); + (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) return; - } if (mii->mii_media_status & IFM_ACTIVE) { if (IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) @@ -453,8 +438,6 @@ sf_link_task(void *arg, int pending) else val &= ~SF_TIMER_TIMES_TEN; csr_write_4(sc, SF_TIMER_CTL, val); - - SF_UNLOCK(sc); } static void @@ -523,20 +506,27 @@ static int sf_ifmedia_upd(struct ifnet *ifp) { struct sf_softc *sc; - struct mii_data *mii; - struct mii_softc *miisc; int error; sc = ifp->if_softc; SF_LOCK(sc); + error = sf_ifmedia_upd_locked(ifp); + SF_UNLOCK(sc); + return (error); +} + +static int +sf_ifmedia_upd_locked(struct ifnet *ifp) +{ + struct sf_softc *sc; + struct mii_data *mii; + struct mii_softc *miisc; + sc = ifp->if_softc; mii = device_get_softc(sc->sf_miibus); LIST_FOREACH(miisc, &mii->mii_phys, mii_list) mii_phy_reset(miisc); - error = mii_mediachg(mii); - SF_UNLOCK(sc); - - return (error); + return (mii_mediachg(mii)); } /* @@ -550,8 +540,12 @@ sf_ifmedia_sts(struct ifnet *ifp, struct sc = ifp->if_softc; SF_LOCK(sc); - mii = device_get_softc(sc->sf_miibus); + if ((ifp->if_flags & IFF_UP) == 0) { + SF_UNLOCK(sc); + return; + } + mii = device_get_softc(sc->sf_miibus); mii_pollstat(mii); ifmr->ifm_active = mii->mii_media_active; ifmr->ifm_status = mii->mii_media_status; @@ -592,7 +586,8 @@ sf_ioctl(struct ifnet *ifp, u_long comma case SIOCADDMULTI: case SIOCDELMULTI: SF_LOCK(sc); - sf_rxfilter(sc); + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + sf_rxfilter(sc); SF_UNLOCK(sc); break; case SIOCGIFMEDIA: @@ -744,7 +739,6 @@ sf_attach(device_t dev) mtx_init(&sc->sf_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); callout_init_mtx(&sc->sf_co, &sc->sf_mtx, 0); - TASK_INIT(&sc->sf_link_task, 0, sf_link_task, sc); /* * Map control/status registers. @@ -946,7 +940,6 @@ sf_detach(device_t dev) sf_stop(sc); SF_UNLOCK(sc); callout_drain(&sc->sf_co); - taskqueue_drain(taskqueue_swi, &sc->sf_link_task); if (ifp != NULL) ether_ifdetach(ifp); } @@ -1548,7 +1541,9 @@ sf_rxeof(struct sf_softc *sc) */ eidx = 0; prog = 0; - for (cons = sc->sf_cdata.sf_rxc_cons; ; SF_INC(cons, SF_RX_CLIST_CNT)) { + for (cons = sc->sf_cdata.sf_rxc_cons; + (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; + SF_INC(cons, SF_RX_CLIST_CNT)) { cur_cmp = &sc->sf_rdata.sf_rx_cring[cons]; status = le32toh(cur_cmp->sf_rx_status1); if (status == 0) @@ -1851,6 +1846,7 @@ sf_intr(void *arg) struct sf_softc *sc; struct ifnet *ifp; uint32_t status; + int cnt; sc = (struct sf_softc *)arg; SF_LOCK(sc); @@ -1869,13 +1865,13 @@ sf_intr(void *arg) if ((ifp->if_capenable & IFCAP_POLLING) != 0) goto done_locked; #endif - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - goto done_locked; /* Disable interrupts. */ csr_write_4(sc, SF_IMR, 0x00000000); - for (; (status & SF_INTRS) != 0;) { + for (cnt = 32; (status & SF_INTRS) != 0;) { + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + break; if ((status & SF_ISR_RXDQ1_DMADONE) != 0) sf_rxeof(sc); @@ -1910,15 +1906,19 @@ sf_intr(void *arg) #endif } } + if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + sf_start_locked(ifp); + if (--cnt <= 0) + break; /* Reading the ISR register clears all interrrupts. */ status = csr_read_4(sc, SF_ISR); } - /* Re-enable interrupts. */ - csr_write_4(sc, SF_IMR, SF_INTRS); + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { + /* Re-enable interrupts. */ + csr_write_4(sc, SF_IMR, SF_INTRS); + } - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - sf_start_locked(ifp); done_locked: SF_UNLOCK(sc); } @@ -2010,6 +2010,7 @@ sf_init_locked(struct sf_softc *sc) if (sf_init_rx_ring(sc) == ENOBUFS) { device_printf(sc->sf_dev, "initialization failed: no memory for rx buffers\n"); + sf_stop(sc); return; } @@ -2135,12 +2136,12 @@ sf_init_locked(struct sf_softc *sc) else SF_CLRBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_RXGFP_ENB); - sc->sf_link = 0; - mii_mediachg(mii); - ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + sc->sf_link = 0; + sf_ifmedia_upd_locked(ifp); + callout_reset(&sc->sf_co, hz, sf_tick, sc); } @@ -2329,6 +2330,9 @@ sf_stop(struct sf_softc *sc) /* Disable Tx/Rx egine. */ csr_write_4(sc, SF_GEN_ETH_CTL, 0); + /* Give hardware chance to drain active DMA cycles. */ + DELAY(1000); + csr_write_4(sc, SF_CQ_CONSIDX, 0); csr_write_4(sc, SF_CQ_PRODIDX, 0); csr_write_4(sc, SF_RXDQ_ADDR_Q1, 0); Modified: stable/8/sys/dev/sf/if_sfreg.h ============================================================================== --- stable/8/sys/dev/sf/if_sfreg.h Mon Mar 26 03:45:46 2012 (r233486) +++ stable/8/sys/dev/sf/if_sfreg.h Mon Mar 26 03:48:21 2012 (r233487) @@ -1083,7 +1083,6 @@ struct sf_softc { int sf_if_flags; struct callout sf_co; int sf_watchdog_timer; - struct task sf_link_task; int sf_link; int sf_suspended; int sf_detach;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203260348.q2Q3mLVf012977>