summaryrefslogtreecommitdiffstats
path: root/sys/dev/vge
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/vge
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/vge')
-rw-r--r--sys/dev/vge/if_vge.c105
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);
OpenPOWER on IntegriCloud