diff options
Diffstat (limited to 'sys/pci/if_ste.c')
-rw-r--r-- | sys/pci/if_ste.c | 73 |
1 files changed, 41 insertions, 32 deletions
diff --git a/sys/pci/if_ste.c b/sys/pci/if_ste.c index eca7e11..f80e676 100644 --- a/sys/pci/if_ste.c +++ b/sys/pci/if_ste.c @@ -621,7 +621,8 @@ ste_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) struct ste_softc *sc = ifp->if_softc; STE_LOCK(sc); - ste_poll_locked(ifp, cmd, count); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + ste_poll_locked(ifp, cmd, count); STE_UNLOCK(sc); } @@ -631,14 +632,6 @@ ste_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count) struct ste_softc *sc = ifp->if_softc; STE_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, STE_IMR, STE_INTRS); - return; - } sc->rxcycles = count; if (cmd == POLL_AND_CHECK_STATUS) @@ -685,15 +678,11 @@ ste_intr(xsc) ifp = sc->ste_ifp; #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) - goto done; - if ((ifp->if_capenable & IFCAP_POLLING) && - ether_poll_register(ste_poll, ifp)) { /* ok, disable interrupts */ - CSR_WRITE_2(sc, STE_IMR, 0); - ste_poll_locked(ifp, 0, 1); - goto done; + if (ifp->if_capenable & IFCAP_POLLING) { + STE_UNLOCK(sc); + return; } -#endif /* DEVICE_POLLING */ +#endif /* See if this is really our interrupt. */ if (!(CSR_READ_2(sc, STE_ISR) & STE_ISR_INTLATCH)) { @@ -739,9 +728,6 @@ ste_intr(xsc) if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) ste_start_locked(ifp); -#ifdef DEVICE_POLLING -done: -#endif /* DEVICE_POLLING */ STE_UNLOCK(sc); return; @@ -791,12 +777,12 @@ ste_rxeof(sc) while((rxstat = sc->ste_cdata.ste_rx_head->ste_ptr->ste_status) & STE_RXSTAT_DMADONE) { #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 if ((STE_RX_LIST_CNT - count) < 3) { break; } @@ -1115,10 +1101,10 @@ ste_attach(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; /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->ste_irq, INTR_TYPE_NET | INTR_MPSAFE, @@ -1155,6 +1141,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); +#endif + /* These should only be active if attach succeeded */ if (device_is_attached(dev)) { STE_LOCK(sc); @@ -1386,10 +1377,10 @@ ste_init_locked(sc) CSR_WRITE_2(sc, STE_ISR, 0xFFFF); #ifdef DEVICE_POLLING /* Disable interrupts if we are polling. */ - if (ifp->if_flags & IFF_POLLING) + if (ifp->if_capenable & IFCAP_POLLING) CSR_WRITE_2(sc, STE_IMR, 0); else -#endif /* DEVICE_POLLING */ +#endif /* Enable interrupts. */ CSR_WRITE_2(sc, STE_IMR, STE_INTRS); @@ -1418,9 +1409,6 @@ ste_stop(sc) callout_stop(&sc->ste_stat_callout); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE); -#ifdef DEVICE_POLLING - ether_poll_deregister(ifp); -#endif /* DEVICE_POLLING */ CSR_WRITE_2(sc, STE_IMR, 0); STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_TX_DISABLE); @@ -1539,10 +1527,31 @@ ste_ioctl(ifp, command, data) error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; case SIOCSIFCAP: - STE_LOCK(sc); - ifp->if_capenable &= ~IFCAP_POLLING; - ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING; - STE_UNLOCK(sc); +#ifdef DEVICE_POLLING + if (ifr->ifr_reqcap & IFCAP_POLLING && + !(ifp->if_capenable & IFCAP_POLLING)) { + error = ether_poll_register(ste_poll, ifp); + if (error) + return(error); + STE_LOCK(sc); + /* Disable interrupts */ + CSR_WRITE_2(sc, STE_IMR, 0); + ifp->if_capenable |= IFCAP_POLLING; + STE_UNLOCK(sc); + return (error); + + } + if (!(ifr->ifr_reqcap & IFCAP_POLLING) && + ifp->if_capenable & IFCAP_POLLING) { + error = ether_poll_deregister(ifp); + /* Enable interrupts. */ + STE_LOCK(sc); + CSR_WRITE_2(sc, STE_IMR, STE_INTRS); + ifp->if_capenable &= ~IFCAP_POLLING; + STE_UNLOCK(sc); + return (error); + } +#endif /* DEVICE_POLLING */ break; default: error = ether_ioctl(ifp, command, data); |