summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2014-03-20 04:47:34 +0000
committeradrian <adrian@FreeBSD.org>2014-03-20 04:47:34 +0000
commit754a06c6fc9ffa8d5472e8eb24739513a9fb1ee1 (patch)
treeff4d09a3627dc17bf8e21c17ce66c7530828a62a
parent6b585f6346a09fbb5eb790b89077271723e3c31e (diff)
downloadFreeBSD-src-754a06c6fc9ffa8d5472e8eb24739513a9fb1ee1.zip
FreeBSD-src-754a06c6fc9ffa8d5472e8eb24739513a9fb1ee1.tar.gz
Don't call ath_init() inside the lock.
Yes, this means that sc_invalid is slightly racy, but there are other issues here which need fixing. This fixes a source of eventual LORs - ath_init() grabs ATH_LOCK to do work and releases it before it calls ieee80211_start_all(). ieee80211_start_all() will grab the net80211 comlock to iterate over the VAPs. TODO: * .. I should just migrate the ieee80211_start_all() work to a deferred task so it can be done later; it doesn't have to be immediately done. Tested: * AR5416, STA mode
-rw-r--r--sys/dev/ath/if_ath.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 49fd9ef..a5bbe42 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -5948,14 +5948,15 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
switch (cmd) {
case SIOCSIFFLAGS:
- ATH_LOCK(sc);
if (IS_RUNNING(ifp)) {
/*
* To avoid rescanning another access point,
* do not call ath_init() here. Instead,
* only reflect promisc mode settings.
*/
+ ATH_LOCK(sc);
ath_mode_init(sc);
+ ATH_UNLOCK(sc);
} else if (ifp->if_flags & IFF_UP) {
/*
* Beware of being called during attach/detach
@@ -5969,14 +5970,15 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
if (!sc->sc_invalid)
ath_init(sc); /* XXX lose error */
} else {
+ ATH_LOCK(sc);
ath_stop_locked(ifp);
#ifdef notyet
/* XXX must wakeup in places like ath_vap_delete */
if (!sc->sc_invalid)
ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP);
#endif
+ ATH_UNLOCK(sc);
}
- ATH_UNLOCK(sc);
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
OpenPOWER on IntegriCloud