aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2014-05-15 10:24:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-05-15 10:24:28 -0400
commit025a58fd9d5785d63c398e96ac543db2639c7ddc (patch)
treef15063ac321fb1d13e35bc75c70e7cee81aa3119 /net
parente84d2f8d2ae33c8215429824e1ecf24cbca9645e (diff)
parentfaf1dc64e345ac4de5c4429df6ed492255ae2248 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/mlme.c20
-rw-r--r--net/mac80211/offchannel.c27
-rw-r--r--net/mac80211/trace.h4
-rw-r--r--net/mac80211/vht.c9
5 files changed, 42 insertions, 19 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 222c28b75315..f169b6ee94ee 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 dee50aefd6e8..27600a9808ba 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3598,18 +3598,24 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
3598 3598
3599 sdata_lock(sdata); 3599 sdata_lock(sdata);
3600 3600
3601 if (ifmgd->auth_data) { 3601 if (ifmgd->auth_data || ifmgd->assoc_data) {
3602 const u8 *bssid = ifmgd->auth_data ?
3603 ifmgd->auth_data->bss->bssid :
3604 ifmgd->assoc_data->bss->bssid;
3605
3602 /* 3606 /*
3603 * If we are trying to authenticate while suspending, cfg80211 3607 * If we are trying to authenticate / associate while suspending,
3604 * won't know and won't actually abort those attempts, thus we 3608 * cfg80211 won't know and won't actually abort those attempts,
3605 * need to do that ourselves. 3609 * thus we need to do that ourselves.
3606 */ 3610 */
3607 ieee80211_send_deauth_disassoc(sdata, 3611 ieee80211_send_deauth_disassoc(sdata, bssid,
3608 ifmgd->auth_data->bss->bssid,
3609 IEEE80211_STYPE_DEAUTH, 3612 IEEE80211_STYPE_DEAUTH,
3610 WLAN_REASON_DEAUTH_LEAVING, 3613 WLAN_REASON_DEAUTH_LEAVING,
3611 false, frame_buf); 3614 false, frame_buf);
3612 ieee80211_destroy_auth_data(sdata, false); 3615 if (ifmgd->assoc_data)
3616 ieee80211_destroy_assoc_data(sdata, false);
3617 if (ifmgd->auth_data)
3618 ieee80211_destroy_auth_data(sdata, false);
3613 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 3619 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
3614 IEEE80211_DEAUTH_FRAME_LEN); 3620 IEEE80211_DEAUTH_FRAME_LEN);
3615 } 3621 }
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;
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index a0b0aea76525..cec5b60487a4 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -21,10 +21,10 @@
21 21
22#define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ 22#define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \
23 __field(bool, p2p) \ 23 __field(bool, p2p) \
24 __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") 24 __string(vif_name, sdata->name)
25#define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ 25#define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \
26 __entry->p2p = sdata->vif.p2p; \ 26 __entry->p2p = sdata->vif.p2p; \
27 __assign_str(vif_name, sdata->dev ? sdata->dev->name : sdata->name) 27 __assign_str(vif_name, sdata->name)
28#define VIF_PR_FMT " vif:%s(%d%s)" 28#define VIF_PR_FMT " vif:%s(%d%s)"
29#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" 29#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
30 30
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index e9e36a256165..9265adfdabfc 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -129,9 +129,12 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
129 if (!vht_cap_ie || !sband->vht_cap.vht_supported) 129 if (!vht_cap_ie || !sband->vht_cap.vht_supported)
130 return; 130 return;
131 131
132 /* A VHT STA must support 40 MHz */ 132 /*
133 if (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) 133 * A VHT STA must support 40 MHz, but if we verify that here
134 return; 134 * then we break a few things - some APs (e.g. Netgear R6300v2
135 * and others based on the BCM4360 chipset) will unset this
136 * capability bit when operating in 20 MHz.
137 */
135 138
136 vht_cap->vht_supported = true; 139 vht_cap->vht_supported = true;
137 140