aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-02-20 08:19:58 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-02-27 14:06:32 -0500
commit79ebfb85d4ad3495d70124a249a1096ab6396c05 (patch)
treea24b8155adbc30e2ed49768351061c48037b9242 /net/mac80211
parentd26ad3771fe7405bf80d736cae9ba4c706a7b1d8 (diff)
mac80211: fix associated vs. idle race
Eliad reports that if a scan finishes in the middle of processing associated (however it happens), the interface can go idle. This is because we set assoc_data to NULL before we set associated. Change the order so any idle check will find either one of them. Doing this requires duplicating the TX sync processing, but I already have a patch to delete that completely and will submit that as soon as my driver changes to no longer require it are submitted. Reported-by: Eliad Peller <eliad@wizery.com> Tested-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/mlme.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 586d4fb8e130..1495fb99b379 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2238,14 +2238,28 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2238 } else { 2238 } else {
2239 printk(KERN_DEBUG "%s: associated\n", sdata->name); 2239 printk(KERN_DEBUG "%s: associated\n", sdata->name);
2240 2240
2241 ieee80211_destroy_assoc_data(sdata, true); 2241 /* tell driver about sync done first */
2242 if (assoc_data->synced) {
2243 drv_finish_tx_sync(sdata->local, sdata,
2244 assoc_data->bss->bssid,
2245 IEEE80211_TX_SYNC_ASSOC);
2246 assoc_data->synced = false;
2247 }
2242 2248
2243 if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { 2249 if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) {
2244 /* oops -- internal error -- send timeout for now */ 2250 /* oops -- internal error -- send timeout for now */
2251 ieee80211_destroy_assoc_data(sdata, true);
2245 sta_info_destroy_addr(sdata, mgmt->bssid); 2252 sta_info_destroy_addr(sdata, mgmt->bssid);
2246 cfg80211_put_bss(*bss); 2253 cfg80211_put_bss(*bss);
2247 return RX_MGMT_CFG80211_ASSOC_TIMEOUT; 2254 return RX_MGMT_CFG80211_ASSOC_TIMEOUT;
2248 } 2255 }
2256
2257 /*
2258 * destroy assoc_data afterwards, as otherwise an idle
2259 * recalc after assoc_data is NULL but before associated
2260 * is set can cause the interface to go idle
2261 */
2262 ieee80211_destroy_assoc_data(sdata, true);
2249 } 2263 }
2250 2264
2251 return RX_MGMT_CFG80211_RX_ASSOC; 2265 return RX_MGMT_CFG80211_RX_ASSOC;