.. | .. |
---|
8 | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
---|
9 | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
---|
10 | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
---|
11 | | - * Copyright(c) 2018 Intel Corporation |
---|
| 11 | + * Copyright(c) 2018 - 2019 Intel Corporation |
---|
12 | 12 | * |
---|
13 | 13 | * This program is free software; you can redistribute it and/or modify |
---|
14 | 14 | * it under the terms of version 2 of the GNU General Public License as |
---|
.. | .. |
---|
18 | 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
19 | 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
20 | 20 | * 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 |
---|
24 | 21 | * |
---|
25 | 22 | * The full GNU General Public License is included in this distribution |
---|
26 | 23 | * in the file called COPYING. |
---|
.. | .. |
---|
34 | 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
---|
35 | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
---|
36 | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
---|
37 | | - * Copyright(c) 2018 Intel Corporation |
---|
| 34 | + * Copyright(c) 2018 - 2019 Intel Corporation |
---|
38 | 35 | * All rights reserved. |
---|
39 | 36 | * |
---|
40 | 37 | * Redistribution and use in source and binary forms, with or without |
---|
.. | .. |
---|
80 | 77 | #define IWL_SCAN_DWELL_FRAGMENTED 44 |
---|
81 | 78 | #define IWL_SCAN_DWELL_EXTENDED 90 |
---|
82 | 79 | #define IWL_SCAN_NUM_OF_FRAGS 3 |
---|
83 | | - |
---|
| 80 | +#define IWL_SCAN_LAST_2_4_CHN 14 |
---|
84 | 81 | |
---|
85 | 82 | /* adaptive dwell max budget time [TU] for full scan */ |
---|
86 | 83 | #define IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300 |
---|
87 | 84 | /* adaptive dwell max budget time [TU] for directed scan */ |
---|
88 | 85 | #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 |
---|
91 | 90 | /* adaptive dwell default APs number in social channels (1, 6, 11) */ |
---|
92 | 91 | #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 |
---|
93 | 102 | |
---|
94 | 103 | struct iwl_mvm_scan_timing_params { |
---|
95 | 104 | u32 suspend_time; |
---|
.. | .. |
---|
113 | 122 | .suspend_time = 95, |
---|
114 | 123 | .max_out_time = 44, |
---|
115 | 124 | }, |
---|
| 125 | + [IWL_SCAN_TYPE_FAST_BALANCE] = { |
---|
| 126 | + .suspend_time = 30, |
---|
| 127 | + .max_out_time = 37, |
---|
| 128 | + }, |
---|
116 | 129 | }; |
---|
117 | 130 | |
---|
118 | 131 | struct iwl_mvm_scan_params { |
---|
.. | .. |
---|
134 | 147 | struct cfg80211_match_set *match_sets; |
---|
135 | 148 | int n_scan_plans; |
---|
136 | 149 | struct cfg80211_sched_scan_plan *scan_plans; |
---|
137 | | - u32 measurement_dwell; |
---|
| 150 | + bool iter_notif; |
---|
138 | 151 | }; |
---|
139 | 152 | |
---|
140 | 153 | static inline void *iwl_mvm_get_scan_req_umac_data(struct iwl_mvm *mvm) |
---|
.. | .. |
---|
190 | 203 | return cpu_to_le16(rx_chain); |
---|
191 | 204 | } |
---|
192 | 205 | |
---|
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 | | - |
---|
201 | 206 | static inline __le32 |
---|
202 | 207 | iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum nl80211_band band, |
---|
203 | 208 | bool no_cck) |
---|
204 | 209 | { |
---|
205 | 210 | u32 tx_ant; |
---|
206 | 211 | |
---|
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); |
---|
210 | 213 | tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS; |
---|
211 | 214 | |
---|
212 | 215 | if (band == NL80211_BAND_2GHZ && !no_cck) |
---|
.. | .. |
---|
238 | 241 | return mvm->tcm.result.band_load[band]; |
---|
239 | 242 | } |
---|
240 | 243 | |
---|
| 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 | + |
---|
241 | 267 | 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, |
---|
243 | 270 | enum iwl_mvm_traffic_load load, |
---|
244 | 271 | bool low_latency) |
---|
245 | 272 | { |
---|
.. | .. |
---|
252 | 279 | if (!global_cnt) |
---|
253 | 280 | return IWL_SCAN_TYPE_UNASSOC; |
---|
254 | 281 | |
---|
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 | + } |
---|
258 | 306 | |
---|
259 | 307 | if (load >= IWL_MVM_TRAFFIC_MEDIUM || low_latency) |
---|
260 | 308 | return IWL_SCAN_TYPE_MILD; |
---|
.. | .. |
---|
263 | 311 | } |
---|
264 | 312 | |
---|
265 | 313 | 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) |
---|
267 | 316 | { |
---|
268 | 317 | enum iwl_mvm_traffic_load load; |
---|
269 | 318 | bool low_latency; |
---|
.. | .. |
---|
271 | 320 | load = iwl_mvm_get_traffic_load(mvm); |
---|
272 | 321 | low_latency = iwl_mvm_low_latency(mvm); |
---|
273 | 322 | |
---|
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); |
---|
275 | 324 | } |
---|
276 | 325 | |
---|
277 | 326 | static enum |
---|
278 | 327 | iwl_mvm_scan_type iwl_mvm_get_scan_type_band(struct iwl_mvm *mvm, |
---|
279 | | - bool p2p_device, |
---|
| 328 | + struct ieee80211_vif *vif, |
---|
280 | 329 | enum nl80211_band band) |
---|
281 | 330 | { |
---|
282 | 331 | enum iwl_mvm_traffic_load load; |
---|
.. | .. |
---|
285 | 334 | load = iwl_mvm_get_traffic_load_band(mvm, band); |
---|
286 | 335 | low_latency = iwl_mvm_low_latency_band(mvm, band); |
---|
287 | 336 | |
---|
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); |
---|
316 | 338 | } |
---|
317 | 339 | |
---|
318 | 340 | static inline bool iwl_mvm_rrm_scan_needed(struct iwl_mvm *mvm) |
---|
.. | .. |
---|
465 | 487 | |
---|
466 | 488 | mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR; |
---|
467 | 489 | ieee80211_scan_completed(mvm->hw, &info); |
---|
468 | | - iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
---|
469 | 490 | cancel_delayed_work(&mvm->scan_timeout_dwork); |
---|
470 | 491 | iwl_mvm_resume_tcm(mvm); |
---|
471 | 492 | } else { |
---|
.. | .. |
---|
501 | 522 | { |
---|
502 | 523 | int i, j; |
---|
503 | 524 | int index; |
---|
| 525 | + u32 tmp_bitmap = 0; |
---|
504 | 526 | |
---|
505 | 527 | /* |
---|
506 | 528 | * copy SSIDs from match list. |
---|
.. | .. |
---|
520 | 542 | } |
---|
521 | 543 | |
---|
522 | 544 | /* add SSIDs from scan SSID list */ |
---|
523 | | - *ssid_bitmap = 0; |
---|
524 | 545 | for (j = params->n_ssids - 1; |
---|
525 | 546 | j >= 0 && i < PROBE_OPTION_MAX; |
---|
526 | 547 | i++, j--) { |
---|
.. | .. |
---|
532 | 553 | ssids[i].len = params->ssids[j].ssid_len; |
---|
533 | 554 | memcpy(ssids[i].ssid, params->ssids[j].ssid, |
---|
534 | 555 | ssids[i].len); |
---|
535 | | - *ssid_bitmap |= BIT(i); |
---|
| 556 | + tmp_bitmap |= BIT(i); |
---|
536 | 557 | } else { |
---|
537 | | - *ssid_bitmap |= BIT(index); |
---|
| 558 | + tmp_bitmap |= BIT(index); |
---|
538 | 559 | } |
---|
539 | 560 | } |
---|
| 561 | + if (ssid_bitmap) |
---|
| 562 | + *ssid_bitmap = tmp_bitmap; |
---|
540 | 563 | } |
---|
541 | 564 | |
---|
542 | 565 | static int |
---|
.. | .. |
---|
544 | 567 | struct cfg80211_sched_scan_request *req) |
---|
545 | 568 | { |
---|
546 | 569 | 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; |
---|
549 | 576 | struct iwl_host_cmd cmd = { |
---|
550 | 577 | .id = SCAN_OFFLOAD_UPDATE_PROFILES_CMD, |
---|
551 | | - .len[1] = sizeof(*profile_cfg), |
---|
| 578 | + .len[1] = profile_cfg_size, |
---|
552 | 579 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, |
---|
553 | 580 | .dataflags[1] = IWL_HCMD_DFL_NOCOPY, |
---|
554 | 581 | }; |
---|
555 | | - int blacklist_len; |
---|
| 582 | + int blocklist_len; |
---|
556 | 583 | int i; |
---|
557 | 584 | int ret; |
---|
558 | 585 | |
---|
559 | | - if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES)) |
---|
| 586 | + if (WARN_ON(req->n_match_sets > max_profiles)) |
---|
560 | 587 | return -EIO; |
---|
561 | 588 | |
---|
562 | 589 | 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; |
---|
564 | 591 | else |
---|
565 | | - blacklist_len = IWL_SCAN_MAX_BLACKLIST_LEN; |
---|
| 592 | + blocklist_len = IWL_SCAN_MAX_BLACKLIST_LEN; |
---|
566 | 593 | |
---|
567 | | - blacklist = kcalloc(blacklist_len, sizeof(*blacklist), GFP_KERNEL); |
---|
568 | | - if (!blacklist) |
---|
| 594 | + blocklist = kcalloc(blocklist_len, sizeof(*blocklist), GFP_KERNEL); |
---|
| 595 | + if (!blocklist) |
---|
569 | 596 | return -ENOMEM; |
---|
570 | 597 | |
---|
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) { |
---|
573 | 600 | ret = -ENOMEM; |
---|
574 | | - goto free_blacklist; |
---|
| 601 | + goto free_blocklist; |
---|
575 | 602 | } |
---|
576 | 603 | |
---|
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; |
---|
580 | 607 | |
---|
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; |
---|
582 | 612 | |
---|
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 | + |
---|
587 | 624 | 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; |
---|
589 | 626 | |
---|
590 | 627 | for (i = 0; i < req->n_match_sets; i++) { |
---|
591 | | - profile = &profile_cfg->profiles[i]; |
---|
| 628 | + profile = &profile_cfg_v1->profiles[i]; |
---|
592 | 629 | profile->ssid_index = i; |
---|
593 | 630 | /* Support any cipher and auth algorithm */ |
---|
594 | 631 | profile->unicast_cipher = 0xff; |
---|
.. | .. |
---|
601 | 638 | IWL_DEBUG_SCAN(mvm, "Sending scheduled scan profile config\n"); |
---|
602 | 639 | |
---|
603 | 640 | 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); |
---|
607 | 644 | |
---|
608 | 645 | return ret; |
---|
609 | 646 | } |
---|
.. | .. |
---|
661 | 698 | tx_cmd[0].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm, |
---|
662 | 699 | NL80211_BAND_2GHZ, |
---|
663 | 700 | 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 | + } |
---|
665 | 716 | |
---|
666 | 717 | tx_cmd[1].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL | |
---|
667 | 718 | TX_CMD_FLG_BT_DIS); |
---|
| 719 | + |
---|
668 | 720 | tx_cmd[1].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm, |
---|
669 | 721 | NL80211_BAND_5GHZ, |
---|
670 | 722 | no_cck); |
---|
671 | | - tx_cmd[1].sta_id = mvm->aux_sta.sta_id; |
---|
672 | 723 | } |
---|
673 | 724 | |
---|
674 | 725 | static void |
---|
.. | .. |
---|
836 | 887 | struct ieee80211_vif *vif) |
---|
837 | 888 | { |
---|
838 | 889 | 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); |
---|
839 | 896 | |
---|
840 | 897 | /* We can only use EBS if: |
---|
841 | 898 | * 1. the feature is supported; |
---|
842 | 899 | * 2. the last EBS was successful; |
---|
843 | 900 | * 3. if only single scan, the single scan EBS API is supported; |
---|
844 | 901 | * 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 |
---|
845 | 904 | */ |
---|
846 | 905 | return ((capa->flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT) && |
---|
847 | 906 | 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))); |
---|
849 | 909 | } |
---|
850 | 910 | |
---|
851 | 911 | static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params) |
---|
852 | 912 | { |
---|
853 | 913 | return params->n_scan_plans == 1 && |
---|
854 | 914 | 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); |
---|
855 | 921 | } |
---|
856 | 922 | |
---|
857 | 923 | static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, |
---|
.. | .. |
---|
866 | 932 | if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0) |
---|
867 | 933 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION; |
---|
868 | 934 | |
---|
869 | | - if (params->type == IWL_SCAN_TYPE_FRAGMENTED) |
---|
| 935 | + if (iwl_mvm_is_scan_fragmented(params->type)) |
---|
870 | 936 | flags |= IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED; |
---|
871 | 937 | |
---|
872 | 938 | if (iwl_mvm_rrm_scan_needed(mvm) && |
---|
.. | .. |
---|
889 | 955 | |
---|
890 | 956 | if (iwl_mvm_is_regular_scan(params) && |
---|
891 | 957 | vif->type != NL80211_IFTYPE_P2P_DEVICE && |
---|
892 | | - params->type != IWL_SCAN_TYPE_FRAGMENTED) |
---|
| 958 | + !iwl_mvm_is_scan_fragmented(params->type)) |
---|
893 | 959 | flags |= IWL_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL; |
---|
894 | 960 | |
---|
895 | 961 | 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)); |
---|
896 | 975 | } |
---|
897 | 976 | |
---|
898 | 977 | static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
---|
899 | 978 | struct iwl_mvm_scan_params *params) |
---|
900 | 979 | { |
---|
901 | 980 | struct iwl_scan_req_lmac *cmd = mvm->scan_cmd; |
---|
902 | | - struct iwl_scan_probe_req *preq = |
---|
| 981 | + struct iwl_scan_probe_req_v1 *preq = |
---|
903 | 982 | (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) * |
---|
904 | 983 | mvm->fw->ucode_capa.n_scan_channels); |
---|
905 | 984 | u32 ssid_bitmap = 0; |
---|
906 | 985 | int i; |
---|
907 | | - |
---|
908 | | - lockdep_assert_held(&mvm->mutex); |
---|
909 | | - |
---|
910 | | - memset(cmd, 0, ksize(cmd)); |
---|
| 986 | + u8 band; |
---|
911 | 987 | |
---|
912 | 988 | if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) |
---|
913 | 989 | return -EINVAL; |
---|
.. | .. |
---|
923 | 999 | cmd->scan_flags = cpu_to_le32(iwl_mvm_scan_lmac_flags(mvm, params, |
---|
924 | 1000 | vif)); |
---|
925 | 1001 | |
---|
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); |
---|
927 | 1004 | cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP | |
---|
928 | 1005 | MAC_FILTER_IN_BEACON); |
---|
929 | 1006 | iwl_mvm_scan_fill_tx_cmd(mvm, cmd->tx_cmd, params->no_cck); |
---|
.. | .. |
---|
969 | 1046 | iwl_mvm_lmac_scan_cfg_channels(mvm, params->channels, |
---|
970 | 1047 | params->n_channels, ssid_bitmap, cmd); |
---|
971 | 1048 | |
---|
972 | | - *preq = params->preq; |
---|
| 1049 | + iwl_mvm_scan_set_legacy_probe_req(preq, ¶ms->preq); |
---|
973 | 1050 | |
---|
974 | 1051 | return 0; |
---|
975 | 1052 | } |
---|
.. | .. |
---|
1022 | 1099 | dwell->extended = IWL_SCAN_DWELL_EXTENDED; |
---|
1023 | 1100 | } |
---|
1024 | 1101 | |
---|
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) |
---|
1026 | 1104 | { |
---|
1027 | 1105 | struct ieee80211_supported_band *band; |
---|
1028 | 1106 | int i, j = 0; |
---|
1029 | 1107 | |
---|
1030 | 1108 | 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++) |
---|
1032 | 1110 | channels[j] = band->channels[i].hw_value; |
---|
1033 | 1111 | 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++) |
---|
1035 | 1113 | channels[j] = band->channels[i].hw_value; |
---|
1036 | 1114 | } |
---|
1037 | 1115 | |
---|
1038 | 1116 | 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) |
---|
1040 | 1119 | { |
---|
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); |
---|
1042 | 1121 | struct iwl_scan_config_v1 *cfg = config; |
---|
1043 | 1122 | |
---|
1044 | 1123 | cfg->flags = cpu_to_le32(flags); |
---|
.. | .. |
---|
1052 | 1131 | |
---|
1053 | 1132 | memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN); |
---|
1054 | 1133 | |
---|
| 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 | + |
---|
1055 | 1138 | cfg->bcast_sta_id = mvm->aux_sta.sta_id; |
---|
1056 | 1139 | cfg->channel_flags = channel_flags; |
---|
1057 | 1140 | |
---|
1058 | | - iwl_mvm_fill_channels(mvm, cfg->channel_array); |
---|
| 1141 | + iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels); |
---|
1059 | 1142 | } |
---|
1060 | 1143 | |
---|
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) |
---|
1063 | 1147 | { |
---|
1064 | | - struct iwl_scan_config *cfg = config; |
---|
| 1148 | + struct iwl_scan_config_v2 *cfg = config; |
---|
1065 | 1149 | |
---|
1066 | 1150 | cfg->flags = cpu_to_le32(flags); |
---|
1067 | 1151 | cfg->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm)); |
---|
.. | .. |
---|
1071 | 1155 | if (iwl_mvm_is_cdb_supported(mvm)) { |
---|
1072 | 1156 | enum iwl_mvm_scan_type lb_type, hb_type; |
---|
1073 | 1157 | |
---|
1074 | | - lb_type = iwl_mvm_get_scan_type_band(mvm, false, |
---|
| 1158 | + lb_type = iwl_mvm_get_scan_type_band(mvm, NULL, |
---|
1075 | 1159 | 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, |
---|
1077 | 1161 | NL80211_BAND_5GHZ); |
---|
1078 | 1162 | |
---|
1079 | 1163 | cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] = |
---|
.. | .. |
---|
1087 | 1171 | cpu_to_le32(scan_timing[hb_type].suspend_time); |
---|
1088 | 1172 | } else { |
---|
1089 | 1173 | enum iwl_mvm_scan_type type = |
---|
1090 | | - iwl_mvm_get_scan_type(mvm, false); |
---|
| 1174 | + iwl_mvm_get_scan_type(mvm, NULL); |
---|
1091 | 1175 | |
---|
1092 | 1176 | cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] = |
---|
1093 | 1177 | cpu_to_le32(scan_timing[type].max_out_time); |
---|
.. | .. |
---|
1099 | 1183 | |
---|
1100 | 1184 | memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN); |
---|
1101 | 1185 | |
---|
| 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 | + |
---|
1102 | 1190 | cfg->bcast_sta_id = mvm->aux_sta.sta_id; |
---|
1103 | 1191 | cfg->channel_flags = channel_flags; |
---|
1104 | 1192 | |
---|
1105 | | - iwl_mvm_fill_channels(mvm, cfg->channel_array); |
---|
| 1193 | + iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels); |
---|
1106 | 1194 | } |
---|
1107 | 1195 | |
---|
1108 | | -int iwl_mvm_config_scan(struct iwl_mvm *mvm) |
---|
| 1196 | +static int iwl_mvm_legacy_config_scan(struct iwl_mvm *mvm) |
---|
1109 | 1197 | { |
---|
1110 | 1198 | void *cfg; |
---|
1111 | 1199 | int ret, cmd_size; |
---|
.. | .. |
---|
1121 | 1209 | u8 channel_flags; |
---|
1122 | 1210 | |
---|
1123 | 1211 | 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; |
---|
1125 | 1213 | |
---|
1126 | 1214 | 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, |
---|
1128 | 1216 | 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, |
---|
1130 | 1218 | NL80211_BAND_5GHZ); |
---|
1131 | 1219 | if (type == mvm->scan_type && hb_type == mvm->hb_scan_type) |
---|
1132 | 1220 | return 0; |
---|
1133 | 1221 | } else { |
---|
1134 | | - type = iwl_mvm_get_scan_type(mvm, false); |
---|
| 1222 | + type = iwl_mvm_get_scan_type(mvm, NULL); |
---|
1135 | 1223 | if (type == mvm->scan_type) |
---|
1136 | 1224 | return 0; |
---|
1137 | 1225 | } |
---|
1138 | 1226 | |
---|
1139 | 1227 | if (iwl_mvm_cdb_scan_api(mvm)) |
---|
1140 | | - cmd_size = sizeof(struct iwl_scan_config); |
---|
| 1228 | + cmd_size = sizeof(struct iwl_scan_config_v2); |
---|
1141 | 1229 | else |
---|
1142 | 1230 | cmd_size = sizeof(struct iwl_scan_config_v1); |
---|
1143 | 1231 | cmd_size += mvm->fw->ucode_capa.n_scan_channels; |
---|
.. | .. |
---|
1156 | 1244 | SCAN_CONFIG_FLAG_SET_MAC_ADDR | |
---|
1157 | 1245 | SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS | |
---|
1158 | 1246 | SCAN_CONFIG_N_CHANNELS(num_channels) | |
---|
1159 | | - (type == IWL_SCAN_TYPE_FRAGMENTED ? |
---|
| 1247 | + (iwl_mvm_is_scan_fragmented(type) ? |
---|
1160 | 1248 | SCAN_CONFIG_FLAG_SET_FRAGMENTED : |
---|
1161 | 1249 | SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED); |
---|
1162 | 1250 | |
---|
.. | .. |
---|
1171 | 1259 | */ |
---|
1172 | 1260 | if (iwl_mvm_cdb_scan_api(mvm)) { |
---|
1173 | 1261 | if (iwl_mvm_is_cdb_supported(mvm)) |
---|
1174 | | - flags |= (hb_type == IWL_SCAN_TYPE_FRAGMENTED) ? |
---|
| 1262 | + flags |= (iwl_mvm_is_scan_fragmented(hb_type)) ? |
---|
1175 | 1263 | SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED : |
---|
1176 | 1264 | 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); |
---|
1178 | 1267 | } 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); |
---|
1180 | 1270 | } |
---|
1181 | 1271 | |
---|
1182 | 1272 | cmd.data[0] = cfg; |
---|
.. | .. |
---|
1193 | 1283 | |
---|
1194 | 1284 | kfree(cfg); |
---|
1195 | 1285 | 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); |
---|
1196 | 1319 | } |
---|
1197 | 1320 | |
---|
1198 | 1321 | static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status) |
---|
.. | .. |
---|
1214 | 1337 | u8 active_dwell, passive_dwell; |
---|
1215 | 1338 | |
---|
1216 | 1339 | 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; |
---|
1221 | 1342 | |
---|
1222 | 1343 | if (iwl_mvm_is_adaptive_dwell_supported(mvm)) { |
---|
1223 | 1344 | cmd->v7.adwell_default_n_aps_social = |
---|
1224 | 1345 | IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL; |
---|
1225 | 1346 | 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; |
---|
1227 | 1352 | |
---|
1228 | 1353 | /* if custom max budget was configured with debugfs */ |
---|
1229 | 1354 | if (IWL_MVM_ADWELL_MAX_BUDGET) |
---|
.. | .. |
---|
1266 | 1391 | } |
---|
1267 | 1392 | } |
---|
1268 | 1393 | } 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; |
---|
1271 | 1395 | cmd->v1.active_dwell = active_dwell; |
---|
1272 | 1396 | cmd->v1.passive_dwell = passive_dwell; |
---|
1273 | 1397 | cmd->v1.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED; |
---|
.. | .. |
---|
1304 | 1428 | cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_2); |
---|
1305 | 1429 | } |
---|
1306 | 1430 | |
---|
| 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 | + |
---|
1307 | 1617 | static void |
---|
1308 | 1618 | iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm, |
---|
1309 | 1619 | struct ieee80211_channel **channels, |
---|
1310 | | - int n_channels, u32 ssid_bitmap, |
---|
| 1620 | + int n_channels, u32 flags, |
---|
1311 | 1621 | struct iwl_scan_channel_cfg_umac *channel_cfg) |
---|
1312 | 1622 | { |
---|
1313 | 1623 | int i; |
---|
1314 | 1624 | |
---|
1315 | 1625 | 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 | + } |
---|
1320 | 1639 | } |
---|
| 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; |
---|
1321 | 1753 | } |
---|
1322 | 1754 | |
---|
1323 | 1755 | static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, |
---|
.. | .. |
---|
1332 | 1764 | if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0) |
---|
1333 | 1765 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT; |
---|
1334 | 1766 | |
---|
1335 | | - if (params->type == IWL_SCAN_TYPE_FRAGMENTED) |
---|
| 1767 | + if (iwl_mvm_is_scan_fragmented(params->type)) |
---|
1336 | 1768 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED; |
---|
1337 | 1769 | |
---|
1338 | 1770 | if (iwl_mvm_is_cdb_supported(mvm) && |
---|
1339 | | - params->hb_type == IWL_SCAN_TYPE_FRAGMENTED) |
---|
| 1771 | + iwl_mvm_is_scan_fragmented(params->hb_type)) |
---|
1340 | 1772 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED; |
---|
1341 | 1773 | |
---|
1342 | 1774 | if (iwl_mvm_rrm_scan_needed(mvm) && |
---|
.. | .. |
---|
1352 | 1784 | if (!iwl_mvm_is_regular_scan(params)) |
---|
1353 | 1785 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC; |
---|
1354 | 1786 | |
---|
1355 | | - if (params->measurement_dwell) |
---|
| 1787 | + if (params->iter_notif) |
---|
1356 | 1788 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE; |
---|
1357 | 1789 | |
---|
1358 | 1790 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
---|
.. | .. |
---|
1363 | 1795 | if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED) |
---|
1364 | 1796 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE; |
---|
1365 | 1797 | |
---|
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) |
---|
1368 | 1799 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_ADAPTIVE_DWELL; |
---|
1369 | 1800 | |
---|
1370 | 1801 | /* |
---|
.. | .. |
---|
1374 | 1805 | */ |
---|
1375 | 1806 | if (iwl_mvm_is_regular_scan(params) && |
---|
1376 | 1807 | vif->type != NL80211_IFTYPE_P2P_DEVICE && |
---|
1377 | | - params->type != IWL_SCAN_TYPE_FRAGMENTED && |
---|
| 1808 | + !iwl_mvm_is_scan_fragmented(params->type) && |
---|
1378 | 1809 | !iwl_mvm_is_adaptive_dwell_supported(mvm) && |
---|
1379 | 1810 | !iwl_mvm_is_oce_supported(mvm)) |
---|
1380 | 1811 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL; |
---|
.. | .. |
---|
1399 | 1830 | return flags; |
---|
1400 | 1831 | } |
---|
1401 | 1832 | |
---|
| 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 | + ¶ms->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 | + |
---|
1402 | 1866 | static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
---|
1403 | 1867 | struct iwl_mvm_scan_params *params, |
---|
1404 | | - int type) |
---|
| 1868 | + int type, int uid) |
---|
1405 | 1869 | { |
---|
1406 | 1870 | struct iwl_scan_req_umac *cmd = mvm->scan_cmd; |
---|
1407 | 1871 | struct iwl_scan_umac_chan_param *chan_param; |
---|
1408 | 1872 | 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; |
---|
1413 | 1880 | u32 ssid_bitmap = 0; |
---|
1414 | 1881 | u8 channel_flags = 0; |
---|
1415 | 1882 | u16 gen_flags; |
---|
1416 | 1883 | struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif); |
---|
1417 | 1884 | |
---|
1418 | 1885 | 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)); |
---|
1430 | 1886 | |
---|
1431 | 1887 | iwl_mvm_scan_umac_dwell(mvm, cmd, params); |
---|
1432 | 1888 | |
---|
.. | .. |
---|
1442 | 1898 | if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED) |
---|
1443 | 1899 | cmd->v8.num_of_fragments[SCAN_HB_LMAC_IDX] = |
---|
1444 | 1900 | IWL_SCAN_NUM_OF_FRAGS; |
---|
| 1901 | + |
---|
| 1902 | + cmd->v8.general_flags2 = |
---|
| 1903 | + IWL_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER; |
---|
1445 | 1904 | } |
---|
1446 | 1905 | |
---|
1447 | 1906 | cmd->scan_start_mac_id = scan_vif->id; |
---|
.. | .. |
---|
1449 | 1908 | if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT) |
---|
1450 | 1909 | cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); |
---|
1451 | 1910 | |
---|
1452 | | - if (iwl_mvm_scan_use_ebs(mvm, vif)) |
---|
| 1911 | + if (iwl_mvm_scan_use_ebs(mvm, vif)) { |
---|
1453 | 1912 | channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | |
---|
1454 | 1913 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | |
---|
1455 | 1914 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD; |
---|
1456 | 1915 | |
---|
| 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 | + |
---|
1457 | 1926 | chan_param->flags = channel_flags; |
---|
1458 | 1927 | chan_param->count = params->n_channels; |
---|
1459 | 1928 | |
---|
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; |
---|
1461 | 1933 | |
---|
| 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 | + ¶ms->preq); |
---|
| 1941 | + direct_scan = tail_v1->direct_scan; |
---|
| 1942 | + } |
---|
| 1943 | + iwl_scan_build_ssids(params, direct_scan, &ssid_bitmap); |
---|
1462 | 1944 | iwl_mvm_umac_scan_cfg_channels(mvm, params->channels, |
---|
1463 | 1945 | params->n_channels, ssid_bitmap, |
---|
1464 | 1946 | cmd_data); |
---|
| 1947 | + return 0; |
---|
| 1948 | +} |
---|
1465 | 1949 | |
---|
1466 | | - for (i = 0; i < params->n_scan_plans; i++) { |
---|
1467 | | - struct cfg80211_sched_scan_plan *scan_plan = |
---|
1468 | | - ¶ms->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); |
---|
1469 | 1958 | |
---|
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); |
---|
1474 | 1960 | |
---|
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); |
---|
1483 | 1962 | |
---|
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); |
---|
1486 | 2086 | |
---|
1487 | 2087 | return 0; |
---|
1488 | 2088 | } |
---|
.. | .. |
---|
1506 | 2106 | * compatibility with old wpa_supplicant that wouldn't stop a |
---|
1507 | 2107 | * scheduled scan before starting a normal scan. |
---|
1508 | 2108 | */ |
---|
| 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; |
---|
1509 | 2114 | |
---|
1510 | 2115 | if (iwl_mvm_num_scans(mvm) < mvm->max_scans) |
---|
1511 | 2116 | return 0; |
---|
.. | .. |
---|
1543 | 2148 | if (mvm->scan_status & IWL_MVM_SCAN_SCHED_MASK) |
---|
1544 | 2149 | return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, |
---|
1545 | 2150 | 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. |
---|
1549 | 2153 | */ |
---|
| 2154 | + /* fall through */ |
---|
1550 | 2155 | default: |
---|
1551 | 2156 | WARN_ON(1); |
---|
1552 | 2157 | break; |
---|
.. | .. |
---|
1570 | 2175 | |
---|
1571 | 2176 | static void iwl_mvm_fill_scan_type(struct iwl_mvm *mvm, |
---|
1572 | 2177 | struct iwl_mvm_scan_params *params, |
---|
1573 | | - bool p2p) |
---|
| 2178 | + struct ieee80211_vif *vif) |
---|
1574 | 2179 | { |
---|
1575 | 2180 | if (iwl_mvm_is_cdb_supported(mvm)) { |
---|
1576 | 2181 | params->type = |
---|
1577 | | - iwl_mvm_get_scan_type_band(mvm, p2p, |
---|
| 2182 | + iwl_mvm_get_scan_type_band(mvm, vif, |
---|
1578 | 2183 | NL80211_BAND_2GHZ); |
---|
1579 | 2184 | params->hb_type = |
---|
1580 | | - iwl_mvm_get_scan_type_band(mvm, p2p, |
---|
| 2185 | + iwl_mvm_get_scan_type_band(mvm, vif, |
---|
1581 | 2186 | NL80211_BAND_5GHZ); |
---|
1582 | 2187 | } else { |
---|
1583 | | - params->type = iwl_mvm_get_scan_type(mvm, p2p); |
---|
| 2188 | + params->type = iwl_mvm_get_scan_type(mvm, vif); |
---|
1584 | 2189 | } |
---|
1585 | 2190 | } |
---|
| 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 | + |
---|
1586 | 2250 | int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
---|
1587 | 2251 | struct cfg80211_scan_request *req, |
---|
1588 | 2252 | struct ieee80211_scan_ies *ies) |
---|
.. | .. |
---|
1630 | 2294 | params.scan_plans = &scan_plan; |
---|
1631 | 2295 | params.n_scan_plans = 1; |
---|
1632 | 2296 | |
---|
1633 | | - iwl_mvm_fill_scan_type(mvm, ¶ms, |
---|
1634 | | - vif->type == NL80211_IFTYPE_P2P_DEVICE); |
---|
| 2297 | + iwl_mvm_fill_scan_type(mvm, ¶ms, vif); |
---|
1635 | 2298 | |
---|
1636 | | - ret = iwl_mvm_get_measurement_dwell(mvm, req, ¶ms); |
---|
1637 | | - if (ret < 0) |
---|
1638 | | - return ret; |
---|
1639 | | - |
---|
1640 | | - params.measurement_dwell = ret; |
---|
| 2299 | + if (req->duration) |
---|
| 2300 | + params.iter_notif = true; |
---|
1641 | 2301 | |
---|
1642 | 2302 | iwl_mvm_build_scan_probe(mvm, vif, ies, ¶ms); |
---|
1643 | 2303 | |
---|
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, ¶ms, |
---|
1647 | | - IWL_MVM_SCAN_REGULAR); |
---|
1648 | | - } else { |
---|
1649 | | - hcmd.id = SCAN_OFFLOAD_REQUEST_CMD; |
---|
1650 | | - ret = iwl_mvm_scan_lmac(mvm, vif, ¶ms); |
---|
1651 | | - } |
---|
| 2304 | + ret = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, ¶ms, |
---|
| 2305 | + IWL_MVM_SCAN_REGULAR); |
---|
1652 | 2306 | |
---|
1653 | 2307 | if (ret) |
---|
1654 | 2308 | return ret; |
---|
.. | .. |
---|
1669 | 2323 | IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); |
---|
1670 | 2324 | mvm->scan_status |= IWL_MVM_SCAN_REGULAR; |
---|
1671 | 2325 | mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif); |
---|
1672 | | - iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); |
---|
1673 | 2326 | |
---|
1674 | 2327 | schedule_delayed_work(&mvm->scan_timeout_dwork, |
---|
1675 | 2328 | msecs_to_jiffies(SCAN_TIMEOUT)); |
---|
.. | .. |
---|
1726 | 2379 | params.n_scan_plans = req->n_scan_plans; |
---|
1727 | 2380 | params.scan_plans = req->scan_plans; |
---|
1728 | 2381 | |
---|
1729 | | - iwl_mvm_fill_scan_type(mvm, ¶ms, |
---|
1730 | | - vif->type == NL80211_IFTYPE_P2P_DEVICE); |
---|
| 2382 | + iwl_mvm_fill_scan_type(mvm, ¶ms, vif); |
---|
1731 | 2383 | |
---|
1732 | 2384 | /* In theory, LMAC scans can handle a 32-bit delay, but since |
---|
1733 | 2385 | * waiting for over 18 hours to start the scan is a bit silly |
---|
.. | .. |
---|
1748 | 2400 | |
---|
1749 | 2401 | iwl_mvm_build_scan_probe(mvm, vif, ies, ¶ms); |
---|
1750 | 2402 | |
---|
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, ¶ms, type); |
---|
1754 | | - } else { |
---|
1755 | | - hcmd.id = SCAN_OFFLOAD_REQUEST_CMD; |
---|
1756 | | - ret = iwl_mvm_scan_lmac(mvm, vif, ¶ms); |
---|
1757 | | - } |
---|
| 2403 | + ret = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, ¶ms, type); |
---|
1758 | 2404 | |
---|
1759 | 2405 | if (ret) |
---|
1760 | 2406 | return ret; |
---|
.. | .. |
---|
1796 | 2442 | memcpy(info.tsf_bssid, mvm->scan_vif->bssid, ETH_ALEN); |
---|
1797 | 2443 | ieee80211_scan_completed(mvm->hw, &info); |
---|
1798 | 2444 | mvm->scan_vif = NULL; |
---|
1799 | | - iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
---|
1800 | 2445 | cancel_delayed_work(&mvm->scan_timeout_dwork); |
---|
1801 | 2446 | iwl_mvm_resume_tcm(mvm); |
---|
1802 | 2447 | } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { |
---|
.. | .. |
---|
1902 | 2547 | return ret; |
---|
1903 | 2548 | } |
---|
1904 | 2549 | |
---|
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 | +} |
---|
1906 | 2553 | |
---|
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; |
---|
1908 | 2566 | } |
---|
1909 | 2567 | |
---|
1910 | 2568 | int iwl_mvm_scan_size(struct iwl_mvm *mvm) |
---|
1911 | 2569 | { |
---|
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 | + |
---|
1913 | 2579 | |
---|
1914 | 2580 | if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm)) |
---|
1915 | 2581 | base_size = IWL_SCAN_REQ_UMAC_SIZE_V8; |
---|
.. | .. |
---|
1917 | 2583 | base_size = IWL_SCAN_REQ_UMAC_SIZE_V7; |
---|
1918 | 2584 | else if (iwl_mvm_cdb_scan_api(mvm)) |
---|
1919 | 2585 | base_size = IWL_SCAN_REQ_UMAC_SIZE_V6; |
---|
| 2586 | + else |
---|
| 2587 | + base_size = IWL_SCAN_REQ_UMAC_SIZE_V1; |
---|
1920 | 2588 | |
---|
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 | + |
---|
1922 | 2595 | return base_size + |
---|
1923 | 2596 | sizeof(struct iwl_scan_channel_cfg_umac) * |
---|
1924 | 2597 | mvm->fw->ucode_capa.n_scan_channels + |
---|
1925 | | - sizeof(struct iwl_scan_req_umac_tail); |
---|
1926 | | - |
---|
| 2598 | + tail_size; |
---|
| 2599 | + } |
---|
1927 | 2600 | return sizeof(struct iwl_scan_req_lmac) + |
---|
1928 | 2601 | sizeof(struct iwl_scan_channel_cfg_lmac) * |
---|
1929 | 2602 | mvm->fw->ucode_capa.n_scan_channels + |
---|
1930 | | - sizeof(struct iwl_scan_probe_req); |
---|
| 2603 | + sizeof(struct iwl_scan_probe_req_v1); |
---|
1931 | 2604 | } |
---|
1932 | 2605 | |
---|
1933 | 2606 | /* |
---|
.. | .. |
---|
1954 | 2627 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; |
---|
1955 | 2628 | mvm->scan_uid_status[uid] = 0; |
---|
1956 | 2629 | } |
---|
| 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; |
---|
1957 | 2639 | |
---|
1958 | 2640 | /* We shouldn't have any UIDs still set. Loop over all the |
---|
1959 | 2641 | * UIDs to make sure there's nothing left there and warn if |
---|
.. | .. |
---|
2010 | 2692 | mvm->scan_status &= ~type; |
---|
2011 | 2693 | |
---|
2012 | 2694 | 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); |
---|
2017 | 2695 | cancel_delayed_work(&mvm->scan_timeout_dwork); |
---|
2018 | 2696 | if (notify) { |
---|
2019 | 2697 | struct cfg80211_scan_info info = { |
---|