aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c14
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c5
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c6
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c12
-rw-r--r--drivers/net/wireless/ath/wil6210/p2p.c6
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c8
-rw-r--r--drivers/net/wireless/atmel/at76c50x-usb.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c6
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/scan.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c37
-rw-r--r--drivers/net/wireless/intersil/orinoco/scan.c12
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c130
-rw-r--r--drivers/net/wireless/marvell/libertas/cfg.c11
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cmdevt.c12
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.c6
-rw-r--r--drivers/net/wireless/marvell/mwifiex/scan.c12
-rw-r--r--drivers/net/wireless/rndis_wlan.c10
-rw-r--r--drivers/net/wireless/st/cw1200/scan.c6
-rw-r--r--drivers/net/wireless/ti/wl1251/event.c6
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c6
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c11
-rw-r--r--drivers/net/wireless/ti/wlcore/scan.c5
-rw-r--r--drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c11
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_cfgoperations.c12
-rw-r--r--drivers/staging/wlan-ng/cfg80211.c5
-rw-r--r--include/linux/ieee80211.h32
-rw-r--r--include/net/cfg80211.h52
-rw-r--r--include/net/mac80211.h5
-rw-r--r--include/uapi/linux/nl80211.h76
-rw-r--r--net/mac80211/agg-rx.c18
-rw-r--r--net/mac80211/cfg.c1
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/mesh.c20
-rw-r--r--net/mac80211/mesh_plink.c16
-rw-r--r--net/mac80211/rx.c7
-rw-r--r--net/mac80211/scan.c42
-rw-r--r--net/mac80211/spectmgmt.c45
-rw-r--r--net/mac80211/tdls.c1
-rw-r--r--net/mac80211/tx.c10
-rw-r--r--net/wireless/core.c4
-rw-r--r--net/wireless/core.h12
-rw-r--r--net/wireless/nl80211.c173
-rw-r--r--net/wireless/scan.c18
-rw-r--r--net/wireless/trace.h33
46 files changed, 744 insertions, 205 deletions
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index d4b7a168f7c0..ebc12c521fe0 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3858,12 +3858,16 @@ void __ath10k_scan_finish(struct ath10k *ar)
3858 break; 3858 break;
3859 case ATH10K_SCAN_RUNNING: 3859 case ATH10K_SCAN_RUNNING:
3860 case ATH10K_SCAN_ABORTING: 3860 case ATH10K_SCAN_ABORTING:
3861 if (!ar->scan.is_roc) 3861 if (!ar->scan.is_roc) {
3862 ieee80211_scan_completed(ar->hw, 3862 struct cfg80211_scan_info info = {
3863 (ar->scan.state == 3863 .aborted = (ar->scan.state ==
3864 ATH10K_SCAN_ABORTING)); 3864 ATH10K_SCAN_ABORTING),
3865 else if (ar->scan.roc_notify) 3865 };
3866
3867 ieee80211_scan_completed(ar->hw, &info);
3868 } else if (ar->scan.roc_notify) {
3866 ieee80211_remain_on_channel_expired(ar->hw); 3869 ieee80211_remain_on_channel_expired(ar->hw);
3870 }
3867 /* fall through */ 3871 /* fall through */
3868 case ATH10K_SCAN_STARTING: 3872 case ATH10K_SCAN_STARTING:
3869 ar->scan.state = ATH10K_SCAN_IDLE; 3873 ar->scan.state = ATH10K_SCAN_IDLE;
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 4e11ba06f089..ef5b40ef6d67 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -859,7 +859,11 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
859 struct ath6kl *ar = vif->ar; 859 struct ath6kl *ar = vif->ar;
860 860
861 if (vif->scan_req) { 861 if (vif->scan_req) {
862 cfg80211_scan_done(vif->scan_req, true); 862 struct cfg80211_scan_info info = {
863 .aborted = true,
864 };
865
866 cfg80211_scan_done(vif->scan_req, &info);
863 vif->scan_req = NULL; 867 vif->scan_req = NULL;
864 } 868 }
865 869
@@ -1069,6 +1073,9 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
1069void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted) 1073void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted)
1070{ 1074{
1071 struct ath6kl *ar = vif->ar; 1075 struct ath6kl *ar = vif->ar;
1076 struct cfg80211_scan_info info = {
1077 .aborted = aborted,
1078 };
1072 int i; 1079 int i;
1073 1080
1074 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status%s\n", __func__, 1081 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status%s\n", __func__,
@@ -1089,7 +1096,7 @@ void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted)
1089 } 1096 }
1090 1097
1091out: 1098out:
1092 cfg80211_scan_done(vif->scan_req, aborted); 1099 cfg80211_scan_done(vif->scan_req, &info);
1093 vif->scan_req = NULL; 1100 vif->scan_req = NULL;
1094} 1101}
1095 1102
@@ -3614,7 +3621,11 @@ void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready)
3614 } 3621 }
3615 3622
3616 if (vif->scan_req) { 3623 if (vif->scan_req) {
3617 cfg80211_scan_done(vif->scan_req, true); 3624 struct cfg80211_scan_info info = {
3625 .aborted = true,
3626 };
3627
3628 cfg80211_scan_done(vif->scan_req, &info);
3618 vif->scan_req = NULL; 3629 vif->scan_req = NULL;
3619 } 3630 }
3620 3631
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index e56bafcf5864..57e26a640477 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -960,6 +960,9 @@ void ath_roc_complete(struct ath_softc *sc, enum ath_roc_complete_reason reason)
960void ath_scan_complete(struct ath_softc *sc, bool abort) 960void ath_scan_complete(struct ath_softc *sc, bool abort)
961{ 961{
962 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 962 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
963 struct cfg80211_scan_info info = {
964 .aborted = abort,
965 };
963 966
964 if (abort) 967 if (abort)
965 ath_dbg(common, CHAN_CTX, "HW scan aborted\n"); 968 ath_dbg(common, CHAN_CTX, "HW scan aborted\n");
@@ -969,7 +972,7 @@ void ath_scan_complete(struct ath_softc *sc, bool abort)
969 sc->offchannel.scan_req = NULL; 972 sc->offchannel.scan_req = NULL;
970 sc->offchannel.scan_vif = NULL; 973 sc->offchannel.scan_vif = NULL;
971 sc->offchannel.state = ATH_OFFCHANNEL_IDLE; 974 sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
972 ieee80211_scan_completed(sc->hw, abort); 975 ieee80211_scan_completed(sc->hw, &info);
973 clear_bit(ATH_OP_SCANNING, &common->op_flags); 976 clear_bit(ATH_OP_SCANNING, &common->op_flags);
974 spin_lock_bh(&sc->chan_lock); 977 spin_lock_bh(&sc->chan_lock);
975 if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) 978 if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 62bf9331bd7f..f0e1175fb76a 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1369,7 +1369,11 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
1369 mutex_lock(&wil->mutex); 1369 mutex_lock(&wil->mutex);
1370 started = wil_p2p_stop_discovery(wil); 1370 started = wil_p2p_stop_discovery(wil);
1371 if (started && wil->scan_request) { 1371 if (started && wil->scan_request) {
1372 cfg80211_scan_done(wil->scan_request, 1); 1372 struct cfg80211_scan_info info = {
1373 .aborted = true,
1374 };
1375
1376 cfg80211_scan_done(wil->scan_request, &info);
1373 wil->scan_request = NULL; 1377 wil->scan_request = NULL;
1374 wil->radio_wdev = wil->wdev; 1378 wil->radio_wdev = wil->wdev;
1375 } 1379 }
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 8e31d755bbee..4bc92e54984a 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -850,10 +850,14 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
850 mutex_unlock(&wil->wmi_mutex); 850 mutex_unlock(&wil->wmi_mutex);
851 851
852 if (wil->scan_request) { 852 if (wil->scan_request) {
853 struct cfg80211_scan_info info = {
854 .aborted = true,
855 };
856
853 wil_dbg_misc(wil, "Abort scan_request 0x%p\n", 857 wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
854 wil->scan_request); 858 wil->scan_request);
855 del_timer_sync(&wil->scan_timer); 859 del_timer_sync(&wil->scan_timer);
856 cfg80211_scan_done(wil->scan_request, true); 860 cfg80211_scan_done(wil->scan_request, &info);
857 wil->scan_request = NULL; 861 wil->scan_request = NULL;
858 } 862 }
859 863
@@ -1049,10 +1053,14 @@ int __wil_down(struct wil6210_priv *wil)
1049 (void)wil_p2p_stop_discovery(wil); 1053 (void)wil_p2p_stop_discovery(wil);
1050 1054
1051 if (wil->scan_request) { 1055 if (wil->scan_request) {
1056 struct cfg80211_scan_info info = {
1057 .aborted = true,
1058 };
1059
1052 wil_dbg_misc(wil, "Abort scan_request 0x%p\n", 1060 wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
1053 wil->scan_request); 1061 wil->scan_request);
1054 del_timer_sync(&wil->scan_timer); 1062 del_timer_sync(&wil->scan_timer);
1055 cfg80211_scan_done(wil->scan_request, true); 1063 cfg80211_scan_done(wil->scan_request, &info);
1056 wil->scan_request = NULL; 1064 wil->scan_request = NULL;
1057 } 1065 }
1058 1066
diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c
index 213b8259638c..e0f8aa0ebfac 100644
--- a/drivers/net/wireless/ath/wil6210/p2p.c
+++ b/drivers/net/wireless/ath/wil6210/p2p.c
@@ -252,8 +252,12 @@ void wil_p2p_search_expired(struct work_struct *work)
252 mutex_unlock(&wil->mutex); 252 mutex_unlock(&wil->mutex);
253 253
254 if (started) { 254 if (started) {
255 struct cfg80211_scan_info info = {
256 .aborted = false,
257 };
258
255 mutex_lock(&wil->p2p_wdev_mutex); 259 mutex_lock(&wil->p2p_wdev_mutex);
256 cfg80211_scan_done(wil->scan_request, 0); 260 cfg80211_scan_done(wil->scan_request, &info);
257 wil->scan_request = NULL; 261 wil->scan_request = NULL;
258 wil->radio_wdev = wil->wdev; 262 wil->radio_wdev = wil->wdev;
259 mutex_unlock(&wil->p2p_wdev_mutex); 263 mutex_unlock(&wil->p2p_wdev_mutex);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index b80c5d850e1e..4d92541913c0 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -426,15 +426,17 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
426{ 426{
427 if (wil->scan_request) { 427 if (wil->scan_request) {
428 struct wmi_scan_complete_event *data = d; 428 struct wmi_scan_complete_event *data = d;
429 bool aborted = (data->status != WMI_SCAN_SUCCESS); 429 struct cfg80211_scan_info info = {
430 .aborted = (data->status != WMI_SCAN_SUCCESS),
431 };
430 432
431 wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status); 433 wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
432 wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n", 434 wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n",
433 wil->scan_request, aborted); 435 wil->scan_request, info.aborted);
434 436
435 del_timer_sync(&wil->scan_timer); 437 del_timer_sync(&wil->scan_timer);
436 mutex_lock(&wil->p2p_wdev_mutex); 438 mutex_lock(&wil->p2p_wdev_mutex);
437 cfg80211_scan_done(wil->scan_request, aborted); 439 cfg80211_scan_done(wil->scan_request, &info);
438 wil->radio_wdev = wil->wdev; 440 wil->radio_wdev = wil->wdev;
439 mutex_unlock(&wil->p2p_wdev_mutex); 441 mutex_unlock(&wil->p2p_wdev_mutex);
440 wil->scan_request = NULL; 442 wil->scan_request = NULL;
diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c
index 7c108047fb46..0e180677c7fc 100644
--- a/drivers/net/wireless/atmel/at76c50x-usb.c
+++ b/drivers/net/wireless/atmel/at76c50x-usb.c
@@ -1922,6 +1922,9 @@ static void at76_dwork_hw_scan(struct work_struct *work)
1922{ 1922{
1923 struct at76_priv *priv = container_of(work, struct at76_priv, 1923 struct at76_priv *priv = container_of(work, struct at76_priv,
1924 dwork_hw_scan.work); 1924 dwork_hw_scan.work);
1925 struct cfg80211_scan_info info = {
1926 .aborted = false,
1927 };
1925 int ret; 1928 int ret;
1926 1929
1927 if (priv->device_unplugged) 1930 if (priv->device_unplugged)
@@ -1948,7 +1951,7 @@ static void at76_dwork_hw_scan(struct work_struct *work)
1948 1951
1949 mutex_unlock(&priv->mtx); 1952 mutex_unlock(&priv->mtx);
1950 1953
1951 ieee80211_scan_completed(priv->hw, false); 1954 ieee80211_scan_completed(priv->hw, &info);
1952 1955
1953 ieee80211_wake_queues(priv->hw); 1956 ieee80211_wake_queues(priv->hw);
1954} 1957}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 264bd638a3d9..afe2b202040a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -775,9 +775,13 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
775 if (!aborted) 775 if (!aborted)
776 cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); 776 cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
777 } else if (scan_request) { 777 } else if (scan_request) {
778 struct cfg80211_scan_info info = {
779 .aborted = aborted,
780 };
781
778 brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n", 782 brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
779 aborted ? "Aborted" : "Done"); 783 aborted ? "Aborted" : "Done");
780 cfg80211_scan_done(scan_request, aborted); 784 cfg80211_scan_done(scan_request, &info);
781 } 785 }
782 if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) 786 if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
783 brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n"); 787 brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n");
diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c
index eb24b9241bb2..140b6ea8f7cc 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.c
+++ b/drivers/net/wireless/intel/iwlegacy/common.c
@@ -1305,10 +1305,14 @@ il_send_scan_abort(struct il_priv *il)
1305static void 1305static void
1306il_complete_scan(struct il_priv *il, bool aborted) 1306il_complete_scan(struct il_priv *il, bool aborted)
1307{ 1307{
1308 struct cfg80211_scan_info info = {
1309 .aborted = aborted,
1310 };
1311
1308 /* check if scan was requested from mac80211 */ 1312 /* check if scan was requested from mac80211 */
1309 if (il->scan_request) { 1313 if (il->scan_request) {
1310 D_SCAN("Complete scan in mac80211\n"); 1314 D_SCAN("Complete scan in mac80211\n");
1311 ieee80211_scan_completed(il->hw, aborted); 1315 ieee80211_scan_completed(il->hw, &info);
1312 } 1316 }
1313 1317
1314 il->scan_vif = NULL; 1318 il->scan_vif = NULL;
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c
index d01766f16175..17e6a32384d3 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c
@@ -94,10 +94,14 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
94 94
95static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) 95static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
96{ 96{
97 struct cfg80211_scan_info info = {
98 .aborted = aborted,
99 };
100
97 /* check if scan was requested from mac80211 */ 101 /* check if scan was requested from mac80211 */
98 if (priv->scan_request) { 102 if (priv->scan_request) {
99 IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n"); 103 IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n");
100 ieee80211_scan_completed(priv->hw, aborted); 104 ieee80211_scan_completed(priv->hw, &info);
101 } 105 }
102 106
103 priv->scan_type = IWL_SCAN_NORMAL; 107 priv->scan_type = IWL_SCAN_NORMAL;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index e78fc567ff7d..1cac10c5d818 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -391,13 +391,16 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm,
391 ieee80211_sched_scan_stopped(mvm->hw); 391 ieee80211_sched_scan_stopped(mvm->hw);
392 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; 392 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
393 } else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) { 393 } else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {
394 struct cfg80211_scan_info info = {
395 .aborted = aborted,
396 };
397
394 IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n", 398 IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n",
395 aborted ? "aborted" : "completed", 399 aborted ? "aborted" : "completed",
396 iwl_mvm_ebs_status_str(scan_notif->ebs_status)); 400 iwl_mvm_ebs_status_str(scan_notif->ebs_status));
397 401
398 mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR; 402 mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
399 ieee80211_scan_completed(mvm->hw, 403 ieee80211_scan_completed(mvm->hw, &info);
400 scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED);
401 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); 404 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
402 del_timer(&mvm->scan_timer); 405 del_timer(&mvm->scan_timer);
403 } else { 406 } else {
@@ -1430,7 +1433,11 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
1430 1433
1431 /* if the scan is already stopping, we don't need to notify mac80211 */ 1434 /* if the scan is already stopping, we don't need to notify mac80211 */
1432 if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) { 1435 if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) {
1433 ieee80211_scan_completed(mvm->hw, aborted); 1436 struct cfg80211_scan_info info = {
1437 .aborted = aborted,
1438 };
1439
1440 ieee80211_scan_completed(mvm->hw, &info);
1434 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); 1441 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
1435 del_timer(&mvm->scan_timer); 1442 del_timer(&mvm->scan_timer);
1436 } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { 1443 } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
@@ -1564,7 +1571,11 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
1564 1571
1565 uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_REGULAR); 1572 uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_REGULAR);
1566 if (uid >= 0) { 1573 if (uid >= 0) {
1567 ieee80211_scan_completed(mvm->hw, true); 1574 struct cfg80211_scan_info info = {
1575 .aborted = true,
1576 };
1577
1578 ieee80211_scan_completed(mvm->hw, &info);
1568 mvm->scan_uid_status[uid] = 0; 1579 mvm->scan_uid_status[uid] = 0;
1569 } 1580 }
1570 uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED); 1581 uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED);
@@ -1585,8 +1596,13 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
1585 mvm->scan_uid_status[i] = 0; 1596 mvm->scan_uid_status[i] = 0;
1586 } 1597 }
1587 } else { 1598 } else {
1588 if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) 1599 if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {
1589 ieee80211_scan_completed(mvm->hw, true); 1600 struct cfg80211_scan_info info = {
1601 .aborted = true,
1602 };
1603
1604 ieee80211_scan_completed(mvm->hw, &info);
1605 }
1590 1606
1591 /* Sched scan will be restarted by mac80211 in 1607 /* Sched scan will be restarted by mac80211 in
1592 * restart_hw, so do not report if FW is about to be 1608 * restart_hw, so do not report if FW is about to be
@@ -1629,8 +1645,13 @@ out:
1629 */ 1645 */
1630 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); 1646 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
1631 del_timer(&mvm->scan_timer); 1647 del_timer(&mvm->scan_timer);
1632 if (notify) 1648 if (notify) {
1633 ieee80211_scan_completed(mvm->hw, true); 1649 struct cfg80211_scan_info info = {
1650 .aborted = true,
1651 };
1652
1653 ieee80211_scan_completed(mvm->hw, &info);
1654 }
1634 } else if (notify) { 1655 } else if (notify) {
1635 ieee80211_sched_scan_stopped(mvm->hw); 1656 ieee80211_sched_scan_stopped(mvm->hw);
1636 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; 1657 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
diff --git a/drivers/net/wireless/intersil/orinoco/scan.c b/drivers/net/wireless/intersil/orinoco/scan.c
index d0ceb06c72d0..6d1d084854fb 100644
--- a/drivers/net/wireless/intersil/orinoco/scan.c
+++ b/drivers/net/wireless/intersil/orinoco/scan.c
@@ -237,7 +237,11 @@ void orinoco_add_hostscan_results(struct orinoco_private *priv,
237 237
238 scan_abort: 238 scan_abort:
239 if (priv->scan_request) { 239 if (priv->scan_request) {
240 cfg80211_scan_done(priv->scan_request, abort); 240 struct cfg80211_scan_info info = {
241 .aborted = abort,
242 };
243
244 cfg80211_scan_done(priv->scan_request, &info);
241 priv->scan_request = NULL; 245 priv->scan_request = NULL;
242 } 246 }
243} 247}
@@ -245,7 +249,11 @@ void orinoco_add_hostscan_results(struct orinoco_private *priv,
245void orinoco_scan_done(struct orinoco_private *priv, bool abort) 249void orinoco_scan_done(struct orinoco_private *priv, bool abort)
246{ 250{
247 if (priv->scan_request) { 251 if (priv->scan_request) {
248 cfg80211_scan_done(priv->scan_request, abort); 252 struct cfg80211_scan_info info = {
253 .aborted = abort,
254 };
255
256 cfg80211_scan_done(priv->scan_request, &info);
249 priv->scan_request = NULL; 257 priv->scan_request = NULL;
250 } 258 }
251} 259}
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index a1e28a4fd658..8c35ac838fce 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -41,8 +41,6 @@ MODULE_AUTHOR("Jouni Malinen");
41MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211"); 41MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");
42MODULE_LICENSE("GPL"); 42MODULE_LICENSE("GPL");
43 43
44static u32 wmediumd_portid;
45
46static int radios = 2; 44static int radios = 2;
47module_param(radios, int, 0444); 45module_param(radios, int, 0444);
48MODULE_PARM_DESC(radios, "Number of simulated radios"); 46MODULE_PARM_DESC(radios, "Number of simulated radios");
@@ -252,12 +250,13 @@ static inline void hwsim_clear_chanctx_magic(struct ieee80211_chanctx_conf *c)
252 cp->magic = 0; 250 cp->magic = 0;
253} 251}
254 252
255static unsigned int hwsim_net_id; 253static int hwsim_net_id;
256 254
257static int hwsim_netgroup; 255static int hwsim_netgroup;
258 256
259struct hwsim_net { 257struct hwsim_net {
260 int netgroup; 258 int netgroup;
259 u32 wmediumd;
261}; 260};
262 261
263static inline int hwsim_net_get_netgroup(struct net *net) 262static inline int hwsim_net_get_netgroup(struct net *net)
@@ -274,6 +273,20 @@ static inline void hwsim_net_set_netgroup(struct net *net)
274 hwsim_net->netgroup = hwsim_netgroup++; 273 hwsim_net->netgroup = hwsim_netgroup++;
275} 274}
276 275
276static inline u32 hwsim_net_get_wmediumd(struct net *net)
277{
278 struct hwsim_net *hwsim_net = net_generic(net, hwsim_net_id);
279
280 return hwsim_net->wmediumd;
281}
282
283static inline void hwsim_net_set_wmediumd(struct net *net, u32 portid)
284{
285 struct hwsim_net *hwsim_net = net_generic(net, hwsim_net_id);
286
287 hwsim_net->wmediumd = portid;
288}
289
277static struct class *hwsim_class; 290static struct class *hwsim_class;
278 291
279static struct net_device *hwsim_mon; /* global monitor netdev */ 292static struct net_device *hwsim_mon; /* global monitor netdev */
@@ -444,10 +457,6 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = {
444 { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) } 457 { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }
445}; 458};
446 459
447static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = {
448 { .max = 8, .types = BIT(NL80211_IFTYPE_AP) },
449};
450
451static const struct ieee80211_iface_combination hwsim_if_comb[] = { 460static const struct ieee80211_iface_combination hwsim_if_comb[] = {
452 { 461 {
453 .limits = hwsim_if_limits, 462 .limits = hwsim_if_limits,
@@ -455,18 +464,12 @@ static const struct ieee80211_iface_combination hwsim_if_comb[] = {
455 .n_limits = ARRAY_SIZE(hwsim_if_limits) - 1, 464 .n_limits = ARRAY_SIZE(hwsim_if_limits) - 1,
456 .max_interfaces = 2048, 465 .max_interfaces = 2048,
457 .num_different_channels = 1, 466 .num_different_channels = 1,
458 },
459 {
460 .limits = hwsim_if_dfs_limits,
461 .n_limits = ARRAY_SIZE(hwsim_if_dfs_limits),
462 .max_interfaces = 8,
463 .num_different_channels = 1,
464 .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | 467 .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
465 BIT(NL80211_CHAN_WIDTH_20) | 468 BIT(NL80211_CHAN_WIDTH_20) |
466 BIT(NL80211_CHAN_WIDTH_40) | 469 BIT(NL80211_CHAN_WIDTH_40) |
467 BIT(NL80211_CHAN_WIDTH_80) | 470 BIT(NL80211_CHAN_WIDTH_80) |
468 BIT(NL80211_CHAN_WIDTH_160), 471 BIT(NL80211_CHAN_WIDTH_160),
469 } 472 },
470}; 473};
471 474
472static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = { 475static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = {
@@ -475,18 +478,12 @@ static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = {
475 .n_limits = ARRAY_SIZE(hwsim_if_limits), 478 .n_limits = ARRAY_SIZE(hwsim_if_limits),
476 .max_interfaces = 2048, 479 .max_interfaces = 2048,
477 .num_different_channels = 1, 480 .num_different_channels = 1,
478 },
479 {
480 .limits = hwsim_if_dfs_limits,
481 .n_limits = ARRAY_SIZE(hwsim_if_dfs_limits),
482 .max_interfaces = 8,
483 .num_different_channels = 1,
484 .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | 481 .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
485 BIT(NL80211_CHAN_WIDTH_20) | 482 BIT(NL80211_CHAN_WIDTH_20) |
486 BIT(NL80211_CHAN_WIDTH_40) | 483 BIT(NL80211_CHAN_WIDTH_40) |
487 BIT(NL80211_CHAN_WIDTH_80) | 484 BIT(NL80211_CHAN_WIDTH_80) |
488 BIT(NL80211_CHAN_WIDTH_160), 485 BIT(NL80211_CHAN_WIDTH_160),
489 } 486 },
490}; 487};
491 488
492static spinlock_t hwsim_radio_lock; 489static spinlock_t hwsim_radio_lock;
@@ -552,6 +549,8 @@ struct mac80211_hwsim_data {
552 549
553 /* group shared by radios created in the same netns */ 550 /* group shared by radios created in the same netns */
554 int netgroup; 551 int netgroup;
552 /* wmediumd portid responsible for netgroup of this radio */
553 u32 wmediumd;
555 554
556 int power_level; 555 int power_level;
557 556
@@ -983,6 +982,29 @@ static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data,
983 return true; 982 return true;
984} 983}
985 984
985static int hwsim_unicast_netgroup(struct mac80211_hwsim_data *data,
986 struct sk_buff *skb, int portid)
987{
988 struct net *net;
989 bool found = false;
990 int res = -ENOENT;
991
992 rcu_read_lock();
993 for_each_net_rcu(net) {
994 if (data->netgroup == hwsim_net_get_netgroup(net)) {
995 res = genlmsg_unicast(net, skb, portid);
996 found = true;
997 break;
998 }
999 }
1000 rcu_read_unlock();
1001
1002 if (!found)
1003 nlmsg_free(skb);
1004
1005 return res;
1006}
1007
986static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, 1008static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
987 struct sk_buff *my_skb, 1009 struct sk_buff *my_skb,
988 int dst_portid) 1010 int dst_portid)
@@ -1062,7 +1084,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
1062 goto nla_put_failure; 1084 goto nla_put_failure;
1063 1085
1064 genlmsg_end(skb, msg_head); 1086 genlmsg_end(skb, msg_head);
1065 if (genlmsg_unicast(&init_net, skb, dst_portid)) 1087 if (hwsim_unicast_netgroup(data, skb, dst_portid))
1066 goto err_free_txskb; 1088 goto err_free_txskb;
1067 1089
1068 /* Enqueue the packet */ 1090 /* Enqueue the packet */
@@ -1355,7 +1377,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
1355 mac80211_hwsim_monitor_rx(hw, skb, channel); 1377 mac80211_hwsim_monitor_rx(hw, skb, channel);
1356 1378
1357 /* wmediumd mode check */ 1379 /* wmediumd mode check */
1358 _portid = ACCESS_ONCE(wmediumd_portid); 1380 _portid = ACCESS_ONCE(data->wmediumd);
1359 1381
1360 if (_portid) 1382 if (_portid)
1361 return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); 1383 return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
@@ -1451,7 +1473,8 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
1451 struct sk_buff *skb, 1473 struct sk_buff *skb,
1452 struct ieee80211_channel *chan) 1474 struct ieee80211_channel *chan)
1453{ 1475{
1454 u32 _pid = ACCESS_ONCE(wmediumd_portid); 1476 struct mac80211_hwsim_data *data = hw->priv;
1477 u32 _pid = ACCESS_ONCE(data->wmediumd);
1455 1478
1456 if (ieee80211_hw_check(hw, SUPPORTS_RC_TABLE)) { 1479 if (ieee80211_hw_check(hw, SUPPORTS_RC_TABLE)) {
1457 struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb); 1480 struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
@@ -1918,8 +1941,12 @@ static void hw_scan_work(struct work_struct *work)
1918 1941
1919 mutex_lock(&hwsim->mutex); 1942 mutex_lock(&hwsim->mutex);
1920 if (hwsim->scan_chan_idx >= req->n_channels) { 1943 if (hwsim->scan_chan_idx >= req->n_channels) {
1944 struct cfg80211_scan_info info = {
1945 .aborted = false,
1946 };
1947
1921 wiphy_debug(hwsim->hw->wiphy, "hw scan complete\n"); 1948 wiphy_debug(hwsim->hw->wiphy, "hw scan complete\n");
1922 ieee80211_scan_completed(hwsim->hw, false); 1949 ieee80211_scan_completed(hwsim->hw, &info);
1923 hwsim->hw_scan_request = NULL; 1950 hwsim->hw_scan_request = NULL;
1924 hwsim->hw_scan_vif = NULL; 1951 hwsim->hw_scan_vif = NULL;
1925 hwsim->tmp_chan = NULL; 1952 hwsim->tmp_chan = NULL;
@@ -2004,13 +2031,16 @@ static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw,
2004 struct ieee80211_vif *vif) 2031 struct ieee80211_vif *vif)
2005{ 2032{
2006 struct mac80211_hwsim_data *hwsim = hw->priv; 2033 struct mac80211_hwsim_data *hwsim = hw->priv;
2034 struct cfg80211_scan_info info = {
2035 .aborted = true,
2036 };
2007 2037
2008 wiphy_debug(hw->wiphy, "hwsim cancel_hw_scan\n"); 2038 wiphy_debug(hw->wiphy, "hwsim cancel_hw_scan\n");
2009 2039
2010 cancel_delayed_work_sync(&hwsim->hw_scan); 2040 cancel_delayed_work_sync(&hwsim->hw_scan);
2011 2041
2012 mutex_lock(&hwsim->mutex); 2042 mutex_lock(&hwsim->mutex);
2013 ieee80211_scan_completed(hwsim->hw, true); 2043 ieee80211_scan_completed(hwsim->hw, &info);
2014 hwsim->tmp_chan = NULL; 2044 hwsim->tmp_chan = NULL;
2015 hwsim->hw_scan_request = NULL; 2045 hwsim->hw_scan_request = NULL;
2016 hwsim->hw_scan_vif = NULL; 2046 hwsim->hw_scan_vif = NULL;
@@ -2448,13 +2478,14 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
2448 hw->wiphy->max_scan_ssids = 255; 2478 hw->wiphy->max_scan_ssids = 255;
2449 hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; 2479 hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
2450 hw->wiphy->max_remain_on_channel_duration = 1000; 2480 hw->wiphy->max_remain_on_channel_duration = 1000;
2451 /* For channels > 1 DFS is not allowed */
2452 hw->wiphy->n_iface_combinations = 1;
2453 hw->wiphy->iface_combinations = &data->if_combination; 2481 hw->wiphy->iface_combinations = &data->if_combination;
2454 if (param->p2p_device) 2482 if (param->p2p_device)
2455 data->if_combination = hwsim_if_comb_p2p_dev[0]; 2483 data->if_combination = hwsim_if_comb_p2p_dev[0];
2456 else 2484 else
2457 data->if_combination = hwsim_if_comb[0]; 2485 data->if_combination = hwsim_if_comb[0];
2486 hw->wiphy->n_iface_combinations = 1;
2487 /* For channels > 1 DFS is not allowed */
2488 data->if_combination.radar_detect_widths = 0;
2458 data->if_combination.num_different_channels = data->channels; 2489 data->if_combination.num_different_channels = data->channels;
2459 } else if (param->p2p_device) { 2490 } else if (param->p2p_device) {
2460 hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev; 2491 hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev;
@@ -2796,6 +2827,20 @@ static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(const u8 *addr)
2796 return data; 2827 return data;
2797} 2828}
2798 2829
2830static void hwsim_register_wmediumd(struct net *net, u32 portid)
2831{
2832 struct mac80211_hwsim_data *data;
2833
2834 hwsim_net_set_wmediumd(net, portid);
2835
2836 spin_lock_bh(&hwsim_radio_lock);
2837 list_for_each_entry(data, &hwsim_radios, list) {
2838 if (data->netgroup == hwsim_net_get_netgroup(net))
2839 data->wmediumd = portid;
2840 }
2841 spin_unlock_bh(&hwsim_radio_lock);
2842}
2843
2799static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, 2844static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
2800 struct genl_info *info) 2845 struct genl_info *info)
2801{ 2846{
@@ -2811,9 +2856,6 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
2811 int i; 2856 int i;
2812 bool found = false; 2857 bool found = false;
2813 2858
2814 if (info->snd_portid != wmediumd_portid)
2815 return -EINVAL;
2816
2817 if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] || 2859 if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
2818 !info->attrs[HWSIM_ATTR_FLAGS] || 2860 !info->attrs[HWSIM_ATTR_FLAGS] ||
2819 !info->attrs[HWSIM_ATTR_COOKIE] || 2861 !info->attrs[HWSIM_ATTR_COOKIE] ||
@@ -2829,6 +2871,12 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
2829 if (!data2) 2871 if (!data2)
2830 goto out; 2872 goto out;
2831 2873
2874 if (hwsim_net_get_netgroup(genl_info_net(info)) != data2->netgroup)
2875 goto out;
2876
2877 if (info->snd_portid != data2->wmediumd)
2878 goto out;
2879
2832 /* look for the skb matching the cookie passed back from user */ 2880 /* look for the skb matching the cookie passed back from user */
2833 skb_queue_walk_safe(&data2->pending, skb, tmp) { 2881 skb_queue_walk_safe(&data2->pending, skb, tmp) {
2834 u64 skb_cookie; 2882 u64 skb_cookie;
@@ -2892,9 +2940,6 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
2892 void *frame_data; 2940 void *frame_data;
2893 struct sk_buff *skb = NULL; 2941 struct sk_buff *skb = NULL;
2894 2942
2895 if (info->snd_portid != wmediumd_portid)
2896 return -EINVAL;
2897
2898 if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] || 2943 if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] ||
2899 !info->attrs[HWSIM_ATTR_FRAME] || 2944 !info->attrs[HWSIM_ATTR_FRAME] ||
2900 !info->attrs[HWSIM_ATTR_RX_RATE] || 2945 !info->attrs[HWSIM_ATTR_RX_RATE] ||
@@ -2920,6 +2965,12 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
2920 if (!data2) 2965 if (!data2)
2921 goto out; 2966 goto out;
2922 2967
2968 if (hwsim_net_get_netgroup(genl_info_net(info)) != data2->netgroup)
2969 goto out;
2970
2971 if (info->snd_portid != data2->wmediumd)
2972 goto out;
2973
2923 /* check if radio is configured properly */ 2974 /* check if radio is configured properly */
2924 2975
2925 if (data2->idle || !data2->started) 2976 if (data2->idle || !data2->started)
@@ -2966,6 +3017,7 @@ out:
2966static int hwsim_register_received_nl(struct sk_buff *skb_2, 3017static int hwsim_register_received_nl(struct sk_buff *skb_2,
2967 struct genl_info *info) 3018 struct genl_info *info)
2968{ 3019{
3020 struct net *net = genl_info_net(info);
2969 struct mac80211_hwsim_data *data; 3021 struct mac80211_hwsim_data *data;
2970 int chans = 1; 3022 int chans = 1;
2971 3023
@@ -2982,10 +3034,10 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2,
2982 if (chans > 1) 3034 if (chans > 1)
2983 return -EOPNOTSUPP; 3035 return -EOPNOTSUPP;
2984 3036
2985 if (wmediumd_portid) 3037 if (hwsim_net_get_wmediumd(net))
2986 return -EBUSY; 3038 return -EBUSY;
2987 3039
2988 wmediumd_portid = info->snd_portid; 3040 hwsim_register_wmediumd(net, info->snd_portid);
2989 3041
2990 printk(KERN_DEBUG "mac80211_hwsim: received a REGISTER, " 3042 printk(KERN_DEBUG "mac80211_hwsim: received a REGISTER, "
2991 "switching to wmediumd mode with pid %d\n", info->snd_portid); 3043 "switching to wmediumd mode with pid %d\n", info->snd_portid);
@@ -3152,7 +3204,7 @@ static const struct genl_ops hwsim_ops[] = {
3152 .cmd = HWSIM_CMD_REGISTER, 3204 .cmd = HWSIM_CMD_REGISTER,
3153 .policy = hwsim_genl_policy, 3205 .policy = hwsim_genl_policy,
3154 .doit = hwsim_register_received_nl, 3206 .doit = hwsim_register_received_nl,
3155 .flags = GENL_ADMIN_PERM, 3207 .flags = GENL_UNS_ADMIN_PERM,
3156 }, 3208 },
3157 { 3209 {
3158 .cmd = HWSIM_CMD_FRAME, 3210 .cmd = HWSIM_CMD_FRAME,
@@ -3218,10 +3270,10 @@ static int mac80211_hwsim_netlink_notify(struct notifier_block *nb,
3218 3270
3219 remove_user_radios(notify->portid); 3271 remove_user_radios(notify->portid);
3220 3272
3221 if (notify->portid == wmediumd_portid) { 3273 if (notify->portid == hwsim_net_get_wmediumd(notify->net)) {
3222 printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink" 3274 printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink"
3223 " socket, switching to perfect channel medium\n"); 3275 " socket, switching to perfect channel medium\n");
3224 wmediumd_portid = 0; 3276 hwsim_register_wmediumd(notify->net, 0);
3225 } 3277 }
3226 return NOTIFY_DONE; 3278 return NOTIFY_DONE;
3227 3279
diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c
index 776b44bfd93a..ea4802446618 100644
--- a/drivers/net/wireless/marvell/libertas/cfg.c
+++ b/drivers/net/wireless/marvell/libertas/cfg.c
@@ -796,10 +796,15 @@ void lbs_scan_done(struct lbs_private *priv)
796{ 796{
797 WARN_ON(!priv->scan_req); 797 WARN_ON(!priv->scan_req);
798 798
799 if (priv->internal_scan) 799 if (priv->internal_scan) {
800 kfree(priv->scan_req); 800 kfree(priv->scan_req);
801 else 801 } else {
802 cfg80211_scan_done(priv->scan_req, false); 802 struct cfg80211_scan_info info = {
803 .aborted = false,
804 };
805
806 cfg80211_scan_done(priv->scan_req, &info);
807 }
803 808
804 priv->scan_req = NULL; 809 priv->scan_req = NULL;
805} 810}
diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 6bc2011d8609..e7a21443647e 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -1057,8 +1057,12 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
1057 if (!priv) 1057 if (!priv)
1058 continue; 1058 continue;
1059 if (priv->scan_request) { 1059 if (priv->scan_request) {
1060 struct cfg80211_scan_info info = {
1061 .aborted = true,
1062 };
1063
1060 mwifiex_dbg(adapter, WARN, "info: aborting scan\n"); 1064 mwifiex_dbg(adapter, WARN, "info: aborting scan\n");
1061 cfg80211_scan_done(priv->scan_request, 1); 1065 cfg80211_scan_done(priv->scan_request, &info);
1062 priv->scan_request = NULL; 1066 priv->scan_request = NULL;
1063 } 1067 }
1064 } 1068 }
@@ -1112,8 +1116,12 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
1112 if (!priv) 1116 if (!priv)
1113 continue; 1117 continue;
1114 if (priv->scan_request) { 1118 if (priv->scan_request) {
1119 struct cfg80211_scan_info info = {
1120 .aborted = true,
1121 };
1122
1115 mwifiex_dbg(adapter, WARN, "info: aborting scan\n"); 1123 mwifiex_dbg(adapter, WARN, "info: aborting scan\n");
1116 cfg80211_scan_done(priv->scan_request, 1); 1124 cfg80211_scan_done(priv->scan_request, &info);
1117 priv->scan_request = NULL; 1125 priv->scan_request = NULL;
1118 } 1126 }
1119 } 1127 }
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 0e280f879b58..db4925db39aa 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -697,9 +697,13 @@ mwifiex_close(struct net_device *dev)
697 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); 697 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
698 698
699 if (priv->scan_request) { 699 if (priv->scan_request) {
700 struct cfg80211_scan_info info = {
701 .aborted = true,
702 };
703
700 mwifiex_dbg(priv->adapter, INFO, 704 mwifiex_dbg(priv->adapter, INFO,
701 "aborting scan on ndo_stop\n"); 705 "aborting scan on ndo_stop\n");
702 cfg80211_scan_done(priv->scan_request, 1); 706 cfg80211_scan_done(priv->scan_request, &info);
703 priv->scan_request = NULL; 707 priv->scan_request = NULL;
704 priv->scan_aborting = true; 708 priv->scan_aborting = true;
705 } 709 }
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
index bc5e52cebce1..fdd749110fcb 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -1956,9 +1956,13 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
1956 mwifiex_complete_scan(priv); 1956 mwifiex_complete_scan(priv);
1957 1957
1958 if (priv->scan_request) { 1958 if (priv->scan_request) {
1959 struct cfg80211_scan_info info = {
1960 .aborted = false,
1961 };
1962
1959 mwifiex_dbg(adapter, INFO, 1963 mwifiex_dbg(adapter, INFO,
1960 "info: notifying scan done\n"); 1964 "info: notifying scan done\n");
1961 cfg80211_scan_done(priv->scan_request, 0); 1965 cfg80211_scan_done(priv->scan_request, &info);
1962 priv->scan_request = NULL; 1966 priv->scan_request = NULL;
1963 } else { 1967 } else {
1964 priv->scan_aborting = false; 1968 priv->scan_aborting = false;
@@ -1977,9 +1981,13 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
1977 1981
1978 if (!adapter->active_scan_triggered) { 1982 if (!adapter->active_scan_triggered) {
1979 if (priv->scan_request) { 1983 if (priv->scan_request) {
1984 struct cfg80211_scan_info info = {
1985 .aborted = true,
1986 };
1987
1980 mwifiex_dbg(adapter, INFO, 1988 mwifiex_dbg(adapter, INFO,
1981 "info: aborting scan\n"); 1989 "info: aborting scan\n");
1982 cfg80211_scan_done(priv->scan_request, 1); 1990 cfg80211_scan_done(priv->scan_request, &info);
1983 priv->scan_request = NULL; 1991 priv->scan_request = NULL;
1984 } else { 1992 } else {
1985 priv->scan_aborting = false; 1993 priv->scan_aborting = false;
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 569918c485b4..603c90470225 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2134,6 +2134,7 @@ static void rndis_get_scan_results(struct work_struct *work)
2134 struct rndis_wlan_private *priv = 2134 struct rndis_wlan_private *priv =
2135 container_of(work, struct rndis_wlan_private, scan_work.work); 2135 container_of(work, struct rndis_wlan_private, scan_work.work);
2136 struct usbnet *usbdev = priv->usbdev; 2136 struct usbnet *usbdev = priv->usbdev;
2137 struct cfg80211_scan_info info = {};
2137 int ret; 2138 int ret;
2138 2139
2139 netdev_dbg(usbdev->net, "get_scan_results\n"); 2140 netdev_dbg(usbdev->net, "get_scan_results\n");
@@ -2143,7 +2144,8 @@ static void rndis_get_scan_results(struct work_struct *work)
2143 2144
2144 ret = rndis_check_bssid_list(usbdev, NULL, NULL); 2145 ret = rndis_check_bssid_list(usbdev, NULL, NULL);
2145 2146
2146 cfg80211_scan_done(priv->scan_request, ret < 0); 2147 info.aborted = ret < 0;
2148 cfg80211_scan_done(priv->scan_request, &info);
2147 2149
2148 priv->scan_request = NULL; 2150 priv->scan_request = NULL;
2149} 2151}
@@ -3574,7 +3576,11 @@ static int rndis_wlan_stop(struct usbnet *usbdev)
3574 flush_workqueue(priv->workqueue); 3576 flush_workqueue(priv->workqueue);
3575 3577
3576 if (priv->scan_request) { 3578 if (priv->scan_request) {
3577 cfg80211_scan_done(priv->scan_request, true); 3579 struct cfg80211_scan_info info = {
3580 .aborted = true,
3581 };
3582
3583 cfg80211_scan_done(priv->scan_request, &info);
3578 priv->scan_request = NULL; 3584 priv->scan_request = NULL;
3579 } 3585 }
3580 3586
diff --git a/drivers/net/wireless/st/cw1200/scan.c b/drivers/net/wireless/st/cw1200/scan.c
index 983788156bb0..0a0ff7e31f5b 100644
--- a/drivers/net/wireless/st/cw1200/scan.c
+++ b/drivers/net/wireless/st/cw1200/scan.c
@@ -167,6 +167,10 @@ void cw1200_scan_work(struct work_struct *work)
167 } 167 }
168 168
169 if (!priv->scan.req || (priv->scan.curr == priv->scan.end)) { 169 if (!priv->scan.req || (priv->scan.curr == priv->scan.end)) {
170 struct cfg80211_scan_info info = {
171 .aborted = priv->scan.status ? 1 : 0,
172 };
173
170 if (priv->scan.output_power != priv->output_power) 174 if (priv->scan.output_power != priv->output_power)
171 wsm_set_output_power(priv, priv->output_power * 10); 175 wsm_set_output_power(priv, priv->output_power * 10);
172 if (priv->join_status == CW1200_JOIN_STATUS_STA && 176 if (priv->join_status == CW1200_JOIN_STATUS_STA &&
@@ -188,7 +192,7 @@ void cw1200_scan_work(struct work_struct *work)
188 cw1200_scan_restart_delayed(priv); 192 cw1200_scan_restart_delayed(priv);
189 wsm_unlock_tx(priv); 193 wsm_unlock_tx(priv);
190 mutex_unlock(&priv->conf_mutex); 194 mutex_unlock(&priv->conf_mutex);
191 ieee80211_scan_completed(priv->hw, priv->scan.status ? 1 : 0); 195 ieee80211_scan_completed(priv->hw, &info);
192 up(&priv->scan.lock); 196 up(&priv->scan.lock);
193 return; 197 return;
194 } else { 198 } else {
diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c
index c98630394a1a..d0593bc1f1a9 100644
--- a/drivers/net/wireless/ti/wl1251/event.c
+++ b/drivers/net/wireless/ti/wl1251/event.c
@@ -36,7 +36,11 @@ static int wl1251_event_scan_complete(struct wl1251 *wl,
36 mbox->scheduled_scan_channels); 36 mbox->scheduled_scan_channels);
37 37
38 if (wl->scanning) { 38 if (wl->scanning) {
39 ieee80211_scan_completed(wl->hw, false); 39 struct cfg80211_scan_info info = {
40 .aborted = false,
41 };
42
43 ieee80211_scan_completed(wl->hw, &info);
40 wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed"); 44 wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed");
41 wl->scanning = false; 45 wl->scanning = false;
42 if (wl->hw->conf.flags & IEEE80211_CONF_IDLE) 46 if (wl->hw->conf.flags & IEEE80211_CONF_IDLE)
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 56384a4e2a35..bbf7604889b7 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -448,7 +448,11 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
448 WARN_ON(wl->state != WL1251_STATE_ON); 448 WARN_ON(wl->state != WL1251_STATE_ON);
449 449
450 if (wl->scanning) { 450 if (wl->scanning) {
451 ieee80211_scan_completed(wl->hw, true); 451 struct cfg80211_scan_info info = {
452 .aborted = true,
453 };
454
455 ieee80211_scan_completed(wl->hw, &info);
452 wl->scanning = false; 456 wl->scanning = false;
453 } 457 }
454 458
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 10fd24c28ece..69267d592504 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -2615,6 +2615,10 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
2615 2615
2616 if (wl->scan.state != WL1271_SCAN_STATE_IDLE && 2616 if (wl->scan.state != WL1271_SCAN_STATE_IDLE &&
2617 wl->scan_wlvif == wlvif) { 2617 wl->scan_wlvif == wlvif) {
2618 struct cfg80211_scan_info info = {
2619 .aborted = true,
2620 };
2621
2618 /* 2622 /*
2619 * Rearm the tx watchdog just before idling scan. This 2623 * Rearm the tx watchdog just before idling scan. This
2620 * prevents just-finished scans from triggering the watchdog 2624 * prevents just-finished scans from triggering the watchdog
@@ -2625,7 +2629,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
2625 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); 2629 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
2626 wl->scan_wlvif = NULL; 2630 wl->scan_wlvif = NULL;
2627 wl->scan.req = NULL; 2631 wl->scan.req = NULL;
2628 ieee80211_scan_completed(wl->hw, true); 2632 ieee80211_scan_completed(wl->hw, &info);
2629 } 2633 }
2630 2634
2631 if (wl->sched_vif == wlvif) 2635 if (wl->sched_vif == wlvif)
@@ -3649,6 +3653,9 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw,
3649{ 3653{
3650 struct wl1271 *wl = hw->priv; 3654 struct wl1271 *wl = hw->priv;
3651 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); 3655 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
3656 struct cfg80211_scan_info info = {
3657 .aborted = true,
3658 };
3652 int ret; 3659 int ret;
3653 3660
3654 wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan"); 3661 wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan");
@@ -3681,7 +3688,7 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw,
3681 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); 3688 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
3682 wl->scan_wlvif = NULL; 3689 wl->scan_wlvif = NULL;
3683 wl->scan.req = NULL; 3690 wl->scan.req = NULL;
3684 ieee80211_scan_completed(wl->hw, true); 3691 ieee80211_scan_completed(wl->hw, &info);
3685 3692
3686out_sleep: 3693out_sleep:
3687 wl1271_ps_elp_sleep(wl); 3694 wl1271_ps_elp_sleep(wl);
diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c
index 23343643207a..5612f5916b4e 100644
--- a/drivers/net/wireless/ti/wlcore/scan.c
+++ b/drivers/net/wireless/ti/wlcore/scan.c
@@ -36,6 +36,9 @@ void wl1271_scan_complete_work(struct work_struct *work)
36 struct delayed_work *dwork; 36 struct delayed_work *dwork;
37 struct wl1271 *wl; 37 struct wl1271 *wl;
38 struct wl12xx_vif *wlvif; 38 struct wl12xx_vif *wlvif;
39 struct cfg80211_scan_info info = {
40 .aborted = false,
41 };
39 int ret; 42 int ret;
40 43
41 dwork = to_delayed_work(work); 44 dwork = to_delayed_work(work);
@@ -82,7 +85,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
82 85
83 wlcore_cmd_regdomain_config_locked(wl); 86 wlcore_cmd_regdomain_config_locked(wl);
84 87
85 ieee80211_scan_completed(wl->hw, false); 88 ieee80211_scan_completed(wl->hw, &info);
86 89
87out: 90out:
88 mutex_unlock(&wl->mutex); 91 mutex_unlock(&wl->mutex);
diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
index 0da559d929bc..d0ba3778990e 100644
--- a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
+++ b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
@@ -1256,10 +1256,15 @@ void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
1256 DBG_8723A("%s with scan req\n", __func__); 1256 DBG_8723A("%s with scan req\n", __func__);
1257 1257
1258 if (pwdev_priv->scan_request->wiphy != 1258 if (pwdev_priv->scan_request->wiphy !=
1259 pwdev_priv->rtw_wdev->wiphy) 1259 pwdev_priv->rtw_wdev->wiphy) {
1260 DBG_8723A("error wiphy compare\n"); 1260 DBG_8723A("error wiphy compare\n");
1261 else 1261 } else {
1262 cfg80211_scan_done(pwdev_priv->scan_request, aborted); 1262 struct cfg80211_scan_info info = {
1263 .aborted = aborted,
1264 };
1265
1266 cfg80211_scan_done(pwdev_priv->scan_request, &info);
1267 }
1263 1268
1264 pwdev_priv->scan_request = NULL; 1269 pwdev_priv->scan_request = NULL;
1265 } else { 1270 } else {
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index 51aff4ff7d7c..a0d8e22e575b 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -454,7 +454,11 @@ static void CfgScanResult(enum scan_event scan_event,
454 mutex_lock(&priv->scan_req_lock); 454 mutex_lock(&priv->scan_req_lock);
455 455
456 if (priv->pstrScanReq) { 456 if (priv->pstrScanReq) {
457 cfg80211_scan_done(priv->pstrScanReq, false); 457 struct cfg80211_scan_info info = {
458 .aborted = false,
459 };
460
461 cfg80211_scan_done(priv->pstrScanReq, &info);
458 priv->u32RcvdChCount = 0; 462 priv->u32RcvdChCount = 0;
459 priv->bCfgScanning = false; 463 priv->bCfgScanning = false;
460 priv->pstrScanReq = NULL; 464 priv->pstrScanReq = NULL;
@@ -464,10 +468,14 @@ static void CfgScanResult(enum scan_event scan_event,
464 mutex_lock(&priv->scan_req_lock); 468 mutex_lock(&priv->scan_req_lock);
465 469
466 if (priv->pstrScanReq) { 470 if (priv->pstrScanReq) {
471 struct cfg80211_scan_info info = {
472 .aborted = false,
473 };
474
467 update_scan_time(); 475 update_scan_time();
468 refresh_scan(priv, 1, false); 476 refresh_scan(priv, 1, false);
469 477
470 cfg80211_scan_done(priv->pstrScanReq, false); 478 cfg80211_scan_done(priv->pstrScanReq, &info);
471 priv->bCfgScanning = false; 479 priv->bCfgScanning = false;
472 priv->pstrScanReq = NULL; 480 priv->pstrScanReq = NULL;
473 } 481 }
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c
index a6e6fb9f42e1..f46dfe6b24e8 100644
--- a/drivers/staging/wlan-ng/cfg80211.c
+++ b/drivers/staging/wlan-ng/cfg80211.c
@@ -338,6 +338,8 @@ static int prism2_scan(struct wiphy *wiphy,
338 struct p80211msg_dot11req_scan msg1; 338 struct p80211msg_dot11req_scan msg1;
339 struct p80211msg_dot11req_scan_results msg2; 339 struct p80211msg_dot11req_scan_results msg2;
340 struct cfg80211_bss *bss; 340 struct cfg80211_bss *bss;
341 struct cfg80211_scan_info info = {};
342
341 int result; 343 int result;
342 int err = 0; 344 int err = 0;
343 int numbss = 0; 345 int numbss = 0;
@@ -440,7 +442,8 @@ static int prism2_scan(struct wiphy *wiphy,
440 err = prism2_result2err(msg2.resultcode.data); 442 err = prism2_result2err(msg2.resultcode.data);
441 443
442exit: 444exit:
443 cfg80211_scan_done(request, err ? 1 : 0); 445 info.aborted = !!(err);
446 cfg80211_scan_done(request, &info);
444 priv->scan_request = NULL; 447 priv->scan_request = NULL;
445 return err; 448 return err;
446} 449}
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index b118744d3382..a80516fd65c8 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -19,6 +19,7 @@
19 19
20#include <linux/types.h> 20#include <linux/types.h>
21#include <linux/if_ether.h> 21#include <linux/if_ether.h>
22#include <linux/etherdevice.h>
22#include <asm/byteorder.h> 23#include <asm/byteorder.h>
23#include <asm/unaligned.h> 24#include <asm/unaligned.h>
24 25
@@ -2464,7 +2465,7 @@ static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
2464 */ 2465 */
2465static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb) 2466static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb)
2466{ 2467{
2467 if (skb->len < 25) 2468 if (skb->len < IEEE80211_MIN_ACTION_SIZE)
2468 return false; 2469 return false;
2469 return _ieee80211_is_robust_mgmt_frame((void *)skb->data); 2470 return _ieee80211_is_robust_mgmt_frame((void *)skb->data);
2470} 2471}
@@ -2487,6 +2488,35 @@ static inline bool ieee80211_is_public_action(struct ieee80211_hdr *hdr,
2487} 2488}
2488 2489
2489/** 2490/**
2491 * _ieee80211_is_group_privacy_action - check if frame is a group addressed
2492 * privacy action frame
2493 * @hdr: the frame
2494 */
2495static inline bool _ieee80211_is_group_privacy_action(struct ieee80211_hdr *hdr)
2496{
2497 struct ieee80211_mgmt *mgmt = (void *)hdr;
2498
2499 if (!ieee80211_is_action(hdr->frame_control) ||
2500 !is_multicast_ether_addr(hdr->addr1))
2501 return false;
2502
2503 return mgmt->u.action.category == WLAN_CATEGORY_MESH_ACTION ||
2504 mgmt->u.action.category == WLAN_CATEGORY_MULTIHOP_ACTION;
2505}
2506
2507/**
2508 * ieee80211_is_group_privacy_action - check if frame is a group addressed
2509 * privacy action frame
2510 * @skb: the skb containing the frame, length will be checked
2511 */
2512static inline bool ieee80211_is_group_privacy_action(struct sk_buff *skb)
2513{
2514 if (skb->len < IEEE80211_MIN_ACTION_SIZE)
2515 return false;
2516 return _ieee80211_is_group_privacy_action((void *)skb->data);
2517}
2518
2519/**
2490 * ieee80211_tu_to_usec - convert time units (TU) to microseconds 2520 * ieee80211_tu_to_usec - convert time units (TU) to microseconds
2491 * @tu: the TUs 2521 * @tu: the TUs
2492 */ 2522 */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7bbb00d8b2cd..9c23f4d33e06 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -330,6 +330,9 @@ struct ieee80211_supported_band {
330 * in a separate chapter. 330 * in a separate chapter.
331 */ 331 */
332 332
333#define VHT_MUMIMO_GROUPS_DATA_LEN (WLAN_MEMBERSHIP_LEN +\
334 WLAN_USER_POSITION_LEN)
335
333/** 336/**
334 * struct vif_params - describes virtual interface parameters 337 * struct vif_params - describes virtual interface parameters
335 * @use_4addr: use 4-address frames 338 * @use_4addr: use 4-address frames
@@ -339,10 +342,13 @@ struct ieee80211_supported_band {
339 * This feature is only fully supported by drivers that enable the 342 * This feature is only fully supported by drivers that enable the
340 * %NL80211_FEATURE_MAC_ON_CREATE flag. Others may support creating 343 * %NL80211_FEATURE_MAC_ON_CREATE flag. Others may support creating
341 ** only p2p devices with specified MAC. 344 ** only p2p devices with specified MAC.
345 * @vht_mumimo_groups: MU-MIMO groupID. used for monitoring only
346 * packets belonging to that MU-MIMO groupID.
342 */ 347 */
343struct vif_params { 348struct vif_params {
344 int use_4addr; 349 int use_4addr;
345 u8 macaddr[ETH_ALEN]; 350 u8 macaddr[ETH_ALEN];
351 u8 vht_mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN];
346}; 352};
347 353
348/** 354/**
@@ -774,6 +780,7 @@ enum station_parameters_apply_mask {
774 * (bitmask of BIT(NL80211_STA_FLAG_...)) 780 * (bitmask of BIT(NL80211_STA_FLAG_...))
775 * @listen_interval: listen interval or -1 for no change 781 * @listen_interval: listen interval or -1 for no change
776 * @aid: AID or zero for no change 782 * @aid: AID or zero for no change
783 * @peer_aid: mesh peer AID or zero for no change
777 * @plink_action: plink action to take 784 * @plink_action: plink action to take
778 * @plink_state: set the peer link state for a station 785 * @plink_state: set the peer link state for a station
779 * @ht_capa: HT capabilities of station 786 * @ht_capa: HT capabilities of station
@@ -805,6 +812,7 @@ struct station_parameters {
805 u32 sta_modify_mask; 812 u32 sta_modify_mask;
806 int listen_interval; 813 int listen_interval;
807 u16 aid; 814 u16 aid;
815 u16 peer_aid;
808 u8 supported_rates_len; 816 u8 supported_rates_len;
809 u8 plink_action; 817 u8 plink_action;
810 u8 plink_state; 818 u8 plink_state;
@@ -1418,6 +1426,21 @@ struct cfg80211_ssid {
1418}; 1426};
1419 1427
1420/** 1428/**
1429 * struct cfg80211_scan_info - information about completed scan
1430 * @scan_start_tsf: scan start time in terms of the TSF of the BSS that the
1431 * wireless device that requested the scan is connected to. If this
1432 * information is not available, this field is left zero.
1433 * @tsf_bssid: the BSSID according to which %scan_start_tsf is set.
1434 * @aborted: set to true if the scan was aborted for any reason,
1435 * userspace will be notified of that
1436 */
1437struct cfg80211_scan_info {
1438 u64 scan_start_tsf;
1439 u8 tsf_bssid[ETH_ALEN] __aligned(2);
1440 bool aborted;
1441};
1442
1443/**
1421 * struct cfg80211_scan_request - scan request description 1444 * struct cfg80211_scan_request - scan request description
1422 * 1445 *
1423 * @ssids: SSIDs to scan for (active scan only) 1446 * @ssids: SSIDs to scan for (active scan only)
@@ -1427,12 +1450,17 @@ struct cfg80211_ssid {
1427 * @scan_width: channel width for scanning 1450 * @scan_width: channel width for scanning
1428 * @ie: optional information element(s) to add into Probe Request or %NULL 1451 * @ie: optional information element(s) to add into Probe Request or %NULL
1429 * @ie_len: length of ie in octets 1452 * @ie_len: length of ie in octets
1453 * @duration: how long to listen on each channel, in TUs. If
1454 * %duration_mandatory is not set, this is the maximum dwell time and
1455 * the actual dwell time may be shorter.
1456 * @duration_mandatory: if set, the scan duration must be as specified by the
1457 * %duration field.
1430 * @flags: bit field of flags controlling operation 1458 * @flags: bit field of flags controlling operation
1431 * @rates: bitmap of rates to advertise for each band 1459 * @rates: bitmap of rates to advertise for each band
1432 * @wiphy: the wiphy this was for 1460 * @wiphy: the wiphy this was for
1433 * @scan_start: time (in jiffies) when the scan started 1461 * @scan_start: time (in jiffies) when the scan started
1434 * @wdev: the wireless device to scan for 1462 * @wdev: the wireless device to scan for
1435 * @aborted: (internal) scan request was notified as aborted 1463 * @info: (internal) information about completed scan
1436 * @notified: (internal) scan request was notified as done or aborted 1464 * @notified: (internal) scan request was notified as done or aborted
1437 * @no_cck: used to send probe requests at non CCK rate in 2GHz band 1465 * @no_cck: used to send probe requests at non CCK rate in 2GHz band
1438 * @mac_addr: MAC address used with randomisation 1466 * @mac_addr: MAC address used with randomisation
@@ -1448,6 +1476,8 @@ struct cfg80211_scan_request {
1448 enum nl80211_bss_scan_width scan_width; 1476 enum nl80211_bss_scan_width scan_width;
1449 const u8 *ie; 1477 const u8 *ie;
1450 size_t ie_len; 1478 size_t ie_len;
1479 u16 duration;
1480 bool duration_mandatory;
1451 u32 flags; 1481 u32 flags;
1452 1482
1453 u32 rates[NUM_NL80211_BANDS]; 1483 u32 rates[NUM_NL80211_BANDS];
@@ -1461,7 +1491,8 @@ struct cfg80211_scan_request {
1461 /* internal */ 1491 /* internal */
1462 struct wiphy *wiphy; 1492 struct wiphy *wiphy;
1463 unsigned long scan_start; 1493 unsigned long scan_start;
1464 bool aborted, notified; 1494 struct cfg80211_scan_info info;
1495 bool notified;
1465 bool no_cck; 1496 bool no_cck;
1466 1497
1467 /* keep last */ 1498 /* keep last */
@@ -1594,12 +1625,19 @@ enum cfg80211_signal_type {
1594 * buffered on the device) and be accurate to about 10ms. 1625 * buffered on the device) and be accurate to about 10ms.
1595 * If the frame isn't buffered, just passing the return value of 1626 * If the frame isn't buffered, just passing the return value of
1596 * ktime_get_boot_ns() is likely appropriate. 1627 * ktime_get_boot_ns() is likely appropriate.
1628 * @parent_tsf: the time at the start of reception of the first octet of the
1629 * timestamp field of the frame. The time is the TSF of the BSS specified
1630 * by %parent_bssid.
1631 * @parent_bssid: the BSS according to which %parent_tsf is set. This is set to
1632 * the BSS that requested the scan in which the beacon/probe was received.
1597 */ 1633 */
1598struct cfg80211_inform_bss { 1634struct cfg80211_inform_bss {
1599 struct ieee80211_channel *chan; 1635 struct ieee80211_channel *chan;
1600 enum nl80211_bss_scan_width scan_width; 1636 enum nl80211_bss_scan_width scan_width;
1601 s32 signal; 1637 s32 signal;
1602 u64 boottime_ns; 1638 u64 boottime_ns;
1639 u64 parent_tsf;
1640 u8 parent_bssid[ETH_ALEN] __aligned(2);
1603}; 1641};
1604 1642
1605/** 1643/**
@@ -4061,10 +4099,10 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator);
4061 * cfg80211_scan_done - notify that scan finished 4099 * cfg80211_scan_done - notify that scan finished
4062 * 4100 *
4063 * @request: the corresponding scan request 4101 * @request: the corresponding scan request
4064 * @aborted: set to true if the scan was aborted for any reason, 4102 * @info: information about the completed scan
4065 * userspace will be notified of that
4066 */ 4103 */
4067void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted); 4104void cfg80211_scan_done(struct cfg80211_scan_request *request,
4105 struct cfg80211_scan_info *info);
4068 4106
4069/** 4107/**
4070 * cfg80211_sched_scan_results - notify that new scan results are available 4108 * cfg80211_sched_scan_results - notify that new scan results are available
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a52009ffc19f..b4faadbb4e01 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4697,9 +4697,10 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw);
4697 * any context, including hardirq context. 4697 * any context, including hardirq context.
4698 * 4698 *
4699 * @hw: the hardware that finished the scan 4699 * @hw: the hardware that finished the scan
4700 * @aborted: set to true if scan was aborted 4700 * @info: information about the completed scan
4701 */ 4701 */
4702void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted); 4702void ieee80211_scan_completed(struct ieee80211_hw *hw,
4703 struct cfg80211_scan_info *info);
4703 4704
4704/** 4705/**
4705 * ieee80211_sched_scan_results - got results from scheduled scan 4706 * ieee80211_sched_scan_results - got results from scheduled scan
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 53c8278827a0..220694151434 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1829,6 +1829,44 @@ enum nl80211_commands {
1829 * %NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities per 1829 * %NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities per
1830 * interface type. 1830 * interface type.
1831 * 1831 *
1832 * @NL80211_ATTR_MU_MIMO_GROUP_DATA: array of 24 bytes that defines a MU-MIMO
1833 * groupID for monitor mode.
1834 * The first 8 bytes are a mask that defines the membership in each
1835 * group (there are 64 groups, group 0 and 63 are reserved),
1836 * each bit represents a group and set to 1 for being a member in
1837 * that group and 0 for not being a member.
1838 * The remaining 16 bytes define the position in each group: 2 bits for
1839 * each group.
1840 * (smaller group numbers represented on most significant bits and bigger
1841 * group numbers on least significant bits.)
1842 * This attribute is used only if all interfaces are in monitor mode.
1843 * Set this attribute in order to monitor packets using the given MU-MIMO
1844 * groupID data.
1845 * to turn off that feature set all the bits of the groupID to zero.
1846 * @NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR: mac address for the sniffer to follow
1847 * when using MU-MIMO air sniffer.
1848 * to turn that feature off set an invalid mac address
1849 * (e.g. FF:FF:FF:FF:FF:FF)
1850 *
1851 * @NL80211_ATTR_SCAN_START_TIME_TSF: The time at which the scan was actually
1852 * started (u64). The time is the TSF of the BSS the interface that
1853 * requested the scan is connected to (if available, otherwise this
1854 * attribute must not be included).
1855 * @NL80211_ATTR_SCAN_START_TIME_TSF_BSSID: The BSS according to which
1856 * %NL80211_ATTR_SCAN_START_TIME_TSF is set.
1857 * @NL80211_ATTR_MEASUREMENT_DURATION: measurement duration in TUs (u16). If
1858 * %NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY is not set, this is the
1859 * maximum measurement duration allowed. This attribute is used with
1860 * measurement requests. It can also be used with %NL80211_CMD_TRIGGER_SCAN
1861 * if the scan is used for beacon report radio measurement.
1862 * @NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY: flag attribute that indicates
1863 * that the duration specified with %NL80211_ATTR_MEASUREMENT_DURATION is
1864 * mandatory. If this flag is not set, the duration is the maximum duration
1865 * and the actual measurement duration may be shorter.
1866 *
1867 * @NL80211_ATTR_MESH_PEER_AID: Association ID for the mesh peer (u16). This is
1868 * used to pull the stored data for mesh peer in power save state.
1869 *
1832 * @NUM_NL80211_ATTR: total number of nl80211_attrs available 1870 * @NUM_NL80211_ATTR: total number of nl80211_attrs available
1833 * @NL80211_ATTR_MAX: highest attribute number currently defined 1871 * @NL80211_ATTR_MAX: highest attribute number currently defined
1834 * @__NL80211_ATTR_AFTER_LAST: internal use 1872 * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2213,6 +2251,16 @@ enum nl80211_attrs {
2213 2251
2214 NL80211_ATTR_IFTYPE_EXT_CAPA, 2252 NL80211_ATTR_IFTYPE_EXT_CAPA,
2215 2253
2254 NL80211_ATTR_MU_MIMO_GROUP_DATA,
2255 NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR,
2256
2257 NL80211_ATTR_SCAN_START_TIME_TSF,
2258 NL80211_ATTR_SCAN_START_TIME_TSF_BSSID,
2259 NL80211_ATTR_MEASUREMENT_DURATION,
2260 NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY,
2261
2262 NL80211_ATTR_MESH_PEER_AID,
2263
2216 /* add attributes here, update the policy in nl80211.c */ 2264 /* add attributes here, update the policy in nl80211.c */
2217 2265
2218 __NL80211_ATTR_AFTER_LAST, 2266 __NL80211_ATTR_AFTER_LAST,
@@ -3474,6 +3522,12 @@ enum nl80211_bss_scan_width {
3474 * was last updated by a received frame. The value is expected to be 3522 * was last updated by a received frame. The value is expected to be
3475 * accurate to about 10ms. (u64, nanoseconds) 3523 * accurate to about 10ms. (u64, nanoseconds)
3476 * @NL80211_BSS_PAD: attribute used for padding for 64-bit alignment 3524 * @NL80211_BSS_PAD: attribute used for padding for 64-bit alignment
3525 * @NL80211_BSS_PARENT_TSF: the time at the start of reception of the first
3526 * octet of the timestamp field of the last beacon/probe received for
3527 * this BSS. The time is the TSF of the BSS specified by
3528 * @NL80211_BSS_PARENT_BSSID. (u64).
3529 * @NL80211_BSS_PARENT_BSSID: the BSS according to which @NL80211_BSS_PARENT_TSF
3530 * is set.
3477 * @__NL80211_BSS_AFTER_LAST: internal 3531 * @__NL80211_BSS_AFTER_LAST: internal
3478 * @NL80211_BSS_MAX: highest BSS attribute 3532 * @NL80211_BSS_MAX: highest BSS attribute
3479 */ 3533 */
@@ -3495,6 +3549,8 @@ enum nl80211_bss {
3495 NL80211_BSS_PRESP_DATA, 3549 NL80211_BSS_PRESP_DATA,
3496 NL80211_BSS_LAST_SEEN_BOOTTIME, 3550 NL80211_BSS_LAST_SEEN_BOOTTIME,
3497 NL80211_BSS_PAD, 3551 NL80211_BSS_PAD,
3552 NL80211_BSS_PARENT_TSF,
3553 NL80211_BSS_PARENT_BSSID,
3498 3554
3499 /* keep last */ 3555 /* keep last */
3500 __NL80211_BSS_AFTER_LAST, 3556 __NL80211_BSS_AFTER_LAST,
@@ -4479,6 +4535,22 @@ enum nl80211_feature_flags {
4479 * %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set 4535 * %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set
4480 * the ASSOC_REQ_USE_RRM flag in the association request even if 4536 * the ASSOC_REQ_USE_RRM flag in the association request even if
4481 * NL80211_FEATURE_QUIET is not advertized. 4537 * NL80211_FEATURE_QUIET is not advertized.
4538 * @NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER: This device supports MU-MIMO air
4539 * sniffer which means that it can be configured to hear packets from
4540 * certain groups which can be configured by the
4541 * %NL80211_ATTR_MU_MIMO_GROUP_DATA attribute,
4542 * or can be configured to follow a station by configuring the
4543 * %NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR attribute.
4544 * @NL80211_EXT_FEATURE_SCAN_START_TIME: This driver includes the actual
4545 * time the scan started in scan results event. The time is the TSF of
4546 * the BSS that the interface that requested the scan is connected to
4547 * (if available).
4548 * @NL80211_EXT_FEATURE_BSS_PARENT_TSF: Per BSS, this driver reports the
4549 * time the last beacon/probe was received. The time is the TSF of the
4550 * BSS that the interface that requested the scan is connected to
4551 * (if available).
4552 * @NL80211_EXT_FEATURE_SET_SCAN_DWELL: This driver supports configuration of
4553 * channel dwell time.
4482 * 4554 *
4483 * @NUM_NL80211_EXT_FEATURES: number of extended features. 4555 * @NUM_NL80211_EXT_FEATURES: number of extended features.
4484 * @MAX_NL80211_EXT_FEATURES: highest extended feature index. 4556 * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4486,6 +4558,10 @@ enum nl80211_feature_flags {
4486enum nl80211_ext_feature_index { 4558enum nl80211_ext_feature_index {
4487 NL80211_EXT_FEATURE_VHT_IBSS, 4559 NL80211_EXT_FEATURE_VHT_IBSS,
4488 NL80211_EXT_FEATURE_RRM, 4560 NL80211_EXT_FEATURE_RRM,
4561 NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER,
4562 NL80211_EXT_FEATURE_SCAN_START_TIME,
4563 NL80211_EXT_FEATURE_BSS_PARENT_TSF,
4564 NL80211_EXT_FEATURE_SET_SCAN_DWELL,
4489 4565
4490 /* add new features before the definition below */ 4566 /* add new features before the definition below */
4491 NUM_NL80211_EXT_FEATURES, 4567 NUM_NL80211_EXT_FEATURES,
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 3a8f881b22f1..a9aff6079c42 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -306,6 +306,24 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
306 mutex_lock(&sta->ampdu_mlme.mtx); 306 mutex_lock(&sta->ampdu_mlme.mtx);
307 307
308 if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) { 308 if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
309 tid_agg_rx = rcu_dereference_protected(
310 sta->ampdu_mlme.tid_rx[tid],
311 lockdep_is_held(&sta->ampdu_mlme.mtx));
312
313 if (tid_agg_rx->dialog_token == dialog_token) {
314 ht_dbg_ratelimited(sta->sdata,
315 "updated AddBA Req from %pM on tid %u\n",
316 sta->sta.addr, tid);
317 /* We have no API to update the timeout value in the
318 * driver so reject the timeout update.
319 */
320 status = WLAN_STATUS_REQUEST_DECLINED;
321 ieee80211_send_addba_resp(sta->sdata, sta->sta.addr,
322 tid, dialog_token, status,
323 1, buf_size, timeout);
324 goto end;
325 }
326
309 ht_dbg_ratelimited(sta->sdata, 327 ht_dbg_ratelimited(sta->sdata,
310 "unexpected AddBA Req from %pM on tid %u\n", 328 "unexpected AddBA Req from %pM on tid %u\n",
311 sta->sta.addr, tid); 329 sta->sta.addr, tid);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0c12e4001f19..47e99ab8d97a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -997,6 +997,7 @@ static void sta_apply_mesh_params(struct ieee80211_local *local,
997 if (sta->mesh->plink_state != NL80211_PLINK_ESTAB) 997 if (sta->mesh->plink_state != NL80211_PLINK_ESTAB)
998 changed = mesh_plink_inc_estab_count(sdata); 998 changed = mesh_plink_inc_estab_count(sdata);
999 sta->mesh->plink_state = params->plink_state; 999 sta->mesh->plink_state = params->plink_state;
1000 sta->mesh->aid = params->peer_aid;
1000 1001
1001 ieee80211_mps_sta_status_update(sta); 1002 ieee80211_mps_sta_status_update(sta);
1002 changed |= ieee80211_mps_set_sta_local_pm(sta, 1003 changed |= ieee80211_mps_set_sta_local_pm(sta,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 54edfb6fc1d1..f56d342c31b8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1250,6 +1250,7 @@ struct ieee80211_local {
1250 int scan_channel_idx; 1250 int scan_channel_idx;
1251 int scan_ies_len; 1251 int scan_ies_len;
1252 int hw_scan_ies_bufsize; 1252 int hw_scan_ies_bufsize;
1253 struct cfg80211_scan_info scan_info;
1253 1254
1254 struct work_struct sched_scan_stopped_work; 1255 struct work_struct sched_scan_stopped_work;
1255 struct ieee80211_sub_if_data __rcu *sched_scan_sdata; 1256 struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 6a1603bcdced..c66411df9863 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -148,25 +148,7 @@ u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
148void mesh_sta_cleanup(struct sta_info *sta) 148void mesh_sta_cleanup(struct sta_info *sta)
149{ 149{
150 struct ieee80211_sub_if_data *sdata = sta->sdata; 150 struct ieee80211_sub_if_data *sdata = sta->sdata;
151 u32 changed = 0; 151 u32 changed = mesh_plink_deactivate(sta);
152
153 /*
154 * maybe userspace handles peer allocation and peering, but in either
155 * case the beacon is still generated by the kernel and we might need
156 * an update.
157 */
158 if (sdata->u.mesh.user_mpm &&
159 sta->mesh->plink_state == NL80211_PLINK_ESTAB)
160 changed |= mesh_plink_dec_estab_count(sdata);
161 changed |= mesh_accept_plinks_update(sdata);
162 if (!sdata->u.mesh.user_mpm) {
163 changed |= mesh_plink_deactivate(sta);
164 del_timer_sync(&sta->mesh->plink_timer);
165 }
166
167 /* make sure no readers can access nexthop sta from here on */
168 mesh_path_flush_by_nexthop(sta);
169 synchronize_net();
170 152
171 if (changed) 153 if (changed)
172 ieee80211_mbss_info_change_notify(sdata, changed); 154 ieee80211_mbss_info_change_notify(sdata, changed);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 79f2a0a13db8..7fcdcf622655 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -370,13 +370,21 @@ u32 mesh_plink_deactivate(struct sta_info *sta)
370 370
371 spin_lock_bh(&sta->mesh->plink_lock); 371 spin_lock_bh(&sta->mesh->plink_lock);
372 changed = __mesh_plink_deactivate(sta); 372 changed = __mesh_plink_deactivate(sta);
373 sta->mesh->reason = WLAN_REASON_MESH_PEER_CANCELED; 373
374 mesh_plink_frame_tx(sdata, sta, WLAN_SP_MESH_PEERING_CLOSE, 374 if (!sdata->u.mesh.user_mpm) {
375 sta->sta.addr, sta->mesh->llid, sta->mesh->plid, 375 sta->mesh->reason = WLAN_REASON_MESH_PEER_CANCELED;
376 sta->mesh->reason); 376 mesh_plink_frame_tx(sdata, sta, WLAN_SP_MESH_PEERING_CLOSE,
377 sta->sta.addr, sta->mesh->llid,
378 sta->mesh->plid, sta->mesh->reason);
379 }
377 spin_unlock_bh(&sta->mesh->plink_lock); 380 spin_unlock_bh(&sta->mesh->plink_lock);
381 if (!sdata->u.mesh.user_mpm)
382 del_timer_sync(&sta->mesh->plink_timer);
378 mesh_path_flush_by_nexthop(sta); 383 mesh_path_flush_by_nexthop(sta);
379 384
385 /* make sure no readers can access nexthop sta from here on */
386 synchronize_net();
387
380 return changed; 388 return changed;
381} 389}
382 390
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9a1eb70cb120..2e8a9024625a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1624,8 +1624,13 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
1624 if (mmie_keyidx < NUM_DEFAULT_KEYS || 1624 if (mmie_keyidx < NUM_DEFAULT_KEYS ||
1625 mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) 1625 mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
1626 return RX_DROP_MONITOR; /* unexpected BIP keyidx */ 1626 return RX_DROP_MONITOR; /* unexpected BIP keyidx */
1627 if (rx->sta) 1627 if (rx->sta) {
1628 if (ieee80211_is_group_privacy_action(skb) &&
1629 test_sta_flag(rx->sta, WLAN_STA_MFP))
1630 return RX_DROP_MONITOR;
1631
1628 rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]); 1632 rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]);
1633 }
1629 if (!rx->key) 1634 if (!rx->key)
1630 rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); 1635 rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
1631 } else if (!ieee80211_has_protected(fc)) { 1636 } else if (!ieee80211_has_protected(fc)) {
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index f9648ef9e31f..070b40f15850 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -7,6 +7,7 @@
7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
9 * Copyright 2013-2015 Intel Mobile Communications GmbH 9 * Copyright 2013-2015 Intel Mobile Communications GmbH
10 * Copyright 2016 Intel Deutschland GmbH
10 * 11 *
11 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as 13 * it under the terms of the GNU General Public License version 2 as
@@ -70,6 +71,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
70 .boottime_ns = rx_status->boottime_ns, 71 .boottime_ns = rx_status->boottime_ns,
71 }; 72 };
72 bool signal_valid; 73 bool signal_valid;
74 struct ieee80211_sub_if_data *scan_sdata;
73 75
74 if (ieee80211_hw_check(&local->hw, SIGNAL_DBM)) 76 if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
75 bss_meta.signal = rx_status->signal * 100; 77 bss_meta.signal = rx_status->signal * 100;
@@ -83,6 +85,20 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
83 bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10; 85 bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10;
84 86
85 bss_meta.chan = channel; 87 bss_meta.chan = channel;
88
89 rcu_read_lock();
90 scan_sdata = rcu_dereference(local->scan_sdata);
91 if (scan_sdata && scan_sdata->vif.type == NL80211_IFTYPE_STATION &&
92 scan_sdata->vif.bss_conf.assoc &&
93 ieee80211_have_rx_timestamp(rx_status)) {
94 bss_meta.parent_tsf =
95 ieee80211_calculate_rx_timestamp(local, rx_status,
96 len + FCS_LEN, 24);
97 ether_addr_copy(bss_meta.parent_bssid,
98 scan_sdata->vif.bss_conf.bssid);
99 }
100 rcu_read_unlock();
101
86 cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta, 102 cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta,
87 mgmt, len, GFP_ATOMIC); 103 mgmt, len, GFP_ATOMIC);
88 if (!cbss) 104 if (!cbss)
@@ -345,6 +361,12 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
345 361
346 if (rc == 0) 362 if (rc == 0)
347 return; 363 return;
364
365 /* HW scan failed and is going to be reported as aborted,
366 * so clear old scan info.
367 */
368 memset(&local->scan_info, 0, sizeof(local->scan_info));
369 aborted = true;
348 } 370 }
349 371
350 kfree(local->hw_scan_req); 372 kfree(local->hw_scan_req);
@@ -353,8 +375,10 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
353 scan_req = rcu_dereference_protected(local->scan_req, 375 scan_req = rcu_dereference_protected(local->scan_req,
354 lockdep_is_held(&local->mtx)); 376 lockdep_is_held(&local->mtx));
355 377
356 if (scan_req != local->int_scan_req) 378 if (scan_req != local->int_scan_req) {
357 cfg80211_scan_done(scan_req, aborted); 379 local->scan_info.aborted = aborted;
380 cfg80211_scan_done(scan_req, &local->scan_info);
381 }
358 RCU_INIT_POINTER(local->scan_req, NULL); 382 RCU_INIT_POINTER(local->scan_req, NULL);
359 383
360 scan_sdata = rcu_dereference_protected(local->scan_sdata, 384 scan_sdata = rcu_dereference_protected(local->scan_sdata,
@@ -391,15 +415,19 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
391 ieee80211_start_next_roc(local); 415 ieee80211_start_next_roc(local);
392} 416}
393 417
394void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) 418void ieee80211_scan_completed(struct ieee80211_hw *hw,
419 struct cfg80211_scan_info *info)
395{ 420{
396 struct ieee80211_local *local = hw_to_local(hw); 421 struct ieee80211_local *local = hw_to_local(hw);
397 422
398 trace_api_scan_completed(local, aborted); 423 trace_api_scan_completed(local, info);
399 424
400 set_bit(SCAN_COMPLETED, &local->scanning); 425 set_bit(SCAN_COMPLETED, &local->scanning);
401 if (aborted) 426 if (info->aborted)
402 set_bit(SCAN_ABORTED, &local->scanning); 427 set_bit(SCAN_ABORTED, &local->scanning);
428
429 memcpy(&local->scan_info, info, sizeof(*info));
430
403 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); 431 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
404} 432}
405EXPORT_SYMBOL(ieee80211_scan_completed); 433EXPORT_SYMBOL(ieee80211_scan_completed);
@@ -566,6 +594,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
566 local->hw_scan_req->req.ie = ies; 594 local->hw_scan_req->req.ie = ies;
567 local->hw_scan_req->req.flags = req->flags; 595 local->hw_scan_req->req.flags = req->flags;
568 eth_broadcast_addr(local->hw_scan_req->req.bssid); 596 eth_broadcast_addr(local->hw_scan_req->req.bssid);
597 local->hw_scan_req->req.duration = req->duration;
598 local->hw_scan_req->req.duration_mandatory =
599 req->duration_mandatory;
569 600
570 local->hw_scan_band = 0; 601 local->hw_scan_band = 0;
571 602
@@ -1073,6 +1104,7 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
1073 */ 1104 */
1074 cancel_delayed_work(&local->scan_work); 1105 cancel_delayed_work(&local->scan_work);
1075 /* and clean up */ 1106 /* and clean up */
1107 memset(&local->scan_info, 0, sizeof(local->scan_info));
1076 __ieee80211_scan_completed(&local->hw, true); 1108 __ieee80211_scan_completed(&local->hw, true);
1077out: 1109out:
1078 mutex_unlock(&local->mtx); 1110 mutex_unlock(&local->mtx);
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index 2ddc661f0988..97f4c9d6b54c 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -129,42 +129,31 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
129 } 129 }
130 130
131 if (wide_bw_chansw_ie) { 131 if (wide_bw_chansw_ie) {
132 new_vht_chandef.chan = new_chan; 132 struct ieee80211_vht_operation vht_oper = {
133 new_vht_chandef.center_freq1 = 133 .chan_width =
134 ieee80211_channel_to_frequency( 134 wide_bw_chansw_ie->new_channel_width,
135 .center_freq_seg1_idx =
135 wide_bw_chansw_ie->new_center_freq_seg0, 136 wide_bw_chansw_ie->new_center_freq_seg0,
136 new_band); 137 .center_freq_seg2_idx =
137 138 wide_bw_chansw_ie->new_center_freq_seg1,
138 switch (wide_bw_chansw_ie->new_channel_width) { 139 /* .basic_mcs_set doesn't matter */
139 default: 140 };
140 /* hmmm, ignore VHT and use HT if present */ 141
141 case IEEE80211_VHT_CHANWIDTH_USE_HT: 142 /* default, for the case of IEEE80211_VHT_CHANWIDTH_USE_HT,
143 * to the previously parsed chandef
144 */
145 new_vht_chandef = csa_ie->chandef;
146
147 /* ignore if parsing fails */
148 if (!ieee80211_chandef_vht_oper(&vht_oper, &new_vht_chandef))
142 new_vht_chandef.chan = NULL; 149 new_vht_chandef.chan = NULL;
143 break; 150
144 case IEEE80211_VHT_CHANWIDTH_80MHZ:
145 new_vht_chandef.width = NL80211_CHAN_WIDTH_80;
146 break;
147 case IEEE80211_VHT_CHANWIDTH_160MHZ:
148 new_vht_chandef.width = NL80211_CHAN_WIDTH_160;
149 break;
150 case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
151 /* field is otherwise reserved */
152 new_vht_chandef.center_freq2 =
153 ieee80211_channel_to_frequency(
154 wide_bw_chansw_ie->new_center_freq_seg1,
155 new_band);
156 new_vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
157 break;
158 }
159 if (sta_flags & IEEE80211_STA_DISABLE_80P80MHZ && 151 if (sta_flags & IEEE80211_STA_DISABLE_80P80MHZ &&
160 new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80) 152 new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80)
161 ieee80211_chandef_downgrade(&new_vht_chandef); 153 ieee80211_chandef_downgrade(&new_vht_chandef);
162 if (sta_flags & IEEE80211_STA_DISABLE_160MHZ && 154 if (sta_flags & IEEE80211_STA_DISABLE_160MHZ &&
163 new_vht_chandef.width == NL80211_CHAN_WIDTH_160) 155 new_vht_chandef.width == NL80211_CHAN_WIDTH_160)
164 ieee80211_chandef_downgrade(&new_vht_chandef); 156 ieee80211_chandef_downgrade(&new_vht_chandef);
165 if (sta_flags & IEEE80211_STA_DISABLE_40MHZ &&
166 new_vht_chandef.width > NL80211_CHAN_WIDTH_20)
167 ieee80211_chandef_downgrade(&new_vht_chandef);
168 } 157 }
169 158
170 /* if VHT data is there validate & use it */ 159 /* if VHT data is there validate & use it */
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index 1c7d45a6d93e..b5d28f14b9cf 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -1747,6 +1747,7 @@ ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata,
1747 goto out; 1747 goto out;
1748 } 1748 }
1749 1749
1750 ret = 0;
1750call_drv: 1751call_drv:
1751 drv_tdls_recv_channel_switch(sdata->local, sdata, &params); 1752 drv_tdls_recv_channel_switch(sdata->local, sdata, &params);
1752 1753
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 44ec605a5682..91461c415525 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -593,6 +593,9 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
593 else if (tx->sta && 593 else if (tx->sta &&
594 (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx]))) 594 (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
595 tx->key = key; 595 tx->key = key;
596 else if (ieee80211_is_group_privacy_action(tx->skb) &&
597 (key = rcu_dereference(tx->sdata->default_multicast_key)))
598 tx->key = key;
596 else if (ieee80211_is_mgmt(hdr->frame_control) && 599 else if (ieee80211_is_mgmt(hdr->frame_control) &&
597 is_multicast_ether_addr(hdr->addr1) && 600 is_multicast_ether_addr(hdr->addr1) &&
598 ieee80211_is_robust_mgmt_frame(tx->skb) && 601 ieee80211_is_robust_mgmt_frame(tx->skb) &&
@@ -625,7 +628,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
625 case WLAN_CIPHER_SUITE_GCMP_256: 628 case WLAN_CIPHER_SUITE_GCMP_256:
626 if (!ieee80211_is_data_present(hdr->frame_control) && 629 if (!ieee80211_is_data_present(hdr->frame_control) &&
627 !ieee80211_use_mfp(hdr->frame_control, tx->sta, 630 !ieee80211_use_mfp(hdr->frame_control, tx->sta,
628 tx->skb)) 631 tx->skb) &&
632 !ieee80211_is_group_privacy_action(tx->skb))
629 tx->key = NULL; 633 tx->key = NULL;
630 else 634 else
631 skip_hw = (tx->key->conf.flags & 635 skip_hw = (tx->key->conf.flags &
@@ -1445,7 +1449,9 @@ int ieee80211_txq_setup_flows(struct ieee80211_local *local)
1445 local->cvars = kcalloc(fq->flows_cnt, sizeof(local->cvars[0]), 1449 local->cvars = kcalloc(fq->flows_cnt, sizeof(local->cvars[0]),
1446 GFP_KERNEL); 1450 GFP_KERNEL);
1447 if (!local->cvars) { 1451 if (!local->cvars) {
1452 spin_lock_bh(&fq->lock);
1448 fq_reset(fq, fq_skb_free_func); 1453 fq_reset(fq, fq_skb_free_func);
1454 spin_unlock_bh(&fq->lock);
1449 return -ENOMEM; 1455 return -ENOMEM;
1450 } 1456 }
1451 1457
@@ -1465,7 +1471,9 @@ void ieee80211_txq_teardown_flows(struct ieee80211_local *local)
1465 kfree(local->cvars); 1471 kfree(local->cvars);
1466 local->cvars = NULL; 1472 local->cvars = NULL;
1467 1473
1474 spin_lock_bh(&fq->lock);
1468 fq_reset(fq, fq_skb_free_func); 1475 fq_reset(fq, fq_skb_free_func);
1476 spin_unlock_bh(&fq->lock);
1469} 1477}
1470 1478
1471struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, 1479struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 39d9abd309ea..7645e97362c0 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -220,7 +220,7 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
220 220
221 if (rdev->scan_req && rdev->scan_req->wdev == wdev) { 221 if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
222 if (WARN_ON(!rdev->scan_req->notified)) 222 if (WARN_ON(!rdev->scan_req->notified))
223 rdev->scan_req->aborted = true; 223 rdev->scan_req->info.aborted = true;
224 ___cfg80211_scan_done(rdev, false); 224 ___cfg80211_scan_done(rdev, false);
225 } 225 }
226} 226}
@@ -1087,7 +1087,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
1087 cfg80211_update_iface_num(rdev, wdev->iftype, -1); 1087 cfg80211_update_iface_num(rdev, wdev->iftype, -1);
1088 if (rdev->scan_req && rdev->scan_req->wdev == wdev) { 1088 if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
1089 if (WARN_ON(!rdev->scan_req->notified)) 1089 if (WARN_ON(!rdev->scan_req->notified))
1090 rdev->scan_req->aborted = true; 1090 rdev->scan_req->info.aborted = true;
1091 ___cfg80211_scan_done(rdev, false); 1091 ___cfg80211_scan_done(rdev, false);
1092 } 1092 }
1093 1093
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a4d547f99f8d..eee91443924d 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -141,6 +141,18 @@ struct cfg80211_internal_bss {
141 unsigned long refcount; 141 unsigned long refcount;
142 atomic_t hold; 142 atomic_t hold;
143 143
144 /* time at the start of the reception of the first octet of the
145 * timestamp field of the last beacon/probe received for this BSS.
146 * The time is the TSF of the BSS specified by %parent_bssid.
147 */
148 u64 parent_tsf;
149
150 /* the BSS according to which %parent_tsf is set. This is set to
151 * the BSS that the interface that requested the scan was connected to
152 * when the beacon/probe was received.
153 */
154 u8 parent_bssid[ETH_ALEN] __aligned(2);
155
144 /* must be last because of priv member */ 156 /* must be last because of priv member */
145 struct cfg80211_bss pub; 157 struct cfg80211_bss pub;
146}; 158};
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c503e96bfd5a..5782f718d567 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -405,6 +405,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
405 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG }, 405 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
406 [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED }, 406 [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
407 [NL80211_ATTR_STA_SUPPORT_P2P_PS] = { .type = NLA_U8 }, 407 [NL80211_ATTR_STA_SUPPORT_P2P_PS] = { .type = NLA_U8 },
408 [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
409 .len = VHT_MUMIMO_GROUPS_DATA_LEN
410 },
411 [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN },
408}; 412};
409 413
410/* policy for the key attributes */ 414/* policy for the key attributes */
@@ -2695,6 +2699,38 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
2695 change = true; 2699 change = true;
2696 } 2700 }
2697 2701
2702 if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
2703 const u8 *mumimo_groups;
2704 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
2705
2706 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
2707 return -EOPNOTSUPP;
2708
2709 mumimo_groups =
2710 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
2711
2712 /* bits 0 and 63 are reserved and must be zero */
2713 if ((mumimo_groups[0] & BIT(7)) ||
2714 (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(0)))
2715 return -EINVAL;
2716
2717 memcpy(params.vht_mumimo_groups, mumimo_groups,
2718 VHT_MUMIMO_GROUPS_DATA_LEN);
2719 change = true;
2720 }
2721
2722 if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
2723 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
2724
2725 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
2726 return -EOPNOTSUPP;
2727
2728 nla_memcpy(params.macaddr,
2729 info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR],
2730 ETH_ALEN);
2731 change = true;
2732 }
2733
2698 if (flags && (*flags & MONITOR_FLAG_ACTIVE) && 2734 if (flags && (*flags & MONITOR_FLAG_ACTIVE) &&
2699 !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) 2735 !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
2700 return -EOPNOTSUPP; 2736 return -EOPNOTSUPP;
@@ -4410,6 +4446,12 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
4410 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); 4446 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
4411 if (params.plink_state >= NUM_NL80211_PLINK_STATES) 4447 if (params.plink_state >= NUM_NL80211_PLINK_STATES)
4412 return -EINVAL; 4448 return -EINVAL;
4449 if (info->attrs[NL80211_ATTR_MESH_PEER_AID]) {
4450 params.peer_aid = nla_get_u16(
4451 info->attrs[NL80211_ATTR_MESH_PEER_AID]);
4452 if (params.peer_aid > IEEE80211_MAX_AID)
4453 return -EINVAL;
4454 }
4413 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE; 4455 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
4414 } 4456 }
4415 4457
@@ -5287,6 +5329,51 @@ static const struct nla_policy
5287 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG }, 5329 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
5288}; 5330};
5289 5331
5332static int nl80211_check_bool(const struct nlattr *nla, u8 min, u8 max, bool *out)
5333{
5334 u8 val = nla_get_u8(nla);
5335 if (val < min || val > max)
5336 return -EINVAL;
5337 *out = val;
5338 return 0;
5339}
5340
5341static int nl80211_check_u8(const struct nlattr *nla, u8 min, u8 max, u8 *out)
5342{
5343 u8 val = nla_get_u8(nla);
5344 if (val < min || val > max)
5345 return -EINVAL;
5346 *out = val;
5347 return 0;
5348}
5349
5350static int nl80211_check_u16(const struct nlattr *nla, u16 min, u16 max, u16 *out)
5351{
5352 u16 val = nla_get_u16(nla);
5353 if (val < min || val > max)
5354 return -EINVAL;
5355 *out = val;
5356 return 0;
5357}
5358
5359static int nl80211_check_u32(const struct nlattr *nla, u32 min, u32 max, u32 *out)
5360{
5361 u32 val = nla_get_u32(nla);
5362 if (val < min || val > max)
5363 return -EINVAL;
5364 *out = val;
5365 return 0;
5366}
5367
5368static int nl80211_check_s32(const struct nlattr *nla, s32 min, s32 max, s32 *out)
5369{
5370 s32 val = nla_get_s32(nla);
5371 if (val < min || val > max)
5372 return -EINVAL;
5373 *out = val;
5374 return 0;
5375}
5376
5290static int nl80211_parse_mesh_config(struct genl_info *info, 5377static int nl80211_parse_mesh_config(struct genl_info *info,
5291 struct mesh_config *cfg, 5378 struct mesh_config *cfg,
5292 u32 *mask_out) 5379 u32 *mask_out)
@@ -5297,9 +5384,8 @@ static int nl80211_parse_mesh_config(struct genl_info *info,
5297#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \ 5384#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \
5298do { \ 5385do { \
5299 if (tb[attr]) { \ 5386 if (tb[attr]) { \
5300 if (fn(tb[attr]) < min || fn(tb[attr]) > max) \ 5387 if (fn(tb[attr], min, max, &cfg->param)) \
5301 return -EINVAL; \ 5388 return -EINVAL; \
5302 cfg->param = fn(tb[attr]); \
5303 mask |= (1 << (attr - 1)); \ 5389 mask |= (1 << (attr - 1)); \
5304 } \ 5390 } \
5305} while (0) 5391} while (0)
@@ -5318,99 +5404,99 @@ do { \
5318 /* Fill in the params struct */ 5404 /* Fill in the params struct */
5319 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 1, 255, 5405 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 1, 255,
5320 mask, NL80211_MESHCONF_RETRY_TIMEOUT, 5406 mask, NL80211_MESHCONF_RETRY_TIMEOUT,
5321 nla_get_u16); 5407 nl80211_check_u16);
5322 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 1, 255, 5408 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 1, 255,
5323 mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, 5409 mask, NL80211_MESHCONF_CONFIRM_TIMEOUT,
5324 nla_get_u16); 5410 nl80211_check_u16);
5325 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, 1, 255, 5411 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, 1, 255,
5326 mask, NL80211_MESHCONF_HOLDING_TIMEOUT, 5412 mask, NL80211_MESHCONF_HOLDING_TIMEOUT,
5327 nla_get_u16); 5413 nl80211_check_u16);
5328 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, 0, 255, 5414 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, 0, 255,
5329 mask, NL80211_MESHCONF_MAX_PEER_LINKS, 5415 mask, NL80211_MESHCONF_MAX_PEER_LINKS,
5330 nla_get_u16); 5416 nl80211_check_u16);
5331 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, 0, 16, 5417 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, 0, 16,
5332 mask, NL80211_MESHCONF_MAX_RETRIES, 5418 mask, NL80211_MESHCONF_MAX_RETRIES,
5333 nla_get_u8); 5419 nl80211_check_u8);
5334 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 1, 255, 5420 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 1, 255,
5335 mask, NL80211_MESHCONF_TTL, nla_get_u8); 5421 mask, NL80211_MESHCONF_TTL, nl80211_check_u8);
5336 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, 1, 255, 5422 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, 1, 255,
5337 mask, NL80211_MESHCONF_ELEMENT_TTL, 5423 mask, NL80211_MESHCONF_ELEMENT_TTL,
5338 nla_get_u8); 5424 nl80211_check_u8);
5339 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, 0, 1, 5425 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, 0, 1,
5340 mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, 5426 mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
5341 nla_get_u8); 5427 nl80211_check_bool);
5342 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor, 5428 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
5343 1, 255, mask, 5429 1, 255, mask,
5344 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, 5430 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
5345 nla_get_u32); 5431 nl80211_check_u32);
5346 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 0, 255, 5432 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 0, 255,
5347 mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, 5433 mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
5348 nla_get_u8); 5434 nl80211_check_u8);
5349 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, 1, 65535, 5435 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, 1, 65535,
5350 mask, NL80211_MESHCONF_PATH_REFRESH_TIME, 5436 mask, NL80211_MESHCONF_PATH_REFRESH_TIME,
5351 nla_get_u32); 5437 nl80211_check_u32);
5352 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, 1, 65535, 5438 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, 1, 65535,
5353 mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, 5439 mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
5354 nla_get_u16); 5440 nl80211_check_u16);
5355 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout, 5441 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
5356 1, 65535, mask, 5442 1, 65535, mask,
5357 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, 5443 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
5358 nla_get_u32); 5444 nl80211_check_u32);
5359 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, 5445 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,
5360 1, 65535, mask, 5446 1, 65535, mask,
5361 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, 5447 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
5362 nla_get_u16); 5448 nl80211_check_u16);
5363 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, 5449 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval,
5364 1, 65535, mask, 5450 1, 65535, mask,
5365 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, 5451 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
5366 nla_get_u16); 5452 nl80211_check_u16);
5367 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, 5453 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
5368 dot11MeshHWMPnetDiameterTraversalTime, 5454 dot11MeshHWMPnetDiameterTraversalTime,
5369 1, 65535, mask, 5455 1, 65535, mask,
5370 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, 5456 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
5371 nla_get_u16); 5457 nl80211_check_u16);
5372 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, 0, 4, 5458 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, 0, 4,
5373 mask, NL80211_MESHCONF_HWMP_ROOTMODE, 5459 mask, NL80211_MESHCONF_HWMP_ROOTMODE,
5374 nla_get_u8); 5460 nl80211_check_u8);
5375 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, 1, 65535, 5461 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, 1, 65535,
5376 mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL, 5462 mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
5377 nla_get_u16); 5463 nl80211_check_u16);
5378 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, 5464 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
5379 dot11MeshGateAnnouncementProtocol, 0, 1, 5465 dot11MeshGateAnnouncementProtocol, 0, 1,
5380 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, 5466 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
5381 nla_get_u8); 5467 nl80211_check_bool);
5382 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1, 5468 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1,
5383 mask, NL80211_MESHCONF_FORWARDING, 5469 mask, NL80211_MESHCONF_FORWARDING,
5384 nla_get_u8); 5470 nl80211_check_bool);
5385 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0, 5471 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0,
5386 mask, NL80211_MESHCONF_RSSI_THRESHOLD, 5472 mask, NL80211_MESHCONF_RSSI_THRESHOLD,
5387 nla_get_s32); 5473 nl80211_check_s32);
5388 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16, 5474 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16,
5389 mask, NL80211_MESHCONF_HT_OPMODE, 5475 mask, NL80211_MESHCONF_HT_OPMODE,
5390 nla_get_u16); 5476 nl80211_check_u16);
5391 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout, 5477 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout,
5392 1, 65535, mask, 5478 1, 65535, mask,
5393 NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, 5479 NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
5394 nla_get_u32); 5480 nl80211_check_u32);
5395 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, 1, 65535, 5481 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, 1, 65535,
5396 mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL, 5482 mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
5397 nla_get_u16); 5483 nl80211_check_u16);
5398 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, 5484 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
5399 dot11MeshHWMPconfirmationInterval, 5485 dot11MeshHWMPconfirmationInterval,
5400 1, 65535, mask, 5486 1, 65535, mask,
5401 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, 5487 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
5402 nla_get_u16); 5488 nl80211_check_u16);
5403 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, 5489 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode,
5404 NL80211_MESH_POWER_ACTIVE, 5490 NL80211_MESH_POWER_ACTIVE,
5405 NL80211_MESH_POWER_MAX, 5491 NL80211_MESH_POWER_MAX,
5406 mask, NL80211_MESHCONF_POWER_MODE, 5492 mask, NL80211_MESHCONF_POWER_MODE,
5407 nla_get_u32); 5493 nl80211_check_u32);
5408 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, 5494 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration,
5409 0, 65535, mask, 5495 0, 65535, mask,
5410 NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16); 5496 NL80211_MESHCONF_AWAKE_WINDOW, nl80211_check_u16);
5411 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 0, 0xffffffff, 5497 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 0, 0xffffffff,
5412 mask, NL80211_MESHCONF_PLINK_TIMEOUT, 5498 mask, NL80211_MESHCONF_PLINK_TIMEOUT,
5413 nla_get_u32); 5499 nl80211_check_u32);
5414 if (mask_out) 5500 if (mask_out)
5415 *mask_out = mask; 5501 *mask_out = mask;
5416 5502
@@ -6143,6 +6229,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
6143 } 6229 }
6144 } 6230 }
6145 6231
6232 if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
6233 if (!wiphy_ext_feature_isset(wiphy,
6234 NL80211_EXT_FEATURE_SET_SCAN_DWELL)) {
6235 err = -EOPNOTSUPP;
6236 goto out_free;
6237 }
6238
6239 request->duration =
6240 nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
6241 request->duration_mandatory =
6242 nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
6243 }
6244
6146 if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { 6245 if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
6147 request->flags = nla_get_u32( 6246 request->flags = nla_get_u32(
6148 info->attrs[NL80211_ATTR_SCAN_FLAGS]); 6247 info->attrs[NL80211_ATTR_SCAN_FLAGS]);
@@ -6976,6 +7075,13 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
6976 jiffies_to_msecs(jiffies - intbss->ts))) 7075 jiffies_to_msecs(jiffies - intbss->ts)))
6977 goto nla_put_failure; 7076 goto nla_put_failure;
6978 7077
7078 if (intbss->parent_tsf &&
7079 (nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF,
7080 intbss->parent_tsf, NL80211_BSS_PAD) ||
7081 nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN,
7082 intbss->parent_bssid)))
7083 goto nla_put_failure;
7084
6979 if (intbss->ts_boottime && 7085 if (intbss->ts_boottime &&
6980 nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME, 7086 nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
6981 intbss->ts_boottime, NL80211_BSS_PAD)) 7087 intbss->ts_boottime, NL80211_BSS_PAD))
@@ -11749,6 +11855,13 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
11749 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags)) 11855 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
11750 goto nla_put_failure; 11856 goto nla_put_failure;
11751 11857
11858 if (req->info.scan_start_tsf &&
11859 (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
11860 req->info.scan_start_tsf, NL80211_BSS_PAD) ||
11861 nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
11862 req->info.tsf_bssid)))
11863 goto nla_put_failure;
11864
11752 return 0; 11865 return 0;
11753 nla_put_failure: 11866 nla_put_failure:
11754 return -ENOBUFS; 11867 return -ENOBUFS;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ef2955c89a00..0358e12be54b 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH 5 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * Copyright 2016 Intel Deutschland GmbH
6 */ 7 */
7#include <linux/kernel.h> 8#include <linux/kernel.h>
8#include <linux/slab.h> 9#include <linux/slab.h>
@@ -194,7 +195,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
194 if (wdev->netdev) 195 if (wdev->netdev)
195 cfg80211_sme_scan_done(wdev->netdev); 196 cfg80211_sme_scan_done(wdev->netdev);
196 197
197 if (!request->aborted && 198 if (!request->info.aborted &&
198 request->flags & NL80211_SCAN_FLAG_FLUSH) { 199 request->flags & NL80211_SCAN_FLAG_FLUSH) {
199 /* flush entries from previous scans */ 200 /* flush entries from previous scans */
200 spin_lock_bh(&rdev->bss_lock); 201 spin_lock_bh(&rdev->bss_lock);
@@ -202,10 +203,10 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
202 spin_unlock_bh(&rdev->bss_lock); 203 spin_unlock_bh(&rdev->bss_lock);
203 } 204 }
204 205
205 msg = nl80211_build_scan_msg(rdev, wdev, request->aborted); 206 msg = nl80211_build_scan_msg(rdev, wdev, request->info.aborted);
206 207
207#ifdef CONFIG_CFG80211_WEXT 208#ifdef CONFIG_CFG80211_WEXT
208 if (wdev->netdev && !request->aborted) { 209 if (wdev->netdev && !request->info.aborted) {
209 memset(&wrqu, 0, sizeof(wrqu)); 210 memset(&wrqu, 0, sizeof(wrqu));
210 211
211 wireless_send_event(wdev->netdev, SIOCGIWSCAN, &wrqu, NULL); 212 wireless_send_event(wdev->netdev, SIOCGIWSCAN, &wrqu, NULL);
@@ -236,12 +237,13 @@ void __cfg80211_scan_done(struct work_struct *wk)
236 rtnl_unlock(); 237 rtnl_unlock();
237} 238}
238 239
239void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) 240void cfg80211_scan_done(struct cfg80211_scan_request *request,
241 struct cfg80211_scan_info *info)
240{ 242{
241 trace_cfg80211_scan_done(request, aborted); 243 trace_cfg80211_scan_done(request, info);
242 WARN_ON(request != wiphy_to_rdev(request->wiphy)->scan_req); 244 WARN_ON(request != wiphy_to_rdev(request->wiphy)->scan_req);
243 245
244 request->aborted = aborted; 246 request->info = *info;
245 request->notified = true; 247 request->notified = true;
246 queue_work(cfg80211_wq, &wiphy_to_rdev(request->wiphy)->scan_done_wk); 248 queue_work(cfg80211_wq, &wiphy_to_rdev(request->wiphy)->scan_done_wk);
247} 249}
@@ -843,6 +845,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
843 found->pub.capability = tmp->pub.capability; 845 found->pub.capability = tmp->pub.capability;
844 found->ts = tmp->ts; 846 found->ts = tmp->ts;
845 found->ts_boottime = tmp->ts_boottime; 847 found->ts_boottime = tmp->ts_boottime;
848 found->parent_tsf = tmp->parent_tsf;
849 ether_addr_copy(found->parent_bssid, tmp->parent_bssid);
846 } else { 850 } else {
847 struct cfg80211_internal_bss *new; 851 struct cfg80211_internal_bss *new;
848 struct cfg80211_internal_bss *hidden; 852 struct cfg80211_internal_bss *hidden;
@@ -1086,6 +1090,8 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
1086 tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); 1090 tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
1087 tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); 1091 tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
1088 tmp.ts_boottime = data->boottime_ns; 1092 tmp.ts_boottime = data->boottime_ns;
1093 tmp.parent_tsf = data->parent_tsf;
1094 ether_addr_copy(tmp.parent_bssid, data->parent_bssid);
1089 1095
1090 signal_valid = abs(data->chan->center_freq - channel->center_freq) <= 1096 signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
1091 wiphy->max_adj_channel_rssi_comp; 1097 wiphy->max_adj_channel_rssi_comp;
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 3c1091ae6c36..72b5255cefe2 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2642,8 +2642,9 @@ TRACE_EVENT(cfg80211_tdls_oper_request,
2642 ); 2642 );
2643 2643
2644TRACE_EVENT(cfg80211_scan_done, 2644TRACE_EVENT(cfg80211_scan_done,
2645 TP_PROTO(struct cfg80211_scan_request *request, bool aborted), 2645 TP_PROTO(struct cfg80211_scan_request *request,
2646 TP_ARGS(request, aborted), 2646 struct cfg80211_scan_info *info),
2647 TP_ARGS(request, info),
2647 TP_STRUCT__entry( 2648 TP_STRUCT__entry(
2648 __field(u32, n_channels) 2649 __field(u32, n_channels)
2649 __dynamic_array(u8, ie, request ? request->ie_len : 0) 2650 __dynamic_array(u8, ie, request ? request->ie_len : 0)
@@ -2652,6 +2653,8 @@ TRACE_EVENT(cfg80211_scan_done,
2652 MAC_ENTRY(wiphy_mac) 2653 MAC_ENTRY(wiphy_mac)
2653 __field(bool, no_cck) 2654 __field(bool, no_cck)
2654 __field(bool, aborted) 2655 __field(bool, aborted)
2656 __field(u64, scan_start_tsf)
2657 MAC_ENTRY(tsf_bssid)
2655 ), 2658 ),
2656 TP_fast_assign( 2659 TP_fast_assign(
2657 if (request) { 2660 if (request) {
@@ -2666,9 +2669,16 @@ TRACE_EVENT(cfg80211_scan_done,
2666 request->wiphy->perm_addr); 2669 request->wiphy->perm_addr);
2667 __entry->no_cck = request->no_cck; 2670 __entry->no_cck = request->no_cck;
2668 } 2671 }
2669 __entry->aborted = aborted; 2672 if (info) {
2673 __entry->aborted = info->aborted;
2674 __entry->scan_start_tsf = info->scan_start_tsf;
2675 MAC_ASSIGN(tsf_bssid, info->tsf_bssid);
2676 }
2670 ), 2677 ),
2671 TP_printk("aborted: %s", BOOL_TO_STR(__entry->aborted)) 2678 TP_printk("aborted: %s, scan start (TSF): %llu, tsf_bssid: " MAC_PR_FMT,
2679 BOOL_TO_STR(__entry->aborted),
2680 (unsigned long long)__entry->scan_start_tsf,
2681 MAC_PR_ARG(tsf_bssid))
2672); 2682);
2673 2683
2674DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_results, 2684DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_results,
@@ -2721,6 +2731,8 @@ TRACE_EVENT(cfg80211_inform_bss_frame,
2721 __dynamic_array(u8, mgmt, len) 2731 __dynamic_array(u8, mgmt, len)
2722 __field(s32, signal) 2732 __field(s32, signal)
2723 __field(u64, ts_boottime) 2733 __field(u64, ts_boottime)
2734 __field(u64, parent_tsf)
2735 MAC_ENTRY(parent_bssid)
2724 ), 2736 ),
2725 TP_fast_assign( 2737 TP_fast_assign(
2726 WIPHY_ASSIGN; 2738 WIPHY_ASSIGN;
@@ -2730,10 +2742,15 @@ TRACE_EVENT(cfg80211_inform_bss_frame,
2730 memcpy(__get_dynamic_array(mgmt), mgmt, len); 2742 memcpy(__get_dynamic_array(mgmt), mgmt, len);
2731 __entry->signal = data->signal; 2743 __entry->signal = data->signal;
2732 __entry->ts_boottime = data->boottime_ns; 2744 __entry->ts_boottime = data->boottime_ns;
2733 ), 2745 __entry->parent_tsf = data->parent_tsf;
2734 TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "(scan_width: %d) signal: %d, tsb:%llu", 2746 MAC_ASSIGN(parent_bssid, data->parent_bssid);
2735 WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width, 2747 ),
2736 __entry->signal, (unsigned long long)__entry->ts_boottime) 2748 TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT
2749 "(scan_width: %d) signal: %d, tsb:%llu, detect_tsf:%llu, tsf_bssid: "
2750 MAC_PR_FMT, WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width,
2751 __entry->signal, (unsigned long long)__entry->ts_boottime,
2752 (unsigned long long)__entry->parent_tsf,
2753 MAC_PR_ARG(parent_bssid))
2737); 2754);
2738 2755
2739DECLARE_EVENT_CLASS(cfg80211_bss_evt, 2756DECLARE_EVENT_CLASS(cfg80211_bss_evt,