summaryrefslogtreecommitdiffstats
path: root/sys/dev/ixgb
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2005-10-01 18:56:19 +0000
committerglebius <glebius@FreeBSD.org>2005-10-01 18:56:19 +0000
commitf41a83bf429b15386f43f43f3f5326d4ece7bfce (patch)
treeb78f9e953b7b58b2789d042cf37cc725045fdcf1 /sys/dev/ixgb
parent6c6c328bd0bbb1d9f6b3230a33d194bf961b0eae (diff)
downloadFreeBSD-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/README15
-rw-r--r--sys/dev/ixgb/if_ixgb.c77
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
OpenPOWER on IntegriCloud