aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2014-05-27 13:47:27 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-05-27 13:47:27 -0400
commit03c4444650969431b3a5effde4995de767e3013a (patch)
treebe95969287c7005d2e384d77c0ba2a071e13a260 /net/mac80211
parentef1b075c15d55c71200c63450756a9bb51ce2a60 (diff)
parent2c316e699fa40f2fc161ebb770b6e2845db4f3b0 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/mlme.c20
-rw-r--r--net/mac80211/offchannel.c27
3 files changed, 34 insertions, 14 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ed2b817d5ece..ac9836e0aab3 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -317,6 +317,7 @@ struct ieee80211_roc_work {
317 317
318 bool started, abort, hw_begun, notified; 318 bool started, abort, hw_begun, notified;
319 bool to_be_freed; 319 bool to_be_freed;
320 bool on_channel;
320 321
321 unsigned long hw_start_time; 322 unsigned long hw_start_time;
322 323
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 7f073ef1e0a6..3345401be1b3 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3626,18 +3626,24 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
3626 3626
3627 sdata_lock(sdata); 3627 sdata_lock(sdata);
3628 3628
3629 if (ifmgd->auth_data) { 3629 if (ifmgd->auth_data || ifmgd->assoc_data) {
3630 const u8 *bssid = ifmgd->auth_data ?
3631 ifmgd->auth_data->bss->bssid :
3632 ifmgd->assoc_data->bss->bssid;
3633
3630 /* 3634 /*
3631 * If we are trying to authenticate while suspending, cfg80211 3635 * If we are trying to authenticate / associate while suspending,
3632 * won't know and won't actually abort those attempts, thus we 3636 * cfg80211 won't know and won't actually abort those attempts,
3633 * need to do that ourselves. 3637 * thus we need to do that ourselves.
3634 */ 3638 */
3635 ieee80211_send_deauth_disassoc(sdata, 3639 ieee80211_send_deauth_disassoc(sdata, bssid,
3636 ifmgd->auth_data->bss->bssid,
3637 IEEE80211_STYPE_DEAUTH, 3640 IEEE80211_STYPE_DEAUTH,
3638 WLAN_REASON_DEAUTH_LEAVING, 3641 WLAN_REASON_DEAUTH_LEAVING,
3639 false, frame_buf); 3642 false, frame_buf);
3640 ieee80211_destroy_auth_data(sdata, false); 3643 if (ifmgd->assoc_data)
3644 ieee80211_destroy_assoc_data(sdata, false);
3645 if (ifmgd->auth_data)
3646 ieee80211_destroy_auth_data(sdata, false);
3641 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 3647 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
3642 IEEE80211_DEAUTH_FRAME_LEN); 3648 IEEE80211_DEAUTH_FRAME_LEN);
3643 } 3649 }
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 6fb38558a5e6..7a17decd27f9 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -333,7 +333,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
333 container_of(work, struct ieee80211_roc_work, work.work); 333 container_of(work, struct ieee80211_roc_work, work.work);
334 struct ieee80211_sub_if_data *sdata = roc->sdata; 334 struct ieee80211_sub_if_data *sdata = roc->sdata;
335 struct ieee80211_local *local = sdata->local; 335 struct ieee80211_local *local = sdata->local;
336 bool started; 336 bool started, on_channel;
337 337
338 mutex_lock(&local->mtx); 338 mutex_lock(&local->mtx);
339 339
@@ -354,14 +354,26 @@ void ieee80211_sw_roc_work(struct work_struct *work)
354 if (!roc->started) { 354 if (!roc->started) {
355 struct ieee80211_roc_work *dep; 355 struct ieee80211_roc_work *dep;
356 356
357 /* start this ROC */ 357 WARN_ON(local->use_chanctx);
358 ieee80211_offchannel_stop_vifs(local); 358
359 /* If actually operating on the desired channel (with at least
360 * 20 MHz channel width) don't stop all the operations but still
361 * treat it as though the ROC operation started properly, so
362 * other ROC operations won't interfere with this one.
363 */
364 roc->on_channel = roc->chan == local->_oper_chandef.chan &&
365 local->_oper_chandef.width != NL80211_CHAN_WIDTH_5 &&
366 local->_oper_chandef.width != NL80211_CHAN_WIDTH_10;
359 367
360 /* switch channel etc */ 368 /* start this ROC */
361 ieee80211_recalc_idle(local); 369 ieee80211_recalc_idle(local);
362 370
363 local->tmp_channel = roc->chan; 371 if (!roc->on_channel) {
364 ieee80211_hw_config(local, 0); 372 ieee80211_offchannel_stop_vifs(local);
373
374 local->tmp_channel = roc->chan;
375 ieee80211_hw_config(local, 0);
376 }
365 377
366 /* tell userspace or send frame */ 378 /* tell userspace or send frame */
367 ieee80211_handle_roc_started(roc); 379 ieee80211_handle_roc_started(roc);
@@ -380,9 +392,10 @@ void ieee80211_sw_roc_work(struct work_struct *work)
380 finish: 392 finish:
381 list_del(&roc->list); 393 list_del(&roc->list);
382 started = roc->started; 394 started = roc->started;
395 on_channel = roc->on_channel;
383 ieee80211_roc_notify_destroy(roc, !roc->abort); 396 ieee80211_roc_notify_destroy(roc, !roc->abort);
384 397
385 if (started) { 398 if (started && !on_channel) {
386 ieee80211_flush_queues(local, NULL); 399 ieee80211_flush_queues(local, NULL);
387 400
388 local->tmp_channel = NULL; 401 local->tmp_channel = NULL;