summaryrefslogtreecommitdiffstats
path: root/sys/pci/if_dc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/pci/if_dc.c')
-rw-r--r--sys/pci/if_dc.c69
1 files changed, 41 insertions, 28 deletions
diff --git a/sys/pci/if_dc.c b/sys/pci/if_dc.c
index 8a9e8c6..a6f4304 100644
--- a/sys/pci/if_dc.c
+++ b/sys/pci/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);
OpenPOWER on IntegriCloud