Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Polling for devices other than NICs [patch]

4 views
Skip to first unread message

Nate Nielsen

unread,
Jan 5, 2006, 9:12:40 PM1/5/06
to
This is a multi-part message in MIME format.
--------------070408040903010200010209
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

I've recently been optimizing the hifn driver for low performance
systems like the Soekris. I've implemented polling (rather than using
interrupts for everything) in the driver, which speeds things up
considerably.

The polling functionality in FreeBSD is currently a bit NIC centric.
With a few changes other types devices can use the polling subsystem.
Attached is my first whack at this.

This is some of my first hacking on the FreeBSD kernel. It'd be great if
there was someone who could take a look and help me get it right.

Cheers,
Nate

Note: The patch applies to RELENG_6_0. When necessary I can prepare a
patch against HEAD.


--------------070408040903010200010209
Content-Type: text/x-patch;
name="device-polling.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="device-polling.patch"

? device-polling.patch
Index: dev/em/if_em.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/em/if_em.c,v
retrieving revision 1.65.2.5.2.1
diff -p -U5 -r1.65.2.5.2.1 if_em.c
--- dev/em/if_em.c 22 Oct 2005 22:07:20 -0000 1.65.2.5.2.1
+++ dev/em/if_em.c 6 Jan 2006 01:37:28 -0000
@@ -716,19 +716,19 @@ em_ioctl(struct ifnet *ifp, u_long comma
reinit = 0;
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
#ifdef DEVICE_POLLING
if (mask & IFCAP_POLLING) {
if (ifr->ifr_reqcap & IFCAP_POLLING) {
- error = ether_poll_register(em_poll, ifp);
+ error = device_poll_register(em_poll, ifp, ifp->if_xname);
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);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupt even in error case */
EM_LOCK(adapter);
em_enable_intr(adapter);
ifp->if_capenable &= ~IFCAP_POLLING;
EM_UNLOCK(adapter);
@@ -946,12 +946,13 @@ em_poll_locked(struct ifnet *ifp, enum p
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
em_start_locked(ifp);
}

static void
-em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+em_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct adapter *adapter = ifp->if_softc;

EM_LOCK(adapter);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
em_poll_locked(ifp, cmd, count);
Index: dev/firewire/if_fwe.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/firewire/if_fwe.c,v
retrieving revision 1.37.2.2
diff -p -U5 -r1.37.2.2 if_fwe.c
--- dev/firewire/if_fwe.c 7 Oct 2005 14:00:03 -0000 1.37.2.2
+++ dev/firewire/if_fwe.c 6 Jan 2006 01:37:28 -0000
@@ -104,12 +104,13 @@ TUNABLE_INT("hw.firewire.fwe.rx_queue_le

#ifdef DEVICE_POLLING
static poll_handler_t fwe_poll;

static void
-fwe_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+fwe_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct fwe_softc *fwe;
struct firewire_comm *fc;

if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
return;
@@ -290,11 +291,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);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif
s = splimp();

fwe_stop(fwe);
#if defined(__DragonFly__) || __FreeBSD_version < 500000
@@ -462,22 +463,22 @@ fwe_ioctl(struct ifnet *ifp, u_long cmd,
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);
+ error = device_poll_register(fwe_poll, ifp, ifp->if_xname);
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);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
fc->set_intr(fc, 1);
ifp->if_capenable &= ~IFCAP_POLLING;
return (error);
}
Index: dev/firewire/if_fwip.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/firewire/if_fwip.c,v
retrieving revision 1.7.2.3
diff -p -U5 -r1.7.2.3 if_fwip.c
--- dev/firewire/if_fwip.c 7 Oct 2005 14:00:03 -0000 1.7.2.3
+++ dev/firewire/if_fwip.c 6 Jan 2006 01:37:28 -0000
@@ -111,12 +111,13 @@ TUNABLE_INT("hw.firewire.fwip.rx_queue_l

#ifdef DEVICE_POLLING
static poll_handler_t fwip_poll;

static void
-fwip_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+fwip_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct fwip_softc *fwip;
struct firewire_comm *fc;

if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
return;
@@ -272,11 +273,11 @@ fwip_detach(device_t dev)
fwip = (struct fwip_softc *)device_get_softc(dev);
ifp = fwip->fw_softc.fwip_ifp;

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

s = splimp();

fwip_stop(fwip);
@@ -444,22 +445,22 @@ fwip_ioctl(struct ifnet *ifp, u_long cmd
struct ifreq *ifr = (struct ifreq *) data;
struct firewire_comm *fc = fc = fwip->fd.fc;

if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(fwip_poll, ifp);
+ error = device_poll_register(fwip_poll, ifp, ifp->if_xname);
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);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
fc->set_intr(fc, 1);
ifp->if_capenable &= ~IFCAP_POLLING;
return (error);
}
Index: dev/fxp/if_fxp.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/fxp/if_fxp.c,v
retrieving revision 1.240.2.5
diff -p -U5 -r1.240.2.5 if_fxp.c
--- dev/fxp/if_fxp.c 7 Oct 2005 14:00:03 -0000 1.240.2.5
+++ dev/fxp/if_fxp.c 6 Jan 2006 01:37:29 -0000
@@ -45,10 +45,11 @@ __FBSDID("$FreeBSD: src/sys/dev/fxp/if_f
/* #include <sys/mutex.h> */
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
+#include <sys/bus.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>

@@ -896,11 +897,11 @@ fxp_detach(device_t dev)
{
struct fxp_softc *sc = device_get_softc(dev);

#ifdef DEVICE_POLLING
if (sc->ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(sc->ifp);
+ device_poll_deregister(sc->ifp, sc->ifp->if_xname);
#endif

FXP_LOCK(sc);
sc->suspended = 1; /* Do same thing as we do for suspend */
/*
@@ -1450,12 +1451,13 @@ fxp_encap(struct fxp_softc *sc, struct m

#ifdef DEVICE_POLLING
static poll_handler_t fxp_poll;

static void
-fxp_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+fxp_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct fxp_softc *sc = ifp->if_softc;
uint8_t statack;

FXP_LOCK(sc);
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
@@ -2415,20 +2417,20 @@ fxp_ioctl(struct ifnet *ifp, u_long comm
case SIOCSIFCAP:
mask = ifp->if_capenable ^ ifr->ifr_reqcap;
#ifdef DEVICE_POLLING
if (mask & IFCAP_POLLING) {
if (ifr->ifr_reqcap & IFCAP_POLLING) {
- error = ether_poll_register(fxp_poll, ifp);
+ error = device_poll_register(fxp_poll, ifp, ifp->if_xname);
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);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* 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);
Index: dev/ixgb/if_ixgb.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ixgb/if_ixgb.c,v
retrieving revision 1.10.2.4
diff -p -U5 -r1.10.2.4 if_ixgb.c
--- dev/ixgb/if_ixgb.c 7 Oct 2005 14:00:04 -0000 1.10.2.4
+++ dev/ixgb/if_ixgb.c 6 Jan 2006 01:37:29 -0000
@@ -375,11 +375,11 @@ ixgb_detach(device_t dev)

INIT_DEBUGOUT("ixgb_detach: begin");

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

IXGB_LOCK(adapter);
adapter->in_detach = 1;

@@ -569,19 +569,19 @@ ixgb_ioctl(struct ifnet * ifp, IOCTL_CMD
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);
+ error = device_poll_register(ixgb_poll, ifp, ifp->if_xname);
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);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupt even in error case */
IXGB_LOCK(adapter);
ixgb_enable_intr(adapter);
ifp->if_capenable &= ~IFCAP_POLLING;
IXGB_UNLOCK(adapter);
@@ -771,12 +771,13 @@ ixgb_poll_locked(struct ifnet * ifp, enu
if (ifp->if_snd.ifq_head != NULL)
ixgb_start_locked(ifp);
}

static void
-ixgb_poll(struct ifnet * ifp, enum poll_cmd cmd, int count)
+ixgb_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct adapter *adapter = ifp->if_softc;

IXGB_LOCK(adapter);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ixgb_poll_locked(ifp, cmd, count);
Index: dev/nge/if_nge.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/nge/if_nge.c,v
retrieving revision 1.75.2.3
diff -p -U5 -r1.75.2.3 if_nge.c
--- dev/nge/if_nge.c 7 Oct 2005 14:00:04 -0000 1.75.2.3
+++ dev/nge/if_nge.c 6 Jan 2006 01:37:29 -0000
@@ -959,11 +959,11 @@ nge_detach(dev)
sc = device_get_softc(dev);
ifp = sc->nge_ifp;

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif
NGE_LOCK(sc);
nge_reset(sc);
nge_stop(sc);
NGE_UNLOCK(sc);
@@ -1374,12 +1374,13 @@ nge_tick_locked(sc)

#ifdef DEVICE_POLLING
static poll_handler_t nge_poll;

static void
-nge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+nge_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct nge_softc *sc = ifp->if_softc;

NGE_LOCK(sc);
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
NGE_UNLOCK(sc);
@@ -2041,11 +2042,11 @@ nge_ioctl(ifp, command, data)
break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(nge_poll, ifp);
+ error = device_poll_register(nge_poll, ifp, ifp->if_xname);
if (error)
return(error);
NGE_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_4(sc, NGE_IER, 0);
@@ -2054,11 +2055,11 @@ nge_ioctl(ifp, command, data)
return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
NGE_LOCK(sc);
CSR_WRITE_4(sc, NGE_IER, 1);
ifp->if_capenable &= ~IFCAP_POLLING;
NGE_UNLOCK(sc);
Index: dev/re/if_re.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/re/if_re.c,v
retrieving revision 1.46.2.7
diff -p -U5 -r1.46.2.7 if_re.c
--- dev/re/if_re.c 8 Oct 2005 07:35:10 -0000 1.46.2.7
+++ dev/re/if_re.c 6 Jan 2006 01:37:30 -0000
@@ -216,11 +216,11 @@ static __inline void re_fixup_rx
(struct mbuf *);
#endif
static void re_rxeof (struct rl_softc *);
static void re_txeof (struct rl_softc *);
#ifdef DEVICE_POLLING
-static void re_poll (struct ifnet *, enum poll_cmd, int);
+static void re_poll (void *arg, enum poll_cmd, int);
static void re_poll_locked (struct ifnet *, enum poll_cmd, int);
#endif
static void re_intr (void *);
static void re_tick (void *);
static void re_start (struct ifnet *);
@@ -1268,11 +1268,11 @@ re_detach(dev)
ifp = sc->rl_ifp;
KASSERT(mtx_initialized(&sc->rl_mtx), ("re mutex not initialized"));

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif
/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
RL_LOCK(sc);
#if 0
@@ -1757,12 +1757,13 @@ re_tick(xsc)
callout_reset(&sc->rl_stat_callout, hz, re_tick, sc);
}

#ifdef DEVICE_POLLING
static void
-re_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+re_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct rl_softc *sc = ifp->if_softc;

RL_LOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
re_poll_locked(ifp, cmd, count);
@@ -2316,21 +2317,21 @@ re_ioctl(ifp, command, data)
{
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(re_poll, ifp);
+ error = device_poll_register(re_poll, ifp, ifp->if_xname);
if (error)
return(error);
RL_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_2(sc, RL_IMR, 0x0000);
ifp->if_capenable |= IFCAP_POLLING;
RL_UNLOCK(sc);

} else {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
RL_LOCK(sc);
CSR_WRITE_2(sc, RL_IMR, RL_INTRS_CPLUS);
ifp->if_capenable &= ~IFCAP_POLLING;
RL_UNLOCK(sc);
Index: dev/vge/if_vge.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/vge/if_vge.c,v
retrieving revision 1.14.2.4
diff -p -U5 -r1.14.2.4 if_vge.c
--- dev/vge/if_vge.c 9 Oct 2005 04:15:12 -0000 1.14.2.4
+++ dev/vge/if_vge.c 6 Jan 2006 01:37:30 -0000
@@ -1107,11 +1107,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);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
vge_stop(sc);
@@ -1617,12 +1617,13 @@ vge_tick(xsc)
return;
}

#ifdef DEVICE_POLLING
static void
-vge_poll (struct ifnet *ifp, enum poll_cmd cmd, int count)
+vge_poll (void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct vge_softc *sc = ifp->if_softc;

VGE_LOCK(sc);
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
goto done;
@@ -2256,21 +2257,21 @@ vge_ioctl(ifp, command, data)
{
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);
+ error = device_poll_register(vge_poll, ifp, ifp->if_xname);
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);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* 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);
Index: kern/kern_poll.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_poll.c,v
retrieving revision 1.19.2.2
diff -p -U5 -r1.19.2.2 kern_poll.c
--- kern/kern_poll.c 7 Oct 2005 14:00:05 -0000 1.19.2.2
+++ kern/kern_poll.c 6 Jan 2006 01:37:30 -0000
@@ -35,10 +35,11 @@ __FBSDID("$FreeBSD: src/sys/kern/kern_po
#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>
+#include <sys/bus.h>

#include <net/if.h> /* for IFF_* flags */
#include <net/netisr.h> /* for NETISR_POLL */

#include <sys/proc.h>
@@ -48,11 +49,11 @@ __FBSDID("$FreeBSD: src/sys/kern/kern_po
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 in idle loop */
+void device_poll(int); /* polling in idle loop */

static struct mtx poll_mtx;

/*
* Polling support for [network] device drivers.
@@ -61,11 +62,12 @@ static struct mtx poll_mtx;
* polling code.
*
* If registration is successful, the driver must disable interrupts,
* and further I/O is performed through the handler, which is invoked
* (at least once per clock tick) with 3 arguments: the "arg" passed at
- * register time (a struct ifnet pointer), a command, and a "count" limit.
+ * register time (a softc, device, or ifnet pointer), a command,
+ * and a "count" limit.
*
* The command can be one of the following:
* POLL_ONLY: quick move of "count" packets from input/output queues.
* POLL_AND_CHECK_STATUS: as above, plus check status registers or do
* other more expensive operations. This command is issued periodically
@@ -250,11 +252,11 @@ SYSCTL_UINT(_kern_polling, OID_AUTO, idl


#define POLL_LIST_LEN 128
struct pollrec {
poll_handler_t *handler;
- struct ifnet *ifp;
+ void *arg;
};

static struct pollrec pr[POLL_LIST_LEN];

static void
@@ -320,25 +322,25 @@ hardclock_device_poll(void)
if (pending_polls++ > 0)
lost_polls++;
}

/*
- * ether_poll is called from the idle loop.
+ * device_poll is called from the idle loop.
*/
void
-ether_poll(int count)
+device_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++)
- pr[i].handler(pr[i].ifp, POLL_ONLY, count);
+ pr[i].handler(pr[i].arg, POLL_ONLY, count);

mtx_unlock(&poll_mtx);
NET_UNLOCK_GIANT();
}

