diff options
author | glebius <glebius@FreeBSD.org> | 2005-10-01 18:56:19 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2005-10-01 18:56:19 +0000 |
commit | f41a83bf429b15386f43f43f3f5326d4ece7bfce (patch) | |
tree | b78f9e953b7b58b2789d042cf37cc725045fdcf1 /sys/pci | |
parent | 6c6c328bd0bbb1d9f6b3230a33d194bf961b0eae (diff) | |
download | FreeBSD-src-f41a83bf429b15386f43f43f3f5326d4ece7bfce.zip FreeBSD-src-f41a83bf429b15386f43f43f3f5326d4ece7bfce.tar.gz |
Big polling(4) cleanup.
o Axe poll in trap.
o Axe IFF_POLLING flag from if_flags.
o Rework revision 1.21 (Giant removal), in such a way that
poll_mtx is not dropped during call to polling handler.
This fixes problem with idle polling.
o Make registration and deregistration from polling in a
functional way, insted of next tick/interrupt.
o Obsolete kern.polling.enable. Polling is turned on/off
with ifconfig.
Detailed kern_poll.c changes:
- Remove polling handler flags, introduced in 1.21. The are not
needed now.
- Forget and do not check if_flags, if_capenable and if_drv_flags.
- Call all registered polling handlers unconditionally.
- Do not drop poll_mtx, when entering polling handlers.
- In ether_poll() NET_LOCK_GIANT prior to locking poll_mtx.
- In netisr_poll() axe the block, where polling code asks drivers
to unregister.
- In netisr_poll() and ether_poll() do polling always, if any
handlers are present.
- In ether_poll_[de]register() remove a lot of error hiding code. Assert
that arguments are correct, instead.
- In ether_poll_[de]register() use standard return values in case of
error or success.
- Introduce poll_switch() that is a sysctl handler for kern.polling.enable.
poll_switch() goes through interface list and enabled/disables polling.
A message that kern.polling.enable is deprecated is printed.
Detailed driver changes:
- On attach driver announces IFCAP_POLLING in if_capabilities, but
not in if_capenable.
- On detach driver calls ether_poll_deregister() if polling is enabled.
- In polling handler driver obtains its lock and checks IFF_DRV_RUNNING
flag. If there is no, then unlocks and returns.
- In ioctl handler driver checks for IFCAP_POLLING flag requested to
be set or cleared. Driver first calls ether_poll_[de]register(), then
obtains driver lock and [dis/en]ables interrupts.
- In interrupt handler driver checks IFCAP_POLLING flag in if_capenable.
If present, then returns.This is important to protect from spurious
interrupts.
Reviewed by: ru, sam, jhb
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/if_dc.c | 69 | ||||
-rw-r--r-- | sys/pci/if_rl.c | 76 | ||||
-rw-r--r-- | sys/pci/if_sf.c | 89 | ||||
-rw-r--r-- | sys/pci/if_sis.c | 75 | ||||
-rw-r--r-- | sys/pci/if_ste.c | 73 | ||||
-rw-r--r-- | sys/pci/if_vr.c | 70 | ||||
-rw-r--r-- | sys/pci/if_xl.c | 86 |
7 files changed, 295 insertions, 243 deletions
diff --git a/sys/pci/if_dc.c b/sys/pci/if_dc.c index 8a9e8c6..a6f4304 100644 --- a/sys/pci/if_dc.c +++ b/sys/pci/if_dc.c @@ -2265,10 +2265,10 @@ dc_attach(device_t dev) */ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); ifp->if_capabilities |= IFCAP_VLAN_MTU; + ifp->if_capenable = ifp->if_capabilities; #ifdef DEVICE_POLLING ifp->if_capabilities |= IFCAP_POLLING; #endif - ifp->if_capenable = ifp->if_capabilities; callout_init_mtx(&sc->dc_stat_ch, &sc->dc_mtx, 0); @@ -2339,6 +2339,11 @@ dc_detach(device_t dev) ifp = sc->dc_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)) { DC_LOCK(sc); @@ -2704,7 +2709,7 @@ dc_rxeof(struct dc_softc *sc) while (!(le32toh(sc->dc_ldata->dc_rx_list[i].dc_status) & DC_RXSTAT_OWN)) { #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) { + if (ifp->if_capenable & IFCAP_POLLING) { if (sc->rxcycles <= 0) break; sc->rxcycles--; @@ -3038,16 +3043,13 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) { struct dc_softc *sc = ifp->if_softc; - if (!(ifp->if_capenable & IFCAP_POLLING)) { - ether_poll_deregister(ifp); - cmd = POLL_DEREGISTER; - } - if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */ - /* Re-enable interrupts. */ - CSR_WRITE_4(sc, DC_IMR, DC_INTRS); + DC_LOCK(sc); + + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + DC_UNLOCK(sc); return; } - DC_LOCK(sc); + sc->rxcycles = count; dc_rxeof(sc); dc_txeof(sc); @@ -3111,12 +3113,9 @@ dc_intr(void *arg) DC_LOCK(sc); ifp = sc->dc_ifp; #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) - goto done; - if ((ifp->if_capenable & IFCAP_POLLING) && - ether_poll_register(dc_poll, ifp)) { /* ok, disable interrupts */ - CSR_WRITE_4(sc, DC_IMR, 0x00000000); - goto done; + if (ifp->if_capenable & IFCAP_POLLING) { + DC_UNLOCK(sc); + return; } #endif @@ -3183,10 +3182,6 @@ dc_intr(void *arg) if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) dc_start_locked(ifp); -#ifdef DEVICE_POLLING -done: -#endif - DC_UNLOCK(sc); } @@ -3534,7 +3529,7 @@ dc_init_locked(struct dc_softc *sc) * the case of polling. Some cards (e.g. fxp) turn interrupts on * after a reset. */ - if (ifp->if_flags & IFF_POLLING) + if (ifp->if_capenable & IFCAP_POLLING) CSR_WRITE_4(sc, DC_IMR, 0x00000000); else #endif @@ -3686,10 +3681,31 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) #endif break; case SIOCSIFCAP: - DC_LOCK(sc); - ifp->if_capenable &= ~IFCAP_POLLING; - ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING; - DC_UNLOCK(sc); +#ifdef DEVICE_POLLING + if (ifr->ifr_reqcap & IFCAP_POLLING && + !(ifp->if_capenable & IFCAP_POLLING)) { + error = ether_poll_register(dc_poll, ifp); + if (error) + return(error); + DC_LOCK(sc); + /* Disable interrupts */ + CSR_WRITE_4(sc, DC_IMR, 0x00000000); + ifp->if_capenable |= IFCAP_POLLING; + DC_UNLOCK(sc); + return (error); + + } + if (!(ifr->ifr_reqcap & IFCAP_POLLING) && + ifp->if_capenable & IFCAP_POLLING) { + error = ether_poll_deregister(ifp); + /* Enable interrupts. */ + DC_LOCK(sc); + CSR_WRITE_4(sc, DC_IMR, DC_INTRS); + ifp->if_capenable &= ~IFCAP_POLLING; + DC_UNLOCK(sc); + return (error); + } +#endif /* DEVICE_POLLING */ break; default: error = ether_ioctl(ifp, command, data); @@ -3744,9 +3760,6 @@ dc_stop(struct dc_softc *sc) callout_stop(&sc->dc_stat_ch); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); -#ifdef DEVICE_POLLING - ether_poll_deregister(ifp); -#endif DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON)); CSR_WRITE_4(sc, DC_IMR, 0x00000000); diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c index c0e42e9..a35e999 100644 --- a/sys/pci/if_rl.c +++ b/sys/pci/if_rl.c @@ -195,10 +195,8 @@ static int rl_miibus_readreg(device_t, int, int); static void rl_miibus_statchg(device_t); static int rl_miibus_writereg(device_t, int, int, int); #ifdef DEVICE_POLLING -static void rl_poll(struct ifnet *ifp, enum poll_cmd cmd, - int count); -static void rl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, - int count); +static void rl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count); +static void rl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count); #endif static int rl_probe(device_t); static void rl_read_eeprom(struct rl_softc *, uint8_t *, int, int, int); @@ -956,10 +954,10 @@ rl_attach(device_t dev) ifp->if_init = rl_init; ifp->if_baudrate = 10000000; ifp->if_capabilities = IFCAP_VLAN_MTU; + ifp->if_capenable = ifp->if_capabilities; #ifdef DEVICE_POLLING ifp->if_capabilities |= IFCAP_POLLING; #endif - ifp->if_capenable = ifp->if_capabilities; IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; IFQ_SET_READY(&ifp->if_snd); @@ -1002,6 +1000,10 @@ rl_detach(device_t dev) KASSERT(mtx_initialized(&sc->rl_mtx), ("rl 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); @@ -1115,12 +1117,12 @@ rl_rxeof(struct rl_softc *sc) while((CSR_READ_1(sc, RL_COMMAND) & RL_CMD_EMPTY_RXBUF) == 0) { #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 rxbufpos = sc->rl_cdata.rl_rx_buf + cur_rx; rxstat = le32toh(*(uint32_t *)rxbufpos); @@ -1283,7 +1285,8 @@ rl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) struct rl_softc *sc = ifp->if_softc; RL_LOCK(sc); - rl_poll_locked(ifp, cmd, count); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + rl_poll_locked(ifp, cmd, count); RL_UNLOCK(sc); } @@ -1294,17 +1297,6 @@ rl_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); - return; - } - sc->rxcycles = count; rl_rxeof(sc); rl_txeof(sc); @@ -1345,17 +1337,9 @@ rl_intr(void *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(rl_poll, ifp)) { - /* Disable interrupts. */ - CSR_WRITE_2(sc, RL_IMR, 0x0000); - rl_poll_locked(ifp, 0, 1); - goto done_locked; - } -#endif /* DEVICE_POLLING */ +#endif for (;;) { status = CSR_READ_2(sc, RL_ISR); @@ -1574,10 +1558,10 @@ rl_init_locked(struct rl_softc *sc) #ifdef DEVICE_POLLING /* 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 -#endif /* DEVICE_POLLING */ +#endif /* Enable interrupts. */ CSR_WRITE_2(sc, RL_IMR, RL_INTRS); @@ -1669,8 +1653,31 @@ rl_ioctl(struct ifnet *ifp, u_long command, caddr_t data) error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; case SIOCSIFCAP: - ifp->if_capenable &= ~IFCAP_POLLING; - ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING; +#ifdef DEVICE_POLLING + if (ifr->ifr_reqcap & IFCAP_POLLING && + !(ifp->if_capenable & IFCAP_POLLING)) { + error = ether_poll_register(rl_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); + return (error); + + } + if (!(ifr->ifr_reqcap & IFCAP_POLLING) && + ifp->if_capenable & IFCAP_POLLING) { + error = ether_poll_deregister(ifp); + /* Enable interrupts. */ + RL_LOCK(sc); + CSR_WRITE_2(sc, RL_IMR, RL_INTRS); + ifp->if_capenable &= ~IFCAP_POLLING; + RL_UNLOCK(sc); + return (error); + } +#endif /* DEVICE_POLLING */ break; default: error = ether_ioctl(ifp, command, data); @@ -1712,9 +1719,6 @@ rl_stop(struct rl_softc *sc) ifp->if_timer = 0; 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); diff --git a/sys/pci/if_sf.c b/sys/pci/if_sf.c index fa7eb83..691a0f6 100644 --- a/sys/pci/if_sf.c +++ b/sys/pci/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); diff --git a/sys/pci/if_sis.c b/sys/pci/if_sis.c index 117a46a..c0417be 100644 --- a/sys/pci/if_sis.c +++ b/sys/pci/if_sis.c @@ -1217,11 +1217,10 @@ sis_attach(device_t dev) */ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); ifp->if_capabilities |= IFCAP_VLAN_MTU; - + ifp->if_capenable = ifp->if_capabilities; #ifdef DEVICE_POLLING ifp->if_capabilities |= IFCAP_POLLING; #endif - ifp->if_capenable = ifp->if_capabilities; /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->sis_res[1], INTR_TYPE_NET | INTR_MPSAFE, @@ -1257,6 +1256,11 @@ sis_detach(device_t dev) KASSERT(mtx_initialized(&sc->sis_mtx), ("sis mutex not initialized")); ifp = sc->sis_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)) { SIS_LOCK(sc); @@ -1404,12 +1408,12 @@ sis_rxeof(struct sis_softc *sc) cur_rx = cur_rx->sis_nextdesc) { #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 rxstat = cur_rx->sis_rxstat; bus_dmamap_sync(sc->sis_tag, cur_rx->sis_map, BUS_DMASYNC_POSTWRITE); @@ -1574,13 +1578,9 @@ sis_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) struct sis_softc *sc = ifp->if_softc; SIS_LOCK(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, SIS_IER, 1); - goto done; + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + SIS_UNLOCK(sc); + return; } /* @@ -1613,7 +1613,7 @@ sis_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) sis_initl(sc); } } -done: + SIS_UNLOCK(sc); } #endif /* DEVICE_POLLING */ @@ -1633,14 +1633,11 @@ sis_intr(void *arg) SIS_LOCK(sc); #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) - goto done; - if ((ifp->if_capenable & IFCAP_POLLING) && - ether_poll_register(sis_poll, ifp)) { /* ok, disable interrupts */ - CSR_WRITE_4(sc, SIS_IER, 0); - goto done; + if (ifp->if_capenable & IFCAP_POLLING) { + SIS_UNLOCK(sc); + return; } -#endif /* DEVICE_POLLING */ +#endif /* Disable interrupts. */ CSR_WRITE_4(sc, SIS_IER, 0); @@ -1679,9 +1676,6 @@ sis_intr(void *arg) if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) sis_startl(ifp); -#ifdef DEVICE_POLLING -done: -#endif /* DEVICE_POLLING */ SIS_UNLOCK(sc); } @@ -2033,10 +2027,10 @@ sis_initl(struct sis_softc *sc) * ... only enable interrupts if we are not polling, make sure * they are off otherwise. */ - if (ifp->if_flags & IFF_POLLING) + if (ifp->if_capenable & IFCAP_POLLING) CSR_WRITE_4(sc, SIS_IER, 0); else -#endif /* DEVICE_POLLING */ +#endif CSR_WRITE_4(sc, SIS_IER, 1); /* Enable receiver and transmitter. */ @@ -2133,10 +2127,32 @@ sis_ioctl(struct ifnet *ifp, u_long command, caddr_t data) error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; case SIOCSIFCAP: - SIS_LOCK(sc); - ifp->if_capenable &= ~IFCAP_POLLING; - ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING; - SIS_UNLOCK(sc); + /* ok, disable interrupts */ +#ifdef DEVICE_POLLING + if (ifr->ifr_reqcap & IFCAP_POLLING && + !(ifp->if_capenable & IFCAP_POLLING)) { + error = ether_poll_register(sis_poll, ifp); + if (error) + return(error); + SIS_LOCK(sc); + /* Disable interrupts */ + CSR_WRITE_4(sc, SIS_IER, 0); + ifp->if_capenable |= IFCAP_POLLING; + SIS_UNLOCK(sc); + return (error); + + } + if (!(ifr->ifr_reqcap & IFCAP_POLLING) && + ifp->if_capenable & IFCAP_POLLING) { + error = ether_poll_deregister(ifp); + /* Enable interrupts. */ + SIS_LOCK(sc); + CSR_WRITE_4(sc, SIS_IER, 1); + ifp->if_capenable &= ~IFCAP_POLLING; + SIS_UNLOCK(sc); + return (error); + } +#endif /* DEVICE_POLLING */ break; default: error = ether_ioctl(ifp, command, data); @@ -2192,9 +2208,6 @@ sis_stop(struct sis_softc *sc) callout_stop(&sc->sis_stat_ch); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); -#ifdef DEVICE_POLLING - ether_poll_deregister(ifp); -#endif CSR_WRITE_4(sc, SIS_IER, 0); CSR_WRITE_4(sc, SIS_IMR, 0); CSR_READ_4(sc, SIS_ISR); /* clear any interrupts already pending */ diff --git a/sys/pci/if_ste.c b/sys/pci/if_ste.c index eca7e11..f80e676 100644 --- a/sys/pci/if_ste.c +++ b/sys/pci/if_ste.c @@ -621,7 +621,8 @@ ste_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) struct ste_softc *sc = ifp->if_softc; STE_LOCK(sc); - ste_poll_locked(ifp, cmd, count); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + ste_poll_locked(ifp, cmd, count); STE_UNLOCK(sc); } @@ -631,14 +632,6 @@ ste_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count) struct ste_softc *sc = ifp->if_softc; STE_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, STE_IMR, STE_INTRS); - return; - } sc->rxcycles = count; if (cmd == POLL_AND_CHECK_STATUS) @@ -685,15 +678,11 @@ ste_intr(xsc) ifp = sc->ste_ifp; #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) - goto done; - if ((ifp->if_capenable & IFCAP_POLLING) && - ether_poll_register(ste_poll, ifp)) { /* ok, disable interrupts */ - CSR_WRITE_2(sc, STE_IMR, 0); - ste_poll_locked(ifp, 0, 1); - goto done; + if (ifp->if_capenable & IFCAP_POLLING) { + STE_UNLOCK(sc); + return; } -#endif /* DEVICE_POLLING */ +#endif /* See if this is really our interrupt. */ if (!(CSR_READ_2(sc, STE_ISR) & STE_ISR_INTLATCH)) { @@ -739,9 +728,6 @@ ste_intr(xsc) if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) ste_start_locked(ifp); -#ifdef DEVICE_POLLING -done: -#endif /* DEVICE_POLLING */ STE_UNLOCK(sc); return; @@ -791,12 +777,12 @@ ste_rxeof(sc) while((rxstat = sc->ste_cdata.ste_rx_head->ste_ptr->ste_status) & STE_RXSTAT_DMADONE) { #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 if ((STE_RX_LIST_CNT - count) < 3) { break; } @@ -1115,10 +1101,10 @@ ste_attach(dev) */ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); ifp->if_capabilities |= IFCAP_VLAN_MTU; + ifp->if_capenable = ifp->if_capabilities; #ifdef DEVICE_POLLING ifp->if_capabilities |= IFCAP_POLLING; #endif - ifp->if_capenable = ifp->if_capabilities; /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->ste_irq, INTR_TYPE_NET | INTR_MPSAFE, @@ -1155,6 +1141,11 @@ ste_detach(dev) KASSERT(mtx_initialized(&sc->ste_mtx), ("ste mutex not initialized")); ifp = sc->ste_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)) { STE_LOCK(sc); @@ -1386,10 +1377,10 @@ ste_init_locked(sc) CSR_WRITE_2(sc, STE_ISR, 0xFFFF); #ifdef DEVICE_POLLING /* Disable interrupts if we are polling. */ - if (ifp->if_flags & IFF_POLLING) + if (ifp->if_capenable & IFCAP_POLLING) CSR_WRITE_2(sc, STE_IMR, 0); else -#endif /* DEVICE_POLLING */ +#endif /* Enable interrupts. */ CSR_WRITE_2(sc, STE_IMR, STE_INTRS); @@ -1418,9 +1409,6 @@ ste_stop(sc) callout_stop(&sc->ste_stat_callout); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE); -#ifdef DEVICE_POLLING - ether_poll_deregister(ifp); -#endif /* DEVICE_POLLING */ CSR_WRITE_2(sc, STE_IMR, 0); STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_TX_DISABLE); @@ -1539,10 +1527,31 @@ ste_ioctl(ifp, command, data) error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; case SIOCSIFCAP: - STE_LOCK(sc); - ifp->if_capenable &= ~IFCAP_POLLING; - ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING; - STE_UNLOCK(sc); +#ifdef DEVICE_POLLING + if (ifr->ifr_reqcap & IFCAP_POLLING && + !(ifp->if_capenable & IFCAP_POLLING)) { + error = ether_poll_register(ste_poll, ifp); + if (error) + return(error); + STE_LOCK(sc); + /* Disable interrupts */ + CSR_WRITE_2(sc, STE_IMR, 0); + ifp->if_capenable |= IFCAP_POLLING; + STE_UNLOCK(sc); + return (error); + + } + if (!(ifr->ifr_reqcap & IFCAP_POLLING) && + ifp->if_capenable & IFCAP_POLLING) { + error = ether_poll_deregister(ifp); + /* Enable interrupts. */ + STE_LOCK(sc); + CSR_WRITE_2(sc, STE_IMR, STE_INTRS); + ifp->if_capenable &= ~IFCAP_POLLING; + STE_UNLOCK(sc); + return (error); + } +#endif /* DEVICE_POLLING */ break; default: error = ether_ioctl(ifp, command, data); diff --git a/sys/pci/if_vr.c b/sys/pci/if_vr.c index 5eabc21..b3c92ea 100644 --- a/sys/pci/if_vr.c +++ b/sys/pci/if_vr.c @@ -742,10 +742,10 @@ vr_attach(dev) IFQ_SET_MAXLEN(&ifp->if_snd, VR_TX_LIST_CNT - 1); ifp->if_snd.ifq_maxlen = VR_TX_LIST_CNT - 1; IFQ_SET_READY(&ifp->if_snd); + ifp->if_capenable = ifp->if_capabilities; #ifdef DEVICE_POLLING ifp->if_capabilities |= IFCAP_POLLING; #endif - ifp->if_capenable = ifp->if_capabilities; /* Do MII setup. */ if (mii_phy_probe(dev, &sc->vr_miibus, @@ -794,6 +794,11 @@ vr_detach(device_t dev) KASSERT(mtx_initialized(&sc->vr_mtx), ("vr mutex not initialized")); +#ifdef DEVICE_POLLING + if (ifp->if_capenable & IFCAP_POLLING) + ether_poll_deregister(ifp); +#endif + VR_LOCK(sc); sc->suspended = 1; @@ -952,12 +957,12 @@ vr_rxeof(struct vr_softc *sc) while (!((rxstat = sc->vr_cdata.vr_rx_head->vr_ptr->vr_status) & VR_RXSTAT_OWN)) { #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 m0 = NULL; cur_rx = sc->vr_cdata.vr_rx_head; sc->vr_cdata.vr_rx_head = cur_rx->vr_nextdesc; @@ -1151,7 +1156,8 @@ vr_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) struct vr_softc *sc = ifp->if_softc; VR_LOCK(sc); - vr_poll_locked(ifp, cmd, count); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + vr_poll_locked(ifp, cmd, count); VR_UNLOCK(sc); } @@ -1162,17 +1168,6 @@ vr_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count) VR_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, VR_IMR, VR_INTRS); - return; - } - sc->rxcycles = count; vr_rxeof(sc); vr_txeof(sc); @@ -1249,17 +1244,9 @@ vr_intr(void *arg) } #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(vr_poll, ifp)) { - /* OK, disable interrupts. */ - CSR_WRITE_2(sc, VR_IMR, 0x0000); - vr_poll_locked(ifp, 0, 1); - goto done_locked; - } -#endif /* DEVICE_POLLING */ +#endif /* Suppress unwanted interrupts. */ if (!(ifp->if_flags & IFF_UP)) { @@ -1534,10 +1521,10 @@ vr_init_locked(struct vr_softc *sc) /* * Disable interrupts if we are polling. */ - if (ifp->if_flags & IFF_POLLING) + if (ifp->if_capenable & IFCAP_POLLING) CSR_WRITE_2(sc, VR_IMR, 0); else -#endif /* DEVICE_POLLING */ +#endif /* * Enable interrupts. */ @@ -1615,7 +1602,31 @@ vr_ioctl(struct ifnet *ifp, u_long command, caddr_t data) error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; case SIOCSIFCAP: - ifp->if_capenable = ifr->ifr_reqcap; +#ifdef DEVICE_POLLING + if (ifr->ifr_reqcap & IFCAP_POLLING && + !(ifp->if_capenable & IFCAP_POLLING)) { + error = ether_poll_register(vr_poll, ifp); + if (error) + return(error); + VR_LOCK(sc); + /* Disable interrupts */ + CSR_WRITE_2(sc, VR_IMR, 0x0000); + ifp->if_capenable |= IFCAP_POLLING; + VR_UNLOCK(sc); + return (error); + + } + if (!(ifr->ifr_reqcap & IFCAP_POLLING) && + ifp->if_capenable & IFCAP_POLLING) { + error = ether_poll_deregister(ifp); + /* Enable interrupts. */ + VR_LOCK(sc); + CSR_WRITE_2(sc, VR_IMR, VR_INTRS); + ifp->if_capenable &= ~IFCAP_POLLING; + VR_UNLOCK(sc); + return (error); + } +#endif /* DEVICE_POLLING */ break; default: error = ether_ioctl(ifp, command, data); @@ -1662,9 +1673,6 @@ vr_stop(struct vr_softc *sc) untimeout(vr_tick, sc, sc->vr_stat_ch); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); -#ifdef DEVICE_POLLING - ether_poll_deregister(ifp); -#endif /* DEVICE_POLLING */ VR_SETBIT16(sc, VR_COMMAND, VR_CMD_STOP); VR_CLRBIT16(sc, VR_COMMAND, (VR_CMD_RX_ON|VR_CMD_TX_ON)); diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c index 520f668..e49997a 100644 --- a/sys/pci/if_xl.c +++ b/sys/pci/if_xl.c @@ -249,7 +249,7 @@ static int xl_resume(device_t); #ifdef DEVICE_POLLING static void xl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count); static void xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count); -#endif /* DEVICE_POLLING */ +#endif static int xl_ifmedia_upd(struct ifnet *); static void xl_ifmedia_sts(struct ifnet *, struct ifmediareq *); @@ -1487,9 +1487,10 @@ xl_attach(device_t dev) ifp->if_capabilities |= IFCAP_HWCSUM; #endif } + ifp->if_capenable = ifp->if_capabilities; #ifdef DEVICE_POLLING ifp->if_capabilities |= IFCAP_POLLING; -#endif /* DEVICE_POLLING */ +#endif ifp->if_start = xl_start; ifp->if_watchdog = xl_watchdog; ifp->if_init = xl_init; @@ -1497,7 +1498,6 @@ xl_attach(device_t dev) IFQ_SET_MAXLEN(&ifp->if_snd, XL_TX_LIST_CNT - 1); ifp->if_snd.ifq_drv_maxlen = XL_TX_LIST_CNT - 1; IFQ_SET_READY(&ifp->if_snd); - ifp->if_capenable = ifp->if_capabilities; /* * Now we have to see what sort of media we have. @@ -1690,6 +1690,11 @@ xl_detach(device_t dev) KASSERT(mtx_initialized(&sc->xl_mtx), ("xl mutex not initialized")); +#ifdef DEVICE_POLLING + if (ifp->if_capenable & IFCAP_POLLING) + ether_poll_deregister(ifp); +#endif + if (sc->xl_flags & XL_FLAG_USE_MMIO) { rid = XL_PCI_LOMEM; res = SYS_RES_MEMORY; @@ -1960,12 +1965,12 @@ again: BUS_DMASYNC_POSTREAD); while ((rxstat = le32toh(sc->xl_cdata.xl_rx_head->xl_ptr->xl_status))) { #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->xl_cdata.xl_rx_head; sc->xl_cdata.xl_rx_head = cur_rx->xl_next; total_len = rxstat & XL_RXSTAT_LENMASK; @@ -2275,24 +2280,11 @@ xl_intr(void *arg) XL_LOCK(sc); #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) { + if (ifp->if_capenable & IFCAP_POLLING) { XL_UNLOCK(sc); return; } - - if ((ifp->if_capenable & IFCAP_POLLING) && - ether_poll_register(xl_poll, ifp)) { - /* Disable interrupts. */ - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|0xFF); - if (sc->xl_flags & XL_FLAG_FUNCREG) - bus_space_write_4(sc->xl_ftag, sc->xl_fhandle, - 4, 0x8000); - xl_poll_locked(ifp, 0, 1); - XL_UNLOCK(sc); - return; - } -#endif /* DEVICE_POLLING */ +#endif while ((status = CSR_READ_2(sc, XL_STATUS)) & XL_INTRS && status != 0xFFFF) { @@ -2351,7 +2343,8 @@ xl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) struct xl_softc *sc = ifp->if_softc; XL_LOCK(sc); - xl_poll_locked(ifp, cmd, count); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + xl_poll_locked(ifp, cmd, count); XL_UNLOCK(sc); } @@ -2362,21 +2355,6 @@ xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count) XL_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, XL_COMMAND, XL_CMD_INTR_ACK|0xFF); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS); - if (sc->xl_flags & XL_FLAG_FUNCREG) - bus_space_write_4(sc->xl_ftag, sc->xl_fhandle, - 4, 0x8000); - return; - } - sc->rxcycles = count; xl_rxeof(sc); if (sc->xl_type == XL_TYPE_905B) @@ -2989,10 +2967,10 @@ xl_init_locked(struct xl_softc *sc) CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STAT_ENB|XL_INTRS); #ifdef DEVICE_POLLING /* Disable interrupts if we are polling. */ - if (ifp->if_flags & IFF_POLLING) + if (ifp->if_capenable & IFCAP_POLLING) CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0); else -#endif /* DEVICE_POLLING */ +#endif CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS); if (sc->xl_flags & XL_FLAG_FUNCREG) bus_space_write_4(sc->xl_ftag, sc->xl_fhandle, 4, 0x8000); @@ -3204,6 +3182,35 @@ xl_ioctl(struct ifnet *ifp, u_long command, caddr_t data) &mii->mii_media, command); break; case SIOCSIFCAP: +#ifdef DEVICE_POLLING + if (ifr->ifr_reqcap & IFCAP_POLLING && + !(ifp->if_capenable & IFCAP_POLLING)) { + error = ether_poll_register(xl_poll, ifp); + if (error) + return(error); + XL_LOCK(sc); + /* Disable interrupts */ + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0); + ifp->if_capenable |= IFCAP_POLLING; + XL_UNLOCK(sc); + return (error); + + } + if (!(ifr->ifr_reqcap & IFCAP_POLLING) && + ifp->if_capenable & IFCAP_POLLING) { + error = ether_poll_deregister(ifp); + /* Enable interrupts. */ + XL_LOCK(sc); + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|0xFF); + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS); + if (sc->xl_flags & XL_FLAG_FUNCREG) + bus_space_write_4(sc->xl_ftag, sc->xl_fhandle, + 4, 0x8000); + ifp->if_capenable &= ~IFCAP_POLLING; + XL_UNLOCK(sc); + return (error); + } +#endif /* DEVICE_POLLING */ XL_LOCK(sc); ifp->if_capenable = ifr->ifr_reqcap; if (ifp->if_capenable & IFCAP_TXCSUM) @@ -3268,9 +3275,6 @@ xl_stop(struct xl_softc *sc) XL_LOCK_ASSERT(sc); ifp->if_timer = 0; -#ifdef DEVICE_POLLING - ether_poll_deregister(ifp); -#endif /* DEVICE_POLLING */ CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_DISABLE); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_DISABLE); |