summaryrefslogtreecommitdiffstats
path: root/sys/dev
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
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')
-rw-r--r--sys/dev/dc/if_dc.c69
-rw-r--r--sys/dev/em/if_em.c71
-rw-r--r--sys/dev/firewire/00README3
-rw-r--r--sys/dev/firewire/if_fwe.c69
-rw-r--r--sys/dev/firewire/if_fwip.c78
-rw-r--r--sys/dev/fxp/if_fxp.c56
-rw-r--r--sys/dev/ixgb/README15
-rw-r--r--sys/dev/ixgb/if_ixgb.c77
-rw-r--r--sys/dev/nge/if_nge.c62
-rw-r--r--sys/dev/re/if_re.c89
-rw-r--r--sys/dev/sf/if_sf.c89
-rw-r--r--sys/dev/vge/if_vge.c105
-rw-r--r--sys/dev/vr/if_vr.c70
13 files changed, 468 insertions, 385 deletions
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c
index 8a9e8c6..a6f4304 100644
--- a/sys/dev/dc/if_dc.c
+++ b/sys/dev/dc/if_dc.c
@@ -2265,10 +2265,10 @@ dc_attach(device_t dev)
*/
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
ifp->if_capabilities |= IFCAP_VLAN_MTU;
+ ifp->if_capenable = ifp->if_capabilities;
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
#endif
- ifp->if_capenable = ifp->if_capabilities;
callout_init_mtx(&sc->dc_stat_ch, &sc->dc_mtx, 0);
@@ -2339,6 +2339,11 @@ dc_detach(device_t dev)
ifp = sc->dc_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)) {
DC_LOCK(sc);
@@ -2704,7 +2709,7 @@ dc_rxeof(struct dc_softc *sc)
while (!(le32toh(sc->dc_ldata->dc_rx_list[i].dc_status) &
DC_RXSTAT_OWN)) {
#ifdef DEVICE_POLLING
- if (ifp->if_flags & IFF_POLLING) {
+ if (ifp->if_capenable & IFCAP_POLLING) {
if (sc->rxcycles <= 0)
break;
sc->rxcycles--;
@@ -3038,16 +3043,13 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
struct dc_softc *sc = ifp->if_softc;
- if (!(ifp->if_capenable & IFCAP_POLLING)) {
- ether_poll_deregister(ifp);
- cmd = POLL_DEREGISTER;
- }
- if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */
- /* Re-enable interrupts. */
- CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
+ DC_LOCK(sc);
+
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ DC_UNLOCK(sc);
return;
}
- DC_LOCK(sc);
+
sc->rxcycles = count;
dc_rxeof(sc);
dc_txeof(sc);
@@ -3111,12 +3113,9 @@ dc_intr(void *arg)
DC_LOCK(sc);
ifp = sc->dc_ifp;
#ifdef DEVICE_POLLING
- if (ifp->if_flags & IFF_POLLING)
- goto done;
- if ((ifp->if_capenable & IFCAP_POLLING) &&
- ether_poll_register(dc_poll, ifp)) { /* ok, disable interrupts */
- CSR_WRITE_4(sc, DC_IMR, 0x00000000);
- goto done;
+ if (ifp->if_capenable & IFCAP_POLLING) {
+ DC_UNLOCK(sc);
+ return;
}
#endif
@@ -3183,10 +3182,6 @@ dc_intr(void *arg)
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start_locked(ifp);
-#ifdef DEVICE_POLLING
-done:
-#endif
-
DC_UNLOCK(sc);
}
@@ -3534,7 +3529,7 @@ dc_init_locked(struct dc_softc *sc)
* the case of polling. Some cards (e.g. fxp) turn interrupts on
* after a reset.
*/
- if (ifp->if_flags & IFF_POLLING)
+ if (ifp->if_capenable & IFCAP_POLLING)
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
else
#endif
@@ -3686,10 +3681,31 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
#endif
break;
case SIOCSIFCAP:
- DC_LOCK(sc);
- ifp->if_capenable &= ~IFCAP_POLLING;
- ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING;
- DC_UNLOCK(sc);
+#ifdef DEVICE_POLLING
+ if (ifr->ifr_reqcap & IFCAP_POLLING &&
+ !(ifp->if_capenable & IFCAP_POLLING)) {
+ error = ether_poll_register(dc_poll, ifp);
+ if (error)
+ return(error);
+ DC_LOCK(sc);
+ /* Disable interrupts */
+ CSR_WRITE_4(sc, DC_IMR, 0x00000000);
+ ifp->if_capenable |= IFCAP_POLLING;
+ DC_UNLOCK(sc);
+ return (error);
+
+ }
+ if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
+ ifp->if_capenable & IFCAP_POLLING) {
+ error = ether_poll_deregister(ifp);
+ /* Enable interrupts. */
+ DC_LOCK(sc);
+ CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ DC_UNLOCK(sc);
+ return (error);
+ }
+#endif /* DEVICE_POLLING */
break;
default:
error = ether_ioctl(ifp, command, data);
@@ -3744,9 +3760,6 @@ dc_stop(struct dc_softc *sc)
callout_stop(&sc->dc_stat_ch);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-#ifdef DEVICE_POLLING
- ether_poll_deregister(ifp);
-#endif
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON));
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c
index f380e1e..3b5db52 100644
--- a/sys/dev/em/if_em.c
+++ b/sys/dev/em/if_em.c
@@ -197,6 +197,9 @@ static int em_sysctl_int_delay(SYSCTL_HANDLER_ARGS);
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 @@ em_detach(device_t dev)
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_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
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 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
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 @@ em_init_locked(struct adapter * adapter)
* 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 @@ em_init(void *arg)
#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 @@ em_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
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 @@ em_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
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 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
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 @@ em_intr(void *arg)
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 @@ em_stop(void *arg)
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 @@ em_setup_interface(device_t dev, struct adapter * adapter)
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
- ifp->if_capenable |= IFCAP_POLLING;
#endif
/*
diff --git a/sys/dev/firewire/00README b/sys/dev/firewire/00README
index d879f31..a6536ae 100644
--- a/sys/dev/firewire/00README
+++ b/sys/dev/firewire/00README
@@ -70,9 +70,6 @@ IEEE 1394 support for FreeBSD-5.X and 4.X.
It also has DEVICE_POLLING[5] support. To enable it, edit your
kernel config file and Makefile.fwe then rebuild kernel and if_fwe.ko.
- Note this driver checks kern.polling.enable only when enabling the
- interface. When you enable polling after the interface is up,
- try 'ifconfig fwe0 down;ifconfig fwe0 up'.
5. FireWire for Kernel Hackers
diff --git a/sys/dev/firewire/if_fwe.c b/sys/dev/firewire/if_fwe.c
index e9d9107..1bf1bcd 100644
--- a/sys/dev/firewire/if_fwe.c
+++ b/sys/dev/firewire/if_fwe.c
@@ -100,19 +100,6 @@ TUNABLE_INT("hw.firewire.fwe.tx_speed", &tx_speed);
TUNABLE_INT("hw.firewire.fwe.rx_queue_len", &rx_queue_len);
#ifdef DEVICE_POLLING
-#define FWE_POLL_REGISTER(func, fwe, ifp) \
- if (ether_poll_register(func, ifp)) { \
- struct firewire_comm *fc = (fwe)->fd.fc; \
- fc->set_intr(fc, 0); \
- }
-
-#define FWE_POLL_DEREGISTER(fwe, ifp) \
- do { \
- struct firewire_comm *fc = (fwe)->fd.fc; \
- ether_poll_deregister(ifp); \
- fc->set_intr(fc, 1); \
- } while(0) \
-
static poll_handler_t fwe_poll;
static void
@@ -121,19 +108,15 @@ fwe_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
struct fwe_softc *fwe;
struct firewire_comm *fc;
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ return;
+
fwe = ((struct fwe_eth_softc *)ifp->if_softc)->fwe;
fc = fwe->fd.fc;
- if (cmd == POLL_DEREGISTER) {
- /* enable interrupts */
- fc->set_intr(fc, 1);
- return;
- }
fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count);
}
-#else
-#define FWE_POLL_REGISTER(func, fwe, ifp)
-#define FWE_POLL_DEREGISTER(fwe, ifp)
-#endif
+#endif /* DEVICE_POLLING */
+
static void
fwe_identify(driver_t *driver, device_t parent)
{
@@ -242,7 +225,7 @@ fwe_attach(device_t dev)
/* Tell the upper layer(s) we support long frames. */
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
- ifp->if_capabilities |= IFCAP_VLAN_MTU;
+ ifp->if_capabilities |= IFCAP_VLAN_MTU & IFCAP_POLLING;
ifp->if_capenable |= IFCAP_VLAN_MTU;
#endif
@@ -262,8 +245,6 @@ fwe_stop(struct fwe_softc *fwe)
fc = fwe->fd.fc;
- FWE_POLL_DEREGISTER(fwe, ifp);
-
if (fwe->dma_ch >= 0) {
xferq = fc->ir[fwe->dma_ch];
@@ -305,6 +286,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);
+#endif
s = splimp();
fwe_stop(fwe);
@@ -416,7 +402,6 @@ found:
ifp->if_flags &= ~IFF_OACTIVE;
#endif
- FWE_POLL_REGISTER(fwe_poll, fwe, ifp);
#if 0
/* attempt to start output */
fwe_start(ifp);
@@ -468,6 +453,34 @@ fwe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
fwe->stream_ch, fwe->dma_ch);
splx(s);
break;
+ case SIOCSIFCAP:
+#ifdef DEVICE_POLLING
+ {
+ 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);
+ 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);
+ /* Enable interrupts. */
+ fc->set_intr(fc, 1);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ return (error);
+ }
+ }
+#endif /* DEVICE_POLLING */
+ break;
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
default:
#else
@@ -634,9 +647,7 @@ fwe_as_input(struct fw_xferq *xferq)
fwe = (struct fwe_softc *)xferq->sc;
ifp = fwe->eth_softc.ifp;
-#if 0
- FWE_POLL_REGISTER(fwe_poll, fwe, ifp);
-#endif
+
while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) {
STAILQ_REMOVE_HEAD(&xferq->stvalid, link);
fp = mtod(sxfer->mbuf, struct fw_pkt *);
diff --git a/sys/dev/firewire/if_fwip.c b/sys/dev/firewire/if_fwip.c
index 20916bc..b3fdda4 100644
--- a/sys/dev/firewire/if_fwip.c
+++ b/sys/dev/firewire/if_fwip.c
@@ -107,19 +107,6 @@ SYSCTL_INT(_hw_firewire_fwip, OID_AUTO, rx_queue_len, CTLFLAG_RW, &rx_queue_len,
TUNABLE_INT("hw.firewire.fwip.rx_queue_len", &rx_queue_len);
#ifdef DEVICE_POLLING
-#define FWIP_POLL_REGISTER(func, fwip, ifp) \
- if (ether_poll_register(func, ifp)) { \
- struct firewire_comm *fc = (fwip)->fd.fc; \
- fc->set_intr(fc, 0); \
- }
-
-#define FWIP_POLL_DEREGISTER(fwip, ifp) \
- do { \
- struct firewire_comm *fc = (fwip)->fd.fc; \
- ether_poll_deregister(ifp); \
- fc->set_intr(fc, 1); \
- } while(0) \
-
static poll_handler_t fwip_poll;
static void
@@ -128,19 +115,15 @@ fwip_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
struct fwip_softc *fwip;
struct firewire_comm *fc;
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ return;
+
fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip;
fc = fwip->fd.fc;
- if (cmd == POLL_DEREGISTER) {
- /* enable interrupts */
- fc->set_intr(fc, 1);
- return;
- }
fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count);
}
-#else
-#define FWIP_POLL_REGISTER(func, fwip, ifp)
-#define FWIP_POLL_DEREGISTER(fwip, ifp)
-#endif
+#endif /* DEVICE_POLLING */
+
static void
fwip_identify(driver_t *driver, device_t parent)
{
@@ -214,6 +197,9 @@ fwip_attach(device_t dev)
ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|
IFF_NEEDSGIANT);
ifp->if_snd.ifq_maxlen = TX_MAX_QUEUE;
+#ifdef DEVICE_POLLING
+ ifp->if_capabilities |= IFCAP_POLLING;
+#endif
s = splimp();
firewire_ifattach(ifp, hwaddr);
@@ -234,8 +220,6 @@ fwip_stop(struct fwip_softc *fwip)
fc = fwip->fd.fc;
- FWIP_POLL_DEREGISTER(fwip, ifp);
-
if (fwip->dma_ch >= 0) {
xferq = fc->ir[fwip->dma_ch];
@@ -279,14 +263,22 @@ static int
fwip_detach(device_t dev)
{
struct fwip_softc *fwip;
+ struct ifnet *ifp;
int s;
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);
+#endif
+
s = splimp();
fwip_stop(fwip);
- firewire_ifdetach(fwip->fw_softc.fwip_ifp);
- if_free(fwip->fw_softc.fwip_ifp);
+ firewire_ifdetach(ifp);
+ if_free(ifp);
splx(s);
return 0;
@@ -408,7 +400,6 @@ found:
ifp->if_flags &= ~IFF_OACTIVE;
#endif
- FWIP_POLL_REGISTER(fwip_poll, fwip, ifp);
#if 0
/* attempt to start output */
fwip_start(ifp);
@@ -444,7 +435,34 @@ fwip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCADDMULTI:
case SIOCDELMULTI:
break;
-
+ case SIOCSIFCAP:
+#ifdef DEVICE_POLLING
+ {
+ 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);
+ 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);
+ /* Enable interrupts. */
+ fc->set_intr(fc, 1);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ return (error);
+ }
+ }
+#endif /* DEVICE_POLLING */
+ break;
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
default:
#else
@@ -757,9 +775,7 @@ fwip_stream_input(struct fw_xferq *xferq)
fwip = (struct fwip_softc *)xferq->sc;
ifp = fwip->fw_softc.fwip_ifp;
-#if 0
- FWIP_POLL_REGISTER(fwip_poll, fwip, ifp);
-#endif
+
while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) {
STAILQ_REMOVE_HEAD(&xferq->stvalid, link);
fp = mtod(sxfer->mbuf, struct fw_pkt *);
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index 944876d..133a96a 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -773,7 +773,6 @@ fxp_attach(device_t dev)
#ifdef DEVICE_POLLING
/* Inform the world we support polling. */
ifp->if_capabilities |= IFCAP_POLLING;
- ifp->if_capenable |= IFCAP_POLLING;
#endif
/*
@@ -891,6 +890,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);
+#endif
+
FXP_LOCK(sc);
sc->suspended = 1; /* Do same thing as we do for suspend */
/*
@@ -1448,15 +1452,11 @@ fxp_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
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 @@ fxp_intr(void *xsc)
}
#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 @@ fxp_stop(struct fxp_softc *sc)
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 @@ fxp_init_body(struct fxp_softc *sc)
* ... 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 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
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 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
sc->flags ^= flag;
if (ifp->if_flags & IFF_UP)
fxp_init_body(sc);
+ FXP_UNLOCK(sc);
}
- FXP_UNLOCK(sc);
break;
default:
diff --git a/sys/dev/ixgb/README b/sys/dev/ixgb/README
index 33f85a7..1508eac 100644
--- a/sys/dev/ixgb/README
+++ b/sys/dev/ixgb/README
@@ -196,18 +196,17 @@ all PRO/10GbE adapters.
options DEVICE_POLLING
options HZ=1000
- At runtime, use the following command to turn on polling mode. Similarly,
- turn off polling mode by setting the variable to 0:
+ At runtime, use the following command to turn on polling mode.
- sysctl kern.polling.enable=1
+ ifconfig ixgb0 polling
+ Similarly, turn off polling mode by removing IFCAP_POLLING flag from
+ interface:
- NOTES: DEVICE POLLING is only valid for non-SMP kernels.
-
- The driver has to be built into the kernel for DEVICE POLLING to be
- enabled in the driver.
-
+ ifconfig ixgb0 -polling
+ The driver has to be built into the kernel for DEVICE POLLING to be
+ enabled in the driver.
Support
=======
diff --git a/sys/dev/ixgb/if_ixgb.c b/sys/dev/ixgb/if_ixgb.c
index 4cb9caa..d273542 100644
--- a/sys/dev/ixgb/if_ixgb.c
+++ b/sys/dev/ixgb/if_ixgb.c
@@ -141,6 +141,9 @@ static int
ixgb_dma_malloc(struct adapter *, bus_size_t,
struct ixgb_dma_alloc *, int);
static void ixgb_dma_free(struct adapter *, struct ixgb_dma_alloc *);
+#ifdef DEVICE_POLLING
+static poll_handler_t ixgb_poll;
+#endif
/*********************************************************************
* FreeBSD Device Interface Entry Points
@@ -368,6 +371,11 @@ ixgb_detach(device_t dev)
INIT_DEBUGOUT("ixgb_detach: begin");
+#ifdef DEVICE_POLLING
+ if (ifp->if_capenable & IFCAP_POLLING)
+ ether_poll_deregister(ifp);
+#endif
+
IXGB_LOCK(adapter);
adapter->in_detach = 1;
@@ -557,6 +565,26 @@ ixgb_ioctl(struct ifnet * ifp, IOCTL_CMD_TYPE command, caddr_t data)
case SIOCSIFCAP:
IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)");
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+#ifdef DEVICE_POLLING
+ if (mask & IFCAP_POLLING) {
+ if (ifr->ifr_reqcap & IFCAP_POLLING) {
+ error = ether_poll_register(ixgb_poll, ifp);
+ if (error)
+ return(error);
+ IXGB_LOCK(adapter);
+ ixgb_disable_intr(adapter);
+ ifp->if_capenable |= IFCAP_POLLING;
+ IXGB_UNLOCK(adapter);
+ } else {
+ error = ether_poll_deregister(ifp);
+ /* Enable interrupt even in error case */
+ IXGB_LOCK(adapter);
+ ixgb_enable_intr(adapter);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ IXGB_UNLOCK(adapter);
+ }
+ }
+#endif /* DEVICE_POLLING */
if (mask & IFCAP_HWCSUM) {
if (IFCAP_HWCSUM & ifp->if_capenable)
ifp->if_capenable &= ~IFCAP_HWCSUM;
@@ -695,10 +723,10 @@ ixgb_init_locked(struct adapter *adapter)
* Only disable interrupts if we are polling, make sure they are on
* otherwise.
*/
- if (ifp->if_flags & IFF_POLLING)
+ if (ifp->if_capenable & IFCAP_POLLING)
ixgb_disable_intr(adapter);
else
-#endif /* DEVICE_POLLING */
+#endif
ixgb_enable_intr(adapter);
return;
@@ -716,8 +744,6 @@ ixgb_init(void *arg)
}
#ifdef DEVICE_POLLING
-static poll_handler_t ixgb_poll;
-
static void
ixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count)
{
@@ -726,15 +752,6 @@ ixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count)
IXGB_LOCK_ASSERT(adapter);
- if (!(ifp->if_capenable & IFCAP_POLLING)) {
- ether_poll_deregister(ifp);
- cmd = POLL_DEREGISTER;
- }
-
- if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */
- ixgb_enable_intr(adapter);
- return;
- }
if (cmd == POLL_AND_CHECK_STATUS) {
reg_icr = IXGB_READ_REG(&adapter->hw, ICR);
if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
@@ -745,12 +762,10 @@ ixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count)
adapter);
}
}
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- ixgb_process_receive_interrupts(adapter, count);
- ixgb_clean_transmit_interrupts(adapter);
- }
- if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
- ifp->if_snd.ifq_head != NULL)
+ ixgb_process_receive_interrupts(adapter, count);
+ ixgb_clean_transmit_interrupts(adapter);
+
+ if (ifp->if_snd.ifq_head != NULL)
ixgb_start_locked(ifp);
}
@@ -760,10 +775,11 @@ ixgb_poll(struct ifnet * ifp, enum poll_cmd cmd, int count)
struct adapter *adapter = ifp->if_softc;
IXGB_LOCK(adapter);
- ixgb_poll_locked(ifp, cmd, count);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ixgb_poll_locked(ifp, cmd, count);
IXGB_UNLOCK(adapter);
}
-#endif /* DEVICE_POLLING */
+#endif /* DEVICE_POLLING */
/*********************************************************************
*
@@ -785,19 +801,11 @@ ixgb_intr(void *arg)
ifp = adapter->ifp;
#ifdef DEVICE_POLLING
- if (ifp->if_flags & IFF_POLLING) {
- IXGB_UNLOCK(adapter);
- return;
- }
-
- if ((ifp->if_capenable & IFCAP_POLLING) &&
- ether_poll_register(ixgb_poll, ifp)) {
- ixgb_disable_intr(adapter);
- ixgb_poll_locked(ifp, 0, 1);
+ if (ifp->if_capenable & IFCAP_POLLING) {
IXGB_UNLOCK(adapter);
return;
}
-#endif /* DEVICE_POLLING */
+#endif
reg_icr = IXGB_READ_REG(&adapter->hw, ICR);
if (reg_icr == 0) {
@@ -1355,9 +1363,6 @@ ixgb_setup_interface(device_t dev, struct adapter * adapter)
#endif
ifp->if_capabilities = IFCAP_HWCSUM;
-#ifdef DEVICE_POLLING
- ifp->if_capabilities |= IFCAP_POLLING;
-#endif
/*
* Tell the upper layer(s) we support long frames.
@@ -1370,6 +1375,10 @@ ixgb_setup_interface(device_t dev, struct adapter * adapter)
ifp->if_capenable = ifp->if_capabilities;
+#ifdef DEVICE_POLLING
+ ifp->if_capabilities |= IFCAP_POLLING;
+#endif
+
/*
* Specify the media types supported by this adapter and register
* callbacks to update media and link information
diff --git a/sys/dev/nge/if_nge.c b/sys/dev/nge/if_nge.c
index a14d4ef..e8a89ea 100644
--- a/sys/dev/nge/if_nge.c
+++ b/sys/dev/nge/if_nge.c
@@ -869,10 +869,10 @@ nge_attach(dev)
ifp->if_snd.ifq_maxlen = NGE_TX_LIST_CNT - 1;
ifp->if_hwassist = NGE_CSUM_FEATURES;
ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_HWTAGGING;
+ ifp->if_capenable = ifp->if_capabilities;
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
#endif
- ifp->if_capenable = ifp->if_capabilities;
/*
* Do MII setup.
@@ -958,6 +958,10 @@ 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);
+#endif
NGE_LOCK(sc);
nge_reset(sc);
nge_stop(sc);
@@ -1126,12 +1130,12 @@ nge_rxeof(sc)
u_int32_t extsts;
#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->nge_ldata->nge_rx_list[i];
rxstat = cur_rx->nge_rxstat;
@@ -1376,12 +1380,7 @@ nge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
struct nge_softc *sc = ifp->if_softc;
NGE_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_4(sc, NGE_IER, 1);
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
NGE_UNLOCK(sc);
return;
}
@@ -1433,18 +1432,11 @@ nge_intr(arg)
NGE_LOCK(sc);
#ifdef DEVICE_POLLING
- if (ifp->if_flags & IFF_POLLING) {
- NGE_UNLOCK(sc);
- return;
- }
- if ((ifp->if_capenable & IFCAP_POLLING) &&
- ether_poll_register(nge_poll, ifp)) { /* ok, disable interrupts */
- CSR_WRITE_4(sc, NGE_IER, 0);
+ if (ifp->if_capenable & IFCAP_POLLING) {
NGE_UNLOCK(sc);
- nge_poll(ifp, 0, 1);
return;
}
-#endif /* DEVICE_POLLING */
+#endif
/* Supress unwanted interrupts */
if (!(ifp->if_flags & IFF_UP)) {
@@ -1840,10 +1832,10 @@ nge_init_locked(sc)
* ... 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)
CSR_WRITE_4(sc, NGE_IER, 0);
else
-#endif /* DEVICE_POLLING */
+#endif
CSR_WRITE_4(sc, NGE_IER, 1);
/* Enable receiver and transmitter. */
@@ -2047,8 +2039,31 @@ nge_ioctl(ifp, command, data)
}
break;
case SIOCSIFCAP:
- ifp->if_capenable &= ~IFCAP_POLLING;
- ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING;
+#ifdef DEVICE_POLLING
+ if (ifr->ifr_reqcap & IFCAP_POLLING &&
+ !(ifp->if_capenable & IFCAP_POLLING)) {
+ error = ether_poll_register(nge_poll, ifp);
+ if (error)
+ return(error);
+ NGE_LOCK(sc);
+ /* Disable interrupts */
+ CSR_WRITE_4(sc, NGE_IER, 0);
+ ifp->if_capenable |= IFCAP_POLLING;
+ NGE_UNLOCK(sc);
+ return (error);
+
+ }
+ if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
+ ifp->if_capenable & IFCAP_POLLING) {
+ error = ether_poll_deregister(ifp);
+ /* Enable interrupts. */
+ NGE_LOCK(sc);
+ CSR_WRITE_4(sc, NGE_IER, 1);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ NGE_UNLOCK(sc);
+ return (error);
+ }
+#endif /* DEVICE_POLLING */
break;
default:
error = ether_ioctl(ifp, command, data);
@@ -2105,9 +2120,6 @@ nge_stop(sc)
}
callout_stop(&sc->nge_stat_ch);
-#ifdef DEVICE_POLLING
- ether_poll_deregister(ifp);
-#endif
CSR_WRITE_4(sc, NGE_IER, 0);
CSR_WRITE_4(sc, NGE_IMR, 0);
NGE_SETBIT(sc, NGE_CSR, NGE_CSR_TX_DISABLE|NGE_CSR_RX_DISABLE);
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c
index c3ce9d7..72fff4e 100644
--- a/sys/dev/re/if_re.c
+++ b/sys/dev/re/if_re.c
@@ -1202,6 +1202,7 @@ re_attach(dev)
ifp->if_start = re_start;
ifp->if_hwassist = /*RE_CSUM_FEATURES*/0;
ifp->if_capabilities |= IFCAP_HWCSUM|IFCAP_VLAN_HWTAGGING;
+ ifp->if_capenable = ifp->if_capabilities & ~IFCAP_HWCSUM;
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
#endif
@@ -1214,7 +1215,6 @@ re_attach(dev)
IFQ_SET_MAXLEN(&ifp->if_snd, RL_IFQ_MAXLEN);
ifp->if_snd.ifq_drv_maxlen = RL_IFQ_MAXLEN;
IFQ_SET_READY(&ifp->if_snd);
- ifp->if_capenable = ifp->if_capabilities & ~IFCAP_HWCSUM;
/*
* Call MI attach routine.
@@ -1264,6 +1264,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);
+#endif
+
/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
RL_LOCK(sc);
@@ -1756,7 +1761,8 @@ re_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
struct rl_softc *sc = ifp->if_softc;
RL_LOCK(sc);
- re_poll_locked(ifp, cmd, count);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ re_poll_locked(ifp, cmd, count);
RL_UNLOCK(sc);
}
@@ -1767,15 +1773,6 @@ re_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
RL_LOCK_ASSERT(sc);
- if (!(ifp->if_capenable & IFCAP_POLLING)) {
- ether_poll_deregister(ifp);
- cmd = POLL_DEREGISTER;
- }
- if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */
- CSR_WRITE_2(sc, RL_IMR, RL_INTRS_CPLUS);
- return;
- }
-
sc->rxcycles = count;
re_rxeof(sc);
re_txeof(sc);
@@ -1822,15 +1819,9 @@ re_intr(arg)
goto done_locked;
#ifdef DEVICE_POLLING
- if (ifp->if_flags & IFF_POLLING)
+ if (ifp->if_capenable & IFCAP_POLLING)
goto done_locked;
- if ((ifp->if_capenable & IFCAP_POLLING) &&
- ether_poll_register(re_poll, ifp)) { /* ok, disable interrupts */
- CSR_WRITE_2(sc, RL_IMR, 0x0000);
- re_poll_locked(ifp, 0, 1);
- goto done_locked;
- }
-#endif /* DEVICE_POLLING */
+#endif
for (;;) {
@@ -2171,10 +2162,10 @@ re_init_locked(sc)
/*
* Disable interrupts if we are polling.
*/
- if (ifp->if_flags & IFF_POLLING)
+ if (ifp->if_capenable & IFCAP_POLLING)
CSR_WRITE_2(sc, RL_IMR, 0);
else /* otherwise ... */
-#endif /* DEVICE_POLLING */
+#endif
/*
* Enable interrupts.
*/
@@ -2289,7 +2280,7 @@ re_ioctl(ifp, command, data)
struct rl_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
struct mii_data *mii;
- int error;
+ int error = 0;
switch (command) {
case SIOCSIFMTU:
@@ -2298,7 +2289,6 @@ re_ioctl(ifp, command, data)
error = EINVAL;
ifp->if_mtu = ifr->ifr_mtu;
RL_UNLOCK(sc);
- error = 0;
break;
case SIOCSIFFLAGS:
RL_LOCK(sc);
@@ -2307,14 +2297,12 @@ re_ioctl(ifp, command, data)
else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
re_stop(sc);
RL_UNLOCK(sc);
- error = 0;
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
RL_LOCK(sc);
re_setmulti(sc);
RL_UNLOCK(sc);
- error = 0;
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
@@ -2322,18 +2310,42 @@ re_ioctl(ifp, command, data)
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
break;
case SIOCSIFCAP:
- RL_LOCK(sc);
- ifp->if_capenable &= ~(IFCAP_HWCSUM | IFCAP_POLLING);
- ifp->if_capenable |=
- ifr->ifr_reqcap & (IFCAP_HWCSUM | IFCAP_POLLING);
- if (ifp->if_capenable & IFCAP_TXCSUM)
- ifp->if_hwassist = RE_CSUM_FEATURES;
- else
- ifp->if_hwassist = 0;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- re_init_locked(sc);
- RL_UNLOCK(sc);
- error = 0;
+ {
+ 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);
+ 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);
+ /* Enable interrupts. */
+ RL_LOCK(sc);
+ CSR_WRITE_2(sc, RL_IMR, RL_INTRS_CPLUS);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ RL_UNLOCK(sc);
+ }
+ }
+#endif /* DEVICE_POLLING */
+ if (mask & IFCAP_HWCSUM) {
+ RL_LOCK(sc);
+ ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_HWCSUM;
+ if (ifp->if_capenable & IFCAP_TXCSUM)
+ ifp->if_hwassist = RE_CSUM_FEATURES;
+ else
+ ifp->if_hwassist = 0;
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ re_init_locked(sc);
+ RL_UNLOCK(sc);
+ }
+ }
break;
default:
error = ether_ioctl(ifp, command, data);
@@ -2379,9 +2391,6 @@ re_stop(sc)
callout_stop(&sc->rl_stat_callout);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-#ifdef DEVICE_POLLING
- ether_poll_deregister(ifp);
-#endif /* DEVICE_POLLING */
CSR_WRITE_1(sc, RL_COMMAND, 0x00);
CSR_WRITE_2(sc, RL_IMR, 0x0000);
diff --git a/sys/dev/sf/if_sf.c b/sys/dev/sf/if_sf.c
index fa7eb83..691a0f6 100644
--- a/sys/dev/sf/if_sf.c
+++ b/sys/dev/sf/if_sf.c
@@ -165,11 +165,9 @@ 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_locked(struct ifnet *ifp, enum poll_cmd cmd,
- int count);
-#endif /* DEVICE_POLLING */
+static void sf_poll(struct ifnet *ifp, 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);
@@ -560,10 +558,31 @@ sf_ioctl(ifp, command, data)
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
break;
case SIOCSIFCAP:
- SF_LOCK(sc);
- ifp->if_capenable &= ~IFCAP_POLLING;
- ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING;
- SF_UNLOCK(sc);
+#ifdef DEVICE_POLLING
+ if (ifr->ifr_reqcap & IFCAP_POLLING &&
+ !(ifp->if_capenable & IFCAP_POLLING)) {
+ error = ether_poll_register(sf_poll, ifp);
+ if (error)
+ return(error);
+ SF_LOCK(sc);
+ /* Disable interrupts */
+ csr_write_4(sc, SF_IMR, 0x00000000);
+ ifp->if_capenable |= IFCAP_POLLING;
+ SF_UNLOCK(sc);
+ return (error);
+
+ }
+ if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
+ ifp->if_capenable & IFCAP_POLLING) {
+ error = ether_poll_deregister(ifp);
+ /* Enable interrupts. */
+ SF_LOCK(sc);
+ csr_write_4(sc, SF_IMR, SF_INTRS);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ SF_UNLOCK(sc);
+ return (error);
+ }
+#endif /* DEVICE_POLLING */
break;
default:
error = ether_ioctl(ifp, command, data);
@@ -749,10 +768,10 @@ sf_attach(dev)
IFQ_SET_MAXLEN(&ifp->if_snd, SF_TX_DLIST_CNT - 1);
ifp->if_snd.ifq_drv_maxlen = SF_TX_DLIST_CNT - 1;
IFQ_SET_READY(&ifp->if_snd);
+ ifp->if_capenable = ifp->if_capabilities;
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
-#endif /* DEVICE_POLLING */
- ifp->if_capenable = ifp->if_capabilities;
+#endif
/*
* Call MI attach routine.
@@ -794,6 +813,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);
+#endif
+
/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
SF_LOCK(sc);
@@ -946,12 +970,12 @@ sf_rxeof(sc)
struct mbuf *m0;
#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->sf_ldata->sf_rx_clist[cmpconsidx];
desc = &sc->sf_ldata->sf_rx_dlist_big[cur_rx->sf_endidx];
@@ -1068,7 +1092,8 @@ sf_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
struct sf_softc *sc = ifp->if_softc;
SF_LOCK(sc);
- sf_poll_locked(ifp, cmd, count);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ sf_poll_locked(ifp, cmd, count);
SF_UNLOCK(sc);
}
@@ -1079,17 +1104,6 @@ sf_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
SF_LOCK_ASSERT(sc);
- if (!(ifp->if_capenable & IFCAP_POLLING)) {
- ether_poll_deregister(ifp);
- cmd = POLL_DEREGISTER;
- }
-
- if (cmd == POLL_DEREGISTER) {
- /* Final call, enable interrupts. */
- csr_write_4(sc, SF_IMR, SF_INTRS);
- return;
- }
-
sc->rxcycles = count;
sf_rxeof(sc);
sf_txeof(sc);
@@ -1131,17 +1145,11 @@ sf_intr(arg)
ifp = sc->sf_ifp;
#ifdef DEVICE_POLLING
- if (ifp->if_flags & IFF_POLLING)
- goto done_locked;
-
- if ((ifp->if_capenable & IFCAP_POLLING) &&
- ether_poll_register(sf_poll, ifp)) {
- /* OK, disable interrupts. */
- csr_write_4(sc, SF_IMR, 0x00000000);
- sf_poll_locked(ifp, 0, 1);
- goto done_locked;
+ if (ifp->if_capenable & IFCAP_POLLING) {
+ SF_UNLOCK(sc);
+ return;
}
-#endif /* DEVICE_POLLING */
+#endif
if (!(csr_read_4(sc, SF_ISR_SHADOW) & SF_ISR_PCIINT_ASSERTED)) {
SF_UNLOCK(sc);
@@ -1185,9 +1193,6 @@ sf_intr(arg)
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
sf_start_locked(ifp);
-#ifdef DEVICE_POLLING
-done_locked:
-#endif /* DEVICE_POLLING */
SF_UNLOCK(sc);
}
@@ -1296,10 +1301,10 @@ sf_init_locked(sc)
#ifdef DEVICE_POLLING
/* Disable interrupts if we are polling. */
- if (ifp->if_flags & IFF_POLLING)
+ if (ifp->if_capenable & IFCAP_POLLING)
csr_write_4(sc, SF_IMR, 0x00000000);
else
-#endif /* DEVICE_POLLING */
+#endif
/* Enable interrupts. */
csr_write_4(sc, SF_IMR, SF_INTRS);
@@ -1478,10 +1483,6 @@ sf_stop(sc)
callout_stop(&sc->sf_stat_callout);
-#ifdef DEVICE_POLLING
- ether_poll_deregister(ifp);
-#endif /* DEVICE_POLLING */
-
csr_write_4(sc, SF_GEN_ETH_CTL, 0);
csr_write_4(sc, SF_CQ_CONSIDX, 0);
csr_write_4(sc, SF_CQ_PRODIDX, 0);
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);
diff --git a/sys/dev/vr/if_vr.c b/sys/dev/vr/if_vr.c
index 5eabc21..b3c92ea 100644
--- a/sys/dev/vr/if_vr.c
+++ b/sys/dev/vr/if_vr.c
@@ -742,10 +742,10 @@ vr_attach(dev)
IFQ_SET_MAXLEN(&ifp->if_snd, VR_TX_LIST_CNT - 1);
ifp->if_snd.ifq_maxlen = VR_TX_LIST_CNT - 1;
IFQ_SET_READY(&ifp->if_snd);
+ ifp->if_capenable = ifp->if_capabilities;
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
#endif
- ifp->if_capenable = ifp->if_capabilities;
/* Do MII setup. */
if (mii_phy_probe(dev, &sc->vr_miibus,
@@ -794,6 +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);
+#endif
+
VR_LOCK(sc);
sc->suspended = 1;
@@ -952,12 +957,12 @@ vr_rxeof(struct vr_softc *sc)
while (!((rxstat = sc->vr_cdata.vr_rx_head->vr_ptr->vr_status) &
VR_RXSTAT_OWN)) {
#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
m0 = NULL;
cur_rx = sc->vr_cdata.vr_rx_head;
sc->vr_cdata.vr_rx_head = cur_rx->vr_nextdesc;
@@ -1151,7 +1156,8 @@ vr_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
struct vr_softc *sc = ifp->if_softc;
VR_LOCK(sc);
- vr_poll_locked(ifp, cmd, count);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ vr_poll_locked(ifp, cmd, count);
VR_UNLOCK(sc);
}
@@ -1162,17 +1168,6 @@ vr_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
VR_LOCK_ASSERT(sc);
- if (!(ifp->if_capenable & IFCAP_POLLING)) {
- ether_poll_deregister(ifp);
- cmd = POLL_DEREGISTER;
- }
-
- if (cmd == POLL_DEREGISTER) {
- /* Final call, enable interrupts. */
- CSR_WRITE_2(sc, VR_IMR, VR_INTRS);
- return;
- }
-
sc->rxcycles = count;
vr_rxeof(sc);
vr_txeof(sc);
@@ -1249,17 +1244,9 @@ vr_intr(void *arg)
}
#ifdef DEVICE_POLLING
- if (ifp->if_flags & IFF_POLLING)
+ if (ifp->if_capenable & IFCAP_POLLING)
goto done_locked;
-
- if ((ifp->if_capenable & IFCAP_POLLING) &&
- ether_poll_register(vr_poll, ifp)) {
- /* OK, disable interrupts. */
- CSR_WRITE_2(sc, VR_IMR, 0x0000);
- vr_poll_locked(ifp, 0, 1);
- goto done_locked;
- }
-#endif /* DEVICE_POLLING */
+#endif
/* Suppress unwanted interrupts. */
if (!(ifp->if_flags & IFF_UP)) {
@@ -1534,10 +1521,10 @@ vr_init_locked(struct vr_softc *sc)
/*
* Disable interrupts if we are polling.
*/
- if (ifp->if_flags & IFF_POLLING)
+ if (ifp->if_capenable & IFCAP_POLLING)
CSR_WRITE_2(sc, VR_IMR, 0);
else
-#endif /* DEVICE_POLLING */
+#endif
/*
* Enable interrupts.
*/
@@ -1615,7 +1602,31 @@ vr_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
break;
case SIOCSIFCAP:
- ifp->if_capenable = ifr->ifr_reqcap;
+#ifdef DEVICE_POLLING
+ if (ifr->ifr_reqcap & IFCAP_POLLING &&
+ !(ifp->if_capenable & IFCAP_POLLING)) {
+ error = ether_poll_register(vr_poll, ifp);
+ if (error)
+ return(error);
+ VR_LOCK(sc);
+ /* Disable interrupts */
+ CSR_WRITE_2(sc, VR_IMR, 0x0000);
+ ifp->if_capenable |= IFCAP_POLLING;
+ VR_UNLOCK(sc);
+ return (error);
+
+ }
+ if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
+ ifp->if_capenable & IFCAP_POLLING) {
+ error = ether_poll_deregister(ifp);
+ /* Enable interrupts. */
+ VR_LOCK(sc);
+ CSR_WRITE_2(sc, VR_IMR, VR_INTRS);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ VR_UNLOCK(sc);
+ return (error);
+ }
+#endif /* DEVICE_POLLING */
break;
default:
error = ether_ioctl(ifp, command, data);
@@ -1662,9 +1673,6 @@ vr_stop(struct vr_softc *sc)
untimeout(vr_tick, sc, sc->vr_stat_ch);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-#ifdef DEVICE_POLLING
- ether_poll_deregister(ifp);
-#endif /* DEVICE_POLLING */
VR_SETBIT16(sc, VR_COMMAND, VR_CMD_STOP);
VR_CLRBIT16(sc, VR_COMMAND, (VR_CMD_RX_ON|VR_CMD_TX_ON));
OpenPOWER on IntegriCloud