aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
diff options
context:
space:
mode:
authorAvrahams Stern <avraham.stern@intel.com>2016-07-19 04:15:09 -0400
committerLuca Coelho <luciano.coelho@intel.com>2016-09-19 03:09:35 -0400
commitaacf8f189b03b3d3c2e577a6d4ef5872bf4d393f (patch)
tree67d99480d33cb6c56f2c845200df02bdcbeaa2c5 /drivers/net/wireless/intel/iwlwifi/mvm/scan.c
parent9a73a7d24d51eaf9e43c771c53cf7b594e5b5334 (diff)
iwlwifi: mvm: Add support for RRM by scan
Implement support for RRM by adding an option to configure the scan dwell time and reporting scan start time and BSS detection time, and Advertise support for these features. Signed-off-by: David Spinadel <david.spinadel@intel.com> Signed-off-by: Avraham Stern <avraham.stern@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/scan.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c61
1 files changed, 55 insertions, 6 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index dac120f8861b..00b03fc5807b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -141,6 +141,7 @@ struct iwl_mvm_scan_params {
141 struct cfg80211_match_set *match_sets; 141 struct cfg80211_match_set *match_sets;
142 int n_scan_plans; 142 int n_scan_plans;
143 struct cfg80211_sched_scan_plan *scan_plans; 143 struct cfg80211_sched_scan_plan *scan_plans;
144 u32 measurement_dwell;
144}; 145};
145 146
146static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm) 147static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)
@@ -232,6 +233,27 @@ iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device)
232 return IWL_SCAN_TYPE_WILD; 233 return IWL_SCAN_TYPE_WILD;
233} 234}
234 235
236static int
237iwl_mvm_get_measurement_dwell(struct iwl_mvm *mvm,
238 struct cfg80211_scan_request *req,
239 struct iwl_mvm_scan_params *params)
240{
241 if (!req->duration)
242 return 0;
243
244 if (req->duration_mandatory &&
245 req->duration > scan_timing[params->type].max_out_time) {
246 IWL_DEBUG_SCAN(mvm,
247 "Measurement scan - too long dwell %hu (max out time %u)\n",
248 req->duration,
249 scan_timing[params->type].max_out_time);
250 return -EOPNOTSUPP;
251 }
252
253 return min_t(u32, (u32)req->duration,
254 scan_timing[params->type].max_out_time);
255}
256
235static inline bool iwl_mvm_rrm_scan_needed(struct iwl_mvm *mvm) 257static inline bool iwl_mvm_rrm_scan_needed(struct iwl_mvm *mvm)
236{ 258{
237 /* require rrm scan whenever the fw supports it */ 259 /* require rrm scan whenever the fw supports it */
@@ -1033,9 +1055,15 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
1033 struct iwl_scan_req_umac *cmd, 1055 struct iwl_scan_req_umac *cmd,
1034 struct iwl_mvm_scan_params *params) 1056 struct iwl_mvm_scan_params *params)
1035{ 1057{
1036 cmd->extended_dwell = scan_timing[params->type].dwell_extended; 1058 if (params->measurement_dwell) {
1037 cmd->active_dwell = scan_timing[params->type].dwell_active; 1059 cmd->active_dwell = params->measurement_dwell;
1038 cmd->passive_dwell = scan_timing[params->type].dwell_passive; 1060 cmd->passive_dwell = params->measurement_dwell;
1061 cmd->extended_dwell = params->measurement_dwell;
1062 } else {
1063 cmd->active_dwell = scan_timing[params->type].dwell_active;
1064 cmd->passive_dwell = scan_timing[params->type].dwell_passive;
1065 cmd->extended_dwell = scan_timing[params->type].dwell_extended;
1066 }
1039 cmd->fragmented_dwell = scan_timing[params->type].dwell_fragmented; 1067 cmd->fragmented_dwell = scan_timing[params->type].dwell_fragmented;
1040 cmd->max_out_time = cpu_to_le32(scan_timing[params->type].max_out_time); 1068 cmd->max_out_time = cpu_to_le32(scan_timing[params->type].max_out_time);
1041 cmd->suspend_time = cpu_to_le32(scan_timing[params->type].suspend_time); 1069 cmd->suspend_time = cpu_to_le32(scan_timing[params->type].suspend_time);
@@ -1067,11 +1095,11 @@ iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
1067 } 1095 }
1068} 1096}
1069 1097
1070static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, 1098static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
1071 struct iwl_mvm_scan_params *params, 1099 struct iwl_mvm_scan_params *params,
1072 struct ieee80211_vif *vif) 1100 struct ieee80211_vif *vif)
1073{ 1101{
1074 int flags = 0; 1102 u16 flags = 0;
1075 1103
1076 if (params->n_ssids == 0) 1104 if (params->n_ssids == 0)
1077 flags = IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE; 1105 flags = IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE;
@@ -1093,6 +1121,9 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
1093 if (!iwl_mvm_is_regular_scan(params)) 1121 if (!iwl_mvm_is_regular_scan(params))
1094 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC; 1122 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC;
1095 1123
1124 if (params->measurement_dwell)
1125 flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;
1126
1096#ifdef CONFIG_IWLWIFI_DEBUGFS 1127#ifdef CONFIG_IWLWIFI_DEBUGFS
1097 if (mvm->scan_iter_notif_enabled) 1128 if (mvm->scan_iter_notif_enabled)
1098 flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE; 1129 flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;
@@ -1119,6 +1150,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1119 mvm->fw->ucode_capa.n_scan_channels; 1150 mvm->fw->ucode_capa.n_scan_channels;
1120 int uid, i; 1151 int uid, i;
1121 u32 ssid_bitmap = 0; 1152 u32 ssid_bitmap = 0;
1153 struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);
1122 1154
1123 lockdep_assert_held(&mvm->mutex); 1155 lockdep_assert_held(&mvm->mutex);
1124 1156
@@ -1136,8 +1168,9 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1136 mvm->scan_uid_status[uid] = type; 1168 mvm->scan_uid_status[uid] = type;
1137 1169
1138 cmd->uid = cpu_to_le32(uid); 1170 cmd->uid = cpu_to_le32(uid);
1139 cmd->general_flags = cpu_to_le32(iwl_mvm_scan_umac_flags(mvm, params, 1171 cmd->general_flags = cpu_to_le16(iwl_mvm_scan_umac_flags(mvm, params,
1140 vif)); 1172 vif));
1173 cmd->scan_start_mac_id = scan_vif->id;
1141 1174
1142 if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT) 1175 if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT)
1143 cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); 1176 cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);
@@ -1289,6 +1322,12 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1289 iwl_mvm_get_scan_type(mvm, 1322 iwl_mvm_get_scan_type(mvm,
1290 vif->type == NL80211_IFTYPE_P2P_DEVICE); 1323 vif->type == NL80211_IFTYPE_P2P_DEVICE);
1291 1324
1325 ret = iwl_mvm_get_measurement_dwell(mvm, req, &params);
1326 if (ret < 0)
1327 return ret;
1328
1329 params.measurement_dwell = ret;
1330
1292 iwl_mvm_build_scan_probe(mvm, vif, ies, &params); 1331 iwl_mvm_build_scan_probe(mvm, vif, ies, &params);
1293 1332
1294 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) { 1333 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
@@ -1315,6 +1354,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1315 1354
1316 IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); 1355 IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
1317 mvm->scan_status |= IWL_MVM_SCAN_REGULAR; 1356 mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
1357 mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
1318 iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); 1358 iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
1319 1359
1320 queue_delayed_work(system_wq, &mvm->scan_timeout_dwork, 1360 queue_delayed_work(system_wq, &mvm->scan_timeout_dwork,
@@ -1437,9 +1477,12 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
1437 if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) { 1477 if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) {
1438 struct cfg80211_scan_info info = { 1478 struct cfg80211_scan_info info = {
1439 .aborted = aborted, 1479 .aborted = aborted,
1480 .scan_start_tsf = mvm->scan_start,
1440 }; 1481 };
1441 1482
1483 memcpy(info.tsf_bssid, mvm->scan_vif->bssid, ETH_ALEN);
1442 ieee80211_scan_completed(mvm->hw, &info); 1484 ieee80211_scan_completed(mvm->hw, &info);
1485 mvm->scan_vif = NULL;
1443 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); 1486 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
1444 cancel_delayed_work(&mvm->scan_timeout_dwork); 1487 cancel_delayed_work(&mvm->scan_timeout_dwork);
1445 } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { 1488 } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
@@ -1473,6 +1516,8 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
1473 struct iwl_umac_scan_iter_complete_notif *notif = (void *)pkt->data; 1516 struct iwl_umac_scan_iter_complete_notif *notif = (void *)pkt->data;
1474 u8 buf[256]; 1517 u8 buf[256];
1475 1518
1519 mvm->scan_start = le64_to_cpu(notif->start_tsf);
1520
1476 IWL_DEBUG_SCAN(mvm, 1521 IWL_DEBUG_SCAN(mvm,
1477 "UMAC Scan iteration complete: status=0x%x scanned_channels=%d channels list: %s\n", 1522 "UMAC Scan iteration complete: status=0x%x scanned_channels=%d channels list: %s\n",
1478 notif->status, notif->scanned_channels, 1523 notif->status, notif->scanned_channels,
@@ -1485,6 +1530,10 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
1485 ieee80211_sched_scan_results(mvm->hw); 1530 ieee80211_sched_scan_results(mvm->hw);
1486 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED; 1531 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED;
1487 } 1532 }
1533
1534 IWL_DEBUG_SCAN(mvm,
1535 "UMAC Scan iteration complete: scan started at %llu (TSF)\n",
1536 mvm->scan_start);
1488} 1537}
1489 1538
1490static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type) 1539static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type)