diff options
author | avos <avos@FreeBSD.org> | 2016-02-29 21:09:09 +0000 |
---|---|---|
committer | avos <avos@FreeBSD.org> | 2016-02-29 21:09:09 +0000 |
commit | c6e60153b0b0f8eae92858998051efe884549ff9 (patch) | |
tree | 724db4fc425ab31748d0e549c2fae141536ef45c | |
parent | f0bc9a635efb74ac834f0014597b9aea77891178 (diff) | |
download | FreeBSD-src-c6e60153b0b0f8eae92858998051efe884549ff9.zip FreeBSD-src-c6e60153b0b0f8eae92858998051efe884549ff9.tar.gz |
net80211: fix scanning after D5145 (PR 197498 related)
- In case, when we are doing <smth> -> INIT (FEXT_REINIT) -> <smth2>
state transition, cancel_scan() may be called in the first transition.
Reenqueue second state transition, so things will be executed in order.
- Discard any AUTH+ state transition request when INIT -> SCAN
transition is not done.
- Allow to track discarded state transitions via 'state' debugging
category.
Tested with:
* RTL8188EU, HOSTAP mode.
* RTL8188CUS, STA mode.
* Intel 3945BG, IBSS and STA modes.
PR: 197498
Approved by: adrian (mentor)
Differential Revision: https://reviews.freebsd.org/D5482
-rw-r--r-- | sys/net80211/ieee80211_proto.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c index c2b50af..3bc3141 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -1800,13 +1800,19 @@ ieee80211_newstate_cb(void *xvap, int npending) * We have been requested to drop back to the INIT before * proceeding to the new state. */ + /* Deny any state changes while we are here. */ + vap->iv_nstate = IEEE80211_S_INIT; IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s arg %d\n", __func__, ieee80211_state_name[vap->iv_state], - ieee80211_state_name[IEEE80211_S_INIT], arg); - vap->iv_newstate(vap, IEEE80211_S_INIT, arg); + ieee80211_state_name[vap->iv_nstate], arg); + vap->iv_newstate(vap, vap->iv_nstate, 0); IEEE80211_LOCK_ASSERT(ic); - vap->iv_flags_ext &= ~IEEE80211_FEXT_REINIT; + vap->iv_flags_ext &= ~(IEEE80211_FEXT_REINIT | + IEEE80211_FEXT_STATEWAIT); + /* enqueue new state transition after cancel_scan() task */ + ieee80211_new_state_locked(vap, nstate, arg); + goto done; } ostate = vap->iv_state; @@ -1917,11 +1923,22 @@ ieee80211_new_state_locked(struct ieee80211vap *vap, IEEE80211_LOCK_ASSERT(ic); if (vap->iv_flags_ext & IEEE80211_FEXT_STATEWAIT) { - if (vap->iv_nstate == IEEE80211_S_INIT) { + if (vap->iv_nstate == IEEE80211_S_INIT || + ((vap->iv_state == IEEE80211_S_INIT || + (vap->iv_flags_ext & IEEE80211_FEXT_REINIT)) && + vap->iv_nstate == IEEE80211_S_SCAN && + nstate > IEEE80211_S_SCAN)) { /* - * XXX The vap is being stopped, do no allow any other - * state changes until this is completed. + * XXX The vap is being stopped/started, + * do not allow any other state changes + * until this is completed. */ + IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, + "%s: %s -> %s (%s) transition discarded\n", + __func__, + ieee80211_state_name[vap->iv_state], + ieee80211_state_name[nstate], + ieee80211_state_name[vap->iv_nstate]); return -1; } else if (vap->iv_state != vap->iv_nstate) { #if 0 |