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/firewire/if_fwe.c | |
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/firewire/if_fwe.c')
-rw-r--r-- | sys/dev/firewire/if_fwe.c | 69 |
1 files changed, 40 insertions, 29 deletions
diff --git a/sys/dev/firewire/if_fwe.c b/sys/dev/firewire/if_fwe.c index e9d9107..1bf1bcd 100644 --- a/sys/dev/firewire/if_fwe.c +++ b/sys/dev/firewire/if_fwe.c @@ -100,19 +100,6 @@ TUNABLE_INT("hw.firewire.fwe.tx_speed", &tx_speed); TUNABLE_INT("hw.firewire.fwe.rx_queue_len", &rx_queue_len); #ifdef DEVICE_POLLING -#define FWE_POLL_REGISTER(func, fwe, ifp) \ - if (ether_poll_register(func, ifp)) { \ - struct firewire_comm *fc = (fwe)->fd.fc; \ - fc->set_intr(fc, 0); \ - } - -#define FWE_POLL_DEREGISTER(fwe, ifp) \ - do { \ - struct firewire_comm *fc = (fwe)->fd.fc; \ - ether_poll_deregister(ifp); \ - fc->set_intr(fc, 1); \ - } while(0) \ - static poll_handler_t fwe_poll; static void @@ -121,19 +108,15 @@ fwe_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) struct fwe_softc *fwe; struct firewire_comm *fc; + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) + return; + fwe = ((struct fwe_eth_softc *)ifp->if_softc)->fwe; fc = fwe->fd.fc; - if (cmd == POLL_DEREGISTER) { - /* enable interrupts */ - fc->set_intr(fc, 1); - return; - } fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count); } -#else -#define FWE_POLL_REGISTER(func, fwe, ifp) -#define FWE_POLL_DEREGISTER(fwe, ifp) -#endif +#endif /* DEVICE_POLLING */ + static void fwe_identify(driver_t *driver, device_t parent) { @@ -242,7 +225,7 @@ fwe_attach(device_t dev) /* Tell the upper layer(s) we support long frames. */ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - ifp->if_capabilities |= IFCAP_VLAN_MTU; + ifp->if_capabilities |= IFCAP_VLAN_MTU & IFCAP_POLLING; ifp->if_capenable |= IFCAP_VLAN_MTU; #endif @@ -262,8 +245,6 @@ fwe_stop(struct fwe_softc *fwe) fc = fwe->fd.fc; - FWE_POLL_DEREGISTER(fwe, ifp); - if (fwe->dma_ch >= 0) { xferq = fc->ir[fwe->dma_ch]; @@ -305,6 +286,11 @@ fwe_detach(device_t dev) fwe = device_get_softc(dev); ifp = fwe->eth_softc.ifp; + +#ifdef DEVICE_POLLING + if (ifp->if_capenable & IFCAP_POLLING) + ether_poll_deregister(ifp); +#endif s = splimp(); fwe_stop(fwe); @@ -416,7 +402,6 @@ found: ifp->if_flags &= ~IFF_OACTIVE; #endif - FWE_POLL_REGISTER(fwe_poll, fwe, ifp); #if 0 /* attempt to start output */ fwe_start(ifp); @@ -468,6 +453,34 @@ fwe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) fwe->stream_ch, fwe->dma_ch); splx(s); break; + case SIOCSIFCAP: +#ifdef DEVICE_POLLING + { + struct ifreq *ifr = (struct ifreq *) data; + struct firewire_comm *fc = fc = fwe->fd.fc; + + if (ifr->ifr_reqcap & IFCAP_POLLING && + !(ifp->if_capenable & IFCAP_POLLING)) { + error = ether_poll_register(fwe_poll, ifp); + if (error) + return(error); + /* Disable interrupts */ + fc->set_intr(fc, 0); + ifp->if_capenable |= IFCAP_POLLING; + return (error); + + } + if (!(ifr->ifr_reqcap & IFCAP_POLLING) && + ifp->if_capenable & IFCAP_POLLING) { + error = ether_poll_deregister(ifp); + /* Enable interrupts. */ + fc->set_intr(fc, 1); + ifp->if_capenable &= ~IFCAP_POLLING; + return (error); + } + } +#endif /* DEVICE_POLLING */ + break; #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 default: #else @@ -634,9 +647,7 @@ fwe_as_input(struct fw_xferq *xferq) fwe = (struct fwe_softc *)xferq->sc; ifp = fwe->eth_softc.ifp; -#if 0 - FWE_POLL_REGISTER(fwe_poll, fwe, ifp); -#endif + while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) { STAILQ_REMOVE_HEAD(&xferq->stvalid, link); fp = mtod(sxfer->mbuf, struct fw_pkt *); |