[REVIEW/TEST] polling(4) changes
Gleb Smirnoff
glebius at FreeBSD.org
Fri Sep 30 09:03:06 PDT 2005
On Fri, Sep 30, 2005 at 04:40:00PM +0400, Gleb Smirnoff wrote:
T> [please, follow-up on net@ only]
T>
T> Colleagues,
T>
T> here are some patches for review.
I have some changes to patch after last compile, and haven't tested them
befire sending patch. Here is an updated one.
--
Totus tuus, Glebius.
GLEBIUS-RIPN GLEB-RIPE
-------------- next part --------------
Index: amd64/amd64/trap.c
===================================================================
RCS file: /home/ncvs/src/sys/amd64/amd64/trap.c,v
retrieving revision 1.293
diff -u -r1.293 trap.c
--- amd64/amd64/trap.c 28 Sep 2005 07:03:02 -0000 1.293
+++ amd64/amd64/trap.c 29 Sep 2005 09:41:32 -0000
@@ -146,11 +146,6 @@
extern char *syscallnames[];
#endif
-#ifdef DEVICE_POLLING
-extern u_int32_t poll_in_trap;
-extern int ether_poll(int count);
-#endif /* DEVICE_POLLING */
-
/*
* Exception, fault, and trap interface to the FreeBSD kernel.
* This common code is called from assembly language IDT gate entry
@@ -241,11 +236,6 @@
trap_fatal(&frame, frame.tf_addr);
}
-#ifdef DEVICE_POLLING
- if (poll_in_trap)
- ether_poll(poll_in_trap);
-#endif /* DEVICE_POLLING */
-
if (ISPL(frame.tf_cs) == SEL_UPL) {
/* user trap */
Index: dev/em/if_em.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/em/if_em.c,v
retrieving revision 1.73
diff -u -r1.73 if_em.c
--- dev/em/if_em.c 29 Sep 2005 13:23:34 -0000 1.73
+++ dev/em/if_em.c 30 Sep 2005 15:17:05 -0000
@@ -197,6 +197,9 @@
static void em_add_int_delay_sysctl(struct adapter *, const char *,
const char *, struct em_int_delay_info *,
int, int);
+#ifdef DEVICE_POLLING
+static poll_handler_t em_poll;
+#endif
/*********************************************************************
* FreeBSD Device Interface Entry Points
@@ -526,6 +529,11 @@
INIT_DEBUGOUT("em_detach: begin");
+#ifdef DEVICE_POLLING
+ if (ifp->if_capenable & IFCAP_POLLING)
+ ether_poll_deregister(ifp);
+#endif
+
EM_LOCK(adapter);
adapter->in_detach = 1;
em_stop(adapter);
@@ -717,7 +725,7 @@
em_initialize_receive_unit(adapter);
}
#ifdef DEVICE_POLLING
- if (!(ifp->if_flags & IFF_POLLING))
+ if (!(ifp->if_capenable & IFCAP_POLLING))
#endif
em_enable_intr(adapter);
EM_UNLOCK(adapter);
@@ -732,8 +740,26 @@
IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)");
reinit = 0;
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
- if (mask & IFCAP_POLLING)
- ifp->if_capenable ^= IFCAP_POLLING;
+#ifdef DEVICE_POLLING
+ if (mask & IFCAP_POLLING) {
+ if (ifr->ifr_reqcap & IFCAP_POLLING) {
+ error = ether_poll_register(em_poll, ifp);
+ if (error)
+ return(error);
+ EM_LOCK(adapter);
+ em_disable_intr(adapter);
+ ifp->if_capenable |= IFCAP_POLLING;
+ EM_UNLOCK(adapter);
+ } else {
+ error = ether_poll_deregister(ifp);
+ /* Enable interrupt even in error case */
+ EM_LOCK(adapter);
+ em_enable_intr(adapter);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ EM_UNLOCK(adapter);
+ }
+ }
+#endif
if (mask & IFCAP_HWCSUM) {
ifp->if_capenable ^= IFCAP_HWCSUM;
reinit = 1;
@@ -895,7 +921,7 @@
* Only enable interrupts if we are not polling, make sure
* they are off otherwise.
*/
- if (ifp->if_flags & IFF_POLLING)
+ if (ifp->if_capenable & IFCAP_POLLING)
em_disable_intr(adapter);
else
#endif /* DEVICE_POLLING */
@@ -920,8 +946,6 @@
#ifdef DEVICE_POLLING
-static poll_handler_t em_poll;
-
static void
em_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
@@ -930,14 +954,6 @@
mtx_assert(&adapter->mtx, MA_OWNED);
- if (!(ifp->if_capenable & IFCAP_POLLING)) {
- ether_poll_deregister(ifp);
- cmd = POLL_DEREGISTER;
- }
- if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */
- em_enable_intr(adapter);
- return;
- }
if (cmd == POLL_AND_CHECK_STATUS) {
reg_icr = E1000_READ_REG(&adapter->hw, ICR);
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
@@ -948,13 +964,10 @@
callout_reset(&adapter->timer, hz, em_local_timer, adapter);
}
}
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- em_process_receive_interrupts(adapter, count);
- em_clean_transmit_interrupts(adapter);
- }
+ em_process_receive_interrupts(adapter, count);
+ em_clean_transmit_interrupts(adapter);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
- !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
em_start_locked(ifp);
}
@@ -964,7 +977,8 @@
struct adapter *adapter = ifp->if_softc;
EM_LOCK(adapter);
- em_poll_locked(ifp, cmd, count);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ em_poll_locked(ifp, cmd, count);
EM_UNLOCK(adapter);
}
#endif /* DEVICE_POLLING */
@@ -987,18 +1001,10 @@
ifp = adapter->ifp;
#ifdef DEVICE_POLLING
- if (ifp->if_flags & IFF_POLLING) {
+ if (ifp->if_capenable & IFCAP_POLLING) {
EM_UNLOCK(adapter);
return;
}
-
- if ((ifp->if_capenable & IFCAP_POLLING) &&
- ether_poll_register(em_poll, ifp)) {
- em_disable_intr(adapter);
- em_poll_locked(ifp, 0, 1);
- EM_UNLOCK(adapter);
- return;
- }
#endif /* DEVICE_POLLING */
reg_icr = E1000_READ_REG(&adapter->hw, ICR);
@@ -1718,9 +1724,7 @@
mtx_assert(&adapter->mtx, MA_OWNED);
INIT_DEBUGOUT("em_stop: begin");
-#ifdef DEVICE_POLLING
- ether_poll_deregister(ifp);
-#endif
+
em_disable_intr(adapter);
em_reset_hw(&adapter->hw);
callout_stop(&adapter->timer);
@@ -1976,7 +1980,6 @@
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
- ifp->if_capenable |= IFCAP_POLLING;
#endif
/*
Index: dev/fxp/if_fxp.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/fxp/if_fxp.c,v
retrieving revision 1.247
diff -u -r1.247 if_fxp.c
--- dev/fxp/if_fxp.c 27 Sep 2005 09:01:10 -0000 1.247
+++ dev/fxp/if_fxp.c 30 Sep 2005 15:37:08 -0000
@@ -773,7 +773,6 @@
#ifdef DEVICE_POLLING
/* Inform the world we support polling. */
ifp->if_capabilities |= IFCAP_POLLING;
- ifp->if_capenable |= IFCAP_POLLING;
#endif
/*
@@ -891,6 +890,11 @@
{
struct fxp_softc *sc = device_get_softc(dev);
+#ifdef DEVICE_POLLING
+ if (sc->ifp->if_capenable & IFCAP_POLLING)
+ ether_poll_deregister(sc->ifp);
+#endif
+
FXP_LOCK(sc);
sc->suspended = 1; /* Do same thing as we do for suspend */
/*
@@ -1448,15 +1452,11 @@
uint8_t statack;
FXP_LOCK(sc);
- if (!(ifp->if_capenable & IFCAP_POLLING)) {
- ether_poll_deregister(ifp);
- cmd = POLL_DEREGISTER;
- }
- if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */
- CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, 0);
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
FXP_UNLOCK(sc);
return;
}
+
statack = FXP_SCB_STATACK_CXTNO | FXP_SCB_STATACK_CNA |
FXP_SCB_STATACK_FR;
if (cmd == POLL_AND_CHECK_STATUS) {
@@ -1495,18 +1495,10 @@
}
#ifdef DEVICE_POLLING
- if (ifp->if_flags & IFF_POLLING) {
+ if (ifp->if_capenable & IFCAP_POLLING) {
FXP_UNLOCK(sc);
return;
}
- if ((ifp->if_capenable & IFCAP_POLLING) &&
- ether_poll_register(fxp_poll, ifp)) {
- /* disable interrupts */
- CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE);
- FXP_UNLOCK(sc);
- fxp_poll(ifp, 0, 1);
- return;
- }
#endif
while ((statack = CSR_READ_1(sc, FXP_CSR_SCB_STATACK)) != 0) {
/*
@@ -1837,9 +1829,6 @@
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
ifp->if_timer = 0;
-#ifdef DEVICE_POLLING
- ether_poll_deregister(ifp);
-#endif
/*
* Cancel stats updater.
*/
@@ -2163,7 +2152,7 @@
* ... but only do that if we are not polling. And because (presumably)
* the default is interrupts on, we need to disable them explicitly!
*/
- if ( ifp->if_flags & IFF_POLLING )
+ if (ifp->if_capenable & IFCAP_POLLING )
CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE);
else
#endif /* DEVICE_POLLING */
@@ -2418,11 +2407,30 @@
break;
case SIOCSIFCAP:
- FXP_LOCK(sc);
mask = ifp->if_capenable ^ ifr->ifr_reqcap;
- if (mask & IFCAP_POLLING)
- ifp->if_capenable ^= IFCAP_POLLING;
+#ifdef DEVICE_POLLING
+ if (mask & IFCAP_POLLING) {
+ if (ifr->ifr_reqcap & IFCAP_POLLING) {
+ error = ether_poll_register(fxp_poll, ifp);
+ if (error)
+ return(error);
+ FXP_LOCK(sc);
+ CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL,
+ FXP_SCB_INTR_DISABLE);
+ ifp->if_capenable |= IFCAP_POLLING;
+ FXP_UNLOCK(sc);
+ } else {
+ error = ether_poll_deregister(ifp);
+ /* Enable interrupts in any case */
+ FXP_LOCK(sc);
+ CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, 0);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ FXP_UNLOCK(sc);
+ }
+ }
+#endif
if (mask & IFCAP_VLAN_MTU) {
+ FXP_LOCK(sc);
ifp->if_capenable ^= IFCAP_VLAN_MTU;
if (sc->revision != FXP_REV_82557)
flag = FXP_FLAG_LONG_PKT_EN;
@@ -2431,8 +2439,8 @@
sc->flags ^= flag;
if (ifp->if_flags & IFF_UP)
fxp_init_body(sc);
+ FXP_UNLOCK(sc);
}
- FXP_UNLOCK(sc);
break;
default:
Index: i386/i386/trap.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/trap.c,v
retrieving revision 1.280
diff -u -r1.280 trap.c
--- i386/i386/trap.c 28 Sep 2005 07:03:03 -0000 1.280
+++ i386/i386/trap.c 29 Sep 2005 09:42:21 -0000
@@ -160,11 +160,6 @@
extern char *syscallnames[];
#endif
-#ifdef DEVICE_POLLING
-extern u_int32_t poll_in_trap;
-extern int ether_poll(int count);
-#endif /* DEVICE_POLLING */
-
/*
* Exception, fault, and trap interface to the FreeBSD kernel.
* This common code is called from assembly language IDT gate entry
@@ -272,11 +267,6 @@
trap_fatal(&frame, eva);
}
-#ifdef DEVICE_POLLING
- if (poll_in_trap)
- ether_poll(poll_in_trap);
-#endif /* DEVICE_POLLING */
-
if ((ISPL(frame.tf_cs) == SEL_UPL) ||
((frame.tf_eflags & PSL_VM) &&
!(PCPU_GET(curpcb)->pcb_flags & PCB_VM86CALL))) {
Index: kern/kern_poll.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_poll.c,v
retrieving revision 1.22
diff -u -r1.22 kern_poll.c
--- kern/kern_poll.c 6 Sep 2005 11:09:18 -0000 1.22
+++ kern/kern_poll.c 30 Sep 2005 14:52:25 -0000
@@ -32,6 +32,7 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h> /* needed by net/if.h */
+#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
@@ -44,14 +45,15 @@
static void netisr_poll(void); /* the two netisr handlers */
static void netisr_pollmore(void);
+static int poll_switch(SYSCTL_HANDLER_ARGS);
void hardclock_device_poll(void); /* hook from hardclock */
-void ether_poll(int); /* polling while in trap */
+void ether_poll(int); /* polling in idle loop */
/*
* Polling support for [network] device drivers.
*
- * Drivers which support this feature try to register with the
+ * Drivers which support this feature can register with the
* polling code.
*
* If registration is successful, the driver must disable interrupts,
@@ -64,10 +66,6 @@
* POLL_AND_CHECK_STATUS: as above, plus check status registers or do
* other more expensive operations. This command is issued periodically
* but less frequently than POLL_ONLY.
- * POLL_DEREGISTER: deregister and return to interrupt mode.
- *
- * The first two commands are only issued if the interface is marked as
- * 'IFF_UP and IFF_DRV_RUNNING', the last one only if IFF_DRV_RUNNING is set.
*
* The count limit specifies how much work the handler can do during the
* call -- typically this is the number of packets to be received, or
@@ -75,11 +73,9 @@
* as the max time spent in the function grows roughly linearly with the
* count).
*
- * Deregistration can be requested by the driver itself (typically in the
- * *_stop() routine), or by the polling code, by invoking the handler.
- *
- * Polling can be globally enabled or disabled with the sysctl variable
- * kern.polling.enable (default is 0, disabled)
+ * Polling is enabled and disabled via setting IFCAP_POLLING flag on
+ * the interface. The driver ioctl handler should register interface
+ * with polling and disable interrupts, if registration was successful.
*
* A second variable controls the sharing of CPU between polling/kernel
* network processing, and other activities (typically userlevel tasks):
@@ -91,7 +87,7 @@
* The following constraints hold
*
* 1 <= poll_each_burst <= poll_burst <= poll_burst_max
- * 0 <= poll_in_trap <= poll_each_burst
+ * 0 <= poll_each_burst
* MIN_POLL_BURST_MAX <= poll_burst_max <= MAX_POLL_BURST_MAX
*/
@@ -117,10 +113,6 @@
SYSCTL_UINT(_kern_polling, OID_AUTO, idle_poll, CTLFLAG_RW,
&poll_in_idle_loop, 0, "Enable device polling in idle loop");
-u_int32_t poll_in_trap; /* used in trap.c */
-SYSCTL_UINT(_kern_polling, OID_AUTO, poll_in_trap, CTLFLAG_RW,
- &poll_in_trap, 0, "Poll burst size during a trap");
-
static u_int32_t user_frac = 50;
SYSCTL_UINT(_kern_polling, OID_AUTO, user_frac, CTLFLAG_RW,
&user_frac, 0, "Desired user fraction of cpu time");
@@ -149,9 +141,9 @@
SYSCTL_UINT(_kern_polling, OID_AUTO, handlers, CTLFLAG_RD,
&poll_handlers, 0, "Number of registered poll handlers");
-static int polling = 0; /* global polling enable */
-SYSCTL_UINT(_kern_polling, OID_AUTO, enable, CTLFLAG_RW,
- &polling, 0, "Polling enabled");
+static int polling = 0;
+SYSCTL_PROC(_kern_polling, OID_AUTO, enable, CTLTYPE_UINT | CTLFLAG_RW,
+ 0, sizeof(int), poll_switch, "I", "Switch polling for all interfaces");
static u_int32_t phase;
SYSCTL_UINT(_kern_polling, OID_AUTO, phase, CTLFLAG_RW,
@@ -174,23 +166,9 @@
struct pollrec {
poll_handler_t *handler;
struct ifnet *ifp;
- /*
- * Flags of polling record (protected by poll_mtx).
- * PRF_RUNNING means that the handler is now executing.
- * PRF_LEAVING means that the handler is now deregistering.
- */
-#define PRF_RUNNING 0x1
-#define PRF_LEAVING 0x2
- uint32_t flags;
};
static struct pollrec pr[POLL_LIST_LEN];
-
-#define PR_VALID(i) (pr[(i)].handler != NULL && \
- !(pr[(i)].flags & (PRF_RUNNING|PRF_LEAVING)) && \
- (pr[(i)].ifp->if_drv_flags & IFF_DRV_RUNNING) &&\
- (pr[(i)].ifp->if_flags & IFF_UP))
-
static struct mtx poll_mtx;
static void
@@ -258,30 +236,24 @@
}
/*
- * ether_poll is called from the idle loop or from the trap handler.
+ * ether_poll is called from the idle loop.
*/
void
ether_poll(int count)
{
int i;
+ NET_LOCK_GIANT();
mtx_lock(&poll_mtx);
if (count > poll_each_burst)
count = poll_each_burst;
- for (i = 0 ; i < poll_handlers ; i++) {
- if (PR_VALID(i)) {
- pr[i].flags |= PRF_RUNNING;
- mtx_unlock(&poll_mtx);
- NET_LOCK_GIANT();
- pr[i].handler(pr[i].ifp, POLL_ONLY, count);
- NET_UNLOCK_GIANT();
- mtx_lock(&poll_mtx);
- pr[i].flags &= ~PRF_RUNNING;
- }
- }
+ for (i = 0 ; i < poll_handlers ; i++)
+ pr[i].handler(pr[i].ifp, POLL_ONLY, count);
+
mtx_unlock(&poll_mtx);
+ NET_UNLOCK_GIANT();
}
/*
@@ -403,60 +375,29 @@
residual_burst : poll_each_burst;
residual_burst -= cycles;
- if (polling) {
- for (i = 0 ; i < poll_handlers ; i++) {
- if (PR_VALID(i)) {
- pr[i].flags |= PRF_RUNNING;
- mtx_unlock(&poll_mtx);
- pr[i].handler(pr[i].ifp, arg, cycles);
- mtx_lock(&poll_mtx);
- pr[i].flags &= ~PRF_RUNNING;
- }
- }
- } else { /* unregister */
- for (i = 0 ; i < poll_handlers ; i++) {
- if (pr[i].handler != NULL &&
- pr[i].ifp->if_drv_flags & IFF_DRV_RUNNING) {
- pr[i].ifp->if_flags &= ~IFF_POLLING;
- pr[i].flags |= PRF_LEAVING;
- mtx_unlock(&poll_mtx);
- pr[i].handler(pr[i].ifp, POLL_DEREGISTER, 1);
- mtx_lock(&poll_mtx);
- pr[i].flags &= ~PRF_LEAVING;
- }
- pr[i].handler = NULL;
- }
- residual_burst = 0;
- poll_handlers = 0;
- }
+ for (i = 0 ; i < poll_handlers ; i++)
+ pr[i].handler(pr[i].ifp, arg, cycles);
phase = 4;
mtx_unlock(&poll_mtx);
}
/*
- * Try to register routine for polling. Returns 1 if successful
- * (and polling should be enabled), 0 otherwise.
+ * Try to register routine for polling. Returns 0 if successful
+ * (and polling should be enabled), error code otherwise.
* A device is not supposed to register itself multiple times.
*
- * This is called from within the *_intr() functions, so we do not need
- * further ifnet locking.
+ * This is called from within the *_ioctl() functions.
*/
int
ether_poll_register(poll_handler_t *h, struct ifnet *ifp)
{
int i;
- NET_ASSERT_GIANT();
+ KASSERT(h != NULL, ("%s: handler is NULL", __func__));
+ KASSERT(ifp != NULL, ("%s: ifp is NULL", __func__));
- if (polling == 0) /* polling disabled, cannot register */
- return 0;
- if (h == NULL || ifp == NULL) /* bad arguments */
- return 0;
- if ( !(ifp->if_flags & IFF_UP) ) /* must be up */
- return 0;
- if (ifp->if_flags & IFF_POLLING) /* already polling */
- return 0;
+ NET_ASSERT_GIANT();
mtx_lock(&poll_mtx);
if (poll_handlers >= POLL_LIST_LEN) {
@@ -474,7 +415,7 @@
verbose--;
}
mtx_unlock(&poll_mtx);
- return 0; /* no polling for you */
+ return (ENOMEM); /* no polling for you */
}
for (i = 0 ; i < poll_handlers ; i++)
@@ -482,45 +423,39 @@
mtx_unlock(&poll_mtx);
log(LOG_DEBUG, "ether_poll_register: %s: handler"
" already registered\n", ifp->if_xname);
- return (0);
+ return (EEXIST);
}
pr[poll_handlers].handler = h;
pr[poll_handlers].ifp = ifp;
poll_handlers++;
- ifp->if_flags |= IFF_POLLING;
mtx_unlock(&poll_mtx);
if (idlepoll_sleeping)
wakeup(&idlepoll_sleeping);
- return 1; /* polling enabled in next call */
+ return (0);
}
/*
- * Remove interface from the polling list. Normally called by *_stop().
- * It is not an error to call it with IFF_POLLING clear, the call is
- * sufficiently rare to be preferable to save the space for the extra
- * test in each driver in exchange of one additional function call.
+ * Remove interface from the polling list. Called from *_ioctl(), too.
*/
int
ether_poll_deregister(struct ifnet *ifp)
{
int i;
- NET_ASSERT_GIANT();
+ KASSERT(ifp != NULL, ("%s: ifp is NULL", __func__));
- if ( !ifp || !(ifp->if_flags & IFF_POLLING) ) {
- return 0;
- }
+ NET_ASSERT_GIANT();
mtx_lock(&poll_mtx);
+
for (i = 0 ; i < poll_handlers ; i++)
if (pr[i].ifp == ifp) /* found it */
break;
- ifp->if_flags &= ~IFF_POLLING; /* found or not... */
if (i == poll_handlers) {
- mtx_unlock(&poll_mtx);
log(LOG_DEBUG, "ether_poll_deregister: %s: not found!\n",
ifp->if_xname);
- return (0);
+ mtx_unlock(&poll_mtx);
+ return (ENOENT);
}
poll_handlers--;
if (i < poll_handlers) { /* Last entry replaces this one. */
@@ -528,7 +463,60 @@
pr[i].ifp = pr[poll_handlers].ifp;
}
mtx_unlock(&poll_mtx);
- return (1);
+ return (0);
+}
+
+/*
+ * Legacy interface for turning polling on all interfaces at one time.
+ */
+static int
+poll_switch(SYSCTL_HANDLER_ARGS)
+{
+ struct ifnet *ifp;
+ int error;
+ int val;
+
+ mtx_lock(&poll_mtx);
+ val = polling;
+ mtx_unlock(&poll_mtx);
+
+ error = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (error || !req->newptr )
+ return (error);
+
+ if (val == polling)
+ return (0);
+
+ if (val < 0 || val > 1)
+ return (EINVAL);
+
+ mtx_lock(&poll_mtx);
+ polling = val;
+ mtx_unlock(&poll_mtx);
+
+ NET_LOCK_GIANT();
+ IFNET_RLOCK();
+ TAILQ_FOREACH(ifp, &ifnet, if_link) {
+ if (ifp->if_capabilities & IFCAP_POLLING) {
+ struct ifreq ifr;
+
+ if (val == 1)
+ ifr.ifr_reqcap =
+ ifp->if_capenable | IFCAP_POLLING;
+ else
+ ifr.ifr_reqcap =
+ ifp->if_capenable & ~IFCAP_POLLING;
+ IFF_LOCKGIANT(ifp); /* LOR here */
+ (void) (*ifp->if_ioctl)(ifp, SIOCSIFCAP, (caddr_t)&ifr);
+ IFF_UNLOCKGIANT(ifp);
+ }
+ }
+ IFNET_RUNLOCK();
+ NET_UNLOCK_GIANT();
+
+ log(LOG_ERR, "kern.polling.enable is deprecated. Use ifconfig(8)");
+
+ return (0);
}
static void
Index: net/if.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if.h,v
retrieving revision 1.98
diff -u -r1.98 if.h
--- net/if.h 9 Aug 2005 12:56:20 -0000 1.98
+++ net/if.h 29 Sep 2005 11:25:05 -0000
@@ -148,7 +148,7 @@
#define IFF_LINK2 0x4000 /* per link layer defined bit */
#define IFF_ALTPHYS IFF_LINK2 /* use alternate physical connection */
#define IFF_MULTICAST 0x8000 /* (i) supports multicast */
-#define IFF_POLLING 0x10000 /* (n) Interface is in polling mode. */
+/* 0x10000 */
#define IFF_PPROMISC 0x20000 /* (n) user-requested promisc mode */
#define IFF_MONITOR 0x40000 /* (n) user-requested monitor mode */
#define IFF_STATICARP 0x80000 /* (n) static ARP */
@@ -166,8 +166,7 @@
/* flags set internally only: */
#define IFF_CANTCHANGE \
(IFF_BROADCAST|IFF_POINTOPOINT|IFF_DRV_RUNNING|IFF_DRV_OACTIVE|\
- IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI|IFF_SMART|IFF_PROMISC|\
- IFF_POLLING)
+ IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI|IFF_SMART|IFF_PROMISC)
/*
* Values for if_link_state.
Index: net/if_var.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if_var.h,v
retrieving revision 1.102
diff -u -r1.102 if_var.h
--- net/if_var.h 9 Aug 2005 10:16:17 -0000 1.102
+++ net/if_var.h 29 Sep 2005 10:19:43 -0000
@@ -660,7 +660,7 @@
LLADDR((struct sockaddr_dl *) ifaddr_byindex((ifp)->if_index)->ifa_addr)
#ifdef DEVICE_POLLING
-enum poll_cmd { POLL_ONLY, POLL_AND_CHECK_STATUS, POLL_DEREGISTER };
+enum poll_cmd { POLL_ONLY, POLL_AND_CHECK_STATUS };
typedef void poll_handler_t(struct ifnet *ifp, enum poll_cmd cmd, int count);
int ether_poll_register(poll_handler_t *h, struct ifnet *ifp);
More information about the freebsd-net
mailing list