From 5506afef173146aea78b11afe5e46f3e2f4e5951 Mon Sep 17 00:00:00 2001 From: Pyun YongHyeon Date: Mon, 10 Jun 2013 07:31:49 +0000 Subject: Avoid unnecessary controller reinitialization by checking driver running state. fxp(4) requires controller reinitialization for the following cases. o RX lockup condition on i82557 o promiscuous mode change o multicast filter change o WOL configuration o TSO/VLAN hardware tagging/checksum offloading configuration o MAC reprogramming after speed/duplex/flow-control resolution o Any events that result in MAC reprogramming(link UP/DOWN, remote link partner's restart of auto-negotiation etc) o Microcode loading/unloading Apart from above cases which come from hardware limitation, upper stack also blindly reinitializes controller whenever an IP address is assigned. After r194573, fxp(4) no longer needs to reinitialize the controller to program multicast filter after upping the interface. So keeping track of driver running state should remove all unnecessary controller reinitializations. This change will also address endless controller reinitialization triggered by dhclient(8). Tested by: hrs, Alban Hertroys --- sys/dev/fxp/if_fxp.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'sys/dev') diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index ba63af734406..11b105ef3d2b 100644 --- a/sys/dev/fxp/if_fxp.c +++ b/sys/dev/fxp/if_fxp.c @@ -1075,7 +1075,8 @@ fxp_suspend(device_t dev) pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; sc->flags |= FXP_FLAG_WOL; /* Reconfigure hardware to accept magic frames. */ - fxp_init_body(sc, 1); + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + fxp_init_body(sc, 0); } pci_write_config(sc->dev, pmc + PCIR_POWER_STATUS, pmstat, 2); } @@ -2141,8 +2142,10 @@ fxp_tick(void *xsc) */ if (sc->rx_idle_secs > FXP_MAX_RX_IDLE) { sc->rx_idle_secs = 0; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; fxp_init_body(sc, 1); + } return; } /* @@ -2240,6 +2243,7 @@ fxp_watchdog(struct fxp_softc *sc) device_printf(sc->dev, "device timeout\n"); sc->ifp->if_oerrors++; + sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; fxp_init_body(sc, 1); } @@ -2274,6 +2278,10 @@ fxp_init_body(struct fxp_softc *sc, int setmedia) int i, prm; FXP_LOCK_ASSERT(sc, MA_OWNED); + + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + return; + /* * Cancel any pending I/O */ @@ -2813,6 +2821,7 @@ fxp_miibus_statchg(device_t dev) */ if (sc->revision == FXP_REV_82557) return; + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; fxp_init_body(sc, 0); } @@ -2836,9 +2845,10 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data) if (ifp->if_flags & IFF_UP) { if (((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) && ((ifp->if_flags ^ sc->if_flags) & - (IFF_PROMISC | IFF_ALLMULTI | IFF_LINK0)) != 0) + (IFF_PROMISC | IFF_ALLMULTI | IFF_LINK0)) != 0) { + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; fxp_init_body(sc, 0); - else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) fxp_init_body(sc, 1); } else { if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) @@ -2851,8 +2861,10 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data) case SIOCADDMULTI: case SIOCDELMULTI: FXP_LOCK(sc); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; fxp_init_body(sc, 0); + } FXP_UNLOCK(sc); break; @@ -2942,8 +2954,10 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data) ~(IFCAP_VLAN_HWTSO | IFCAP_VLAN_HWCSUM); reinit++; } - if (reinit > 0 && ifp->if_flags & IFF_UP) + if (reinit > 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; fxp_init_body(sc, 0); + } FXP_UNLOCK(sc); VLAN_CAPABILITIES(ifp); break; -- cgit v1.3