diff options
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, | |||
1069 | void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted) | 1073 | void 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 | ||
1091 | out: | 1098 | out: |
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) | |||
960 | void ath_scan_complete(struct ath_softc *sc, bool abort) | 960 | void 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) | |||
1305 | static void | 1305 | static void |
1306 | il_complete_scan(struct il_priv *il, bool aborted) | 1306 | il_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 | ||
95 | static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) | 95 | static 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, | |||
245 | void orinoco_scan_done(struct orinoco_private *priv, bool abort) | 249 | void 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"); | |||
41 | MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211"); | 41 | MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211"); |
42 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
43 | 43 | ||
44 | static u32 wmediumd_portid; | ||
45 | |||
46 | static int radios = 2; | 44 | static int radios = 2; |
47 | module_param(radios, int, 0444); | 45 | module_param(radios, int, 0444); |
48 | MODULE_PARM_DESC(radios, "Number of simulated radios"); | 46 | MODULE_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 | ||
255 | static unsigned int hwsim_net_id; | 253 | static int hwsim_net_id; |
256 | 254 | ||
257 | static int hwsim_netgroup; | 255 | static int hwsim_netgroup; |
258 | 256 | ||
259 | struct hwsim_net { | 257 | struct hwsim_net { |
260 | int netgroup; | 258 | int netgroup; |
259 | u32 wmediumd; | ||
261 | }; | 260 | }; |
262 | 261 | ||
263 | static inline int hwsim_net_get_netgroup(struct net *net) | 262 | static 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 | ||
276 | static 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 | |||
283 | static 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 | |||
277 | static struct class *hwsim_class; | 290 | static struct class *hwsim_class; |
278 | 291 | ||
279 | static struct net_device *hwsim_mon; /* global monitor netdev */ | 292 | static 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 | ||
447 | static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = { | ||
448 | { .max = 8, .types = BIT(NL80211_IFTYPE_AP) }, | ||
449 | }; | ||
450 | |||
451 | static const struct ieee80211_iface_combination hwsim_if_comb[] = { | 460 | static 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 | ||
472 | static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = { | 475 | static 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 | ||
492 | static spinlock_t hwsim_radio_lock; | 489 | static 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 | ||
985 | static 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 | |||
986 | static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, | 1008 | static 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 | ||
2830 | static 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 | |||
2799 | static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, | 2844 | static 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: | |||
2966 | static int hwsim_register_received_nl(struct sk_buff *skb_2, | 3017 | static 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 | ||
3686 | out_sleep: | 3693 | out_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 | ||
87 | out: | 90 | out: |
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 | ||
442 | exit: | 444 | exit: |
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 | */ |
2465 | static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb) | 2466 | static 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 | */ | ||
2495 | static 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 | */ | ||
2512 | static 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 | */ |
343 | struct vif_params { | 348 | struct 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 | */ | ||
1437 | struct 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 | */ |
1598 | struct cfg80211_inform_bss { | 1634 | struct 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 | */ |
4067 | void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted); | 4104 | void 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 | */ |
4702 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted); | 4702 | void 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 { | |||
4486 | enum nl80211_ext_feature_index { | 4558 | enum 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) | |||
148 | void mesh_sta_cleanup(struct sta_info *sta) | 148 | void 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 | ||
394 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 418 | void 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 | } |
405 | EXPORT_SYMBOL(ieee80211_scan_completed); | 433 | EXPORT_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); |
1077 | out: | 1109 | out: |
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; | ||
1750 | call_drv: | 1751 | call_drv: |
1751 | drv_tdls_recv_channel_switch(sdata->local, sdata, ¶ms); | 1752 | drv_tdls_recv_channel_switch(sdata->local, sdata, ¶ms); |
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 | ||
1471 | struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, | 1479 | struct 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 | ||
5332 | static 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 | |||
5341 | static 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 | |||
5350 | static 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 | |||
5359 | static 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 | |||
5368 | static 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 | |||
5290 | static int nl80211_parse_mesh_config(struct genl_info *info, | 5377 | static 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) \ |
5298 | do { \ | 5385 | do { \ |
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 | ||
239 | void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) | 240 | void 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 | ||
2644 | TRACE_EVENT(cfg80211_scan_done, | 2644 | TRACE_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 | ||
2674 | DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_results, | 2684 | DEFINE_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 | ||
2739 | DECLARE_EVENT_CLASS(cfg80211_bss_evt, | 2756 | DECLARE_EVENT_CLASS(cfg80211_bss_evt, |