diff options
Diffstat (limited to 'sys/dev/re/if_re.c')
-rw-r--r-- | sys/dev/re/if_re.c | 89 |
1 files changed, 49 insertions, 40 deletions
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c index c3ce9d7..72fff4e 100644 --- a/sys/dev/re/if_re.c +++ b/sys/dev/re/if_re.c @@ -1202,6 +1202,7 @@ re_attach(dev) ifp->if_start = re_start; ifp->if_hwassist = /*RE_CSUM_FEATURES*/0; ifp->if_capabilities |= IFCAP_HWCSUM|IFCAP_VLAN_HWTAGGING; + ifp->if_capenable = ifp->if_capabilities & ~IFCAP_HWCSUM; #ifdef DEVICE_POLLING ifp->if_capabilities |= IFCAP_POLLING; #endif @@ -1214,7 +1215,6 @@ re_attach(dev) IFQ_SET_MAXLEN(&ifp->if_snd, RL_IFQ_MAXLEN); ifp->if_snd.ifq_drv_maxlen = RL_IFQ_MAXLEN; IFQ_SET_READY(&ifp->if_snd); - ifp->if_capenable = ifp->if_capabilities & ~IFCAP_HWCSUM; /* * Call MI attach routine. @@ -1264,6 +1264,11 @@ re_detach(dev) ifp = sc->rl_ifp; KASSERT(mtx_initialized(&sc->rl_mtx), ("re mutex not initialized")); +#ifdef DEVICE_POLLING + if (ifp->if_capenable & IFCAP_POLLING) + ether_poll_deregister(ifp); +#endif + /* These should only be active if attach succeeded */ if (device_is_attached(dev)) { RL_LOCK(sc); @@ -1756,7 +1761,8 @@ re_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) struct rl_softc *sc = ifp->if_softc; RL_LOCK(sc); - re_poll_locked(ifp, cmd, count); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + re_poll_locked(ifp, cmd, count); RL_UNLOCK(sc); } @@ -1767,15 +1773,6 @@ re_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count) RL_LOCK_ASSERT(sc); - if (!(ifp->if_capenable & IFCAP_POLLING)) { - ether_poll_deregister(ifp); - cmd = POLL_DEREGISTER; - } - if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */ - CSR_WRITE_2(sc, RL_IMR, RL_INTRS_CPLUS); - return; - } - sc->rxcycles = count; re_rxeof(sc); re_txeof(sc); @@ -1822,15 +1819,9 @@ re_intr(arg) goto done_locked; #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) + if (ifp->if_capenable & IFCAP_POLLING) goto done_locked; - if ((ifp->if_capenable & IFCAP_POLLING) && - ether_poll_register(re_poll, ifp)) { /* ok, disable interrupts */ - CSR_WRITE_2(sc, RL_IMR, 0x0000); - re_poll_locked(ifp, 0, 1); - goto done_locked; - } -#endif /* DEVICE_POLLING */ +#endif for (;;) { @@ -2171,10 +2162,10 @@ re_init_locked(sc) /* * Disable interrupts if we are polling. */ - if (ifp->if_flags & IFF_POLLING) + if (ifp->if_capenable & IFCAP_POLLING) CSR_WRITE_2(sc, RL_IMR, 0); else /* otherwise ... */ -#endif /* DEVICE_POLLING */ +#endif /* * Enable interrupts. */ @@ -2289,7 +2280,7 @@ re_ioctl(ifp, command, data) struct rl_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; struct mii_data *mii; - int error; + int error = 0; switch (command) { case SIOCSIFMTU: @@ -2298,7 +2289,6 @@ re_ioctl(ifp, command, data) error = EINVAL; ifp->if_mtu = ifr->ifr_mtu; RL_UNLOCK(sc); - error = 0; break; case SIOCSIFFLAGS: RL_LOCK(sc); @@ -2307,14 +2297,12 @@ re_ioctl(ifp, command, data) else if (ifp->if_drv_flags & IFF_DRV_RUNNING) re_stop(sc); RL_UNLOCK(sc); - error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: RL_LOCK(sc); re_setmulti(sc); RL_UNLOCK(sc); - error = 0; break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: @@ -2322,18 +2310,42 @@ re_ioctl(ifp, command, data) error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; case SIOCSIFCAP: - RL_LOCK(sc); - ifp->if_capenable &= ~(IFCAP_HWCSUM | IFCAP_POLLING); - ifp->if_capenable |= - ifr->ifr_reqcap & (IFCAP_HWCSUM | IFCAP_POLLING); - if (ifp->if_capenable & IFCAP_TXCSUM) - ifp->if_hwassist = RE_CSUM_FEATURES; - else - ifp->if_hwassist = 0; - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - re_init_locked(sc); - RL_UNLOCK(sc); - error = 0; + { + int mask = ifr->ifr_reqcap ^ ifp->if_capenable; +#ifdef DEVICE_POLLING + if (mask & IFCAP_POLLING) { + if (ifr->ifr_reqcap & IFCAP_POLLING) { + error = ether_poll_register(re_poll, ifp); + if (error) + return(error); + RL_LOCK(sc); + /* Disable interrupts */ + CSR_WRITE_2(sc, RL_IMR, 0x0000); + ifp->if_capenable |= IFCAP_POLLING; + RL_UNLOCK(sc); + + } else { + error = ether_poll_deregister(ifp); + /* Enable interrupts. */ + RL_LOCK(sc); + CSR_WRITE_2(sc, RL_IMR, RL_INTRS_CPLUS); + ifp->if_capenable &= ~IFCAP_POLLING; + RL_UNLOCK(sc); + } + } +#endif /* DEVICE_POLLING */ + if (mask & IFCAP_HWCSUM) { + RL_LOCK(sc); + ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_HWCSUM; + if (ifp->if_capenable & IFCAP_TXCSUM) + ifp->if_hwassist = RE_CSUM_FEATURES; + else + ifp->if_hwassist = 0; + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + re_init_locked(sc); + RL_UNLOCK(sc); + } + } break; default: error = ether_ioctl(ifp, command, data); @@ -2379,9 +2391,6 @@ re_stop(sc) callout_stop(&sc->rl_stat_callout); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); -#ifdef DEVICE_POLLING - ether_poll_deregister(ifp); -#endif /* DEVICE_POLLING */ CSR_WRITE_1(sc, RL_COMMAND, 0x00); CSR_WRITE_2(sc, RL_IMR, 0x0000); |