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/dev/vge | |
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/dev/vge')
-rw-r--r-- | sys/dev/vge/if_vge.c | 105 |
1 files changed, 51 insertions, 54 deletions
diff --git a/sys/dev/vge/if_vge.c b/sys/dev/vge/if_vge.c index 0780bc5..9101945 100644 --- a/sys/dev/vge/if_vge.c +++ b/sys/dev/vge/if_vge.c @@ -1051,16 +1051,14 @@ vge_attach(dev) ifp->if_start = vge_start; ifp->if_hwassist = VGE_CSUM_FEATURES; ifp->if_capabilities |= IFCAP_HWCSUM|IFCAP_VLAN_HWTAGGING; + ifp->if_capenable = ifp->if_capabilities; #ifdef DEVICE_POLLING -#ifdef IFCAP_POLLING ifp->if_capabilities |= IFCAP_POLLING; #endif -#endif ifp->if_watchdog = vge_watchdog; ifp->if_init = vge_init; ifp->if_baudrate = 1000000000; ifp->if_snd.ifq_maxlen = VGE_IFQ_MAXLEN; - ifp->if_capenable = ifp->if_capabilities; TASK_INIT(&sc->vge_txtask, 0, vge_tx_task, ifp); @@ -1105,6 +1103,11 @@ vge_detach(dev) KASSERT(mtx_initialized(&sc->vge_mtx), ("vge mutex not initialized")); ifp = sc->vge_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)) { vge_stop(sc); @@ -1351,12 +1354,12 @@ vge_rxeof(sc) while (!VGE_OWN(&sc->vge_ldata.vge_rx_list[i])) { #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->vge_ldata.vge_rx_list[i]; m = sc->vge_ldata.vge_rx_mbuf[i]; @@ -1617,18 +1620,8 @@ vge_poll (struct ifnet *ifp, enum poll_cmd cmd, int count) struct vge_softc *sc = ifp->if_softc; VGE_LOCK(sc); -#ifdef IFCAP_POLLING - if (!(ifp->if_capenable & IFCAP_POLLING)) { - ether_poll_deregister(ifp); - cmd = POLL_DEREGISTER; - } -#endif - if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */ - CSR_WRITE_4(sc, VGE_IMR, VGE_INTRS); - CSR_WRITE_4(sc, VGE_ISR, 0xFFFFFFFF); - CSR_WRITE_1(sc, VGE_CRS3, VGE_CR3_INT_GMSK); + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) goto done; - } sc->rxcycles = count; vge_rxeof(sc); @@ -1692,20 +1685,11 @@ vge_intr(arg) } #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) - goto done; - if ( -#ifdef IFCAP_POLLING - (ifp->if_capenable & IFCAP_POLLING) && -#endif - ether_poll_register(vge_poll, ifp)) { /* ok, disable interrupts */ - CSR_WRITE_4(sc, VGE_IMR, 0); - CSR_WRITE_1(sc, VGE_CRC3, VGE_CR3_INT_GMSK); - vge_poll(ifp, 0, 1); - goto done; + if (ifp->if_capenable & IFCAP_POLLING) { + VGE_UNLOCK(sc); + return; } - -#endif /* DEVICE_POLLING */ +#endif /* Disable interrupts */ CSR_WRITE_1(sc, VGE_CRC3, VGE_CR3_INT_GMSK); @@ -1745,9 +1729,6 @@ vge_intr(arg) /* Re-enable interrupts */ CSR_WRITE_1(sc, VGE_CRS3, VGE_CR3_INT_GMSK); -#ifdef DEVICE_POLLING -done: -#endif VGE_UNLOCK(sc); #if __FreeBSD_version < 502114 @@ -2104,11 +2085,11 @@ vge_init(xsc) /* * Disable interrupts if we are polling. */ - if (ifp->if_flags & IFF_POLLING) { + if (ifp->if_capenable & IFCAP_POLLING) { CSR_WRITE_4(sc, VGE_IMR, 0); CSR_WRITE_1(sc, VGE_CRC3, VGE_CR3_INT_GMSK); } else /* otherwise ... */ -#endif /* DEVICE_POLLING */ +#endif { /* * Enable interrupts. @@ -2268,23 +2249,42 @@ vge_ioctl(ifp, command, data) error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; case SIOCSIFCAP: -#ifdef IFCAP_POLLING - ifp->if_capenable &= ~(IFCAP_HWCSUM | IFCAP_POLLING); -#else - ifp->if_capenable &= ~(IFCAP_HWCSUM); -#endif - ifp->if_capenable |= -#ifdef IFCAP_POLLING - ifr->ifr_reqcap & (IFCAP_HWCSUM | IFCAP_POLLING); -#else - ifr->ifr_reqcap & (IFCAP_HWCSUM); -#endif - if (ifp->if_capenable & IFCAP_TXCSUM) - ifp->if_hwassist = VGE_CSUM_FEATURES; - else - ifp->if_hwassist = 0; - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - vge_init(sc); + { + 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(vge_poll, ifp); + if (error) + return(error); + VGE_LOCK(sc); + /* Disable interrupts */ + CSR_WRITE_4(sc, VGE_IMR, 0); + CSR_WRITE_1(sc, VGE_CRC3, VGE_CR3_INT_GMSK); + ifp->if_capenable |= IFCAP_POLLING; + VGE_UNLOCK(sc); + } else { + error = ether_poll_deregister(ifp); + /* Enable interrupts. */ + VGE_LOCK(sc); + CSR_WRITE_4(sc, VGE_IMR, VGE_INTRS); + CSR_WRITE_4(sc, VGE_ISR, 0xFFFFFFFF); + CSR_WRITE_1(sc, VGE_CRS3, VGE_CR3_INT_GMSK); + ifp->if_capenable &= ~IFCAP_POLLING; + VGE_UNLOCK(sc); + } + } +#endif /* DEVICE_POLLING */ + if (mask & IFCAP_HWCSUM) { + ifp->if_capenable |= ifr->ifr_reqcap & (IFCAP_HWCSUM); + if (ifp->if_capenable & IFCAP_TXCSUM) + ifp->if_hwassist = VGE_CSUM_FEATURES; + else + ifp->if_hwassist = 0; + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + vge_init(sc); + } + } break; default: error = ether_ioctl(ifp, command, data); @@ -2331,9 +2331,6 @@ vge_stop(sc) ifp->if_timer = 0; ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); -#ifdef DEVICE_POLLING - ether_poll_deregister(ifp); -#endif /* DEVICE_POLLING */ CSR_WRITE_1(sc, VGE_CRC3, VGE_CR3_INT_GMSK); CSR_WRITE_1(sc, VGE_CRS0, VGE_CR0_STOP); |