@@ -433,30 +435,30 @@ netisr_poll(void)
cycles = (residual_burst < poll_each_burst) ?
residual_burst : poll_each_burst;
residual_burst -= cycles;

for (i = 0 ; i < poll_handlers ; i++)
- pr[i].handler(pr[i].ifp, arg, cycles);
+ pr[i].handler(pr[i].arg, arg, cycles);

phase = 4;
mtx_unlock(&poll_mtx);
}

/*
* 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 *_ioctl() functions.
+ * This is called from within the interface *_ioctl() functions.
*/
int
-ether_poll_register(poll_handler_t *h, struct ifnet *ifp)
+device_poll_register(poll_handler_t *h, void *arg, const char *devname)
{
int i;

KASSERT(h != NULL, ("%s: handler is NULL", __func__));
- KASSERT(ifp != NULL, ("%s: ifp is NULL", __func__));
+ KASSERT(arg != NULL, ("%s: arg is NULL", __func__));

NET_ASSERT_GIANT();

mtx_lock(&poll_mtx);
if (poll_handlers >= POLL_LIST_LEN) {
@@ -476,58 +478,73 @@ ether_poll_register(poll_handler_t *h, s
mtx_unlock(&poll_mtx);
return (ENOMEM); /* no polling for you */
}

for (i = 0 ; i < poll_handlers ; i++)
- if (pr[i].ifp == ifp && pr[i].handler != NULL) {
+ if (pr[i].arg == arg && pr[i].handler != NULL) {
mtx_unlock(&poll_mtx);
- log(LOG_DEBUG, "ether_poll_register: %s: handler"
- " already registered\n", ifp->if_xname);
+ log(LOG_DEBUG, "device_poll_register: %s: handler"
+ " already registered\n", devname ? devname : "UNKNOWN");
return (EEXIST);
}

pr[poll_handlers].handler = h;
- pr[poll_handlers].ifp = ifp;
+ pr[poll_handlers].arg = arg;
poll_handlers++;
mtx_unlock(&poll_mtx);
if (idlepoll_sleeping)
wakeup(&idlepoll_sleeping);
return (0);
}

/*
- * Remove interface from the polling list. Called from *_ioctl(), too.
+ * Remove device from the polling list. Called from *_ioctl(), too.
*/
int
-ether_poll_deregister(struct ifnet *ifp)
+device_poll_deregister(void *arg, const char *devname)
{
int i;

- KASSERT(ifp != NULL, ("%s: ifp is NULL", __func__));
+ KASSERT(arg != NULL, ("%s: arg is NULL", __func__));

NET_ASSERT_GIANT();
mtx_lock(&poll_mtx);

for (i = 0 ; i < poll_handlers ; i++)
- if (pr[i].ifp == ifp) /* found it */
+ if (pr[i].arg == arg) /* found it */
break;
if (i == poll_handlers) {
- log(LOG_DEBUG, "ether_poll_deregister: %s: not found!\n",
- ifp->if_xname);
+ log(LOG_DEBUG, "device_poll_deregister: %s: not found!\n",
+ devname ? devname : "UNKNOWN");
mtx_unlock(&poll_mtx);
return (ENOENT);
}
poll_handlers--;
if (i < poll_handlers) { /* Last entry replaces this one. */
pr[i].handler = pr[poll_handlers].handler;
- pr[i].ifp = pr[poll_handlers].ifp;
+ pr[i].arg = pr[poll_handlers].arg;
}
mtx_unlock(&poll_mtx);
return (0);
}

/*
+ * Deprecated compatibility functions for external drivers.
+ */
+int
+ether_poll_register(void *h, struct ifnet *ifp)
+{
+ return device_poll_register((poll_handler_t*)h, ifp, ifp->if_xname);
+}
+
+int
+ether_poll_deregister(struct ifnet *ifp)
+{
+ return device_poll_deregister(ifp, ifp->if_xname);
+}
+
+/*
* Legacy interface for turning polling on all interfaces at one time.
*/
static int
poll_switch(SYSCTL_HANDLER_ARGS)
{
@@ -565,11 +582,12 @@ poll_switch(SYSCTL_HANDLER_ARGS)
}
}
IFNET_RUNLOCK();
NET_UNLOCK_GIANT();

- log(LOG_ERR, "kern.polling.enable is deprecated. Use ifconfig(8)");
+ log(LOG_ERR, "kern.polling.enable (which enables polling on all interfaces) "
+ "is deprecated. Use ifconfig(8)");

return (0);
}

