From c8b27aca43d59709360b624314f4b81bf1de01b0 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 18 Aug 2005 19:10:07 +0000 Subject: [PATCH] Fixup locking and mark MPSAFE: - Add locked versions of start and init. The SRM_MEDIA code in dc_init() stayed in dc_init() instead of moving to dc_init_locked() to make the locking saner. - Use callout_init_mtx(). - Fixup locking in detach and ioctl. - Lock the driver in the ifmedia callouts. - Don't recurse on the driver lock. - De-spl. MFC after: 3 days --- sys/dev/dc/if_dc.c | 147 ++++++++++++++++++++++++--------------------- sys/pci/if_dc.c | 147 ++++++++++++++++++++++++--------------------- 2 files changed, 154 insertions(+), 140 deletions(-) diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c index 4daa230bd602..fce20b4e4f5b 100644 --- a/sys/dev/dc/if_dc.c +++ b/sys/dev/dc/if_dc.c @@ -235,8 +235,10 @@ static void dc_tick(void *); static void dc_tx_underrun(struct dc_softc *); static void dc_intr(void *); static void dc_start(struct ifnet *); +static void dc_start_locked(struct ifnet *); static int dc_ioctl(struct ifnet *, u_long, caddr_t); static void dc_init(void *); +static void dc_init_locked(struct dc_softc *); static void dc_stop(struct dc_softc *); static void dc_watchdog(struct ifnet *); static void dc_shutdown(device_t); @@ -343,8 +345,6 @@ DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0); #define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x)) #define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x)) -#define IS_MPSAFE 0 - static void dc_delay(struct dc_softc *sc) { @@ -670,8 +670,6 @@ dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame) { int i, ack; - DC_LOCK(sc); - /* * Set up frame for RX. */ @@ -724,8 +722,6 @@ dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame) dc_mii_writebit(sc, 0); dc_mii_writebit(sc, 0); - DC_UNLOCK(sc); - if (ack) return (1); return (0); @@ -738,7 +734,6 @@ static int dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame) { - DC_LOCK(sc); /* * Set up frame for TX. */ @@ -763,8 +758,6 @@ dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame) dc_mii_writebit(sc, 0); dc_mii_writebit(sc, 0); - DC_UNLOCK(sc); - return (0); } @@ -1844,7 +1837,7 @@ dc_attach(device_t dev) sc = device_get_softc(dev); mtx_init(&sc->dc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); + MTX_DEF); /* * Map control/status registers. @@ -2194,8 +2187,6 @@ dc_attach(device_t dev) /* XXX: bleah, MTU gets overwritten in ether_ifattach() */ ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - if (!IS_MPSAFE) - ifp->if_flags |= IFF_NEEDSGIANT; ifp->if_ioctl = dc_ioctl; ifp->if_start = dc_start; ifp->if_watchdog = dc_watchdog; @@ -2276,7 +2267,7 @@ dc_attach(device_t dev) #endif ifp->if_capenable = ifp->if_capabilities; - callout_init(&sc->dc_stat_ch, IS_MPSAFE ? CALLOUT_MPSAFE : 0); + callout_init_mtx(&sc->dc_stat_ch, &sc->dc_mtx, 0); #ifdef SRM_MEDIA sc->dc_srm_media = 0; @@ -2310,8 +2301,7 @@ dc_attach(device_t dev) ether_ifattach(ifp, eaddr); /* Hook interrupt last to avoid having to lock softc */ - error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET | - (IS_MPSAFE ? INTR_MPSAFE : 0), + error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET | INTR_MPSAFE, dc_intr, sc, &sc->dc_intrhand); if (error) { @@ -2344,13 +2334,15 @@ dc_detach(device_t dev) sc = device_get_softc(dev); KASSERT(mtx_initialized(&sc->dc_mtx), ("dc mutex not initialized")); - DC_LOCK(sc); ifp = sc->dc_ifp; /* These should only be active if attach succeeded */ if (device_is_attached(dev)) { + DC_LOCK(sc); dc_stop(sc); + DC_UNLOCK(sc); + callout_drain(&sc->dc_stat_ch); ether_ifdetach(ifp); if_free(ifp); } @@ -2390,7 +2382,6 @@ dc_detach(device_t dev) } free(sc->dc_srom, M_DEVBUF); - DC_UNLOCK(sc); mtx_destroy(&sc->dc_mtx); return (0); @@ -2751,7 +2742,7 @@ dc_rxeof(struct dc_softc *sc) DC_INC(i, DC_RX_LIST_CNT); continue; } else { - dc_init(sc); + dc_init_locked(sc); return; } } @@ -2879,7 +2870,7 @@ dc_txeof(struct dc_softc *sc) if (txstat & DC_TXSTAT_LATECOLL) ifp->if_collisions++; if (!(txstat & DC_TXSTAT_UNDERRUN)) { - dc_init(sc); + dc_init_locked(sc); return; } } @@ -2918,7 +2909,7 @@ dc_tick(void *xsc) u_int32_t r; sc = xsc; - DC_LOCK(sc); + DC_LOCK_ASSERT(sc); ifp = sc->dc_ifp; mii = device_get_softc(sc->dc_miibus); @@ -2972,15 +2963,13 @@ dc_tick(void *xsc) IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { sc->dc_link++; if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - dc_start(ifp); + dc_start_locked(ifp); } if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link) callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc); else callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc); - - DC_UNLOCK(sc); } /* @@ -2994,7 +2983,7 @@ dc_tx_underrun(struct dc_softc *sc) int i; if (DC_IS_DAVICOM(sc)) - dc_init(sc); + dc_init_locked(sc); if (DC_IS_INTEL(sc)) { /* @@ -3013,7 +3002,7 @@ dc_tx_underrun(struct dc_softc *sc) if (i == DC_TIMEOUT) { if_printf(sc->dc_ifp, "failed to force tx to idle state\n"); - dc_init(sc); + dc_init_locked(sc); } } @@ -3055,7 +3044,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) dc_txeof(sc); if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_drv_flags & IFF_DRV_OACTIVE)) - dc_start(ifp); + dc_start_locked(ifp); if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */ u_int32_t status; @@ -3088,7 +3077,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) if (status & DC_ISR_BUS_ERR) { if_printf(ifp, "dc_poll: bus error\n"); dc_reset(sc); - dc_init(sc); + dc_init_locked(sc); } } DC_UNLOCK(sc); @@ -3175,7 +3164,7 @@ dc_intr(void *arg) if (status & DC_ISR_BUS_ERR) { dc_reset(sc); - dc_init(sc); + dc_init_locked(sc); } } @@ -3183,7 +3172,7 @@ dc_intr(void *arg) CSR_WRITE_4(sc, DC_IMR, DC_INTRS); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - dc_start(ifp); + dc_start_locked(ifp); #ifdef DEVICE_POLLING done: @@ -3310,6 +3299,17 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head) static void dc_start(struct ifnet *ifp) +{ + struct dc_softc *sc; + + sc = ifp->if_softc; + DC_LOCK(sc); + dc_start_locked(ifp); + DC_UNLOCK(sc); +} + +static void +dc_start_locked(struct ifnet *ifp) { struct dc_softc *sc; struct mbuf *m_head = NULL, *m; @@ -3318,17 +3318,13 @@ dc_start(struct ifnet *ifp) sc = ifp->if_softc; - DC_LOCK(sc); + DC_LOCK_ASSERT(sc); - if (!sc->dc_link && ifp->if_snd.ifq_len < 10) { - DC_UNLOCK(sc); + if (!sc->dc_link && ifp->if_snd.ifq_len < 10) return; - } - if (ifp->if_drv_flags & IFF_DRV_OACTIVE) { - DC_UNLOCK(sc); + if (ifp->if_drv_flags & IFF_DRV_OACTIVE) return; - } idx = sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod; @@ -3380,18 +3376,37 @@ dc_start(struct ifnet *ifp) */ ifp->if_timer = 5; } - - DC_UNLOCK(sc); } static void dc_init(void *xsc) { struct dc_softc *sc = xsc; + + DC_LOCK(sc); + dc_init_locked(sc); +#ifdef SRM_MEDIA + if(sc->dc_srm_media) { + struct ifreq ifr; + struct mii_data *mii; + + ifr.ifr_media = sc->dc_srm_media; + sc->dc_srm_media = 0; + DC_UNLOCK(sc); + mii = device_get_softc(sc->dc_miibus); + ifmedia_ioctl(sc->dc_ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA); + } else +#endif + DC_UNLOCK(sc); +} + +static void +dc_init_locked(struct dc_softc *sc) +{ struct ifnet *ifp = sc->dc_ifp; struct mii_data *mii; - DC_LOCK(sc); + DC_LOCK_ASSERT(sc); mii = device_get_softc(sc->dc_miibus); @@ -3487,7 +3502,6 @@ dc_init(void *xsc) if_printf(ifp, "initialization failed: no memory for rx buffers\n"); dc_stop(sc); - DC_UNLOCK(sc); return; } @@ -3559,17 +3573,6 @@ dc_init(void *xsc) else callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc); } - -#ifdef SRM_MEDIA - if(sc->dc_srm_media) { - struct ifreq ifr; - - ifr.ifr_media = sc->dc_srm_media; - ifmedia_ioctl(ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA); - sc->dc_srm_media = 0; - } -#endif - DC_UNLOCK(sc); } /* @@ -3584,6 +3587,7 @@ dc_ifmedia_upd(struct ifnet *ifp) sc = ifp->if_softc; mii = device_get_softc(sc->dc_miibus); + DC_LOCK(sc); mii_mediachg(mii); ifm = &mii->mii_media; @@ -3592,6 +3596,7 @@ dc_ifmedia_upd(struct ifnet *ifp) dc_setcfg(sc, ifm->ifm_media); else sc->dc_link = 0; + DC_UNLOCK(sc); return (0); } @@ -3608,6 +3613,7 @@ dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) sc = ifp->if_softc; mii = device_get_softc(sc->dc_miibus); + DC_LOCK(sc); mii_pollstat(mii); ifm = &mii->mii_media; if (DC_IS_DAVICOM(sc)) { @@ -3619,6 +3625,7 @@ dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) } ifmr->ifm_active = mii->mii_media_active; ifmr->ifm_status = mii->mii_media_status; + DC_UNLOCK(sc); } static int @@ -3629,10 +3636,9 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) struct mii_data *mii; int error = 0; - DC_LOCK(sc); - switch (command) { case SIOCSIFFLAGS: + DC_LOCK(sc); if (ifp->if_flags & IFF_UP) { int need_setfilt = (ifp->if_flags ^ sc->dc_if_flags) & (IFF_PROMISC | IFF_ALLMULTI); @@ -3642,18 +3648,21 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) dc_setfilt(sc); } else { sc->dc_txthresh = 0; - dc_init(sc); + dc_init_locked(sc); } } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) dc_stop(sc); } sc->dc_if_flags = ifp->if_flags; + DC_UNLOCK(sc); error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: + DC_LOCK(sc); dc_setfilt(sc); + DC_UNLOCK(sc); error = 0; break; case SIOCGIFMEDIA: @@ -3661,21 +3670,23 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) mii = device_get_softc(sc->dc_miibus); error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); #ifdef SRM_MEDIA + DC_LOCK(sc); if (sc->dc_srm_media) sc->dc_srm_media = 0; + DC_UNLOCK(sc); #endif break; case SIOCSIFCAP: + DC_LOCK(sc); ifp->if_capenable &= ~IFCAP_POLLING; ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING; + DC_UNLOCK(sc); break; default: error = ether_ioctl(ifp, command, data); break; } - DC_UNLOCK(sc); - return (error); } @@ -3693,10 +3704,10 @@ dc_watchdog(struct ifnet *ifp) dc_stop(sc); dc_reset(sc); - dc_init(sc); + dc_init_locked(sc); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - dc_start(ifp); + dc_start_locked(ifp); DC_UNLOCK(sc); } @@ -3714,7 +3725,7 @@ dc_stop(struct dc_softc *sc) int i; u_int32_t ctl; - DC_LOCK(sc); + DC_LOCK_ASSERT(sc); ifp = sc->dc_ifp; ifp->if_timer = 0; @@ -3762,8 +3773,6 @@ dc_stop(struct dc_softc *sc) } } bzero(&ld->dc_tx_list, sizeof(ld->dc_tx_list)); - - DC_UNLOCK(sc); } /* @@ -3775,15 +3784,13 @@ static int dc_suspend(device_t dev) { struct dc_softc *sc; - int s; - - s = splimp(); sc = device_get_softc(dev); + DC_LOCK(sc); dc_stop(sc); sc->suspended = 1; + DC_UNLOCK(sc); - splx(s); return (0); } @@ -3797,20 +3804,18 @@ dc_resume(device_t dev) { struct dc_softc *sc; struct ifnet *ifp; - int s; - - s = splimp(); sc = device_get_softc(dev); ifp = sc->dc_ifp; /* reinitialize interface if necessary */ + DC_LOCK(sc); if (ifp->if_flags & IFF_UP) - dc_init(sc); + dc_init_locked(sc); sc->suspended = 0; + DC_UNLOCK(sc); - splx(s); return (0); } @@ -3825,5 +3830,7 @@ dc_shutdown(device_t dev) sc = device_get_softc(dev); + DC_LOCK(sc); dc_stop(sc); + DC_UNLOCK(sc); } diff --git a/sys/pci/if_dc.c b/sys/pci/if_dc.c index 4daa230bd602..fce20b4e4f5b 100644 --- a/sys/pci/if_dc.c +++ b/sys/pci/if_dc.c @@ -235,8 +235,10 @@ static void dc_tick(void *); static void dc_tx_underrun(struct dc_softc *); static void dc_intr(void *); static void dc_start(struct ifnet *); +static void dc_start_locked(struct ifnet *); static int dc_ioctl(struct ifnet *, u_long, caddr_t); static void dc_init(void *); +static void dc_init_locked(struct dc_softc *); static void dc_stop(struct dc_softc *); static void dc_watchdog(struct ifnet *); static void dc_shutdown(device_t); @@ -343,8 +345,6 @@ DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0); #define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x)) #define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x)) -#define IS_MPSAFE 0 - static void dc_delay(struct dc_softc *sc) { @@ -670,8 +670,6 @@ dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame) { int i, ack; - DC_LOCK(sc); - /* * Set up frame for RX. */ @@ -724,8 +722,6 @@ dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame) dc_mii_writebit(sc, 0); dc_mii_writebit(sc, 0); - DC_UNLOCK(sc); - if (ack) return (1); return (0); @@ -738,7 +734,6 @@ static int dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame) { - DC_LOCK(sc); /* * Set up frame for TX. */ @@ -763,8 +758,6 @@ dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame) dc_mii_writebit(sc, 0); dc_mii_writebit(sc, 0); - DC_UNLOCK(sc); - return (0); } @@ -1844,7 +1837,7 @@ dc_attach(device_t dev) sc = device_get_softc(dev); mtx_init(&sc->dc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); + MTX_DEF); /* * Map control/status registers. @@ -2194,8 +2187,6 @@ dc_attach(device_t dev) /* XXX: bleah, MTU gets overwritten in ether_ifattach() */ ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - if (!IS_MPSAFE) - ifp->if_flags |= IFF_NEEDSGIANT; ifp->if_ioctl = dc_ioctl; ifp->if_start = dc_start; ifp->if_watchdog = dc_watchdog; @@ -2276,7 +2267,7 @@ dc_attach(device_t dev) #endif ifp->if_capenable = ifp->if_capabilities; - callout_init(&sc->dc_stat_ch, IS_MPSAFE ? CALLOUT_MPSAFE : 0); + callout_init_mtx(&sc->dc_stat_ch, &sc->dc_mtx, 0); #ifdef SRM_MEDIA sc->dc_srm_media = 0; @@ -2310,8 +2301,7 @@ dc_attach(device_t dev) ether_ifattach(ifp, eaddr); /* Hook interrupt last to avoid having to lock softc */ - error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET | - (IS_MPSAFE ? INTR_MPSAFE : 0), + error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET | INTR_MPSAFE, dc_intr, sc, &sc->dc_intrhand); if (error) { @@ -2344,13 +2334,15 @@ dc_detach(device_t dev) sc = device_get_softc(dev); KASSERT(mtx_initialized(&sc->dc_mtx), ("dc mutex not initialized")); - DC_LOCK(sc); ifp = sc->dc_ifp; /* These should only be active if attach succeeded */ if (device_is_attached(dev)) { + DC_LOCK(sc); dc_stop(sc); + DC_UNLOCK(sc); + callout_drain(&sc->dc_stat_ch); ether_ifdetach(ifp); if_free(ifp); } @@ -2390,7 +2382,6 @@ dc_detach(device_t dev) } free(sc->dc_srom, M_DEVBUF); - DC_UNLOCK(sc); mtx_destroy(&sc->dc_mtx); return (0); @@ -2751,7 +2742,7 @@ dc_rxeof(struct dc_softc *sc) DC_INC(i, DC_RX_LIST_CNT); continue; } else { - dc_init(sc); + dc_init_locked(sc); return; } } @@ -2879,7 +2870,7 @@ dc_txeof(struct dc_softc *sc) if (txstat & DC_TXSTAT_LATECOLL) ifp->if_collisions++; if (!(txstat & DC_TXSTAT_UNDERRUN)) { - dc_init(sc); + dc_init_locked(sc); return; } } @@ -2918,7 +2909,7 @@ dc_tick(void *xsc) u_int32_t r; sc = xsc; - DC_LOCK(sc); + DC_LOCK_ASSERT(sc); ifp = sc->dc_ifp; mii = device_get_softc(sc->dc_miibus); @@ -2972,15 +2963,13 @@ dc_tick(void *xsc) IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { sc->dc_link++; if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - dc_start(ifp); + dc_start_locked(ifp); } if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link) callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc); else callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc); - - DC_UNLOCK(sc); } /* @@ -2994,7 +2983,7 @@ dc_tx_underrun(struct dc_softc *sc) int i; if (DC_IS_DAVICOM(sc)) - dc_init(sc); + dc_init_locked(sc); if (DC_IS_INTEL(sc)) { /* @@ -3013,7 +3002,7 @@ dc_tx_underrun(struct dc_softc *sc) if (i == DC_TIMEOUT) { if_printf(sc->dc_ifp, "failed to force tx to idle state\n"); - dc_init(sc); + dc_init_locked(sc); } } @@ -3055,7 +3044,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) dc_txeof(sc); if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_drv_flags & IFF_DRV_OACTIVE)) - dc_start(ifp); + dc_start_locked(ifp); if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */ u_int32_t status; @@ -3088,7 +3077,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) if (status & DC_ISR_BUS_ERR) { if_printf(ifp, "dc_poll: bus error\n"); dc_reset(sc); - dc_init(sc); + dc_init_locked(sc); } } DC_UNLOCK(sc); @@ -3175,7 +3164,7 @@ dc_intr(void *arg) if (status & DC_ISR_BUS_ERR) { dc_reset(sc); - dc_init(sc); + dc_init_locked(sc); } } @@ -3183,7 +3172,7 @@ dc_intr(void *arg) CSR_WRITE_4(sc, DC_IMR, DC_INTRS); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - dc_start(ifp); + dc_start_locked(ifp); #ifdef DEVICE_POLLING done: @@ -3310,6 +3299,17 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head) static void dc_start(struct ifnet *ifp) +{ + struct dc_softc *sc; + + sc = ifp->if_softc; + DC_LOCK(sc); + dc_start_locked(ifp); + DC_UNLOCK(sc); +} + +static void +dc_start_locked(struct ifnet *ifp) { struct dc_softc *sc; struct mbuf *m_head = NULL, *m; @@ -3318,17 +3318,13 @@ dc_start(struct ifnet *ifp) sc = ifp->if_softc; - DC_LOCK(sc); + DC_LOCK_ASSERT(sc); - if (!sc->dc_link && ifp->if_snd.ifq_len < 10) { - DC_UNLOCK(sc); + if (!sc->dc_link && ifp->if_snd.ifq_len < 10) return; - } - if (ifp->if_drv_flags & IFF_DRV_OACTIVE) { - DC_UNLOCK(sc); + if (ifp->if_drv_flags & IFF_DRV_OACTIVE) return; - } idx = sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod; @@ -3380,18 +3376,37 @@ dc_start(struct ifnet *ifp) */ ifp->if_timer = 5; } - - DC_UNLOCK(sc); } static void dc_init(void *xsc) { struct dc_softc *sc = xsc; + + DC_LOCK(sc); + dc_init_locked(sc); +#ifdef SRM_MEDIA + if(sc->dc_srm_media) { + struct ifreq ifr; + struct mii_data *mii; + + ifr.ifr_media = sc->dc_srm_media; + sc->dc_srm_media = 0; + DC_UNLOCK(sc); + mii = device_get_softc(sc->dc_miibus); + ifmedia_ioctl(sc->dc_ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA); + } else +#endif + DC_UNLOCK(sc); +} + +static void +dc_init_locked(struct dc_softc *sc) +{ struct ifnet *ifp = sc->dc_ifp; struct mii_data *mii; - DC_LOCK(sc); + DC_LOCK_ASSERT(sc); mii = device_get_softc(sc->dc_miibus); @@ -3487,7 +3502,6 @@ dc_init(void *xsc) if_printf(ifp, "initialization failed: no memory for rx buffers\n"); dc_stop(sc); - DC_UNLOCK(sc); return; } @@ -3559,17 +3573,6 @@ dc_init(void *xsc) else callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc); } - -#ifdef SRM_MEDIA - if(sc->dc_srm_media) { - struct ifreq ifr; - - ifr.ifr_media = sc->dc_srm_media; - ifmedia_ioctl(ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA); - sc->dc_srm_media = 0; - } -#endif - DC_UNLOCK(sc); } /* @@ -3584,6 +3587,7 @@ dc_ifmedia_upd(struct ifnet *ifp) sc = ifp->if_softc; mii = device_get_softc(sc->dc_miibus); + DC_LOCK(sc); mii_mediachg(mii); ifm = &mii->mii_media; @@ -3592,6 +3596,7 @@ dc_ifmedia_upd(struct ifnet *ifp) dc_setcfg(sc, ifm->ifm_media); else sc->dc_link = 0; + DC_UNLOCK(sc); return (0); } @@ -3608,6 +3613,7 @@ dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) sc = ifp->if_softc; mii = device_get_softc(sc->dc_miibus); + DC_LOCK(sc); mii_pollstat(mii); ifm = &mii->mii_media; if (DC_IS_DAVICOM(sc)) { @@ -3619,6 +3625,7 @@ dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) } ifmr->ifm_active = mii->mii_media_active; ifmr->ifm_status = mii->mii_media_status; + DC_UNLOCK(sc); } static int @@ -3629,10 +3636,9 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) struct mii_data *mii; int error = 0; - DC_LOCK(sc); - switch (command) { case SIOCSIFFLAGS: + DC_LOCK(sc); if (ifp->if_flags & IFF_UP) { int need_setfilt = (ifp->if_flags ^ sc->dc_if_flags) & (IFF_PROMISC | IFF_ALLMULTI); @@ -3642,18 +3648,21 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) dc_setfilt(sc); } else { sc->dc_txthresh = 0; - dc_init(sc); + dc_init_locked(sc); } } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) dc_stop(sc); } sc->dc_if_flags = ifp->if_flags; + DC_UNLOCK(sc); error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: + DC_LOCK(sc); dc_setfilt(sc); + DC_UNLOCK(sc); error = 0; break; case SIOCGIFMEDIA: @@ -3661,21 +3670,23 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) mii = device_get_softc(sc->dc_miibus); error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); #ifdef SRM_MEDIA + DC_LOCK(sc); if (sc->dc_srm_media) sc->dc_srm_media = 0; + DC_UNLOCK(sc); #endif break; case SIOCSIFCAP: + DC_LOCK(sc); ifp->if_capenable &= ~IFCAP_POLLING; ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING; + DC_UNLOCK(sc); break; default: error = ether_ioctl(ifp, command, data); break; } - DC_UNLOCK(sc); - return (error); } @@ -3693,10 +3704,10 @@ dc_watchdog(struct ifnet *ifp) dc_stop(sc); dc_reset(sc); - dc_init(sc); + dc_init_locked(sc); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - dc_start(ifp); + dc_start_locked(ifp); DC_UNLOCK(sc); } @@ -3714,7 +3725,7 @@ dc_stop(struct dc_softc *sc) int i; u_int32_t ctl; - DC_LOCK(sc); + DC_LOCK_ASSERT(sc); ifp = sc->dc_ifp; ifp->if_timer = 0; @@ -3762,8 +3773,6 @@ dc_stop(struct dc_softc *sc) } } bzero(&ld->dc_tx_list, sizeof(ld->dc_tx_list)); - - DC_UNLOCK(sc); } /* @@ -3775,15 +3784,13 @@ static int dc_suspend(device_t dev) { struct dc_softc *sc; - int s; - - s = splimp(); sc = device_get_softc(dev); + DC_LOCK(sc); dc_stop(sc); sc->suspended = 1; + DC_UNLOCK(sc); - splx(s); return (0); } @@ -3797,20 +3804,18 @@ dc_resume(device_t dev) { struct dc_softc *sc; struct ifnet *ifp; - int s; - - s = splimp(); sc = device_get_softc(dev); ifp = sc->dc_ifp; /* reinitialize interface if necessary */ + DC_LOCK(sc); if (ifp->if_flags & IFF_UP) - dc_init(sc); + dc_init_locked(sc); sc->suspended = 0; + DC_UNLOCK(sc); - splx(s); return (0); } @@ -3825,5 +3830,7 @@ dc_shutdown(device_t dev) sc = device_get_softc(dev); + DC_LOCK(sc); dc_stop(sc); + DC_UNLOCK(sc); }