summaryrefslogtreecommitdiffstats
path: root/sys/dev/sf/if_sf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sf/if_sf.c')
-rw-r--r--sys/dev/sf/if_sf.c89
1 files changed, 45 insertions, 44 deletions
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);
OpenPOWER on IntegriCloud