From 01ea11e4890bb7b1baf1ee0486027a6d2e74d411 Mon Sep 17 00:00:00 2001 From: damien Date: Tue, 21 Mar 2006 21:15:43 +0000 Subject: o fixes the locking of if_init(). o don't send management frames if the IFF_DRV_RUNNING flag is not set. this prevents the timeout watchdog from being potentially re-armed when the interface is brought down. fixes a crash that occurs with RT2661 based adapters. reported by Arnaud Lacombe. --- sys/dev/ral/rt2560.c | 22 ++++++++++++++++++++-- sys/dev/ral/rt2661.c | 26 +++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) (limited to 'sys') diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c index 9676406..b5f08db 100644 --- a/sys/dev/ral/rt2560.c +++ b/sys/dev/ral/rt2560.c @@ -1368,6 +1368,7 @@ void rt2560_intr(void *arg) { struct rt2560_softc *sc = arg; + struct ifnet *ifp = sc->sc_ifp; uint32_t r; RAL_LOCK(sc); @@ -1375,6 +1376,12 @@ rt2560_intr(void *arg) /* disable interrupts */ RAL_WRITE(sc, RT2560_CSR8, 0xffffffff); + /* don't re-enable interrupts if we're shutting down */ + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + RAL_UNLOCK(sc); + return; + } + r = RAL_READ(sc, RT2560_CSR7); RAL_WRITE(sc, RT2560_CSR7, r); @@ -1937,6 +1944,12 @@ rt2560_start(struct ifnet *ifp) RAL_LOCK(sc); + /* prevent management frames from being sent if we're not ready */ + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + RAL_UNLOCK(sc); + return; + } + for (;;) { IF_POLL(&ic->ic_mgtq, m0); if (m0 != NULL) { @@ -2592,6 +2605,8 @@ rt2560_init(void *priv) uint32_t tmp; int i; + RAL_LOCK(sc); + rt2560_stop(sc); /* setup tx rings */ @@ -2634,6 +2649,7 @@ rt2560_init(void *priv) if (rt2560_bbp_init(sc) != 0) { rt2560_stop(sc); + RAL_UNLOCK(sc); return; } @@ -2669,6 +2685,8 @@ rt2560_init(void *priv) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); } else ieee80211_new_state(ic, IEEE80211_S_RUN, -1); + + RAL_UNLOCK(sc); #undef N } @@ -2679,12 +2697,12 @@ rt2560_stop(void *priv) struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = ic->ic_ifp; - ieee80211_new_state(ic, IEEE80211_S_INIT, -1); - sc->sc_tx_timer = 0; ifp->if_timer = 0; ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + ieee80211_new_state(ic, IEEE80211_S_INIT, -1); + /* abort Tx */ RAL_WRITE(sc, RT2560_TXCSR0, RT2560_ABORT_TX); diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c index ec010b8..811bdf4 100644 --- a/sys/dev/ral/rt2661.c +++ b/sys/dev/ral/rt2661.c @@ -1209,6 +1209,7 @@ void rt2661_intr(void *arg) { struct rt2661_softc *sc = arg; + struct ifnet *ifp = sc->sc_ifp; uint32_t r1, r2; RAL_LOCK(sc); @@ -1217,6 +1218,12 @@ rt2661_intr(void *arg) RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffff7f); RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff); + /* don't re-enable interrupts if we're shutting down */ + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + RAL_UNLOCK(sc); + return; + } + r1 = RAL_READ(sc, RT2661_INT_SOURCE_CSR); RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, r1); @@ -1758,6 +1765,12 @@ rt2661_start(struct ifnet *ifp) RAL_LOCK(sc); + /* prevent management frames from being sent if we're not ready */ + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + RAL_UNLOCK(sc); + return; + } + for (;;) { IF_POLL(&ic->ic_mgtq, m0); if (m0 != NULL) { @@ -2469,6 +2482,8 @@ rt2661_init(void *priv) uint32_t tmp, sta[3]; int i, ntries; + RAL_LOCK(sc); + rt2661_stop(sc); /* initialize Tx rings */ @@ -2530,11 +2545,13 @@ rt2661_init(void *priv) if (ntries == 1000) { printf("timeout waiting for BBP/RF to wakeup\n"); rt2661_stop(sc); + RAL_UNLOCK(sc); return; } if (rt2661_bbp_init(sc) != 0) { rt2661_stop(sc); + RAL_UNLOCK(sc); return; } @@ -2583,6 +2600,9 @@ rt2661_init(void *priv) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); } else ieee80211_new_state(ic, IEEE80211_S_RUN, -1); + + RAL_UNLOCK(sc); +#undef N } void @@ -2611,9 +2631,13 @@ rt2661_stop(void *priv) RAL_WRITE(sc, RT2661_MAC_CSR1, 0); /* disable interrupts */ - RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffff7f); + RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffffff); RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff); + /* clear any pending interrupt */ + RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, 0xffffffff); + RAL_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, 0xffffffff); + /* reset Tx and Rx rings */ rt2661_reset_tx_ring(sc, &sc->txq[0]); rt2661_reset_tx_ring(sc, &sc->txq[1]); -- cgit v1.1