diff options
Diffstat (limited to 'sys/dev/sf/if_sf.c')
-rw-r--r-- | sys/dev/sf/if_sf.c | 89 |
1 files changed, 45 insertions, 44 deletions
diff --git a/sys/dev/sf/if_sf.c b/sys/dev/sf/if_sf.c index fa7eb83..691a0f6 100644 --- a/sys/dev/sf/if_sf.c +++ b/sys/dev/sf/if_sf.c @@ -165,11 +165,9 @@ 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); #ifdef DEVICE_POLLING -static void sf_poll(struct ifnet *ifp, enum poll_cmd cmd, - int count); -static void sf_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, - int count); -#endif /* DEVICE_POLLING */ +static void sf_poll(struct ifnet *ifp, enum poll_cmd cmd, int count); +static void sf_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count); +#endif static u_int32_t csr_read_4(struct sf_softc *, int); static void csr_write_4(struct sf_softc *, int, u_int32_t); @@ -560,10 +558,31 @@ sf_ioctl(ifp, command, data) error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; case SIOCSIFCAP: - SF_LOCK(sc); - ifp->if_capenable &= ~IFCAP_POLLING; - ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING; - SF_UNLOCK(sc); +#ifdef DEVICE_POLLING + if (ifr->ifr_reqcap & IFCAP_POLLING && + !(ifp->if_capenable & IFCAP_POLLING)) { + error = ether_poll_register(sf_poll, ifp); + if (error) + return(error); + SF_LOCK(sc); + /* Disable interrupts */ + csr_write_4(sc, SF_IMR, 0x00000000); + ifp->if_capenable |= IFCAP_POLLING; + SF_UNLOCK(sc); + return (error); + + } + if (!(ifr->ifr_reqcap & IFCAP_POLLING) && + ifp->if_capenable & IFCAP_POLLING) { + error = ether_poll_deregister(ifp); + /* Enable interrupts. */ + SF_LOCK(sc); + csr_write_4(sc, SF_IMR, SF_INTRS); + ifp->if_capenable &= ~IFCAP_POLLING; + SF_UNLOCK(sc); + return (error); + } +#endif /* DEVICE_POLLING */ break; default: error = ether_ioctl(ifp, command, data); @@ -749,10 +768,10 @@ sf_attach(dev) IFQ_SET_MAXLEN(&ifp->if_snd, SF_TX_DLIST_CNT - 1); ifp->if_snd.ifq_drv_maxlen = SF_TX_DLIST_CNT - 1; IFQ_SET_READY(&ifp->if_snd); + ifp->if_capenable = ifp->if_capabilities; #ifdef DEVICE_POLLING ifp->if_capabilities |= IFCAP_POLLING; -#endif /* DEVICE_POLLING */ - ifp->if_capenable = ifp->if_capabilities; +#endif /* * Call MI attach routine. @@ -794,6 +813,11 @@ sf_detach(dev) KASSERT(mtx_initialized(&sc->sf_mtx), ("sf mutex not initialized")); ifp = sc->sf_ifp; +#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)) { SF_LOCK(sc); @@ -946,12 +970,12 @@ sf_rxeof(sc) struct mbuf *m0; #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) { + if (ifp->if_capenable & IFCAP_POLLING) { if (sc->rxcycles <= 0) break; sc->rxcycles--; } -#endif /* DEVICE_POLLING */ +#endif cur_rx = &sc->sf_ldata->sf_rx_clist[cmpconsidx]; desc = &sc->sf_ldata->sf_rx_dlist_big[cur_rx->sf_endidx]; @@ -1068,7 +1092,8 @@ sf_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) struct sf_softc *sc = ifp->if_softc; SF_LOCK(sc); - sf_poll_locked(ifp, cmd, count); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + sf_poll_locked(ifp, cmd, count); SF_UNLOCK(sc); } @@ -1079,17 +1104,6 @@ sf_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count) SF_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_4(sc, SF_IMR, SF_INTRS); - return; - } - sc->rxcycles = count; sf_rxeof(sc); sf_txeof(sc); @@ -1131,17 +1145,11 @@ sf_intr(arg) ifp = sc->sf_ifp; #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) - goto done_locked; - - if ((ifp->if_capenable & IFCAP_POLLING) && - ether_poll_register(sf_poll, ifp)) { - /* OK, disable interrupts. */ - csr_write_4(sc, SF_IMR, 0x00000000); - sf_poll_locked(ifp, 0, 1); - goto done_locked; + if (ifp->if_capenable & IFCAP_POLLING) { + SF_UNLOCK(sc); + return; } -#endif /* DEVICE_POLLING */ +#endif if (!(csr_read_4(sc, SF_ISR_SHADOW) & SF_ISR_PCIINT_ASSERTED)) { SF_UNLOCK(sc); @@ -1185,9 +1193,6 @@ sf_intr(arg) if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) sf_start_locked(ifp); -#ifdef DEVICE_POLLING -done_locked: -#endif /* DEVICE_POLLING */ SF_UNLOCK(sc); } @@ -1296,10 +1301,10 @@ sf_init_locked(sc) #ifdef DEVICE_POLLING /* Disable interrupts if we are polling. */ - if (ifp->if_flags & IFF_POLLING) + if (ifp->if_capenable & IFCAP_POLLING) csr_write_4(sc, SF_IMR, 0x00000000); else -#endif /* DEVICE_POLLING */ +#endif /* Enable interrupts. */ csr_write_4(sc, SF_IMR, SF_INTRS); @@ -1478,10 +1483,6 @@ sf_stop(sc) callout_stop(&sc->sf_stat_callout); -#ifdef DEVICE_POLLING - ether_poll_deregister(ifp); -#endif /* DEVICE_POLLING */ - csr_write_4(sc, SF_GEN_ETH_CTL, 0); csr_write_4(sc, SF_CQ_CONSIDX, 0); csr_write_4(sc, SF_CQ_PRODIDX, 0); |