static void
@@ -587,11 +605,11 @@ poll_idle(void)
mtx_unlock_spin(&sched_lock);

for (;;) {
if (poll_in_idle_loop && poll_handlers > 0) {
idlepoll_sleeping = 0;
- ether_poll(poll_each_burst);
+ device_poll(poll_each_burst);
mtx_lock_spin(&sched_lock);
mi_switch(SW_VOL, NULL);
mtx_unlock_spin(&sched_lock);
} else {
idlepoll_sleeping = 1;
Index: net/if_var.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if_var.h,v
retrieving revision 1.98.2.5
diff -p -U5 -r1.98.2.5 if_var.h
--- net/if_var.h 7 Oct 2005 14:00:05 -0000 1.98.2.5
+++ net/if_var.h 6 Jan 2006 01:37:34 -0000
@@ -658,14 +658,12 @@ void if_deregister_com_alloc(u_char type

#define IF_LLADDR(ifp) \
LLADDR((struct sockaddr_dl *) ifaddr_byindex((ifp)->if_index)->ifa_addr)

#ifdef DEVICE_POLLING
-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);
+/* DEPRECATED: For compatibility only. Use device_poll_register/deregister */
+int ether_poll_register(void*, struct ifnet *ifp);
int ether_poll_deregister(struct ifnet *ifp);
#endif /* DEVICE_POLLING */

#endif /* _KERNEL */

Index: pci/if_dc.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/Attic/if_dc.c,v
retrieving revision 1.160.2.6
diff -p -U5 -r1.160.2.6 if_dc.c
--- pci/if_dc.c 9 Oct 2005 04:11:19 -0000 1.160.2.6
+++ pci/if_dc.c 6 Jan 2006 01:37:34 -0000
@@ -2340,11 +2340,11 @@ dc_detach(device_t dev)

ifp = sc->dc_ifp;

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
DC_LOCK(sc);
@@ -3038,12 +3038,13 @@ dc_tx_underrun(struct dc_softc *sc)

#ifdef DEVICE_POLLING
static poll_handler_t dc_poll;

static void
-dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+dc_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct dc_softc *sc = ifp->if_softc;

DC_LOCK(sc);

if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
@@ -3683,11 +3684,11 @@ dc_ioctl(struct ifnet *ifp, u_long comma
break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(dc_poll, ifp);
+ error = device_poll_register(dc_poll, ifp, ifp->if_xname);
if (error)
return(error);
DC_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
@@ -3696,11 +3697,11 @@ dc_ioctl(struct ifnet *ifp, u_long comma
return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
DC_LOCK(sc);
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
ifp->if_capenable &= ~IFCAP_POLLING;
DC_UNLOCK(sc);
Index: pci/if_rl.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_rl.c,v
retrieving revision 1.152.2.4
diff -p -U5 -r1.152.2.4 if_rl.c
--- pci/if_rl.c 7 Oct 2005 14:00:06 -0000 1.152.2.4
+++ pci/if_rl.c 6 Jan 2006 01:37:34 -0000
@@ -197,11 +197,11 @@ static int rl_mii_readreg(struct rl_soft
static int rl_mii_writereg(struct rl_softc *, struct rl_mii_frame *);
static int rl_miibus_readreg(device_t, int, int);
static void rl_miibus_statchg(device_t);
static int rl_miibus_writereg(device_t, int, int, int);
#ifdef DEVICE_POLLING
-static void rl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count);
+static void rl_poll(void *arg, enum poll_cmd cmd, int count);
static void rl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count);
#endif
static int rl_probe(device_t);
static void rl_read_eeprom(struct rl_softc *, uint8_t *, int, int, int);
static void rl_reset(struct rl_softc *);
@@ -1003,11 +1003,11 @@ rl_detach(device_t dev)
ifp = sc->rl_ifp;

KASSERT(mtx_initialized(&sc->rl_mtx), ("rl mutex not initialized"));
#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif
/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
RL_LOCK(sc);
rl_stop(sc);
@@ -1281,12 +1281,13 @@ rl_tick(void *xsc)
callout_reset(&sc->rl_stat_callout, hz, rl_tick, sc);
}

#ifdef DEVICE_POLLING
static void
-rl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+rl_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct rl_softc *sc = ifp->if_softc;

RL_LOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
rl_poll_locked(ifp, cmd, count);
@@ -1657,11 +1658,11 @@ rl_ioctl(struct ifnet *ifp, u_long comma
break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(rl_poll, ifp);
+ error = device_poll_register(rl_poll, ifp, ifp->if_xname);
if (error)
return(error);
RL_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_2(sc, RL_IMR, 0x0000);
@@ -1670,11 +1671,11 @@ rl_ioctl(struct ifnet *ifp, u_long comma
return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
RL_LOCK(sc);
CSR_WRITE_2(sc, RL_IMR, RL_INTRS);
ifp->if_capenable &= ~IFCAP_POLLING;
RL_UNLOCK(sc);
Index: pci/if_sf.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_sf.c,v
retrieving revision 1.82.2.5
diff -p -U5 -r1.82.2.5 if_sf.c
--- pci/if_sf.c 9 Oct 2005 04:11:19 -0000 1.82.2.5
+++ pci/if_sf.c 6 Jan 2006 01:37:34 -0000
@@ -167,11 +167,11 @@ static u_int8_t sf_read_eeprom(struct sf

static int sf_miibus_readreg(device_t, int, int);
static int sf_miibus_writereg(device_t, int, int, int);
static void sf_miibus_statchg(device_t);
#ifdef DEVICE_POLLING
-static void sf_poll(struct ifnet *ifp, enum poll_cmd cmd, int count);
+static void sf_poll(void *arg, enum poll_cmd cmd, int count);
static void sf_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count);
#endif

static u_int32_t csr_read_4(struct sf_softc *, int);
static void csr_write_4(struct sf_softc *, int, u_int32_t);
@@ -563,11 +563,11 @@ sf_ioctl(ifp, command, data)
break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(sf_poll, ifp);
+ error = device_poll_register(sf_poll, ifp, ifp->if_xname);
if (error)
return(error);
SF_LOCK(sc);
/* Disable interrupts */
csr_write_4(sc, SF_IMR, 0x00000000);
@@ -576,11 +576,11 @@ sf_ioctl(ifp, command, data)
return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
SF_LOCK(sc);
csr_write_4(sc, SF_IMR, SF_INTRS);
ifp->if_capenable &= ~IFCAP_POLLING;
SF_UNLOCK(sc);
@@ -817,11 +817,11 @@ sf_detach(dev)
KASSERT(mtx_initialized(&sc->sf_mtx), ("sf mutex not initialized"));
ifp = sc->sf_ifp;

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
SF_LOCK(sc);
@@ -1089,12 +1089,13 @@ sf_txthresh_adjust(sc)
}
}

#ifdef DEVICE_POLLING
static void
-sf_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+sf_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct sf_softc *sc = ifp->if_softc;

SF_LOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
sf_poll_locked(ifp, cmd, count);
Index: pci/if_sis.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_sis.c,v
retrieving revision 1.132.2.6
diff -p -U5 -r1.132.2.6 if_sis.c
--- pci/if_sis.c 9 Oct 2005 04:11:19 -0000 1.132.2.6
+++ pci/if_sis.c 6 Jan 2006 01:37:34 -0000
@@ -1262,11 +1262,11 @@ sis_detach(device_t dev)
KASSERT(mtx_initialized(&sc->sis_mtx), ("sis mutex not initialized"));
ifp = sc->sis_ifp;

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

/* These should only be active if attach succeeded. */
if (device_is_attached(dev)) {
SIS_LOCK(sc);
@@ -1580,12 +1580,13 @@ sis_tick(void *xsc)

#ifdef DEVICE_POLLING
static poll_handler_t sis_poll;

static void
-sis_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+sis_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct sis_softc *sc = ifp->if_softc;

SIS_LOCK(sc);
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
SIS_UNLOCK(sc);
@@ -2138,11 +2139,11 @@ sis_ioctl(struct ifnet *ifp, u_long comm
case SIOCSIFCAP:
/* ok, disable interrupts */
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(sis_poll, ifp);
+ error = device_poll_register(sis_poll, ifp, ifp->if_xname);
if (error)
return(error);
SIS_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_4(sc, SIS_IER, 0);
@@ -2151,11 +2152,11 @@ sis_ioctl(struct ifnet *ifp, u_long comm
return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
SIS_LOCK(sc);
CSR_WRITE_4(sc, SIS_IER, 1);
ifp->if_capenable &= ~IFCAP_POLLING;
SIS_UNLOCK(sc);
Index: pci/if_ste.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_ste.c,v
retrieving revision 1.84.2.6
diff -p -U5 -r1.84.2.6 if_ste.c
--- pci/if_ste.c 9 Oct 2005 04:11:19 -0000 1.84.2.6
+++ pci/if_ste.c 6 Jan 2006 01:37:34 -0000
@@ -615,22 +615,11 @@ ste_setmulti(sc)

return;
}

#ifdef DEVICE_POLLING
-static poll_handler_t ste_poll, ste_poll_locked;
-
-static void
-ste_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
-{
- struct ste_softc *sc = ifp->if_softc;
-
- STE_LOCK(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ste_poll_locked(ifp, cmd, count);
- STE_UNLOCK(sc);
-}
+static poll_handler_t ste_poll;

static void
ste_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
struct ste_softc *sc = ifp->if_softc;
@@ -665,10 +654,23 @@ ste_poll_locked(struct ifnet *ifp, enum
ste_reset(sc);
ste_init_locked(sc);
}
}
}
+
+static void
+ste_poll(void *arg, enum poll_cmd cmd, int count)
+{
+ struct ifnet *ifp = arg;
+ struct ste_softc *sc = ifp->if_softc;
+
+ STE_LOCK(sc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ste_poll_locked(ifp, cmd, count);
+ STE_UNLOCK(sc);
+}
+
#endif /* DEVICE_POLLING */

static void
ste_intr(xsc)
void *xsc;
@@ -1145,11 +1147,11 @@ ste_detach(dev)
KASSERT(mtx_initialized(&sc->ste_mtx), ("ste mutex not initialized"));
ifp = sc->ste_ifp;

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
STE_LOCK(sc);
@@ -1532,11 +1534,11 @@ ste_ioctl(ifp, command, data)
break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(ste_poll, ifp);
+ error = device_poll_register(ste_poll, ifp, ifp->if_xname);
if (error)
return(error);
STE_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_2(sc, STE_IMR, 0);
@@ -1545,11 +1547,11 @@ ste_ioctl(ifp, command, data)
return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
STE_LOCK(sc);
CSR_WRITE_2(sc, STE_IMR, STE_INTRS);
ifp->if_capenable &= ~IFCAP_POLLING;
STE_UNLOCK(sc);
Index: pci/if_vr.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_vr.c,v
retrieving revision 1.104.2.4
diff -p -U5 -r1.104.2.4 if_vr.c
--- pci/if_vr.c 9 Oct 2005 04:11:20 -0000 1.104.2.4
+++ pci/if_vr.c 6 Jan 2006 01:37:34 -0000
@@ -798,11 +798,11 @@ vr_detach(device_t dev)

KASSERT(mtx_initialized(&sc->vr_mtx), ("vr mutex not initialized"));

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

VR_LOCK(sc);

sc->suspended = 1;
@@ -1150,22 +1150,10 @@ vr_tick(void *xsc)
VR_UNLOCK(sc);
}

#ifdef DEVICE_POLLING
static poll_handler_t vr_poll;
-static poll_handler_t vr_poll_locked;
-
-static void
-vr_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
-{
- struct vr_softc *sc = ifp->if_softc;
-
- VR_LOCK(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- vr_poll_locked(ifp, cmd, count);
- VR_UNLOCK(sc);
-}

static void
vr_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
struct vr_softc *sc = ifp->if_softc;
@@ -1224,10 +1212,23 @@ vr_poll_locked(struct ifnet *ifp, enum p
VR_SETBIT16(sc, VR_COMMAND, VR_CMD_TX_GO);
}
}
}
}
+
+static void
+vr_poll(void *arg, enum poll_cmd cmd, int count)
+{
+ struct ifnet *ifp = arg;
+ struct vr_softc *sc = ifp->if_softc;
+
+ VR_LOCK(sc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ vr_poll_locked(ifp, cmd, count);
+ VR_UNLOCK(sc);
+}
+
#endif /* DEVICE_POLLING */

static void
vr_intr(void *arg)
{
@@ -1607,11 +1608,11 @@ vr_ioctl(struct ifnet *ifp, u_long comma
break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(vr_poll, ifp);
+ error = device_poll_register(vr_poll, ifp, ifp->if_xname);
if (error)
return(error);
VR_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_2(sc, VR_IMR, 0x0000);
@@ -1620,11 +1621,11 @@ vr_ioctl(struct ifnet *ifp, u_long comma
return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
VR_LOCK(sc);
CSR_WRITE_2(sc, VR_IMR, VR_INTRS);
ifp->if_capenable &= ~IFCAP_POLLING;
VR_UNLOCK(sc);
Index: pci/if_xl.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_xl.c,v
retrieving revision 1.190.2.6
diff -p -U5 -r1.190.2.6 if_xl.c
--- pci/if_xl.c 9 Oct 2005 04:11:20 -0000 1.190.2.6
+++ pci/if_xl.c 6 Jan 2006 01:37:34 -0000
@@ -249,11 +249,11 @@ static void xl_watchdog(struct ifnet *);
static void xl_shutdown(device_t);
static int xl_suspend(device_t);
static int xl_resume(device_t);

#ifdef DEVICE_POLLING
-static void xl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count);
+static void xl_poll(void *arg, enum poll_cmd cmd, int count);
static void xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count);
#endif

static int xl_ifmedia_upd(struct ifnet *);
static void xl_ifmedia_sts(struct ifnet *, struct ifmediareq *);
@@ -1689,11 +1689,11 @@ xl_detach(device_t dev)

KASSERT(mtx_initialized(&sc->xl_mtx), ("xl mutex not initialized"));

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

if (sc->xl_flags & XL_FLAG_USE_MMIO) {
rid = XL_PCI_LOMEM;
res = SYS_RES_MEMORY;
@@ -2335,12 +2335,13 @@ xl_intr(void *arg)
XL_UNLOCK(sc);
}

#ifdef DEVICE_POLLING
static void
-xl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+xl_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct xl_softc *sc = ifp->if_softc;

XL_LOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
xl_poll_locked(ifp, cmd, count);
@@ -3182,11 +3183,11 @@ xl_ioctl(struct ifnet *ifp, u_long comma
break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(xl_poll, ifp);
+ error = device_poll_register(xl_poll, ifp, ifp->if_xname);
if (error)
return(error);
XL_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0);
@@ -3195,11 +3196,11 @@ xl_ioctl(struct ifnet *ifp, u_long comma
return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
XL_LOCK(sc);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|0xFF);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS);
if (sc->xl_flags & XL_FLAG_FUNCREG)
Index: sys/bus.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/bus.h,v
retrieving revision 1.70
diff -p -U5 -r1.70 bus.h
--- sys/bus.h 12 Apr 2005 15:20:36 -0000 1.70
+++ sys/bus.h 6 Jan 2006 01:37:34 -0000
@@ -453,10 +453,20 @@ void bus_data_generation_update(void);
/**
* Shorthand for constructing method tables.
*/
#define DEVMETHOD KOBJMETHOD

+/* Device polling functionality */
+#ifdef DEVICE_POLLING
+
+enum poll_cmd { POLL_ONLY, POLL_AND_CHECK_STATUS };
+typedef void poll_handler_t(void *arg, enum poll_cmd cmd, int count);
+int device_poll_register(poll_handler_t *h, void *arg, const char *devname);
+int device_poll_deregister(void *arg, const char *devname);
+
+#endif /* DEVICE_POLLING */
+
/*
* Some common device interfaces.
*/
#include "device_if.h"
#include "bus_if.h"

--------------070408040903010200010209
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
freebsd...@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hacke...@freebsd.org"
--------------070408040903010200010209--

Nate Nielsen

unread,
Jan 7, 2006, 6:00:42 PM1/7/06
to
This is a multi-part message in MIME format.
--------------060508080200040308080909

Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Nate Nielsen wrote:
> The polling functionality in FreeBSD is currently a bit NIC centric.
> With a few changes other types devices can use the polling subsystem.
> Attached is my first whack at this.
>
> This is some of my first hacking on the FreeBSD kernel. It'd be great if
> there was someone who could take a look and help me get it right.

Attached is a patch against HEAD.

Cheers,
Nate

--------------060508080200040308080909
Content-Type: text/x-patch;
name="device-polling-7.0-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="device-polling-7.0-2.patch"

Index: dev/dc/if_dc.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/dc/if_dc.c,v
retrieving revision 1.178
diff -p -U5 -r1.178 if_dc.c
--- dev/dc/if_dc.c 28 Dec 2005 18:00:37 -0000 1.178
+++ dev/dc/if_dc.c 7 Jan 2006 22:20:46 -0000
@@ -2346,11 +2346,11 @@ dc_detach(device_t dev)



ifp = sc->dc_ifp;

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
DC_LOCK(sc);

@@ -3045,12 +3045,13 @@ dc_tx_underrun(struct dc_softc *sc)



#ifdef DEVICE_POLLING
static poll_handler_t dc_poll;

static void
-dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+dc_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct dc_softc *sc = ifp->if_softc;

DC_LOCK(sc);

if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {

@@ -3691,11 +3692,11 @@ dc_ioctl(struct ifnet *ifp, u_long comma


break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(dc_poll, ifp);
+ error = device_poll_register(dc_poll, ifp, ifp->if_xname);
if (error)
return(error);
DC_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_4(sc, DC_IMR, 0x00000000);

@@ -3704,11 +3705,11 @@ dc_ioctl(struct ifnet *ifp, u_long comma


return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
DC_LOCK(sc);
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
ifp->if_capenable &= ~IFCAP_POLLING;
DC_UNLOCK(sc);

Index: dev/em/if_em.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/em/if_em.c,v

retrieving revision 1.97
diff -p -U5 -r1.97 if_em.c
--- dev/em/if_em.c 28 Dec 2005 09:37:04 -0000 1.97
+++ dev/em/if_em.c 7 Jan 2006 22:21:04 -0000
@@ -803,19 +803,19 @@ em_ioctl(struct ifnet *ifp, u_long comma


reinit = 0;
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
#ifdef DEVICE_POLLING
if (mask & IFCAP_POLLING) {
if (ifr->ifr_reqcap & IFCAP_POLLING) {
- error = ether_poll_register(em_poll, ifp);
+ error = device_poll_register(em_poll, ifp, ifp->if_xname);
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);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupt even in error case */
EM_LOCK(adapter);
em_enable_intr(adapter);
ifp->if_capenable &= ~IFCAP_POLLING;
EM_UNLOCK(adapter);

@@ -1039,12 +1039,13 @@ em_poll_locked(struct ifnet *ifp, enum p


if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
em_start_locked(ifp);
}

static void
-em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+em_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct adapter *adapter = ifp->if_softc;

EM_LOCK(adapter);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
em_poll_locked(ifp, cmd, count);
Index: dev/firewire/if_fwe.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/firewire/if_fwe.c,v

retrieving revision 1.41
diff -p -U5 -r1.41 if_fwe.c
--- dev/firewire/if_fwe.c 11 Oct 2005 07:30:06 -0000 1.41
+++ dev/firewire/if_fwe.c 7 Jan 2006 22:21:04 -0000


@@ -104,12 +104,13 @@ TUNABLE_INT("hw.firewire.fwe.rx_queue_le

#ifdef DEVICE_POLLING
static poll_handler_t fwe_poll;

static void
-fwe_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+fwe_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct fwe_softc *fwe;
struct firewire_comm *fc;

if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
return;
@@ -290,11 +291,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);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif
s = splimp();

fwe_stop(fwe);
#if defined(__DragonFly__) || __FreeBSD_version < 500000

@@ -462,21 +463,21 @@ fwe_ioctl(struct ifnet *ifp, u_long cmd,


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);

+ error = device_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);

+ error = device_poll_deregister(ifp);


/* Enable interrupts. */
fc->set_intr(fc, 1);
ifp->if_capenable &= ~IFCAP_POLLING;
return (error);
}
Index: dev/firewire/if_fwip.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/firewire/if_fwip.c,v

retrieving revision 1.11
diff -p -U5 -r1.11 if_fwip.c
--- dev/firewire/if_fwip.c 5 Oct 2005 10:09:14 -0000 1.11
+++ dev/firewire/if_fwip.c 7 Jan 2006 22:21:05 -0000

retrieving revision 1.252
diff -p -U5 -r1.252 if_fxp.c
--- dev/fxp/if_fxp.c 12 Dec 2005 14:30:13 -0000 1.252
+++ dev/fxp/if_fxp.c 7 Jan 2006 22:21:06 -0000


@@ -45,10 +45,11 @@ __FBSDID("$FreeBSD: src/sys/dev/fxp/if_f
/* #include <sys/mutex.h> */
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
+#include <sys/bus.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>

@@ -895,11 +896,11 @@ fxp_detach(device_t dev)


{
struct fxp_softc *sc = device_get_softc(dev);

#ifdef DEVICE_POLLING
if (sc->ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(sc->ifp);
+ device_poll_deregister(sc->ifp, sc->ifp->if_xname);
#endif

FXP_LOCK(sc);
sc->suspended = 1; /* Do same thing as we do for suspend */
/*

@@ -1449,12 +1450,13 @@ fxp_encap(struct fxp_softc *sc, struct m



#ifdef DEVICE_POLLING
static poll_handler_t fxp_poll;

static void
-fxp_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+fxp_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct fxp_softc *sc = ifp->if_softc;
uint8_t statack;

FXP_LOCK(sc);
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {

@@ -2413,20 +2415,20 @@ fxp_ioctl(struct ifnet *ifp, u_long comm

retrieving revision 1.18
diff -p -U5 -r1.18 if_ixgb.c
--- dev/ixgb/if_ixgb.c 18 Dec 2005 18:24:26 -0000 1.18
+++ dev/ixgb/if_ixgb.c 7 Jan 2006 22:21:07 -0000


@@ -375,11 +375,11 @@ ixgb_detach(device_t dev)

INIT_DEBUGOUT("ixgb_detach: begin");

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

IXGB_LOCK(adapter);
adapter->in_detach = 1;

@@ -570,19 +570,19 @@ ixgb_ioctl(struct ifnet * ifp, IOCTL_CMD


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);
+ error = device_poll_register(ixgb_poll, ifp, ifp->if_xname);
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);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupt even in error case */
IXGB_LOCK(adapter);
ixgb_enable_intr(adapter);
ifp->if_capenable &= ~IFCAP_POLLING;
IXGB_UNLOCK(adapter);

@@ -772,12 +772,13 @@ ixgb_poll_locked(struct ifnet * ifp, enu


if (ifp->if_snd.ifq_head != NULL)
ixgb_start_locked(ifp);
}

static void
-ixgb_poll(struct ifnet * ifp, enum poll_cmd cmd, int count)
+ixgb_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct adapter *adapter = ifp->if_softc;

IXGB_LOCK(adapter);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ixgb_poll_locked(ifp, cmd, count);
Index: dev/nge/if_nge.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/nge/if_nge.c,v

retrieving revision 1.85
diff -p -U5 -r1.85 if_nge.c
--- dev/nge/if_nge.c 18 Dec 2005 18:24:26 -0000 1.85
+++ dev/nge/if_nge.c 7 Jan 2006 22:21:08 -0000
@@ -948,11 +948,11 @@ nge_detach(dev)


sc = device_get_softc(dev);
ifp = sc->nge_ifp;

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif
NGE_LOCK(sc);
nge_reset(sc);
nge_stop(sc);
NGE_UNLOCK(sc);

@@ -1355,12 +1355,13 @@ nge_tick(xsc)



#ifdef DEVICE_POLLING
static poll_handler_t nge_poll;

static void
-nge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+nge_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct nge_softc *sc = ifp->if_softc;

NGE_LOCK(sc);
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
NGE_UNLOCK(sc);

@@ -2039,11 +2040,11 @@ nge_ioctl(ifp, command, data)


break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(nge_poll, ifp);
+ error = device_poll_register(nge_poll, ifp, ifp->if_xname);
if (error)
return(error);
NGE_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_4(sc, NGE_IER, 0);

@@ -2052,11 +2053,11 @@ nge_ioctl(ifp, command, data)


return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
NGE_LOCK(sc);
CSR_WRITE_4(sc, NGE_IER, 1);
ifp->if_capenable &= ~IFCAP_POLLING;
NGE_UNLOCK(sc);
Index: dev/re/if_re.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/re/if_re.c,v

retrieving revision 1.62
diff -p -U5 -r1.62 if_re.c
--- dev/re/if_re.c 18 Dec 2005 18:24:26 -0000 1.62
+++ dev/re/if_re.c 7 Jan 2006 22:21:17 -0000
@@ -218,11 +218,11 @@ static __inline void re_fixup_rx


(struct mbuf *);
#endif
static void re_rxeof (struct rl_softc *);
static void re_txeof (struct rl_softc *);
#ifdef DEVICE_POLLING
-static void re_poll (struct ifnet *, enum poll_cmd, int);
+static void re_poll (void *arg, enum poll_cmd, int);
static void re_poll_locked (struct ifnet *, enum poll_cmd, int);
#endif
static void re_intr (void *);
static void re_tick (void *);
static void re_start (struct ifnet *);

@@ -1281,11 +1281,11 @@ re_detach(dev)


ifp = sc->rl_ifp;
KASSERT(mtx_initialized(&sc->rl_mtx), ("re mutex not initialized"));

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
RL_LOCK(sc);

@@ -1774,12 +1774,13 @@ re_tick(xsc)


callout_reset(&sc->rl_stat_callout, hz, re_tick, sc);
}

#ifdef DEVICE_POLLING
static void
-re_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+re_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct rl_softc *sc = ifp->if_softc;

RL_LOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
re_poll_locked(ifp, cmd, count);

@@ -2335,21 +2336,21 @@ re_ioctl(ifp, command, data)


{
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(re_poll, ifp);
+ error = device_poll_register(re_poll, ifp, ifp->if_xname);
if (error)
return(error);
RL_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_2(sc, RL_IMR, 0x0000);
ifp->if_capenable |= IFCAP_POLLING;
RL_UNLOCK(sc);

} else {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
RL_LOCK(sc);
CSR_WRITE_2(sc, RL_IMR, RL_INTRS_CPLUS);
ifp->if_capenable &= ~IFCAP_POLLING;
RL_UNLOCK(sc);
Index: dev/vge/if_vge.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/vge/if_vge.c,v

retrieving revision 1.23
diff -p -U5 -r1.23 if_vge.c
--- dev/vge/if_vge.c 18 Dec 2005 18:24:27 -0000 1.23
+++ dev/vge/if_vge.c 7 Jan 2006 22:21:18 -0000


@@ -1107,11 +1107,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);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
vge_stop(sc);

@@ -1620,12 +1620,13 @@ vge_tick(xsc)


return;
}

#ifdef DEVICE_POLLING
static void
-vge_poll (struct ifnet *ifp, enum poll_cmd cmd, int count)
+vge_poll (void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct vge_softc *sc = ifp->if_softc;

VGE_LOCK(sc);
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
goto done;

@@ -2259,21 +2260,21 @@ vge_ioctl(ifp, command, data)

retrieving revision 1.25
diff -p -U5 -r1.25 kern_poll.c
--- kern/kern_poll.c 5 Oct 2005 10:09:16 -0000 1.25
+++ kern/kern_poll.c 7 Jan 2006 22:21:19 -0000

retrieving revision 1.105
diff -p -U5 -r1.105 if_var.h
--- net/if_var.h 11 Nov 2005 16:04:48 -0000 1.105
+++ net/if_var.h 7 Jan 2006 22:21:23 -0000


@@ -658,14 +658,12 @@ void if_deregister_com_alloc(u_char type

#define IF_LLADDR(ifp) \

LLADDR((struct sockaddr_dl *)((ifp)->if_addr->ifa_addr))



#ifdef DEVICE_POLLING
-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);
+/* DEPRECATED: For compatibility only. Use device_poll_register/deregister */
+int ether_poll_register(void*, struct ifnet *ifp);
int ether_poll_deregister(struct ifnet *ifp);
#endif /* DEVICE_POLLING */

#endif /* _KERNEL */

Index: pci/if_rl.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_rl.c,v

retrieving revision 1.162
diff -p -U5 -r1.162 if_rl.c
--- pci/if_rl.c 11 Nov 2005 16:04:58 -0000 1.162
+++ pci/if_rl.c 7 Jan 2006 22:21:34 -0000


@@ -197,11 +197,11 @@ static int rl_mii_readreg(struct rl_soft
static int rl_mii_writereg(struct rl_softc *, struct rl_mii_frame *);
static int rl_miibus_readreg(device_t, int, int);
static void rl_miibus_statchg(device_t);
static int rl_miibus_writereg(device_t, int, int, int);
#ifdef DEVICE_POLLING
-static void rl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count);
+static void rl_poll(void *arg, enum poll_cmd cmd, int count);
static void rl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count);
#endif
static int rl_probe(device_t);
static void rl_read_eeprom(struct rl_softc *, uint8_t *, int, int, int);
static void rl_reset(struct rl_softc *);

@@ -1004,11 +1004,11 @@ rl_detach(device_t dev)



KASSERT(mtx_initialized(&sc->rl_mtx), ("rl mutex not initialized"));

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif
/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
RL_LOCK(sc);
rl_stop(sc);

@@ -1283,12 +1283,13 @@ rl_tick(void *xsc)


callout_reset(&sc->rl_stat_callout, hz, rl_tick, sc);
}

#ifdef DEVICE_POLLING
static void
-rl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+rl_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct rl_softc *sc = ifp->if_softc;

RL_LOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
rl_poll_locked(ifp, cmd, count);

@@ -1659,11 +1660,11 @@ rl_ioctl(struct ifnet *ifp, u_long comma


break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(rl_poll, ifp);
+ error = device_poll_register(rl_poll, ifp, ifp->if_xname);
if (error)
return(error);
RL_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_2(sc, RL_IMR, 0x0000);

@@ -1672,11 +1673,11 @@ rl_ioctl(struct ifnet *ifp, u_long comma


return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
RL_LOCK(sc);
CSR_WRITE_2(sc, RL_IMR, RL_INTRS);
ifp->if_capenable &= ~IFCAP_POLLING;
RL_UNLOCK(sc);
Index: pci/if_sf.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_sf.c,v

retrieving revision 1.92
diff -p -U5 -r1.92 if_sf.c
--- pci/if_sf.c 11 Nov 2005 16:04:58 -0000 1.92
+++ pci/if_sf.c 7 Jan 2006 22:21:35 -0000

@@ -1090,12 +1090,13 @@ sf_txthresh_adjust(sc)


}
}

#ifdef DEVICE_POLLING
static void
-sf_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+sf_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct sf_softc *sc = ifp->if_softc;

SF_LOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
sf_poll_locked(ifp, cmd, count);
Index: pci/if_sis.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_sis.c,v

retrieving revision 1.144
diff -p -U5 -r1.144 if_sis.c
--- pci/if_sis.c 11 Nov 2005 16:04:58 -0000 1.144
+++ pci/if_sis.c 7 Jan 2006 22:21:36 -0000
@@ -1260,11 +1260,11 @@ sis_detach(device_t dev)


KASSERT(mtx_initialized(&sc->sis_mtx), ("sis mutex not initialized"));
ifp = sc->sis_ifp;

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

/* These should only be active if attach succeeded. */
if (device_is_attached(dev)) {
SIS_LOCK(sc);

@@ -1576,12 +1576,13 @@ sis_tick(void *xsc)



#ifdef DEVICE_POLLING
static poll_handler_t sis_poll;

static void
-sis_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+sis_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct sis_softc *sc = ifp->if_softc;

SIS_LOCK(sc);
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
SIS_UNLOCK(sc);

@@ -2134,11 +2135,11 @@ sis_ioctl(struct ifnet *ifp, u_long comm


case SIOCSIFCAP:
/* ok, disable interrupts */
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(sis_poll, ifp);
+ error = device_poll_register(sis_poll, ifp, ifp->if_xname);
if (error)
return(error);
SIS_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_4(sc, SIS_IER, 0);

@@ -2147,11 +2148,11 @@ sis_ioctl(struct ifnet *ifp, u_long comm


return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
SIS_LOCK(sc);
CSR_WRITE_4(sc, SIS_IER, 1);
ifp->if_capenable &= ~IFCAP_POLLING;
SIS_UNLOCK(sc);
Index: pci/if_ste.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_ste.c,v

retrieving revision 1.94
diff -p -U5 -r1.94 if_ste.c
--- pci/if_ste.c 11 Nov 2005 16:04:58 -0000 1.94
+++ pci/if_ste.c 7 Jan 2006 22:21:37 -0000

@@ -1533,11 +1535,11 @@ ste_ioctl(ifp, command, data)


break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(ste_poll, ifp);
+ error = device_poll_register(ste_poll, ifp, ifp->if_xname);
if (error)
return(error);
STE_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_2(sc, STE_IMR, 0);

@@ -1546,11 +1548,11 @@ ste_ioctl(ifp, command, data)


return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
STE_LOCK(sc);
CSR_WRITE_2(sc, STE_IMR, STE_INTRS);
ifp->if_capenable &= ~IFCAP_POLLING;
STE_UNLOCK(sc);
Index: pci/if_vr.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_vr.c,v

retrieving revision 1.114
diff -p -U5 -r1.114 if_vr.c
--- pci/if_vr.c 11 Nov 2005 16:04:58 -0000 1.114
+++ pci/if_vr.c 7 Jan 2006 22:21:38 -0000
@@ -794,11 +794,11 @@ vr_detach(device_t dev)



KASSERT(mtx_initialized(&sc->vr_mtx), ("vr mutex not initialized"));

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {

VR_LOCK(sc);
@@ -1140,22 +1140,10 @@ vr_tick(void *xsc)
callout_reset(&sc->vr_stat_callout, hz, vr_tick, sc);


}

#ifdef DEVICE_POLLING
static poll_handler_t vr_poll;
-static poll_handler_t vr_poll_locked;
-
-static void
-vr_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
-{
- struct vr_softc *sc = ifp->if_softc;
-
- VR_LOCK(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- vr_poll_locked(ifp, cmd, count);
- VR_UNLOCK(sc);
-}

static void
vr_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
struct vr_softc *sc = ifp->if_softc;

@@ -1213,10 +1201,23 @@ vr_poll_locked(struct ifnet *ifp, enum p


VR_SETBIT16(sc, VR_COMMAND, VR_CMD_TX_GO);
}
}
}
}
+
+static void
+vr_poll(void *arg, enum poll_cmd cmd, int count)
+{
+ struct ifnet *ifp = arg;
+ struct vr_softc *sc = ifp->if_softc;
+
+ VR_LOCK(sc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ vr_poll_locked(ifp, cmd, count);
+ VR_UNLOCK(sc);
+}
+
#endif /* DEVICE_POLLING */

static void
vr_intr(void *arg)
{

@@ -1595,11 +1596,11 @@ vr_ioctl(struct ifnet *ifp, u_long comma


break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(vr_poll, ifp);
+ error = device_poll_register(vr_poll, ifp, ifp->if_xname);
if (error)
return(error);
VR_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_2(sc, VR_IMR, 0x0000);

@@ -1608,11 +1609,11 @@ vr_ioctl(struct ifnet *ifp, u_long comma


return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
VR_LOCK(sc);
CSR_WRITE_2(sc, VR_IMR, VR_INTRS);
ifp->if_capenable &= ~IFCAP_POLLING;
VR_UNLOCK(sc);
Index: pci/if_xl.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_xl.c,v

retrieving revision 1.201
diff -p -U5 -r1.201 if_xl.c
--- pci/if_xl.c 11 Nov 2005 16:04:58 -0000 1.201
+++ pci/if_xl.c 7 Jan 2006 22:21:39 -0000


@@ -249,11 +249,11 @@ static void xl_watchdog(struct ifnet *);
static void xl_shutdown(device_t);
static int xl_suspend(device_t);
static int xl_resume(device_t);

#ifdef DEVICE_POLLING
-static void xl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count);
+static void xl_poll(void *arg, enum poll_cmd cmd, int count);
static void xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count);
#endif

static int xl_ifmedia_upd(struct ifnet *);
static void xl_ifmedia_sts(struct ifnet *, struct ifmediareq *);

@@ -1694,11 +1694,11 @@ xl_detach(device_t dev)



KASSERT(mtx_initialized(&sc->xl_mtx), ("xl mutex not initialized"));

#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
+ device_poll_deregister(ifp, ifp->if_xname);
#endif

if (sc->xl_flags & XL_FLAG_USE_MMIO) {
rid = XL_PCI_LOMEM;
res = SYS_RES_MEMORY;

@@ -2341,12 +2341,13 @@ xl_intr(void *arg)


XL_UNLOCK(sc);
}

#ifdef DEVICE_POLLING
static void
-xl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+xl_poll(void *arg, enum poll_cmd cmd, int count)
{
+ struct ifnet *ifp = arg;
struct xl_softc *sc = ifp->if_softc;

XL_LOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
xl_poll_locked(ifp, cmd, count);

@@ -3188,11 +3189,11 @@ xl_ioctl(struct ifnet *ifp, u_long comma


break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(xl_poll, ifp);
+ error = device_poll_register(xl_poll, ifp, ifp->if_xname);
if (error)
return(error);
XL_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0);

@@ -3201,11 +3202,11 @@ xl_ioctl(struct ifnet *ifp, u_long comma


return (error);

}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
+ error = device_poll_deregister(ifp, ifp->if_xname);
/* Enable interrupts. */
XL_LOCK(sc);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|0xFF);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS);
if (sc->xl_flags & XL_FLAG_FUNCREG)
Index: sys/bus.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/bus.h,v

retrieving revision 1.73
diff -p -U5 -r1.73 bus.h
--- sys/bus.h 24 Sep 2005 20:11:06 -0000 1.73
+++ sys/bus.h 7 Jan 2006 22:21:40 -0000
@@ -459,10 +459,20 @@ void bus_data_generation_update(void);


/**
* Shorthand for constructing method tables.
*/
#define DEVMETHOD KOBJMETHOD

+/* Device polling functionality */
+#ifdef DEVICE_POLLING
+
+enum poll_cmd { POLL_ONLY, POLL_AND_CHECK_STATUS };
+typedef void poll_handler_t(void *arg, enum poll_cmd cmd, int count);
+int device_poll_register(poll_handler_t *h, void *arg, const char *devname);
+int device_poll_deregister(void *arg, const char *devname);
+
+#endif /* DEVICE_POLLING */
+
/*
* Some common device interfaces.
*/
#include "device_if.h"
#include "bus_if.h"

--------------060508080200040308080909


Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
freebsd...@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hacke...@freebsd.org"

--------------060508080200040308080909--

Ed Maste

unread,
Jan 9, 2006, 1:43:38 PM1/9/06
to
On Sat, Jan 07, 2006 at 11:17:00PM +0000, Nate Nielsen wrote:

> Nate Nielsen wrote:
> > The polling functionality in FreeBSD is currently a bit NIC centric.
> > With a few changes other types devices can use the polling subsystem.
> > Attached is my first whack at this.
> >
> > This is some of my first hacking on the FreeBSD kernel. It'd be great if
> > there was someone who could take a look and help me get it right.
>
> Attached is a patch against HEAD.

This looks like a good start to expanding polling beyond network
interfaces, but it doesn't address the fact that the polling code
currently has a single feedback parameter, shared by all devices,
to control the amount of work done in each handler.

Passing the count parameter to devices other than network interfaces
implies that their drivers should do roughly as much work as a network
interface would to process that number of packets. If the other
devices take too long per count then polling-enabled network interfaces
will end up without enough CPU time to do their required work.

In addition, the current polling algorithm breaks down when you get to
very high CPU utilization by the stack (e.g. if acting as a high
bandwidth router). This happens because it adds one count per tick
if the polling did not run longer than one hardclock interval, but
brings it down to 7/8ths if it did.

This ends up producing a sawtooth effect in the amount of work done by
the polling handlers. Andre Oppermann is performing some high-perf
stack testing, and he ran into this effect; in polling mode the maximum
packet rate was achieved while there was still idle CPU time.

I have a proof of concept patch that modifies the polling feedback
algorithm to measure the amount of time spent in the polling handlers,
and then attempt to schedule an appropriate amount of work to fill out
the time slot. Andre is going to be testing it out shortly.

Don't get me wrong, I think your patch is a step in the right direction,
but we do have more work to do in order to completely generalize the
polling code.

(By the way, it seems some of your driver diffs move the *_poll
functions around, making it harder to see what you actually changed.
It would be better to leave the functions where they already are, I
think.)

-Ed Maste

Nate Nielsen

unread,
Jan 10, 2006, 11:19:48 PM1/10/06
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Ed Maste wrote:
> In addition, the current polling algorithm breaks down when you get to
> very high CPU utilization by the stack (e.g. if acting as a high
> bandwidth router). This happens because it adds one count per tick
> if the polling did not run longer than one hardclock interval, but
> brings it down to 7/8ths if it did.
>
> This ends up producing a sawtooth effect in the amount of work done by
> the polling handlers. Andre Oppermann is performing some high-perf
> stack testing, and he ran into this effect; in polling mode the maximum
> packet rate was achieved while there was still idle CPU time.

Interesting. My (simple) work on this has been on low powered CPU
machines (such as the Soekris single board systems):

http://memberwebs.com/nielsen/freebsd/slow-cpu-routers.html

> I have a proof of concept patch that modifies the polling feedback
> algorithm to measure the amount of time spent in the polling handlers,
> and then attempt to schedule an appropriate amount of work to fill out
> the time slot. Andre is going to be testing it out shortly.
>
> Don't get me wrong, I think your patch is a step in the right direction,
> but we do have more work to do in order to completely generalize the
> polling code.

Agreed. And sometime in the future, we should probably work towards
implementing auto-switching between polling and interrupts:

http://www.stanford.edu/class/cs240/readings/mogul.pdf

Cheers,
Nate
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFDwwfte/sRCNknZa8RAnMAAJ0de3eQELrbEgp5NF56wFtR2poYBACbBetq
p/ZLh5bY6dbdPiIkIJMsCEM=
=RADi
-----END PGP SIGNATURE-----

0 new messages