aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvraham Stern <avraham.stern@intel.com>2016-07-05 08:23:12 -0400
committerJohannes Berg <johannes.berg@intel.com>2016-07-06 08:53:19 -0400
commit7947d3e075cde1a18e538f2dafbc850aa356ff79 (patch)
tree2d283b23e55dde9f32e3803d79c0b82c8c79907e
parent1d76250bd34af86c6498fc51e50cab3bfbbeceaa (diff)
mac80211: Add support for beacon report radio measurement
Add the following to support beacon report radio measurement with the measurement mode field set to passive or active: 1. Propagate the required scan duration to the device 2. Report the scan start time (in terms of TSF) 3. Report each BSS's detection time (also in terms of TSF) TSF times refer to the BSS that the interface that requested the scan is connected to. Signed-off-by: Assaf Krauss <assaf.krauss@intel.com> Signed-off-by: Avraham Stern <avraham.stern@intel.com> [changed ath9k/10k, at76c59x-usb, iwlegacy, wl1251 and wlcore to match the new API] Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c14
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c5
-rw-r--r--drivers/net/wireless/atmel/at76c50x-usb.c5
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/scan.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c37
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c11
-rw-r--r--drivers/net/wireless/st/cw1200/scan.c6
-rw-r--r--drivers/net/wireless/ti/wl1251/event.c6
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c6
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c11
-rw-r--r--drivers/net/wireless/ti/wlcore/scan.c5
-rw-r--r--include/net/mac80211.h5
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/scan.c42
15 files changed, 131 insertions, 35 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/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index e56bafcf5864..57e26a640477 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -960,6 +960,9 @@ void ath_roc_complete(struct ath_softc *sc, enum ath_roc_complete_reason reason)
960void ath_scan_complete(struct ath_softc *sc, bool abort) 960void ath_scan_complete(struct ath_softc *sc, bool abort)
961{ 961{
962 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 962 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
963 struct cfg80211_scan_info info = {
964 .aborted = abort,
965 };
963 966
964 if (abort) 967 if (abort)
965 ath_dbg(common, CHAN_CTX, "HW scan aborted\n"); 968 ath_dbg(common, CHAN_CTX, "HW scan aborted\n");
@@ -969,7 +972,7 @@ void ath_scan_complete(struct ath_softc *sc, bool abort)
969 sc->offchannel.scan_req = NULL; 972 sc->offchannel.scan_req = NULL;
970 sc->offchannel.scan_vif = NULL; 973 sc->offchannel.scan_vif = NULL;
971 sc->offchannel.state = ATH_OFFCHANNEL_IDLE; 974 sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
972 ieee80211_scan_completed(sc->hw, abort); 975 ieee80211_scan_completed(sc->hw, &info);
973 clear_bit(ATH_OP_SCANNING, &common->op_flags); 976 clear_bit(ATH_OP_SCANNING, &common->op_flags);
974 spin_lock_bh(&sc->chan_lock); 977 spin_lock_bh(&sc->chan_lock);
975 if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) 978 if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
diff --git a/drivers/net/wireless/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/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c
index eb24b9241bb2..140b6ea8f7cc 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.c
+++ b/drivers/net/wireless/intel/iwlegacy/common.c
@@ -1305,10 +1305,14 @@ il_send_scan_abort(struct il_priv *il)
1305static void 1305static void
1306il_complete_scan(struct il_priv *il, bool aborted) 1306il_complete_scan(struct il_priv *il, bool aborted)
1307{ 1307{
1308 struct cfg80211_scan_info info = {
1309 .aborted = aborted,
1310 };
1311
1308 /* check if scan was requested from mac80211 */ 1312 /* check if scan was requested from mac80211 */
1309 if (il->scan_request) { 1313 if (il->scan_request) {
1310 D_SCAN("Complete scan in mac80211\n"); 1314 D_SCAN("Complete scan in mac80211\n");
1311 ieee80211_scan_completed(il->hw, aborted); 1315 ieee80211_scan_completed(il->hw, &info);
1312 } 1316 }
1313 1317
1314 il->scan_vif = NULL; 1318 il->scan_vif = NULL;
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c
index d01766f16175..17e6a32384d3 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c
@@ -94,10 +94,14 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
94 94
95static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) 95static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
96{ 96{
97 struct cfg80211_scan_info info = {
98 .aborted = aborted,
99 };
100
97 /* check if scan was requested from mac80211 */ 101 /* check if scan was requested from mac80211 */
98 if (priv->scan_request) { 102 if (priv->scan_request) {
99 IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n"); 103 IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n");
100 ieee80211_scan_completed(priv->hw, aborted); 104 ieee80211_scan_completed(priv->hw, &info);
101 } 105 }
102 106
103 priv->scan_type = IWL_SCAN_NORMAL; 107 priv->scan_type = IWL_SCAN_NORMAL;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index e78fc567ff7d..1cac10c5d818 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -391,13 +391,16 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm,
391 ieee80211_sched_scan_stopped(mvm->hw); 391 ieee80211_sched_scan_stopped(mvm->hw);
392 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; 392 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
393 } else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) { 393 } else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {
394 struct cfg80211_scan_info info = {
395 .aborted = aborted,
396 };
397
394 IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n", 398 IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n",
395 aborted ? "aborted" : "completed", 399 aborted ? "aborted" : "completed",
396 iwl_mvm_ebs_status_str(scan_notif->ebs_status)); 400 iwl_mvm_ebs_status_str(scan_notif->ebs_status));
397 401
398 mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR; 402 mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
399 ieee80211_scan_completed(mvm->hw, 403 ieee80211_scan_completed(mvm->hw, &info);
400 scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED);
401 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); 404 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
402 del_timer(&mvm->scan_timer); 405 del_timer(&mvm->scan_timer);
403 } else { 406 } else {
@@ -1430,7 +1433,11 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
1430 1433
1431 /* if the scan is already stopping, we don't need to notify mac80211 */ 1434 /* if the scan is already stopping, we don't need to notify mac80211 */
1432 if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) { 1435 if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) {
1433 ieee80211_scan_completed(mvm->hw, aborted); 1436 struct cfg80211_scan_info info = {
1437 .aborted = aborted,
1438 };
1439
1440 ieee80211_scan_completed(mvm->hw, &info);
1434 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); 1441 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
1435 del_timer(&mvm->scan_timer); 1442 del_timer(&mvm->scan_timer);
1436 } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { 1443 } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
@@ -1564,7 +1571,11 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
1564 1571
1565 uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_REGULAR); 1572 uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_REGULAR);
1566 if (uid >= 0) { 1573 if (uid >= 0) {
1567 ieee80211_scan_completed(mvm->hw, true); 1574 struct cfg80211_scan_info info = {
1575 .aborted = true,
1576 };
1577
1578 ieee80211_scan_completed(mvm->hw, &info);
1568 mvm->scan_uid_status[uid] = 0; 1579 mvm->scan_uid_status[uid] = 0;
1569 } 1580 }
1570 uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED); 1581 uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED);
@@ -1585,8 +1596,13 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
1585 mvm->scan_uid_status[i] = 0; 1596 mvm->scan_uid_status[i] = 0;
1586 } 1597 }
1587 } else { 1598 } else {
1588 if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) 1599 if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {
1589 ieee80211_scan_completed(mvm->hw, true); 1600 struct cfg80211_scan_info info = {
1601 .aborted = true,
1602 };
1603
1604 ieee80211_scan_completed(mvm->hw, &info);
1605 }
1590 1606
1591 /* Sched scan will be restarted by mac80211 in 1607 /* Sched scan will be restarted by mac80211 in
1592 * restart_hw, so do not report if FW is about to be 1608 * restart_hw, so do not report if FW is about to be
@@ -1629,8 +1645,13 @@ out:
1629 */ 1645 */
1630 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); 1646 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
1631 del_timer(&mvm->scan_timer); 1647 del_timer(&mvm->scan_timer);
1632 if (notify) 1648 if (notify) {
1633 ieee80211_scan_completed(mvm->hw, true); 1649 struct cfg80211_scan_info info = {
1650 .aborted = true,
1651 };
1652
1653 ieee80211_scan_completed(mvm->hw, &info);
1654 }
1634 } else if (notify) { 1655 } else if (notify) {
1635 ieee80211_sched_scan_stopped(mvm->hw); 1656 ieee80211_sched_scan_stopped(mvm->hw);
1636 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; 1657 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 337794f9506e..8c35ac838fce 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1941,8 +1941,12 @@ static void hw_scan_work(struct work_struct *work)
1941 1941
1942 mutex_lock(&hwsim->mutex); 1942 mutex_lock(&hwsim->mutex);
1943 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
1944 wiphy_debug(hwsim->hw->wiphy, "hw scan complete\n"); 1948 wiphy_debug(hwsim->hw->wiphy, "hw scan complete\n");
1945 ieee80211_scan_completed(hwsim->hw, false); 1949 ieee80211_scan_completed(hwsim->hw, &info);
1946 hwsim->hw_scan_request = NULL; 1950 hwsim->hw_scan_request = NULL;
1947 hwsim->hw_scan_vif = NULL; 1951 hwsim->hw_scan_vif = NULL;
1948 hwsim->tmp_chan = NULL; 1952 hwsim->tmp_chan = NULL;
@@ -2027,13 +2031,16 @@ static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw,
2027 struct ieee80211_vif *vif) 2031 struct ieee80211_vif *vif)
2028{ 2032{
2029 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 };
2030 2037
2031 wiphy_debug(hw->wiphy, "hwsim cancel_hw_scan\n"); 2038 wiphy_debug(hw->wiphy, "hwsim cancel_hw_scan\n");
2032 2039
2033 cancel_delayed_work_sync(&hwsim->hw_scan); 2040 cancel_delayed_work_sync(&hwsim->hw_scan);
2034 2041
2035 mutex_lock(&hwsim->mutex); 2042 mutex_lock(&hwsim->mutex);
2036 ieee80211_scan_completed(hwsim->hw, true); 2043 ieee80211_scan_completed(hwsim->hw, &info);
2037 hwsim->tmp_chan = NULL; 2044 hwsim->tmp_chan = NULL;
2038 hwsim->hw_scan_request = NULL; 2045 hwsim->hw_scan_request = NULL;
2039 hwsim->hw_scan_vif = NULL; 2046 hwsim->hw_scan_vif = NULL;
diff --git a/drivers/net/wireless/st/cw1200/scan.c b/drivers/net/wireless/st/cw1200/scan.c
index 983788156bb0..0a0ff7e31f5b 100644
--- a/drivers/net/wireless/st/cw1200/scan.c
+++ b/drivers/net/wireless/st/cw1200/scan.c
@@ -167,6 +167,10 @@ void cw1200_scan_work(struct work_struct *work)
167 } 167 }
168 168
169 if (!priv->scan.req || (priv->scan.curr == priv->scan.end)) { 169 if (!priv->scan.req || (priv->scan.curr == priv->scan.end)) {
170 struct cfg80211_scan_info info = {
171 .aborted = priv->scan.status ? 1 : 0,
172 };
173
170 if (priv->scan.output_power != priv->output_power) 174 if (priv->scan.output_power != priv->output_power)
171 wsm_set_output_power(priv, priv->output_power * 10); 175 wsm_set_output_power(priv, priv->output_power * 10);
172 if (priv->join_status == CW1200_JOIN_STATUS_STA && 176 if (priv->join_status == CW1200_JOIN_STATUS_STA &&
@@ -188,7 +192,7 @@ void cw1200_scan_work(struct work_struct *work)
188 cw1200_scan_restart_delayed(priv); 192 cw1200_scan_restart_delayed(priv);
189 wsm_unlock_tx(priv); 193 wsm_unlock_tx(priv);
190 mutex_unlock(&priv->conf_mutex); 194 mutex_unlock(&priv->conf_mutex);
191 ieee80211_scan_completed(priv->hw, priv->scan.status ? 1 : 0); 195 ieee80211_scan_completed(priv->hw, &info);
192 up(&priv->scan.lock); 196 up(&priv->scan.lock);
193 return; 197 return;
194 } else { 198 } else {
diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c
index c98630394a1a..d0593bc1f1a9 100644
--- a/drivers/net/wireless/ti/wl1251/event.c
+++ b/drivers/net/wireless/ti/wl1251/event.c
@@ -36,7 +36,11 @@ static int wl1251_event_scan_complete(struct wl1251 *wl,
36 mbox->scheduled_scan_channels); 36 mbox->scheduled_scan_channels);
37 37
38 if (wl->scanning) { 38 if (wl->scanning) {
39 ieee80211_scan_completed(wl->hw, false); 39 struct cfg80211_scan_info info = {
40 .aborted = false,
41 };
42
43 ieee80211_scan_completed(wl->hw, &info);
40 wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed"); 44 wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed");
41 wl->scanning = false; 45 wl->scanning = false;
42 if (wl->hw->conf.flags & IEEE80211_CONF_IDLE) 46 if (wl->hw->conf.flags & IEEE80211_CONF_IDLE)
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 56384a4e2a35..bbf7604889b7 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -448,7 +448,11 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
448 WARN_ON(wl->state != WL1251_STATE_ON); 448 WARN_ON(wl->state != WL1251_STATE_ON);
449 449
450 if (wl->scanning) { 450 if (wl->scanning) {
451 ieee80211_scan_completed(wl->hw, true); 451 struct cfg80211_scan_info info = {
452 .aborted = true,
453 };
454
455 ieee80211_scan_completed(wl->hw, &info);
452 wl->scanning = false; 456 wl->scanning = false;
453 } 457 }
454 458
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 10fd24c28ece..69267d592504 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -2615,6 +2615,10 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
2615 2615
2616 if (wl->scan.state != WL1271_SCAN_STATE_IDLE && 2616 if (wl->scan.state != WL1271_SCAN_STATE_IDLE &&
2617 wl->scan_wlvif == wlvif) { 2617 wl->scan_wlvif == wlvif) {
2618 struct cfg80211_scan_info info = {
2619 .aborted = true,
2620 };
2621
2618 /* 2622 /*
2619 * Rearm the tx watchdog just before idling scan. This 2623 * Rearm the tx watchdog just before idling scan. This
2620 * prevents just-finished scans from triggering the watchdog 2624 * prevents just-finished scans from triggering the watchdog
@@ -2625,7 +2629,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
2625 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); 2629 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
2626 wl->scan_wlvif = NULL; 2630 wl->scan_wlvif = NULL;
2627 wl->scan.req = NULL; 2631 wl->scan.req = NULL;
2628 ieee80211_scan_completed(wl->hw, true); 2632 ieee80211_scan_completed(wl->hw, &info);
2629 } 2633 }
2630 2634
2631 if (wl->sched_vif == wlvif) 2635 if (wl->sched_vif == wlvif)
@@ -3649,6 +3653,9 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw,
3649{ 3653{
3650 struct wl1271 *wl = hw->priv; 3654 struct wl1271 *wl = hw->priv;
3651 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); 3655 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
3656 struct cfg80211_scan_info info = {
3657 .aborted = true,
3658 };
3652 int ret; 3659 int ret;
3653 3660
3654 wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan"); 3661 wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan");
@@ -3681,7 +3688,7 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw,
3681 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); 3688 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
3682 wl->scan_wlvif = NULL; 3689 wl->scan_wlvif = NULL;
3683 wl->scan.req = NULL; 3690 wl->scan.req = NULL;
3684 ieee80211_scan_completed(wl->hw, true); 3691 ieee80211_scan_completed(wl->hw, &info);
3685 3692
3686out_sleep: 3693out_sleep:
3687 wl1271_ps_elp_sleep(wl); 3694 wl1271_ps_elp_sleep(wl);
diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c
index 23343643207a..5612f5916b4e 100644
--- a/drivers/net/wireless/ti/wlcore/scan.c
+++ b/drivers/net/wireless/ti/wlcore/scan.c
@@ -36,6 +36,9 @@ void wl1271_scan_complete_work(struct work_struct *work)
36 struct delayed_work *dwork; 36 struct delayed_work *dwork;
37 struct wl1271 *wl; 37 struct wl1271 *wl;
38 struct wl12xx_vif *wlvif; 38 struct wl12xx_vif *wlvif;
39 struct cfg80211_scan_info info = {
40 .aborted = false,
41 };
39 int ret; 42 int ret;
40 43
41 dwork = to_delayed_work(work); 44 dwork = to_delayed_work(work);
@@ -82,7 +85,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
82 85
83 wlcore_cmd_regdomain_config_locked(wl); 86 wlcore_cmd_regdomain_config_locked(wl);
84 87
85 ieee80211_scan_completed(wl->hw, false); 88 ieee80211_scan_completed(wl->hw, &info);
86 89
87out: 90out:
88 mutex_unlock(&wl->mutex); 91 mutex_unlock(&wl->mutex);
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a52009ffc19f..b4faadbb4e01 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4697,9 +4697,10 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw);
4697 * any context, including hardirq context. 4697 * any context, including hardirq context.
4698 * 4698 *
4699 * @hw: the hardware that finished the scan 4699 * @hw: the hardware that finished the scan
4700 * @aborted: set to true if scan was aborted 4700 * @info: information about the completed scan
4701 */ 4701 */
4702void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted); 4702void ieee80211_scan_completed(struct ieee80211_hw *hw,
4703 struct cfg80211_scan_info *info);
4703 4704
4704/** 4705/**
4705 * ieee80211_sched_scan_results - got results from scheduled scan 4706 * ieee80211_sched_scan_results - got results from scheduled scan
diff --git a/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/scan.c b/net/mac80211/scan.c
index 4ec1c52a1549..8d4a9cd8a39a 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,11 @@ 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 done, so clear
366 * old scan info.
367 */
368 memset(&local->scan_info, 0, sizeof(local->scan_info));
348 } 369 }
349 370
350 kfree(local->hw_scan_req); 371 kfree(local->hw_scan_req);
@@ -354,11 +375,8 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
354 lockdep_is_held(&local->mtx)); 375 lockdep_is_held(&local->mtx));
355 376
356 if (scan_req != local->int_scan_req) { 377 if (scan_req != local->int_scan_req) {
357 struct cfg80211_scan_info info = { 378 local->scan_info.aborted = aborted;
358 .aborted = aborted, 379 cfg80211_scan_done(scan_req, &local->scan_info);
359 };
360
361 cfg80211_scan_done(scan_req, &info);
362 } 380 }
363 RCU_INIT_POINTER(local->scan_req, NULL); 381 RCU_INIT_POINTER(local->scan_req, NULL);
364 382
@@ -396,15 +414,19 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
396 ieee80211_start_next_roc(local); 414 ieee80211_start_next_roc(local);
397} 415}
398 416
399void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) 417void ieee80211_scan_completed(struct ieee80211_hw *hw,
418 struct cfg80211_scan_info *info)
400{ 419{
401 struct ieee80211_local *local = hw_to_local(hw); 420 struct ieee80211_local *local = hw_to_local(hw);
402 421
403 trace_api_scan_completed(local, aborted); 422 trace_api_scan_completed(local, info);
404 423
405 set_bit(SCAN_COMPLETED, &local->scanning); 424 set_bit(SCAN_COMPLETED, &local->scanning);
406 if (aborted) 425 if (info->aborted)
407 set_bit(SCAN_ABORTED, &local->scanning); 426 set_bit(SCAN_ABORTED, &local->scanning);
427
428 memcpy(&local->scan_info, info, sizeof(*info));
429
408 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); 430 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
409} 431}
410EXPORT_SYMBOL(ieee80211_scan_completed); 432EXPORT_SYMBOL(ieee80211_scan_completed);
@@ -571,6 +593,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
571 local->hw_scan_req->req.ie = ies; 593 local->hw_scan_req->req.ie = ies;
572 local->hw_scan_req->req.flags = req->flags; 594 local->hw_scan_req->req.flags = req->flags;
573 eth_broadcast_addr(local->hw_scan_req->req.bssid); 595 eth_broadcast_addr(local->hw_scan_req->req.bssid);
596 local->hw_scan_req->req.duration = req->duration;
597 local->hw_scan_req->req.duration_mandatory =
598 req->duration_mandatory;
574 599
575 local->hw_scan_band = 0; 600 local->hw_scan_band = 0;
576 601
@@ -1078,6 +1103,7 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
1078 */ 1103 */
1079 cancel_delayed_work(&local->scan_work); 1104 cancel_delayed_work(&local->scan_work);
1080 /* and clean up */ 1105 /* and clean up */
1106 memset(&local->scan_info, 0, sizeof(local->scan_info));
1081 __ieee80211_scan_completed(&local->hw, true); 1107 __ieee80211_scan_completed(&local->hw, true);
1082out: 1108out:
1083 mutex_unlock(&local->mtx); 1109 mutex_unlock(&local->mtx);