diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 20 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 27 | ||||
-rw-r--r-- | net/mac80211/rx.c | 3 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 3 | ||||
-rw-r--r-- | net/mac80211/status.c | 5 | ||||
-rw-r--r-- | net/mac80211/trace.h | 4 | ||||
-rw-r--r-- | net/mac80211/util.c | 2 | ||||
-rw-r--r-- | net/mac80211/vht.c | 9 |
9 files changed, 49 insertions, 25 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/rx.c b/net/mac80211/rx.c index 216c45b949e5..2b608b2b70ec 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1231,7 +1231,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1231 | if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) && | 1231 | if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) && |
1232 | test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { | 1232 | test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { |
1233 | sta->last_rx = jiffies; | 1233 | sta->last_rx = jiffies; |
1234 | if (ieee80211_is_data(hdr->frame_control)) { | 1234 | if (ieee80211_is_data(hdr->frame_control) && |
1235 | !is_multicast_ether_addr(hdr->addr1)) { | ||
1235 | sta->last_rx_rate_idx = status->rate_idx; | 1236 | sta->last_rx_rate_idx = status->rate_idx; |
1236 | sta->last_rx_rate_flag = status->flag; | 1237 | sta->last_rx_rate_flag = status->flag; |
1237 | sta->last_rx_rate_vht_flag = status->vht_flag; | 1238 | sta->last_rx_rate_vht_flag = status->vht_flag; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 137a192e64bc..847d92f6bef6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -1148,7 +1148,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1148 | atomic_dec(&ps->num_sta_ps); | 1148 | atomic_dec(&ps->num_sta_ps); |
1149 | 1149 | ||
1150 | /* This station just woke up and isn't aware of our SMPS state */ | 1150 | /* This station just woke up and isn't aware of our SMPS state */ |
1151 | if (!ieee80211_smps_is_restrictive(sta->known_smps_mode, | 1151 | if (!ieee80211_vif_is_mesh(&sdata->vif) && |
1152 | !ieee80211_smps_is_restrictive(sta->known_smps_mode, | ||
1152 | sdata->smps_mode) && | 1153 | sdata->smps_mode) && |
1153 | sta->known_smps_mode != sdata->bss->req_smps && | 1154 | sta->known_smps_mode != sdata->bss->req_smps && |
1154 | sta_info_tx_streams(sta) != 1) { | 1155 | sta_info_tx_streams(sta) != 1) { |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 00ba90b02ab2..60cb7a665976 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -314,10 +314,9 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, | |||
314 | !is_multicast_ether_addr(hdr->addr1)) | 314 | !is_multicast_ether_addr(hdr->addr1)) |
315 | txflags |= IEEE80211_RADIOTAP_F_TX_FAIL; | 315 | txflags |= IEEE80211_RADIOTAP_F_TX_FAIL; |
316 | 316 | ||
317 | if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | 317 | if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) |
318 | (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
319 | txflags |= IEEE80211_RADIOTAP_F_TX_CTS; | 318 | txflags |= IEEE80211_RADIOTAP_F_TX_CTS; |
320 | else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) | 319 | if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) |
321 | txflags |= IEEE80211_RADIOTAP_F_TX_RTS; | 320 | txflags |= IEEE80211_RADIOTAP_F_TX_RTS; |
322 | 321 | ||
323 | put_unaligned_le16(txflags, pos); | 322 | put_unaligned_le16(txflags, pos); |
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/util.c b/net/mac80211/util.c index 275c94f995f7..3c365837e910 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1780,7 +1780,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1780 | mutex_unlock(&local->mtx); | 1780 | mutex_unlock(&local->mtx); |
1781 | 1781 | ||
1782 | if (sched_scan_stopped) | 1782 | if (sched_scan_stopped) |
1783 | cfg80211_sched_scan_stopped(local->hw.wiphy); | 1783 | cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy); |
1784 | 1784 | ||
1785 | /* | 1785 | /* |
1786 | * If this is for hw restart things are still running. | 1786 | * If this is for hw restart things are still running. |
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 | ||