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/ixgb | |
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/ixgb')
-rw-r--r-- | sys/dev/ixgb/README | 15 | ||||
-rw-r--r-- | sys/dev/ixgb/if_ixgb.c | 77 |
2 files changed, 50 insertions, 42 deletions
diff --git a/sys/dev/ixgb/README b/sys/dev/ixgb/README index 33f85a7..1508eac 100644 --- a/sys/dev/ixgb/README +++ b/sys/dev/ixgb/README @@ -196,18 +196,17 @@ all PRO/10GbE adapters. options DEVICE_POLLING options HZ=1000 - At runtime, use the following command to turn on polling mode. Similarly, - turn off polling mode by setting the variable to 0: + At runtime, use the following command to turn on polling mode. - sysctl kern.polling.enable=1 + ifconfig ixgb0 polling + Similarly, turn off polling mode by removing IFCAP_POLLING flag from + interface: - NOTES: DEVICE POLLING is only valid for non-SMP kernels. - - The driver has to be built into the kernel for DEVICE POLLING to be - enabled in the driver. - + ifconfig ixgb0 -polling + The driver has to be built into the kernel for DEVICE POLLING to be + enabled in the driver. Support ======= diff --git a/sys/dev/ixgb/if_ixgb.c b/sys/dev/ixgb/if_ixgb.c index 4cb9caa..d273542 100644 --- a/sys/dev/ixgb/if_ixgb.c +++ b/sys/dev/ixgb/if_ixgb.c @@ -141,6 +141,9 @@ static int ixgb_dma_malloc(struct adapter *, bus_size_t, struct ixgb_dma_alloc *, int); static void ixgb_dma_free(struct adapter *, struct ixgb_dma_alloc *); +#ifdef DEVICE_POLLING +static poll_handler_t ixgb_poll; +#endif /********************************************************************* * FreeBSD Device Interface Entry Points @@ -368,6 +371,11 @@ ixgb_detach(device_t dev) INIT_DEBUGOUT("ixgb_detach: begin"); +#ifdef DEVICE_POLLING + if (ifp->if_capenable & IFCAP_POLLING) + ether_poll_deregister(ifp); +#endif + IXGB_LOCK(adapter); adapter->in_detach = 1; @@ -557,6 +565,26 @@ ixgb_ioctl(struct ifnet * ifp, IOCTL_CMD_TYPE command, caddr_t data) case SIOCSIFCAP: IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)"); mask = ifr->ifr_reqcap ^ ifp->if_capenable; +#ifdef DEVICE_POLLING + if (mask & IFCAP_POLLING) { + if (ifr->ifr_reqcap & IFCAP_POLLING) { + error = ether_poll_register(ixgb_poll, ifp); + if (error) + return(error); + IXGB_LOCK(adapter); + ixgb_disable_intr(adapter); + ifp->if_capenable |= IFCAP_POLLING; + IXGB_UNLOCK(adapter); + } else { + error = ether_poll_deregister(ifp); + /* Enable interrupt even in error case */ + IXGB_LOCK(adapter); + ixgb_enable_intr(adapter); + ifp->if_capenable &= ~IFCAP_POLLING; + IXGB_UNLOCK(adapter); + } + } +#endif /* DEVICE_POLLING */ if (mask & IFCAP_HWCSUM) { if (IFCAP_HWCSUM & ifp->if_capenable) ifp->if_capenable &= ~IFCAP_HWCSUM; @@ -695,10 +723,10 @@ ixgb_init_locked(struct adapter *adapter) * Only disable interrupts if we are polling, make sure they are on * otherwise. */ - if (ifp->if_flags & IFF_POLLING) + if (ifp->if_capenable & IFCAP_POLLING) ixgb_disable_intr(adapter); else -#endif /* DEVICE_POLLING */ +#endif ixgb_enable_intr(adapter); return; @@ -716,8 +744,6 @@ ixgb_init(void *arg) } #ifdef DEVICE_POLLING -static poll_handler_t ixgb_poll; - static void ixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count) { @@ -726,15 +752,6 @@ ixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count) IXGB_LOCK_ASSERT(adapter); - if (!(ifp->if_capenable & IFCAP_POLLING)) { - ether_poll_deregister(ifp); - cmd = POLL_DEREGISTER; - } - - if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */ - ixgb_enable_intr(adapter); - return; - } if (cmd == POLL_AND_CHECK_STATUS) { reg_icr = IXGB_READ_REG(&adapter->hw, ICR); if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) { @@ -745,12 +762,10 @@ ixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count) adapter); } } - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - ixgb_process_receive_interrupts(adapter, count); - ixgb_clean_transmit_interrupts(adapter); - } - if (ifp->if_drv_flags & IFF_DRV_RUNNING && - ifp->if_snd.ifq_head != NULL) + ixgb_process_receive_interrupts(adapter, count); + ixgb_clean_transmit_interrupts(adapter); + + if (ifp->if_snd.ifq_head != NULL) ixgb_start_locked(ifp); } @@ -760,10 +775,11 @@ ixgb_poll(struct ifnet * ifp, enum poll_cmd cmd, int count) struct adapter *adapter = ifp->if_softc; IXGB_LOCK(adapter); - ixgb_poll_locked(ifp, cmd, count); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + ixgb_poll_locked(ifp, cmd, count); IXGB_UNLOCK(adapter); } -#endif /* DEVICE_POLLING */ +#endif /* DEVICE_POLLING */ /********************************************************************* * @@ -785,19 +801,11 @@ ixgb_intr(void *arg) ifp = adapter->ifp; #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) { - IXGB_UNLOCK(adapter); - return; - } - - if ((ifp->if_capenable & IFCAP_POLLING) && - ether_poll_register(ixgb_poll, ifp)) { - ixgb_disable_intr(adapter); - ixgb_poll_locked(ifp, 0, 1); + if (ifp->if_capenable & IFCAP_POLLING) { IXGB_UNLOCK(adapter); return; } -#endif /* DEVICE_POLLING */ +#endif reg_icr = IXGB_READ_REG(&adapter->hw, ICR); if (reg_icr == 0) { @@ -1355,9 +1363,6 @@ ixgb_setup_interface(device_t dev, struct adapter * adapter) #endif ifp->if_capabilities = IFCAP_HWCSUM; -#ifdef DEVICE_POLLING - ifp->if_capabilities |= IFCAP_POLLING; -#endif /* * Tell the upper layer(s) we support long frames. @@ -1370,6 +1375,10 @@ ixgb_setup_interface(device_t dev, struct adapter * adapter) ifp->if_capenable = ifp->if_capabilities; +#ifdef DEVICE_POLLING + ifp->if_capabilities |= IFCAP_POLLING; +#endif + /* * Specify the media types supported by this adapter and register * callbacks to update media and link information |