hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
....@@ -8,7 +8,7 @@
88 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
99 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
1010 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
11
- * Copyright(c) 2018 Intel Corporation
11
+ * Copyright(c) 2018 - 2019 Intel Corporation
1212 *
1313 * This program is free software; you can redistribute it and/or modify
1414 * it under the terms of version 2 of the GNU General Public License as
....@@ -18,9 +18,6 @@
1818 * WITHOUT ANY WARRANTY; without even the implied warranty of
1919 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2020 * General Public License for more details.
21
- *
22
- * You should have received a copy of the GNU General Public License
23
- * along with this program
2421 *
2522 * The full GNU General Public License is included in this distribution
2623 * in the file called COPYING.
....@@ -34,7 +31,7 @@
3431 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
3532 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
3633 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
37
- * Copyright(c) 2018 Intel Corporation
34
+ * Copyright(c) 2018 - 2019 Intel Corporation
3835 * All rights reserved.
3936 *
4037 * Redistribution and use in source and binary forms, with or without
....@@ -80,16 +77,28 @@
8077 #define IWL_SCAN_DWELL_FRAGMENTED 44
8178 #define IWL_SCAN_DWELL_EXTENDED 90
8279 #define IWL_SCAN_NUM_OF_FRAGS 3
83
-
80
+#define IWL_SCAN_LAST_2_4_CHN 14
8481
8582 /* adaptive dwell max budget time [TU] for full scan */
8683 #define IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300
8784 /* adaptive dwell max budget time [TU] for directed scan */
8885 #define IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN 100
89
-/* adaptive dwell default APs number */
90
-#define IWL_SCAN_ADWELL_DEFAULT_N_APS 2
86
+/* adaptive dwell default high band APs number */
87
+#define IWL_SCAN_ADWELL_DEFAULT_HB_N_APS 8
88
+/* adaptive dwell default low band APs number */
89
+#define IWL_SCAN_ADWELL_DEFAULT_LB_N_APS 2
9190 /* adaptive dwell default APs number in social channels (1, 6, 11) */
9291 #define IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 10
92
+/* number of scan channels */
93
+#define IWL_SCAN_NUM_CHANNELS 112
94
+/* adaptive dwell number of APs override mask for p2p friendly GO */
95
+#define IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY_BIT BIT(20)
96
+/* adaptive dwell number of APs override mask for social channels */
97
+#define IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS_BIT BIT(21)
98
+/* adaptive dwell number of APs override for p2p friendly GO channels */
99
+#define IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY 10
100
+/* adaptive dwell number of APs override for social channels */
101
+#define IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS 2
93102
94103 struct iwl_mvm_scan_timing_params {
95104 u32 suspend_time;
....@@ -113,6 +122,10 @@
113122 .suspend_time = 95,
114123 .max_out_time = 44,
115124 },
125
+ [IWL_SCAN_TYPE_FAST_BALANCE] = {
126
+ .suspend_time = 30,
127
+ .max_out_time = 37,
128
+ },
116129 };
117130
118131 struct iwl_mvm_scan_params {
....@@ -134,7 +147,7 @@
134147 struct cfg80211_match_set *match_sets;
135148 int n_scan_plans;
136149 struct cfg80211_sched_scan_plan *scan_plans;
137
- u32 measurement_dwell;
150
+ bool iter_notif;
138151 };
139152
140153 static inline void *iwl_mvm_get_scan_req_umac_data(struct iwl_mvm *mvm)
....@@ -190,23 +203,13 @@
190203 return cpu_to_le16(rx_chain);
191204 }
192205
193
-static __le32 iwl_mvm_scan_rxon_flags(enum nl80211_band band)
194
-{
195
- if (band == NL80211_BAND_2GHZ)
196
- return cpu_to_le32(PHY_BAND_24);
197
- else
198
- return cpu_to_le32(PHY_BAND_5);
199
-}
200
-
201206 static inline __le32
202207 iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum nl80211_band band,
203208 bool no_cck)
204209 {
205210 u32 tx_ant;
206211
207
- mvm->scan_last_antenna_idx =
208
- iwl_mvm_next_antenna(mvm, iwl_mvm_get_valid_tx_ant(mvm),
209
- mvm->scan_last_antenna_idx);
212
+ iwl_mvm_toggle_tx_ant(mvm, &mvm->scan_last_antenna_idx);
210213 tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS;
211214
212215 if (band == NL80211_BAND_2GHZ && !no_cck)
....@@ -238,8 +241,32 @@
238241 return mvm->tcm.result.band_load[band];
239242 }
240243
244
+struct iwl_is_dcm_with_go_iterator_data {
245
+ struct ieee80211_vif *current_vif;
246
+ bool is_dcm_with_p2p_go;
247
+};
248
+
249
+static void iwl_mvm_is_dcm_with_go_iterator(void *_data, u8 *mac,
250
+ struct ieee80211_vif *vif)
251
+{
252
+ struct iwl_is_dcm_with_go_iterator_data *data = _data;
253
+ struct iwl_mvm_vif *other_mvmvif = iwl_mvm_vif_from_mac80211(vif);
254
+ struct iwl_mvm_vif *curr_mvmvif =
255
+ iwl_mvm_vif_from_mac80211(data->current_vif);
256
+
257
+ /* exclude the given vif */
258
+ if (vif == data->current_vif)
259
+ return;
260
+
261
+ if (vif->type == NL80211_IFTYPE_AP && vif->p2p &&
262
+ other_mvmvif->phy_ctxt && curr_mvmvif->phy_ctxt &&
263
+ other_mvmvif->phy_ctxt->id != curr_mvmvif->phy_ctxt->id)
264
+ data->is_dcm_with_p2p_go = true;
265
+}
266
+
241267 static enum
242
-iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device,
268
+iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm,
269
+ struct ieee80211_vif *vif,
243270 enum iwl_mvm_traffic_load load,
244271 bool low_latency)
245272 {
....@@ -252,9 +279,30 @@
252279 if (!global_cnt)
253280 return IWL_SCAN_TYPE_UNASSOC;
254281
255
- if ((load == IWL_MVM_TRAFFIC_HIGH || low_latency) && !p2p_device &&
256
- fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_FRAGMENTED_SCAN))
257
- return IWL_SCAN_TYPE_FRAGMENTED;
282
+ if (fw_has_api(&mvm->fw->ucode_capa,
283
+ IWL_UCODE_TLV_API_FRAGMENTED_SCAN)) {
284
+ if ((load == IWL_MVM_TRAFFIC_HIGH || low_latency) &&
285
+ (!vif || vif->type != NL80211_IFTYPE_P2P_DEVICE))
286
+ return IWL_SCAN_TYPE_FRAGMENTED;
287
+
288
+ /* in case of DCM with GO where BSS DTIM interval < 220msec
289
+ * set all scan requests as fast-balance scan
290
+ * */
291
+ if (vif && vif->type == NL80211_IFTYPE_STATION &&
292
+ vif->bss_conf.dtim_period < 220) {
293
+ struct iwl_is_dcm_with_go_iterator_data data = {
294
+ .current_vif = vif,
295
+ .is_dcm_with_p2p_go = false,
296
+ };
297
+
298
+ ieee80211_iterate_active_interfaces_atomic(mvm->hw,
299
+ IEEE80211_IFACE_ITER_NORMAL,
300
+ iwl_mvm_is_dcm_with_go_iterator,
301
+ &data);
302
+ if (data.is_dcm_with_p2p_go)
303
+ return IWL_SCAN_TYPE_FAST_BALANCE;
304
+ }
305
+ }
258306
259307 if (load >= IWL_MVM_TRAFFIC_MEDIUM || low_latency)
260308 return IWL_SCAN_TYPE_MILD;
....@@ -263,7 +311,8 @@
263311 }
264312
265313 static enum
266
-iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device)
314
+iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm,
315
+ struct ieee80211_vif *vif)
267316 {
268317 enum iwl_mvm_traffic_load load;
269318 bool low_latency;
....@@ -271,12 +320,12 @@
271320 load = iwl_mvm_get_traffic_load(mvm);
272321 low_latency = iwl_mvm_low_latency(mvm);
273322
274
- return _iwl_mvm_get_scan_type(mvm, p2p_device, load, low_latency);
323
+ return _iwl_mvm_get_scan_type(mvm, vif, load, low_latency);
275324 }
276325
277326 static enum
278327 iwl_mvm_scan_type iwl_mvm_get_scan_type_band(struct iwl_mvm *mvm,
279
- bool p2p_device,
328
+ struct ieee80211_vif *vif,
280329 enum nl80211_band band)
281330 {
282331 enum iwl_mvm_traffic_load load;
....@@ -285,34 +334,7 @@
285334 load = iwl_mvm_get_traffic_load_band(mvm, band);
286335 low_latency = iwl_mvm_low_latency_band(mvm, band);
287336
288
- return _iwl_mvm_get_scan_type(mvm, p2p_device, load, low_latency);
289
-}
290
-
291
-static int
292
-iwl_mvm_get_measurement_dwell(struct iwl_mvm *mvm,
293
- struct cfg80211_scan_request *req,
294
- struct iwl_mvm_scan_params *params)
295
-{
296
- u32 duration = scan_timing[params->type].max_out_time;
297
-
298
- if (!req->duration)
299
- return 0;
300
-
301
- if (iwl_mvm_is_cdb_supported(mvm)) {
302
- u32 hb_time = scan_timing[params->hb_type].max_out_time;
303
-
304
- duration = min_t(u32, duration, hb_time);
305
- }
306
-
307
- if (req->duration_mandatory && req->duration > duration) {
308
- IWL_DEBUG_SCAN(mvm,
309
- "Measurement scan - too long dwell %hu (max out time %u)\n",
310
- req->duration,
311
- duration);
312
- return -EOPNOTSUPP;
313
- }
314
-
315
- return min_t(u32, (u32)req->duration, duration);
337
+ return _iwl_mvm_get_scan_type(mvm, vif, load, low_latency);
316338 }
317339
318340 static inline bool iwl_mvm_rrm_scan_needed(struct iwl_mvm *mvm)
....@@ -465,7 +487,6 @@
465487
466488 mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
467489 ieee80211_scan_completed(mvm->hw, &info);
468
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
469490 cancel_delayed_work(&mvm->scan_timeout_dwork);
470491 iwl_mvm_resume_tcm(mvm);
471492 } else {
....@@ -501,6 +522,7 @@
501522 {
502523 int i, j;
503524 int index;
525
+ u32 tmp_bitmap = 0;
504526
505527 /*
506528 * copy SSIDs from match list.
....@@ -520,7 +542,6 @@
520542 }
521543
522544 /* add SSIDs from scan SSID list */
523
- *ssid_bitmap = 0;
524545 for (j = params->n_ssids - 1;
525546 j >= 0 && i < PROBE_OPTION_MAX;
526547 i++, j--) {
....@@ -532,11 +553,13 @@
532553 ssids[i].len = params->ssids[j].ssid_len;
533554 memcpy(ssids[i].ssid, params->ssids[j].ssid,
534555 ssids[i].len);
535
- *ssid_bitmap |= BIT(i);
556
+ tmp_bitmap |= BIT(i);
536557 } else {
537
- *ssid_bitmap |= BIT(index);
558
+ tmp_bitmap |= BIT(index);
538559 }
539560 }
561
+ if (ssid_bitmap)
562
+ *ssid_bitmap = tmp_bitmap;
540563 }
541564
542565 static int
....@@ -544,51 +567,65 @@
544567 struct cfg80211_sched_scan_request *req)
545568 {
546569 struct iwl_scan_offload_profile *profile;
547
- struct iwl_scan_offload_profile_cfg *profile_cfg;
548
- struct iwl_scan_offload_blacklist *blacklist;
570
+ struct iwl_scan_offload_profile_cfg_v1 *profile_cfg_v1;
571
+ struct iwl_scan_offload_blocklist *blocklist;
572
+ struct iwl_scan_offload_profile_cfg_data *data;
573
+ int max_profiles = iwl_umac_scan_get_max_profiles(mvm->fw);
574
+ int profile_cfg_size = sizeof(*data) +
575
+ sizeof(*profile) * max_profiles;
549576 struct iwl_host_cmd cmd = {
550577 .id = SCAN_OFFLOAD_UPDATE_PROFILES_CMD,
551
- .len[1] = sizeof(*profile_cfg),
578
+ .len[1] = profile_cfg_size,
552579 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
553580 .dataflags[1] = IWL_HCMD_DFL_NOCOPY,
554581 };
555
- int blacklist_len;
582
+ int blocklist_len;
556583 int i;
557584 int ret;
558585
559
- if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES))
586
+ if (WARN_ON(req->n_match_sets > max_profiles))
560587 return -EIO;
561588
562589 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL)
563
- blacklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN;
590
+ blocklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN;
564591 else
565
- blacklist_len = IWL_SCAN_MAX_BLACKLIST_LEN;
592
+ blocklist_len = IWL_SCAN_MAX_BLACKLIST_LEN;
566593
567
- blacklist = kcalloc(blacklist_len, sizeof(*blacklist), GFP_KERNEL);
568
- if (!blacklist)
594
+ blocklist = kcalloc(blocklist_len, sizeof(*blocklist), GFP_KERNEL);
595
+ if (!blocklist)
569596 return -ENOMEM;
570597
571
- profile_cfg = kzalloc(sizeof(*profile_cfg), GFP_KERNEL);
572
- if (!profile_cfg) {
598
+ profile_cfg_v1 = kzalloc(profile_cfg_size, GFP_KERNEL);
599
+ if (!profile_cfg_v1) {
573600 ret = -ENOMEM;
574
- goto free_blacklist;
601
+ goto free_blocklist;
575602 }
576603
577
- cmd.data[0] = blacklist;
578
- cmd.len[0] = sizeof(*blacklist) * blacklist_len;
579
- cmd.data[1] = profile_cfg;
604
+ cmd.data[0] = blocklist;
605
+ cmd.len[0] = sizeof(*blocklist) * blocklist_len;
606
+ cmd.data[1] = profile_cfg_v1;
580607
581
- /* No blacklist configuration */
608
+ /* if max_profile is MAX_PROFILES_V2, we have the new API */
609
+ if (max_profiles == IWL_SCAN_MAX_PROFILES_V2) {
610
+ struct iwl_scan_offload_profile_cfg *profile_cfg =
611
+ (struct iwl_scan_offload_profile_cfg *)profile_cfg_v1;
582612
583
- profile_cfg->num_profiles = req->n_match_sets;
584
- profile_cfg->active_clients = SCAN_CLIENT_SCHED_SCAN;
585
- profile_cfg->pass_match = SCAN_CLIENT_SCHED_SCAN;
586
- profile_cfg->match_notify = SCAN_CLIENT_SCHED_SCAN;
613
+ data = &profile_cfg->data;
614
+ } else {
615
+ data = &profile_cfg_v1->data;
616
+ }
617
+
618
+ /* No blocklist configuration */
619
+ data->num_profiles = req->n_match_sets;
620
+ data->active_clients = SCAN_CLIENT_SCHED_SCAN;
621
+ data->pass_match = SCAN_CLIENT_SCHED_SCAN;
622
+ data->match_notify = SCAN_CLIENT_SCHED_SCAN;
623
+
587624 if (!req->n_match_sets || !req->match_sets[0].ssid.ssid_len)
588
- profile_cfg->any_beacon_notify = SCAN_CLIENT_SCHED_SCAN;
625
+ data->any_beacon_notify = SCAN_CLIENT_SCHED_SCAN;
589626
590627 for (i = 0; i < req->n_match_sets; i++) {
591
- profile = &profile_cfg->profiles[i];
628
+ profile = &profile_cfg_v1->profiles[i];
592629 profile->ssid_index = i;
593630 /* Support any cipher and auth algorithm */
594631 profile->unicast_cipher = 0xff;
....@@ -601,9 +638,9 @@
601638 IWL_DEBUG_SCAN(mvm, "Sending scheduled scan profile config\n");
602639
603640 ret = iwl_mvm_send_cmd(mvm, &cmd);
604
- kfree(profile_cfg);
605
-free_blacklist:
606
- kfree(blacklist);
641
+ kfree(profile_cfg_v1);
642
+free_blocklist:
643
+ kfree(blocklist);
607644
608645 return ret;
609646 }
....@@ -661,14 +698,28 @@
661698 tx_cmd[0].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm,
662699 NL80211_BAND_2GHZ,
663700 no_cck);
664
- tx_cmd[0].sta_id = mvm->aux_sta.sta_id;
701
+
702
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
703
+ ADD_STA,
704
+ 0) < 12) {
705
+ tx_cmd[0].sta_id = mvm->aux_sta.sta_id;
706
+ tx_cmd[1].sta_id = mvm->aux_sta.sta_id;
707
+
708
+ /*
709
+ * Fw doesn't use this sta anymore, pending deprecation via HOST API
710
+ * change
711
+ */
712
+ } else {
713
+ tx_cmd[0].sta_id = 0xff;
714
+ tx_cmd[1].sta_id = 0xff;
715
+ }
665716
666717 tx_cmd[1].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
667718 TX_CMD_FLG_BT_DIS);
719
+
668720 tx_cmd[1].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm,
669721 NL80211_BAND_5GHZ,
670722 no_cck);
671
- tx_cmd[1].sta_id = mvm->aux_sta.sta_id;
672723 }
673724
674725 static void
....@@ -836,22 +887,37 @@
836887 struct ieee80211_vif *vif)
837888 {
838889 const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa;
890
+ bool low_latency;
891
+
892
+ if (iwl_mvm_is_cdb_supported(mvm))
893
+ low_latency = iwl_mvm_low_latency_band(mvm, NL80211_BAND_5GHZ);
894
+ else
895
+ low_latency = iwl_mvm_low_latency(mvm);
839896
840897 /* We can only use EBS if:
841898 * 1. the feature is supported;
842899 * 2. the last EBS was successful;
843900 * 3. if only single scan, the single scan EBS API is supported;
844901 * 4. it's not a p2p find operation.
902
+ * 5. we are not in low latency mode,
903
+ * or if fragmented ebs is supported by the FW
845904 */
846905 return ((capa->flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT) &&
847906 mvm->last_ebs_successful && IWL_MVM_ENABLE_EBS &&
848
- vif->type != NL80211_IFTYPE_P2P_DEVICE);
907
+ vif->type != NL80211_IFTYPE_P2P_DEVICE &&
908
+ (!low_latency || iwl_mvm_is_frag_ebs_supported(mvm)));
849909 }
850910
851911 static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params)
852912 {
853913 return params->n_scan_plans == 1 &&
854914 params->scan_plans[0].iterations == 1;
915
+}
916
+
917
+static bool iwl_mvm_is_scan_fragmented(enum iwl_mvm_scan_type type)
918
+{
919
+ return (type == IWL_SCAN_TYPE_FRAGMENTED ||
920
+ type == IWL_SCAN_TYPE_FAST_BALANCE);
855921 }
856922
857923 static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm,
....@@ -866,7 +932,7 @@
866932 if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0)
867933 flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION;
868934
869
- if (params->type == IWL_SCAN_TYPE_FRAGMENTED)
935
+ if (iwl_mvm_is_scan_fragmented(params->type))
870936 flags |= IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED;
871937
872938 if (iwl_mvm_rrm_scan_needed(mvm) &&
....@@ -889,25 +955,35 @@
889955
890956 if (iwl_mvm_is_regular_scan(params) &&
891957 vif->type != NL80211_IFTYPE_P2P_DEVICE &&
892
- params->type != IWL_SCAN_TYPE_FRAGMENTED)
958
+ !iwl_mvm_is_scan_fragmented(params->type))
893959 flags |= IWL_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL;
894960
895961 return flags;
962
+}
963
+
964
+static void
965
+iwl_mvm_scan_set_legacy_probe_req(struct iwl_scan_probe_req_v1 *p_req,
966
+ struct iwl_scan_probe_req *src_p_req)
967
+{
968
+ int i;
969
+
970
+ p_req->mac_header = src_p_req->mac_header;
971
+ for (i = 0; i < SCAN_NUM_BAND_PROBE_DATA_V_1; i++)
972
+ p_req->band_data[i] = src_p_req->band_data[i];
973
+ p_req->common_data = src_p_req->common_data;
974
+ memcpy(p_req->buf, src_p_req->buf, sizeof(p_req->buf));
896975 }
897976
898977 static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
899978 struct iwl_mvm_scan_params *params)
900979 {
901980 struct iwl_scan_req_lmac *cmd = mvm->scan_cmd;
902
- struct iwl_scan_probe_req *preq =
981
+ struct iwl_scan_probe_req_v1 *preq =
903982 (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *
904983 mvm->fw->ucode_capa.n_scan_channels);
905984 u32 ssid_bitmap = 0;
906985 int i;
907
-
908
- lockdep_assert_held(&mvm->mutex);
909
-
910
- memset(cmd, 0, ksize(cmd));
986
+ u8 band;
911987
912988 if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))
913989 return -EINVAL;
....@@ -923,7 +999,8 @@
923999 cmd->scan_flags = cpu_to_le32(iwl_mvm_scan_lmac_flags(mvm, params,
9241000 vif));
9251001
926
- cmd->flags = iwl_mvm_scan_rxon_flags(params->channels[0]->band);
1002
+ band = iwl_mvm_phy_band_from_nl80211(params->channels[0]->band);
1003
+ cmd->flags = cpu_to_le32(band);
9271004 cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP |
9281005 MAC_FILTER_IN_BEACON);
9291006 iwl_mvm_scan_fill_tx_cmd(mvm, cmd->tx_cmd, params->no_cck);
....@@ -969,7 +1046,7 @@
9691046 iwl_mvm_lmac_scan_cfg_channels(mvm, params->channels,
9701047 params->n_channels, ssid_bitmap, cmd);
9711048
972
- *preq = params->preq;
1049
+ iwl_mvm_scan_set_legacy_probe_req(preq, &params->preq);
9731050
9741051 return 0;
9751052 }
....@@ -1022,23 +1099,25 @@
10221099 dwell->extended = IWL_SCAN_DWELL_EXTENDED;
10231100 }
10241101
1025
-static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels)
1102
+static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels,
1103
+ u32 max_channels)
10261104 {
10271105 struct ieee80211_supported_band *band;
10281106 int i, j = 0;
10291107
10301108 band = &mvm->nvm_data->bands[NL80211_BAND_2GHZ];
1031
- for (i = 0; i < band->n_channels; i++, j++)
1109
+ for (i = 0; i < band->n_channels && j < max_channels; i++, j++)
10321110 channels[j] = band->channels[i].hw_value;
10331111 band = &mvm->nvm_data->bands[NL80211_BAND_5GHZ];
1034
- for (i = 0; i < band->n_channels; i++, j++)
1112
+ for (i = 0; i < band->n_channels && j < max_channels; i++, j++)
10351113 channels[j] = band->channels[i].hw_value;
10361114 }
10371115
10381116 static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
1039
- u32 flags, u8 channel_flags)
1117
+ u32 flags, u8 channel_flags,
1118
+ u32 max_channels)
10401119 {
1041
- enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, false);
1120
+ enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, NULL);
10421121 struct iwl_scan_config_v1 *cfg = config;
10431122
10441123 cfg->flags = cpu_to_le32(flags);
....@@ -1052,16 +1131,21 @@
10521131
10531132 memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
10541133
1134
+ /* This function should not be called when using ADD_STA ver >=12 */
1135
+ WARN_ON_ONCE(iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
1136
+ ADD_STA, 0) >= 12);
1137
+
10551138 cfg->bcast_sta_id = mvm->aux_sta.sta_id;
10561139 cfg->channel_flags = channel_flags;
10571140
1058
- iwl_mvm_fill_channels(mvm, cfg->channel_array);
1141
+ iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels);
10591142 }
10601143
1061
-static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
1062
- u32 flags, u8 channel_flags)
1144
+static void iwl_mvm_fill_scan_config_v2(struct iwl_mvm *mvm, void *config,
1145
+ u32 flags, u8 channel_flags,
1146
+ u32 max_channels)
10631147 {
1064
- struct iwl_scan_config *cfg = config;
1148
+ struct iwl_scan_config_v2 *cfg = config;
10651149
10661150 cfg->flags = cpu_to_le32(flags);
10671151 cfg->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
....@@ -1071,9 +1155,9 @@
10711155 if (iwl_mvm_is_cdb_supported(mvm)) {
10721156 enum iwl_mvm_scan_type lb_type, hb_type;
10731157
1074
- lb_type = iwl_mvm_get_scan_type_band(mvm, false,
1158
+ lb_type = iwl_mvm_get_scan_type_band(mvm, NULL,
10751159 NL80211_BAND_2GHZ);
1076
- hb_type = iwl_mvm_get_scan_type_band(mvm, false,
1160
+ hb_type = iwl_mvm_get_scan_type_band(mvm, NULL,
10771161 NL80211_BAND_5GHZ);
10781162
10791163 cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] =
....@@ -1087,7 +1171,7 @@
10871171 cpu_to_le32(scan_timing[hb_type].suspend_time);
10881172 } else {
10891173 enum iwl_mvm_scan_type type =
1090
- iwl_mvm_get_scan_type(mvm, false);
1174
+ iwl_mvm_get_scan_type(mvm, NULL);
10911175
10921176 cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] =
10931177 cpu_to_le32(scan_timing[type].max_out_time);
....@@ -1099,13 +1183,17 @@
10991183
11001184 memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
11011185
1186
+ /* This function should not be called when using ADD_STA ver >=12 */
1187
+ WARN_ON_ONCE(iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
1188
+ ADD_STA, 0) >= 12);
1189
+
11021190 cfg->bcast_sta_id = mvm->aux_sta.sta_id;
11031191 cfg->channel_flags = channel_flags;
11041192
1105
- iwl_mvm_fill_channels(mvm, cfg->channel_array);
1193
+ iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels);
11061194 }
11071195
1108
-int iwl_mvm_config_scan(struct iwl_mvm *mvm)
1196
+static int iwl_mvm_legacy_config_scan(struct iwl_mvm *mvm)
11091197 {
11101198 void *cfg;
11111199 int ret, cmd_size;
....@@ -1121,23 +1209,23 @@
11211209 u8 channel_flags;
11221210
11231211 if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels))
1124
- return -ENOBUFS;
1212
+ num_channels = mvm->fw->ucode_capa.n_scan_channels;
11251213
11261214 if (iwl_mvm_is_cdb_supported(mvm)) {
1127
- type = iwl_mvm_get_scan_type_band(mvm, false,
1215
+ type = iwl_mvm_get_scan_type_band(mvm, NULL,
11281216 NL80211_BAND_2GHZ);
1129
- hb_type = iwl_mvm_get_scan_type_band(mvm, false,
1217
+ hb_type = iwl_mvm_get_scan_type_band(mvm, NULL,
11301218 NL80211_BAND_5GHZ);
11311219 if (type == mvm->scan_type && hb_type == mvm->hb_scan_type)
11321220 return 0;
11331221 } else {
1134
- type = iwl_mvm_get_scan_type(mvm, false);
1222
+ type = iwl_mvm_get_scan_type(mvm, NULL);
11351223 if (type == mvm->scan_type)
11361224 return 0;
11371225 }
11381226
11391227 if (iwl_mvm_cdb_scan_api(mvm))
1140
- cmd_size = sizeof(struct iwl_scan_config);
1228
+ cmd_size = sizeof(struct iwl_scan_config_v2);
11411229 else
11421230 cmd_size = sizeof(struct iwl_scan_config_v1);
11431231 cmd_size += mvm->fw->ucode_capa.n_scan_channels;
....@@ -1156,7 +1244,7 @@
11561244 SCAN_CONFIG_FLAG_SET_MAC_ADDR |
11571245 SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS |
11581246 SCAN_CONFIG_N_CHANNELS(num_channels) |
1159
- (type == IWL_SCAN_TYPE_FRAGMENTED ?
1247
+ (iwl_mvm_is_scan_fragmented(type) ?
11601248 SCAN_CONFIG_FLAG_SET_FRAGMENTED :
11611249 SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED);
11621250
....@@ -1171,12 +1259,14 @@
11711259 */
11721260 if (iwl_mvm_cdb_scan_api(mvm)) {
11731261 if (iwl_mvm_is_cdb_supported(mvm))
1174
- flags |= (hb_type == IWL_SCAN_TYPE_FRAGMENTED) ?
1262
+ flags |= (iwl_mvm_is_scan_fragmented(hb_type)) ?
11751263 SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED :
11761264 SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED;
1177
- iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags);
1265
+ iwl_mvm_fill_scan_config_v2(mvm, cfg, flags, channel_flags,
1266
+ num_channels);
11781267 } else {
1179
- iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags);
1268
+ iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags,
1269
+ num_channels);
11801270 }
11811271
11821272 cmd.data[0] = cfg;
....@@ -1193,6 +1283,39 @@
11931283
11941284 kfree(cfg);
11951285 return ret;
1286
+}
1287
+
1288
+int iwl_mvm_config_scan(struct iwl_mvm *mvm)
1289
+{
1290
+ struct iwl_scan_config cfg;
1291
+ struct iwl_host_cmd cmd = {
1292
+ .id = iwl_cmd_id(SCAN_CFG_CMD, IWL_ALWAYS_LONG_GROUP, 0),
1293
+ .len[0] = sizeof(cfg),
1294
+ .data[0] = &cfg,
1295
+ .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
1296
+ };
1297
+
1298
+ if (!iwl_mvm_is_reduced_config_scan_supported(mvm))
1299
+ return iwl_mvm_legacy_config_scan(mvm);
1300
+
1301
+ memset(&cfg, 0, sizeof(cfg));
1302
+
1303
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
1304
+ ADD_STA, 0) < 12)
1305
+ cfg.bcast_sta_id = mvm->aux_sta.sta_id;
1306
+ /*
1307
+ * Fw doesn't use this sta anymore, pending deprecation via HOST API
1308
+ * change.
1309
+ */
1310
+ else
1311
+ cfg.bcast_sta_id = 0xff;
1312
+
1313
+ cfg.tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
1314
+ cfg.rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));
1315
+
1316
+ IWL_DEBUG_SCAN(mvm, "Sending UMAC scan config\n");
1317
+
1318
+ return iwl_mvm_send_cmd(mvm, &cmd);
11961319 }
11971320
11981321 static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status)
....@@ -1214,16 +1337,18 @@
12141337 u8 active_dwell, passive_dwell;
12151338
12161339 timing = &scan_timing[params->type];
1217
- active_dwell = params->measurement_dwell ?
1218
- params->measurement_dwell : IWL_SCAN_DWELL_ACTIVE;
1219
- passive_dwell = params->measurement_dwell ?
1220
- params->measurement_dwell : IWL_SCAN_DWELL_PASSIVE;
1340
+ active_dwell = IWL_SCAN_DWELL_ACTIVE;
1341
+ passive_dwell = IWL_SCAN_DWELL_PASSIVE;
12211342
12221343 if (iwl_mvm_is_adaptive_dwell_supported(mvm)) {
12231344 cmd->v7.adwell_default_n_aps_social =
12241345 IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;
12251346 cmd->v7.adwell_default_n_aps =
1226
- IWL_SCAN_ADWELL_DEFAULT_N_APS;
1347
+ IWL_SCAN_ADWELL_DEFAULT_LB_N_APS;
1348
+
1349
+ if (iwl_mvm_is_adwell_hb_ap_num_supported(mvm))
1350
+ cmd->v9.adwell_default_hb_n_aps =
1351
+ IWL_SCAN_ADWELL_DEFAULT_HB_N_APS;
12271352
12281353 /* if custom max budget was configured with debugfs */
12291354 if (IWL_MVM_ADWELL_MAX_BUDGET)
....@@ -1266,8 +1391,7 @@
12661391 }
12671392 }
12681393 } else {
1269
- cmd->v1.extended_dwell = params->measurement_dwell ?
1270
- params->measurement_dwell : IWL_SCAN_DWELL_EXTENDED;
1394
+ cmd->v1.extended_dwell = IWL_SCAN_DWELL_EXTENDED;
12711395 cmd->v1.active_dwell = active_dwell;
12721396 cmd->v1.passive_dwell = passive_dwell;
12731397 cmd->v1.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED;
....@@ -1304,20 +1428,328 @@
13041428 cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_2);
13051429 }
13061430
1431
+static u32 iwl_mvm_scan_umac_ooc_priority(struct iwl_mvm_scan_params *params)
1432
+{
1433
+ return iwl_mvm_is_regular_scan(params) ?
1434
+ IWL_SCAN_PRIORITY_EXT_6 :
1435
+ IWL_SCAN_PRIORITY_EXT_2;
1436
+}
1437
+
1438
+static void
1439
+iwl_mvm_scan_umac_dwell_v10(struct iwl_mvm *mvm,
1440
+ struct iwl_scan_general_params_v10 *general_params,
1441
+ struct iwl_mvm_scan_params *params)
1442
+{
1443
+ struct iwl_mvm_scan_timing_params *timing, *hb_timing;
1444
+ u8 active_dwell, passive_dwell;
1445
+
1446
+ timing = &scan_timing[params->type];
1447
+ active_dwell = IWL_SCAN_DWELL_ACTIVE;
1448
+ passive_dwell = IWL_SCAN_DWELL_PASSIVE;
1449
+
1450
+ general_params->adwell_default_social_chn =
1451
+ IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;
1452
+ general_params->adwell_default_2g = IWL_SCAN_ADWELL_DEFAULT_LB_N_APS;
1453
+ general_params->adwell_default_5g = IWL_SCAN_ADWELL_DEFAULT_HB_N_APS;
1454
+
1455
+ /* if custom max budget was configured with debugfs */
1456
+ if (IWL_MVM_ADWELL_MAX_BUDGET)
1457
+ general_params->adwell_max_budget =
1458
+ cpu_to_le16(IWL_MVM_ADWELL_MAX_BUDGET);
1459
+ else if (params->ssids && params->ssids[0].ssid_len)
1460
+ general_params->adwell_max_budget =
1461
+ cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);
1462
+ else
1463
+ general_params->adwell_max_budget =
1464
+ cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN);
1465
+
1466
+ general_params->scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);
1467
+ general_params->max_out_of_time[SCAN_LB_LMAC_IDX] =
1468
+ cpu_to_le32(timing->max_out_time);
1469
+ general_params->suspend_time[SCAN_LB_LMAC_IDX] =
1470
+ cpu_to_le32(timing->suspend_time);
1471
+
1472
+ hb_timing = &scan_timing[params->hb_type];
1473
+
1474
+ general_params->max_out_of_time[SCAN_HB_LMAC_IDX] =
1475
+ cpu_to_le32(hb_timing->max_out_time);
1476
+ general_params->suspend_time[SCAN_HB_LMAC_IDX] =
1477
+ cpu_to_le32(hb_timing->suspend_time);
1478
+
1479
+ general_params->active_dwell[SCAN_LB_LMAC_IDX] = active_dwell;
1480
+ general_params->passive_dwell[SCAN_LB_LMAC_IDX] = passive_dwell;
1481
+ general_params->active_dwell[SCAN_HB_LMAC_IDX] = active_dwell;
1482
+ general_params->passive_dwell[SCAN_HB_LMAC_IDX] = passive_dwell;
1483
+}
1484
+
1485
+struct iwl_mvm_scan_channel_segment {
1486
+ u8 start_idx;
1487
+ u8 end_idx;
1488
+ u8 first_channel_id;
1489
+ u8 last_channel_id;
1490
+ u8 channel_spacing_shift;
1491
+ u8 band;
1492
+};
1493
+
1494
+static const struct iwl_mvm_scan_channel_segment scan_channel_segments[] = {
1495
+ {
1496
+ .start_idx = 0,
1497
+ .end_idx = 13,
1498
+ .first_channel_id = 1,
1499
+ .last_channel_id = 14,
1500
+ .channel_spacing_shift = 0,
1501
+ .band = PHY_BAND_24
1502
+ },
1503
+ {
1504
+ .start_idx = 14,
1505
+ .end_idx = 41,
1506
+ .first_channel_id = 36,
1507
+ .last_channel_id = 144,
1508
+ .channel_spacing_shift = 2,
1509
+ .band = PHY_BAND_5
1510
+ },
1511
+ {
1512
+ .start_idx = 42,
1513
+ .end_idx = 50,
1514
+ .first_channel_id = 149,
1515
+ .last_channel_id = 181,
1516
+ .channel_spacing_shift = 2,
1517
+ .band = PHY_BAND_5
1518
+ },
1519
+};
1520
+
1521
+static int iwl_mvm_scan_ch_and_band_to_idx(u8 channel_id, u8 band)
1522
+{
1523
+ int i, index;
1524
+
1525
+ if (!channel_id)
1526
+ return -EINVAL;
1527
+
1528
+ for (i = 0; i < ARRAY_SIZE(scan_channel_segments); i++) {
1529
+ const struct iwl_mvm_scan_channel_segment *ch_segment =
1530
+ &scan_channel_segments[i];
1531
+ u32 ch_offset;
1532
+
1533
+ if (ch_segment->band != band ||
1534
+ ch_segment->first_channel_id > channel_id ||
1535
+ ch_segment->last_channel_id < channel_id)
1536
+ continue;
1537
+
1538
+ ch_offset = (channel_id - ch_segment->first_channel_id) >>
1539
+ ch_segment->channel_spacing_shift;
1540
+
1541
+ index = scan_channel_segments[i].start_idx + ch_offset;
1542
+ if (index < IWL_SCAN_NUM_CHANNELS)
1543
+ return index;
1544
+
1545
+ break;
1546
+ }
1547
+
1548
+ return -EINVAL;
1549
+}
1550
+
1551
+static const u8 p2p_go_friendly_chs[] = {
1552
+ 36, 40, 44, 48, 149, 153, 157, 161, 165,
1553
+};
1554
+
1555
+static const u8 social_chs[] = {
1556
+ 1, 6, 11
1557
+};
1558
+
1559
+static void iwl_mvm_scan_ch_add_n_aps_override(enum nl80211_iftype vif_type,
1560
+ u8 ch_id, u8 band, u8 *ch_bitmap,
1561
+ size_t bitmap_n_entries)
1562
+{
1563
+ int i;
1564
+
1565
+ if (vif_type != NL80211_IFTYPE_P2P_DEVICE)
1566
+ return;
1567
+
1568
+ for (i = 0; i < ARRAY_SIZE(p2p_go_friendly_chs); i++) {
1569
+ if (p2p_go_friendly_chs[i] == ch_id) {
1570
+ int ch_idx, bitmap_idx;
1571
+
1572
+ ch_idx = iwl_mvm_scan_ch_and_band_to_idx(ch_id, band);
1573
+ if (ch_idx < 0)
1574
+ return;
1575
+
1576
+ bitmap_idx = ch_idx / 8;
1577
+ if (bitmap_idx >= bitmap_n_entries)
1578
+ return;
1579
+
1580
+ ch_idx = ch_idx % 8;
1581
+ ch_bitmap[bitmap_idx] |= BIT(ch_idx);
1582
+
1583
+ return;
1584
+ }
1585
+ }
1586
+}
1587
+
1588
+static u32 iwl_mvm_scan_ch_n_aps_flag(enum nl80211_iftype vif_type, u8 ch_id)
1589
+{
1590
+ int i;
1591
+ u32 flags = 0;
1592
+
1593
+ if (vif_type != NL80211_IFTYPE_P2P_DEVICE)
1594
+ goto out;
1595
+
1596
+ for (i = 0; i < ARRAY_SIZE(p2p_go_friendly_chs); i++) {
1597
+ if (p2p_go_friendly_chs[i] == ch_id) {
1598
+ flags |= IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY_BIT;
1599
+ break;
1600
+ }
1601
+ }
1602
+
1603
+ if (flags)
1604
+ goto out;
1605
+
1606
+ for (i = 0; i < ARRAY_SIZE(social_chs); i++) {
1607
+ if (social_chs[i] == ch_id) {
1608
+ flags |= IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS_BIT;
1609
+ break;
1610
+ }
1611
+ }
1612
+
1613
+out:
1614
+ return flags;
1615
+}
1616
+
13071617 static void
13081618 iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
13091619 struct ieee80211_channel **channels,
1310
- int n_channels, u32 ssid_bitmap,
1620
+ int n_channels, u32 flags,
13111621 struct iwl_scan_channel_cfg_umac *channel_cfg)
13121622 {
13131623 int i;
13141624
13151625 for (i = 0; i < n_channels; i++) {
1316
- channel_cfg[i].flags = cpu_to_le32(ssid_bitmap);
1317
- channel_cfg[i].channel_num = channels[i]->hw_value;
1318
- channel_cfg[i].iter_count = 1;
1319
- channel_cfg[i].iter_interval = 0;
1626
+ channel_cfg[i].flags = cpu_to_le32(flags);
1627
+ channel_cfg[i].v1.channel_num = channels[i]->hw_value;
1628
+ if (iwl_mvm_is_scan_ext_chan_supported(mvm)) {
1629
+ enum nl80211_band band = channels[i]->band;
1630
+
1631
+ channel_cfg[i].v2.band =
1632
+ iwl_mvm_phy_band_from_nl80211(band);
1633
+ channel_cfg[i].v2.iter_count = 1;
1634
+ channel_cfg[i].v2.iter_interval = 0;
1635
+ } else {
1636
+ channel_cfg[i].v1.iter_count = 1;
1637
+ channel_cfg[i].v1.iter_interval = 0;
1638
+ }
13201639 }
1640
+}
1641
+
1642
+static void
1643
+iwl_mvm_umac_scan_cfg_channels_v4(struct iwl_mvm *mvm,
1644
+ struct ieee80211_channel **channels,
1645
+ struct iwl_scan_channel_params_v4 *cp,
1646
+ int n_channels, u32 flags,
1647
+ enum nl80211_iftype vif_type)
1648
+{
1649
+ u8 *bitmap = cp->adwell_ch_override_bitmap;
1650
+ size_t bitmap_n_entries = ARRAY_SIZE(cp->adwell_ch_override_bitmap);
1651
+ int i;
1652
+
1653
+ for (i = 0; i < n_channels; i++) {
1654
+ enum nl80211_band band = channels[i]->band;
1655
+ struct iwl_scan_channel_cfg_umac *cfg =
1656
+ &cp->channel_config[i];
1657
+
1658
+ cfg->flags = cpu_to_le32(flags);
1659
+ cfg->v2.channel_num = channels[i]->hw_value;
1660
+ cfg->v2.band = iwl_mvm_phy_band_from_nl80211(band);
1661
+ cfg->v2.iter_count = 1;
1662
+ cfg->v2.iter_interval = 0;
1663
+
1664
+ iwl_mvm_scan_ch_add_n_aps_override(vif_type,
1665
+ cfg->v2.channel_num,
1666
+ cfg->v2.band, bitmap,
1667
+ bitmap_n_entries);
1668
+ }
1669
+}
1670
+
1671
+static void
1672
+iwl_mvm_umac_scan_cfg_channels_v6(struct iwl_mvm *mvm,
1673
+ struct ieee80211_channel **channels,
1674
+ struct iwl_scan_channel_params_v6 *cp,
1675
+ int n_channels, u32 flags,
1676
+ enum nl80211_iftype vif_type)
1677
+{
1678
+ int i;
1679
+
1680
+ for (i = 0; i < n_channels; i++) {
1681
+ enum nl80211_band band = channels[i]->band;
1682
+ struct iwl_scan_channel_cfg_umac *cfg = &cp->channel_config[i];
1683
+ u32 n_aps_flag =
1684
+ iwl_mvm_scan_ch_n_aps_flag(vif_type,
1685
+ channels[i]->hw_value);
1686
+
1687
+ cfg->flags = cpu_to_le32(flags | n_aps_flag);
1688
+ cfg->v2.channel_num = channels[i]->hw_value;
1689
+ cfg->v2.band = iwl_mvm_phy_band_from_nl80211(band);
1690
+ cfg->v2.iter_count = 1;
1691
+ cfg->v2.iter_interval = 0;
1692
+ }
1693
+}
1694
+
1695
+static u8 iwl_mvm_scan_umac_chan_flags_v2(struct iwl_mvm *mvm,
1696
+ struct iwl_mvm_scan_params *params,
1697
+ struct ieee80211_vif *vif)
1698
+{
1699
+ u8 flags = 0;
1700
+
1701
+ flags |= IWL_SCAN_CHANNEL_FLAG_ENABLE_CHAN_ORDER;
1702
+
1703
+ if (iwl_mvm_scan_use_ebs(mvm, vif))
1704
+ flags |= IWL_SCAN_CHANNEL_FLAG_EBS |
1705
+ IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
1706
+ IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
1707
+
1708
+ /* set fragmented ebs for fragmented scan on HB channels */
1709
+ if ((!iwl_mvm_is_cdb_supported(mvm) &&
1710
+ iwl_mvm_is_scan_fragmented(params->type)) ||
1711
+ (iwl_mvm_is_cdb_supported(mvm) &&
1712
+ iwl_mvm_is_scan_fragmented(params->hb_type)))
1713
+ flags |= IWL_SCAN_CHANNEL_FLAG_EBS_FRAG;
1714
+
1715
+ return flags;
1716
+}
1717
+
1718
+static u16 iwl_mvm_scan_umac_flags_v2(struct iwl_mvm *mvm,
1719
+ struct iwl_mvm_scan_params *params,
1720
+ struct ieee80211_vif *vif,
1721
+ int type)
1722
+{
1723
+ u16 flags = 0;
1724
+
1725
+ if (params->n_ssids == 0)
1726
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE;
1727
+
1728
+ if (iwl_mvm_is_scan_fragmented(params->type))
1729
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1;
1730
+
1731
+ if (iwl_mvm_is_scan_fragmented(params->hb_type))
1732
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2;
1733
+
1734
+ if (params->pass_all)
1735
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_PASS_ALL;
1736
+ else
1737
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_MATCH;
1738
+
1739
+ if (!iwl_mvm_is_regular_scan(params))
1740
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_PERIODIC;
1741
+
1742
+ if (params->iter_notif ||
1743
+ mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED)
1744
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_NTFY_ITER_COMPLETE;
1745
+
1746
+ if (IWL_MVM_ADWELL_ENABLE)
1747
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_ADAPTIVE_DWELL;
1748
+
1749
+ if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT)
1750
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_PREEMPTIVE;
1751
+
1752
+ return flags;
13211753 }
13221754
13231755 static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
....@@ -1332,11 +1764,11 @@
13321764 if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0)
13331765 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT;
13341766
1335
- if (params->type == IWL_SCAN_TYPE_FRAGMENTED)
1767
+ if (iwl_mvm_is_scan_fragmented(params->type))
13361768 flags |= IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED;
13371769
13381770 if (iwl_mvm_is_cdb_supported(mvm) &&
1339
- params->hb_type == IWL_SCAN_TYPE_FRAGMENTED)
1771
+ iwl_mvm_is_scan_fragmented(params->hb_type))
13401772 flags |= IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED;
13411773
13421774 if (iwl_mvm_rrm_scan_needed(mvm) &&
....@@ -1352,7 +1784,7 @@
13521784 if (!iwl_mvm_is_regular_scan(params))
13531785 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC;
13541786
1355
- if (params->measurement_dwell)
1787
+ if (params->iter_notif)
13561788 flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;
13571789
13581790 #ifdef CONFIG_IWLWIFI_DEBUGFS
....@@ -1363,8 +1795,7 @@
13631795 if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED)
13641796 flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;
13651797
1366
- if (iwl_mvm_is_adaptive_dwell_supported(mvm) && IWL_MVM_ADWELL_ENABLE &&
1367
- vif->type != NL80211_IFTYPE_P2P_DEVICE)
1798
+ if (iwl_mvm_is_adaptive_dwell_supported(mvm) && IWL_MVM_ADWELL_ENABLE)
13681799 flags |= IWL_UMAC_SCAN_GEN_FLAGS_ADAPTIVE_DWELL;
13691800
13701801 /*
....@@ -1374,7 +1805,7 @@
13741805 */
13751806 if (iwl_mvm_is_regular_scan(params) &&
13761807 vif->type != NL80211_IFTYPE_P2P_DEVICE &&
1377
- params->type != IWL_SCAN_TYPE_FRAGMENTED &&
1808
+ !iwl_mvm_is_scan_fragmented(params->type) &&
13781809 !iwl_mvm_is_adaptive_dwell_supported(mvm) &&
13791810 !iwl_mvm_is_oce_supported(mvm))
13801811 flags |= IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL;
....@@ -1399,34 +1830,59 @@
13991830 return flags;
14001831 }
14011832
1833
+static int
1834
+iwl_mvm_fill_scan_sched_params(struct iwl_mvm_scan_params *params,
1835
+ struct iwl_scan_umac_schedule *schedule,
1836
+ __le16 *delay)
1837
+{
1838
+ int i;
1839
+ if (WARN_ON(!params->n_scan_plans ||
1840
+ params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))
1841
+ return -EINVAL;
1842
+
1843
+ for (i = 0; i < params->n_scan_plans; i++) {
1844
+ struct cfg80211_sched_scan_plan *scan_plan =
1845
+ &params->scan_plans[i];
1846
+
1847
+ schedule[i].iter_count = scan_plan->iterations;
1848
+ schedule[i].interval =
1849
+ cpu_to_le16(scan_plan->interval);
1850
+ }
1851
+
1852
+ /*
1853
+ * If the number of iterations of the last scan plan is set to
1854
+ * zero, it should run infinitely. However, this is not always the case.
1855
+ * For example, when regular scan is requested the driver sets one scan
1856
+ * plan with one iteration.
1857
+ */
1858
+ if (!schedule[params->n_scan_plans - 1].iter_count)
1859
+ schedule[params->n_scan_plans - 1].iter_count = 0xff;
1860
+
1861
+ *delay = cpu_to_le16(params->delay);
1862
+
1863
+ return 0;
1864
+}
1865
+
14021866 static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
14031867 struct iwl_mvm_scan_params *params,
1404
- int type)
1868
+ int type, int uid)
14051869 {
14061870 struct iwl_scan_req_umac *cmd = mvm->scan_cmd;
14071871 struct iwl_scan_umac_chan_param *chan_param;
14081872 void *cmd_data = iwl_mvm_get_scan_req_umac_data(mvm);
1409
- struct iwl_scan_req_umac_tail *sec_part = cmd_data +
1410
- sizeof(struct iwl_scan_channel_cfg_umac) *
1411
- mvm->fw->ucode_capa.n_scan_channels;
1412
- int uid, i;
1873
+ void *sec_part = cmd_data + sizeof(struct iwl_scan_channel_cfg_umac) *
1874
+ mvm->fw->ucode_capa.n_scan_channels;
1875
+ struct iwl_scan_req_umac_tail_v2 *tail_v2 =
1876
+ (struct iwl_scan_req_umac_tail_v2 *)sec_part;
1877
+ struct iwl_scan_req_umac_tail_v1 *tail_v1;
1878
+ struct iwl_ssid_ie *direct_scan;
1879
+ int ret = 0;
14131880 u32 ssid_bitmap = 0;
14141881 u8 channel_flags = 0;
14151882 u16 gen_flags;
14161883 struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);
14171884
14181885 chan_param = iwl_mvm_get_scan_req_umac_channel(mvm);
1419
-
1420
- lockdep_assert_held(&mvm->mutex);
1421
-
1422
- if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))
1423
- return -EINVAL;
1424
-
1425
- uid = iwl_mvm_scan_uid_by_status(mvm, 0);
1426
- if (uid < 0)
1427
- return uid;
1428
-
1429
- memset(cmd, 0, ksize(cmd));
14301886
14311887 iwl_mvm_scan_umac_dwell(mvm, cmd, params);
14321888
....@@ -1442,6 +1898,9 @@
14421898 if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED)
14431899 cmd->v8.num_of_fragments[SCAN_HB_LMAC_IDX] =
14441900 IWL_SCAN_NUM_OF_FRAGS;
1901
+
1902
+ cmd->v8.general_flags2 =
1903
+ IWL_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER;
14451904 }
14461905
14471906 cmd->scan_start_mac_id = scan_vif->id;
....@@ -1449,40 +1908,181 @@
14491908 if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT)
14501909 cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);
14511910
1452
- if (iwl_mvm_scan_use_ebs(mvm, vif))
1911
+ if (iwl_mvm_scan_use_ebs(mvm, vif)) {
14531912 channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS |
14541913 IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
14551914 IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
14561915
1916
+ /* set fragmented ebs for fragmented scan on HB channels */
1917
+ if (iwl_mvm_is_frag_ebs_supported(mvm)) {
1918
+ if (gen_flags &
1919
+ IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED ||
1920
+ (!iwl_mvm_is_cdb_supported(mvm) &&
1921
+ gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED))
1922
+ channel_flags |= IWL_SCAN_CHANNEL_FLAG_EBS_FRAG;
1923
+ }
1924
+ }
1925
+
14571926 chan_param->flags = channel_flags;
14581927 chan_param->count = params->n_channels;
14591928
1460
- iwl_scan_build_ssids(params, sec_part->direct_scan, &ssid_bitmap);
1929
+ ret = iwl_mvm_fill_scan_sched_params(params, tail_v2->schedule,
1930
+ &tail_v2->delay);
1931
+ if (ret)
1932
+ return ret;
14611933
1934
+ if (iwl_mvm_is_scan_ext_chan_supported(mvm)) {
1935
+ tail_v2->preq = params->preq;
1936
+ direct_scan = tail_v2->direct_scan;
1937
+ } else {
1938
+ tail_v1 = (struct iwl_scan_req_umac_tail_v1 *)sec_part;
1939
+ iwl_mvm_scan_set_legacy_probe_req(&tail_v1->preq,
1940
+ &params->preq);
1941
+ direct_scan = tail_v1->direct_scan;
1942
+ }
1943
+ iwl_scan_build_ssids(params, direct_scan, &ssid_bitmap);
14621944 iwl_mvm_umac_scan_cfg_channels(mvm, params->channels,
14631945 params->n_channels, ssid_bitmap,
14641946 cmd_data);
1947
+ return 0;
1948
+}
14651949
1466
- for (i = 0; i < params->n_scan_plans; i++) {
1467
- struct cfg80211_sched_scan_plan *scan_plan =
1468
- &params->scan_plans[i];
1950
+static void
1951
+iwl_mvm_scan_umac_fill_general_p_v10(struct iwl_mvm *mvm,
1952
+ struct iwl_mvm_scan_params *params,
1953
+ struct ieee80211_vif *vif,
1954
+ struct iwl_scan_general_params_v10 *gp,
1955
+ u16 gen_flags)
1956
+{
1957
+ struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);
14691958
1470
- sec_part->schedule[i].iter_count = scan_plan->iterations;
1471
- sec_part->schedule[i].interval =
1472
- cpu_to_le16(scan_plan->interval);
1473
- }
1959
+ iwl_mvm_scan_umac_dwell_v10(mvm, gp, params);
14741960
1475
- /*
1476
- * If the number of iterations of the last scan plan is set to
1477
- * zero, it should run infinitely. However, this is not always the case.
1478
- * For example, when regular scan is requested the driver sets one scan
1479
- * plan with one iteration.
1480
- */
1481
- if (!sec_part->schedule[i - 1].iter_count)
1482
- sec_part->schedule[i - 1].iter_count = 0xff;
1961
+ gp->flags = cpu_to_le16(gen_flags);
14831962
1484
- sec_part->delay = cpu_to_le16(params->delay);
1485
- sec_part->preq = params->preq;
1963
+ if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1)
1964
+ gp->num_of_fragments[SCAN_LB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS;
1965
+ if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2)
1966
+ gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS;
1967
+
1968
+ gp->scan_start_mac_id = scan_vif->id;
1969
+}
1970
+
1971
+static void
1972
+iwl_mvm_scan_umac_fill_probe_p_v3(struct iwl_mvm_scan_params *params,
1973
+ struct iwl_scan_probe_params_v3 *pp)
1974
+{
1975
+ pp->preq = params->preq;
1976
+ pp->ssid_num = params->n_ssids;
1977
+ iwl_scan_build_ssids(params, pp->direct_scan, NULL);
1978
+}
1979
+
1980
+static void
1981
+iwl_mvm_scan_umac_fill_probe_p_v4(struct iwl_mvm_scan_params *params,
1982
+ struct iwl_scan_probe_params_v4 *pp,
1983
+ u32 *bitmap_ssid)
1984
+{
1985
+ pp->preq = params->preq;
1986
+ iwl_scan_build_ssids(params, pp->direct_scan, bitmap_ssid);
1987
+}
1988
+
1989
+static void
1990
+iwl_mvm_scan_umac_fill_ch_p_v4(struct iwl_mvm *mvm,
1991
+ struct iwl_mvm_scan_params *params,
1992
+ struct ieee80211_vif *vif,
1993
+ struct iwl_scan_channel_params_v4 *cp,
1994
+ u32 channel_cfg_flags)
1995
+{
1996
+ cp->flags = iwl_mvm_scan_umac_chan_flags_v2(mvm, params, vif);
1997
+ cp->count = params->n_channels;
1998
+ cp->num_of_aps_override = IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY;
1999
+
2000
+ iwl_mvm_umac_scan_cfg_channels_v4(mvm, params->channels, cp,
2001
+ params->n_channels,
2002
+ channel_cfg_flags,
2003
+ vif->type);
2004
+}
2005
+
2006
+static void
2007
+iwl_mvm_scan_umac_fill_ch_p_v6(struct iwl_mvm *mvm,
2008
+ struct iwl_mvm_scan_params *params,
2009
+ struct ieee80211_vif *vif,
2010
+ struct iwl_scan_channel_params_v6 *cp,
2011
+ u32 channel_cfg_flags)
2012
+{
2013
+ cp->flags = iwl_mvm_scan_umac_chan_flags_v2(mvm, params, vif);
2014
+ cp->count = params->n_channels;
2015
+ cp->n_aps_override[0] = IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY;
2016
+ cp->n_aps_override[1] = IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS;
2017
+
2018
+ iwl_mvm_umac_scan_cfg_channels_v6(mvm, params->channels, cp,
2019
+ params->n_channels,
2020
+ channel_cfg_flags,
2021
+ vif->type);
2022
+}
2023
+
2024
+static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
2025
+ struct iwl_mvm_scan_params *params, int type,
2026
+ int uid)
2027
+{
2028
+ struct iwl_scan_req_umac_v12 *cmd = mvm->scan_cmd;
2029
+ struct iwl_scan_req_params_v12 *scan_p = &cmd->scan_params;
2030
+ int ret;
2031
+ u16 gen_flags;
2032
+
2033
+ mvm->scan_uid_status[uid] = type;
2034
+
2035
+ cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(params));
2036
+ cmd->uid = cpu_to_le32(uid);
2037
+
2038
+ gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
2039
+ iwl_mvm_scan_umac_fill_general_p_v10(mvm, params, vif,
2040
+ &scan_p->general_params,
2041
+ gen_flags);
2042
+
2043
+ ret = iwl_mvm_fill_scan_sched_params(params,
2044
+ scan_p->periodic_params.schedule,
2045
+ &scan_p->periodic_params.delay);
2046
+ if (ret)
2047
+ return ret;
2048
+
2049
+ iwl_mvm_scan_umac_fill_probe_p_v3(params, &scan_p->probe_params);
2050
+ iwl_mvm_scan_umac_fill_ch_p_v4(mvm, params, vif,
2051
+ &scan_p->channel_params, 0);
2052
+
2053
+ return 0;
2054
+}
2055
+
2056
+static int iwl_mvm_scan_umac_v14(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
2057
+ struct iwl_mvm_scan_params *params, int type,
2058
+ int uid)
2059
+{
2060
+ struct iwl_scan_req_umac_v14 *cmd = mvm->scan_cmd;
2061
+ struct iwl_scan_req_params_v14 *scan_p = &cmd->scan_params;
2062
+ int ret;
2063
+ u16 gen_flags;
2064
+ u32 bitmap_ssid = 0;
2065
+
2066
+ mvm->scan_uid_status[uid] = type;
2067
+
2068
+ cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(params));
2069
+ cmd->uid = cpu_to_le32(uid);
2070
+
2071
+ gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
2072
+ iwl_mvm_scan_umac_fill_general_p_v10(mvm, params, vif,
2073
+ &scan_p->general_params,
2074
+ gen_flags);
2075
+
2076
+ ret = iwl_mvm_fill_scan_sched_params(params,
2077
+ scan_p->periodic_params.schedule,
2078
+ &scan_p->periodic_params.delay);
2079
+ if (ret)
2080
+ return ret;
2081
+
2082
+ iwl_mvm_scan_umac_fill_probe_p_v4(params, &scan_p->probe_params,
2083
+ &bitmap_ssid);
2084
+ iwl_mvm_scan_umac_fill_ch_p_v6(mvm, params, vif,
2085
+ &scan_p->channel_params, bitmap_ssid);
14862086
14872087 return 0;
14882088 }
....@@ -1506,6 +2106,11 @@
15062106 * compatibility with old wpa_supplicant that wouldn't stop a
15072107 * scheduled scan before starting a normal scan.
15082108 */
2109
+
2110
+ /* FW supports only a single periodic scan */
2111
+ if ((type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT) &&
2112
+ mvm->scan_status & (IWL_MVM_SCAN_SCHED | IWL_MVM_SCAN_NETDETECT))
2113
+ return -EBUSY;
15092114
15102115 if (iwl_mvm_num_scans(mvm) < mvm->max_scans)
15112116 return 0;
....@@ -1543,10 +2148,10 @@
15432148 if (mvm->scan_status & IWL_MVM_SCAN_SCHED_MASK)
15442149 return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED,
15452150 true);
1546
-
1547
- /* fall through, something is wrong if no scan was
1548
- * running but we ran out of scans.
2151
+ /* Something is wrong if no scan was running but we
2152
+ * ran out of scans.
15492153 */
2154
+ /* fall through */
15502155 default:
15512156 WARN_ON(1);
15522157 break;
....@@ -1570,19 +2175,78 @@
15702175
15712176 static void iwl_mvm_fill_scan_type(struct iwl_mvm *mvm,
15722177 struct iwl_mvm_scan_params *params,
1573
- bool p2p)
2178
+ struct ieee80211_vif *vif)
15742179 {
15752180 if (iwl_mvm_is_cdb_supported(mvm)) {
15762181 params->type =
1577
- iwl_mvm_get_scan_type_band(mvm, p2p,
2182
+ iwl_mvm_get_scan_type_band(mvm, vif,
15782183 NL80211_BAND_2GHZ);
15792184 params->hb_type =
1580
- iwl_mvm_get_scan_type_band(mvm, p2p,
2185
+ iwl_mvm_get_scan_type_band(mvm, vif,
15812186 NL80211_BAND_5GHZ);
15822187 } else {
1583
- params->type = iwl_mvm_get_scan_type(mvm, p2p);
2188
+ params->type = iwl_mvm_get_scan_type(mvm, vif);
15842189 }
15852190 }
2191
+
2192
+struct iwl_scan_umac_handler {
2193
+ u8 version;
2194
+ int (*handler)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
2195
+ struct iwl_mvm_scan_params *params, int type, int uid);
2196
+};
2197
+
2198
+#define IWL_SCAN_UMAC_HANDLER(_ver) { \
2199
+ .version = _ver, \
2200
+ .handler = iwl_mvm_scan_umac_v##_ver, \
2201
+}
2202
+
2203
+static const struct iwl_scan_umac_handler iwl_scan_umac_handlers[] = {
2204
+ /* set the newest version first to shorten the list traverse time */
2205
+ IWL_SCAN_UMAC_HANDLER(14),
2206
+ IWL_SCAN_UMAC_HANDLER(12),
2207
+};
2208
+
2209
+static int iwl_mvm_build_scan_cmd(struct iwl_mvm *mvm,
2210
+ struct ieee80211_vif *vif,
2211
+ struct iwl_host_cmd *hcmd,
2212
+ struct iwl_mvm_scan_params *params,
2213
+ int type)
2214
+{
2215
+ int uid, i;
2216
+ u8 scan_ver;
2217
+
2218
+ lockdep_assert_held(&mvm->mutex);
2219
+ memset(mvm->scan_cmd, 0, ksize(mvm->scan_cmd));
2220
+
2221
+ if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
2222
+ hcmd->id = SCAN_OFFLOAD_REQUEST_CMD;
2223
+
2224
+ return iwl_mvm_scan_lmac(mvm, vif, params);
2225
+ }
2226
+
2227
+ uid = iwl_mvm_scan_uid_by_status(mvm, 0);
2228
+ if (uid < 0)
2229
+ return uid;
2230
+
2231
+ hcmd->id = iwl_cmd_id(SCAN_REQ_UMAC, IWL_ALWAYS_LONG_GROUP, 0);
2232
+
2233
+ scan_ver = iwl_fw_lookup_cmd_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
2234
+ SCAN_REQ_UMAC,
2235
+ IWL_FW_CMD_VER_UNKNOWN);
2236
+
2237
+ for (i = 0; i < ARRAY_SIZE(iwl_scan_umac_handlers); i++) {
2238
+ const struct iwl_scan_umac_handler *ver_handler =
2239
+ &iwl_scan_umac_handlers[i];
2240
+
2241
+ if (ver_handler->version != scan_ver)
2242
+ continue;
2243
+
2244
+ return ver_handler->handler(mvm, vif, params, type, uid);
2245
+ }
2246
+
2247
+ return iwl_mvm_scan_umac(mvm, vif, params, type, uid);
2248
+}
2249
+
15862250 int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
15872251 struct cfg80211_scan_request *req,
15882252 struct ieee80211_scan_ies *ies)
....@@ -1630,25 +2294,15 @@
16302294 params.scan_plans = &scan_plan;
16312295 params.n_scan_plans = 1;
16322296
1633
- iwl_mvm_fill_scan_type(mvm, &params,
1634
- vif->type == NL80211_IFTYPE_P2P_DEVICE);
2297
+ iwl_mvm_fill_scan_type(mvm, &params, vif);
16352298
1636
- ret = iwl_mvm_get_measurement_dwell(mvm, req, &params);
1637
- if (ret < 0)
1638
- return ret;
1639
-
1640
- params.measurement_dwell = ret;
2299
+ if (req->duration)
2300
+ params.iter_notif = true;
16412301
16422302 iwl_mvm_build_scan_probe(mvm, vif, ies, &params);
16432303
1644
- if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
1645
- hcmd.id = iwl_cmd_id(SCAN_REQ_UMAC, IWL_ALWAYS_LONG_GROUP, 0);
1646
- ret = iwl_mvm_scan_umac(mvm, vif, &params,
1647
- IWL_MVM_SCAN_REGULAR);
1648
- } else {
1649
- hcmd.id = SCAN_OFFLOAD_REQUEST_CMD;
1650
- ret = iwl_mvm_scan_lmac(mvm, vif, &params);
1651
- }
2304
+ ret = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, &params,
2305
+ IWL_MVM_SCAN_REGULAR);
16522306
16532307 if (ret)
16542308 return ret;
....@@ -1669,7 +2323,6 @@
16692323 IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
16702324 mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
16712325 mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
1672
- iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
16732326
16742327 schedule_delayed_work(&mvm->scan_timeout_dwork,
16752328 msecs_to_jiffies(SCAN_TIMEOUT));
....@@ -1726,8 +2379,7 @@
17262379 params.n_scan_plans = req->n_scan_plans;
17272380 params.scan_plans = req->scan_plans;
17282381
1729
- iwl_mvm_fill_scan_type(mvm, &params,
1730
- vif->type == NL80211_IFTYPE_P2P_DEVICE);
2382
+ iwl_mvm_fill_scan_type(mvm, &params, vif);
17312383
17322384 /* In theory, LMAC scans can handle a 32-bit delay, but since
17332385 * waiting for over 18 hours to start the scan is a bit silly
....@@ -1748,13 +2400,7 @@
17482400
17492401 iwl_mvm_build_scan_probe(mvm, vif, ies, &params);
17502402
1751
- if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
1752
- hcmd.id = iwl_cmd_id(SCAN_REQ_UMAC, IWL_ALWAYS_LONG_GROUP, 0);
1753
- ret = iwl_mvm_scan_umac(mvm, vif, &params, type);
1754
- } else {
1755
- hcmd.id = SCAN_OFFLOAD_REQUEST_CMD;
1756
- ret = iwl_mvm_scan_lmac(mvm, vif, &params);
1757
- }
2403
+ ret = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, &params, type);
17582404
17592405 if (ret)
17602406 return ret;
....@@ -1796,7 +2442,6 @@
17962442 memcpy(info.tsf_bssid, mvm->scan_vif->bssid, ETH_ALEN);
17972443 ieee80211_scan_completed(mvm->hw, &info);
17982444 mvm->scan_vif = NULL;
1799
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
18002445 cancel_delayed_work(&mvm->scan_timeout_dwork);
18012446 iwl_mvm_resume_tcm(mvm);
18022447 } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
....@@ -1902,14 +2547,35 @@
19022547 return ret;
19032548 }
19042549
1905
- ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
2550
+ return iwl_wait_notification(&mvm->notif_wait, &wait_scan_done,
2551
+ 1 * HZ);
2552
+}
19062553
1907
- return ret;
2554
+#define IWL_SCAN_REQ_UMAC_HANDLE_SIZE(_ver) { \
2555
+ case (_ver): return sizeof(struct iwl_scan_req_umac_v##_ver); \
2556
+}
2557
+
2558
+static int iwl_scan_req_umac_get_size(u8 scan_ver)
2559
+{
2560
+ switch (scan_ver) {
2561
+ IWL_SCAN_REQ_UMAC_HANDLE_SIZE(14);
2562
+ IWL_SCAN_REQ_UMAC_HANDLE_SIZE(12);
2563
+ }
2564
+
2565
+ return 0;
19082566 }
19092567
19102568 int iwl_mvm_scan_size(struct iwl_mvm *mvm)
19112569 {
1912
- int base_size = IWL_SCAN_REQ_UMAC_SIZE_V1;
2570
+ int base_size, tail_size;
2571
+ u8 scan_ver = iwl_fw_lookup_cmd_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
2572
+ SCAN_REQ_UMAC,
2573
+ IWL_FW_CMD_VER_UNKNOWN);
2574
+
2575
+ base_size = iwl_scan_req_umac_get_size(scan_ver);
2576
+ if (base_size)
2577
+ return base_size;
2578
+
19132579
19142580 if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm))
19152581 base_size = IWL_SCAN_REQ_UMAC_SIZE_V8;
....@@ -1917,17 +2583,24 @@
19172583 base_size = IWL_SCAN_REQ_UMAC_SIZE_V7;
19182584 else if (iwl_mvm_cdb_scan_api(mvm))
19192585 base_size = IWL_SCAN_REQ_UMAC_SIZE_V6;
2586
+ else
2587
+ base_size = IWL_SCAN_REQ_UMAC_SIZE_V1;
19202588
1921
- if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN))
2589
+ if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
2590
+ if (iwl_mvm_is_scan_ext_chan_supported(mvm))
2591
+ tail_size = sizeof(struct iwl_scan_req_umac_tail_v2);
2592
+ else
2593
+ tail_size = sizeof(struct iwl_scan_req_umac_tail_v1);
2594
+
19222595 return base_size +
19232596 sizeof(struct iwl_scan_channel_cfg_umac) *
19242597 mvm->fw->ucode_capa.n_scan_channels +
1925
- sizeof(struct iwl_scan_req_umac_tail);
1926
-
2598
+ tail_size;
2599
+ }
19272600 return sizeof(struct iwl_scan_req_lmac) +
19282601 sizeof(struct iwl_scan_channel_cfg_lmac) *
19292602 mvm->fw->ucode_capa.n_scan_channels +
1930
- sizeof(struct iwl_scan_probe_req);
2603
+ sizeof(struct iwl_scan_probe_req_v1);
19312604 }
19322605
19332606 /*
....@@ -1954,6 +2627,15 @@
19542627 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
19552628 mvm->scan_uid_status[uid] = 0;
19562629 }
2630
+ uid = iwl_mvm_scan_uid_by_status(mvm,
2631
+ IWL_MVM_SCAN_STOPPING_REGULAR);
2632
+ if (uid >= 0)
2633
+ mvm->scan_uid_status[uid] = 0;
2634
+
2635
+ uid = iwl_mvm_scan_uid_by_status(mvm,
2636
+ IWL_MVM_SCAN_STOPPING_SCHED);
2637
+ if (uid >= 0)
2638
+ mvm->scan_uid_status[uid] = 0;
19572639
19582640 /* We shouldn't have any UIDs still set. Loop over all the
19592641 * UIDs to make sure there's nothing left there and warn if
....@@ -2010,10 +2692,6 @@
20102692 mvm->scan_status &= ~type;
20112693
20122694 if (type == IWL_MVM_SCAN_REGULAR) {
2013
- /* Since the rx handler won't do anything now, we have
2014
- * to release the scan reference here.
2015
- */
2016
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
20172695 cancel_delayed_work(&mvm->scan_timeout_dwork);
20182696 if (notify) {
20192697 struct cfg80211_scan_info info = {