3857 lines · c
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause2/*3 * Copyright (C) 2012-2014, 2018-2024 Intel Corporation4 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH5 * Copyright (C) 2016-2017 Intel Deutschland GmbH6 */7#include <linux/etherdevice.h>8#include <net/mac80211.h>9#include <linux/crc32.h>10 11#include "mvm.h"12#include "fw/api/scan.h"13#include "iwl-io.h"14 15#define IWL_DENSE_EBS_SCAN_RATIO 516#define IWL_SPARSE_EBS_SCAN_RATIO 117 18#define IWL_SCAN_DWELL_ACTIVE 1019#define IWL_SCAN_DWELL_PASSIVE 11020#define IWL_SCAN_DWELL_FRAGMENTED 4421#define IWL_SCAN_DWELL_EXTENDED 9022#define IWL_SCAN_NUM_OF_FRAGS 323 24/* adaptive dwell max budget time [TU] for full scan */25#define IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 30026/* adaptive dwell max budget time [TU] for directed scan */27#define IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN 10028/* adaptive dwell default high band APs number */29#define IWL_SCAN_ADWELL_DEFAULT_HB_N_APS 830/* adaptive dwell default low band APs number */31#define IWL_SCAN_ADWELL_DEFAULT_LB_N_APS 232/* adaptive dwell default APs number in social channels (1, 6, 11) */33#define IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 1034/* number of scan channels */35#define IWL_SCAN_NUM_CHANNELS 11236/* adaptive dwell number of APs override mask for p2p friendly GO */37#define IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY_BIT BIT(20)38/* adaptive dwell number of APs override mask for social channels */39#define IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS_BIT BIT(21)40/* adaptive dwell number of APs override for p2p friendly GO channels */41#define IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY 1042/* adaptive dwell number of APs override for social channels */43#define IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS 244 45/* minimal number of 2GHz and 5GHz channels in the regular scan request */46#define IWL_MVM_6GHZ_PASSIVE_SCAN_MIN_CHANS 447 48/* Number of iterations on the channel for mei filtered scan */49#define IWL_MEI_SCAN_NUM_ITER 5U50 51#define WFA_TPC_IE_LEN 952 53struct iwl_mvm_scan_timing_params {54 u32 suspend_time;55 u32 max_out_time;56};57 58static struct iwl_mvm_scan_timing_params scan_timing[] = {59 [IWL_SCAN_TYPE_UNASSOC] = {60 .suspend_time = 0,61 .max_out_time = 0,62 },63 [IWL_SCAN_TYPE_WILD] = {64 .suspend_time = 30,65 .max_out_time = 120,66 },67 [IWL_SCAN_TYPE_MILD] = {68 .suspend_time = 120,69 .max_out_time = 120,70 },71 [IWL_SCAN_TYPE_FRAGMENTED] = {72 .suspend_time = 95,73 .max_out_time = 44,74 },75 [IWL_SCAN_TYPE_FAST_BALANCE] = {76 .suspend_time = 30,77 .max_out_time = 37,78 },79};80 81struct iwl_mvm_scan_params {82 /* For CDB this is low band scan type, for non-CDB - type. */83 enum iwl_mvm_scan_type type;84 enum iwl_mvm_scan_type hb_type;85 u32 n_channels;86 u16 delay;87 int n_ssids;88 struct cfg80211_ssid *ssids;89 struct ieee80211_channel **channels;90 u32 flags;91 u8 *mac_addr;92 u8 *mac_addr_mask;93 bool no_cck;94 bool pass_all;95 int n_match_sets;96 struct iwl_scan_probe_req preq;97 struct cfg80211_match_set *match_sets;98 int n_scan_plans;99 struct cfg80211_sched_scan_plan *scan_plans;100 bool iter_notif;101 struct cfg80211_scan_6ghz_params *scan_6ghz_params;102 u32 n_6ghz_params;103 bool scan_6ghz;104 bool enable_6ghz_passive;105 bool respect_p2p_go, respect_p2p_go_hb;106 s8 tsf_report_link_id;107 u8 bssid[ETH_ALEN] __aligned(2);108};109 110static inline void *iwl_mvm_get_scan_req_umac_data(struct iwl_mvm *mvm)111{112 struct iwl_scan_req_umac *cmd = mvm->scan_cmd;113 114 if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm))115 return (void *)&cmd->v8.data;116 117 if (iwl_mvm_is_adaptive_dwell_supported(mvm))118 return (void *)&cmd->v7.data;119 120 if (iwl_mvm_cdb_scan_api(mvm))121 return (void *)&cmd->v6.data;122 123 return (void *)&cmd->v1.data;124}125 126static inline struct iwl_scan_umac_chan_param *127iwl_mvm_get_scan_req_umac_channel(struct iwl_mvm *mvm)128{129 struct iwl_scan_req_umac *cmd = mvm->scan_cmd;130 131 if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm))132 return &cmd->v8.channel;133 134 if (iwl_mvm_is_adaptive_dwell_supported(mvm))135 return &cmd->v7.channel;136 137 if (iwl_mvm_cdb_scan_api(mvm))138 return &cmd->v6.channel;139 140 return &cmd->v1.channel;141}142 143static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)144{145 if (mvm->scan_rx_ant != ANT_NONE)146 return mvm->scan_rx_ant;147 return iwl_mvm_get_valid_rx_ant(mvm);148}149 150static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)151{152 u16 rx_chain;153 u8 rx_ant;154 155 rx_ant = iwl_mvm_scan_rx_ant(mvm);156 rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS;157 rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;158 rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS;159 rx_chain |= 0x1 << PHY_RX_CHAIN_DRIVER_FORCE_POS;160 return cpu_to_le16(rx_chain);161}162 163static inline __le32164iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum nl80211_band band,165 bool no_cck)166{167 u32 tx_ant;168 169 iwl_mvm_toggle_tx_ant(mvm, &mvm->scan_last_antenna_idx);170 tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS;171 172 if (band == NL80211_BAND_2GHZ && !no_cck)173 return cpu_to_le32(IWL_RATE_1M_PLCP | RATE_MCS_CCK_MSK_V1 |174 tx_ant);175 else176 return cpu_to_le32(IWL_RATE_6M_PLCP | tx_ant);177}178 179static enum iwl_mvm_traffic_load iwl_mvm_get_traffic_load(struct iwl_mvm *mvm)180{181 return mvm->tcm.result.global_load;182}183 184static enum iwl_mvm_traffic_load185iwl_mvm_get_traffic_load_band(struct iwl_mvm *mvm, enum nl80211_band band)186{187 return mvm->tcm.result.band_load[band];188}189 190struct iwl_mvm_scan_iter_data {191 u32 global_cnt;192 struct ieee80211_vif *current_vif;193 bool is_dcm_with_p2p_go;194};195 196static void iwl_mvm_scan_iterator(void *_data, u8 *mac,197 struct ieee80211_vif *vif)198{199 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);200 struct iwl_mvm_scan_iter_data *data = _data;201 struct iwl_mvm_vif *curr_mvmvif;202 203 if (vif->type != NL80211_IFTYPE_P2P_DEVICE &&204 mvmvif->deflink.phy_ctxt &&205 mvmvif->deflink.phy_ctxt->id < NUM_PHY_CTX)206 data->global_cnt += 1;207 208 if (!data->current_vif || vif == data->current_vif)209 return;210 211 curr_mvmvif = iwl_mvm_vif_from_mac80211(data->current_vif);212 213 if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_P2P_GO &&214 mvmvif->deflink.phy_ctxt && curr_mvmvif->deflink.phy_ctxt &&215 mvmvif->deflink.phy_ctxt->id != curr_mvmvif->deflink.phy_ctxt->id)216 data->is_dcm_with_p2p_go = true;217}218 219static enum220iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm,221 struct ieee80211_vif *vif,222 enum iwl_mvm_traffic_load load,223 bool low_latency)224{225 struct iwl_mvm_scan_iter_data data = {226 .current_vif = vif,227 .is_dcm_with_p2p_go = false,228 .global_cnt = 0,229 };230 231 /*232 * A scanning AP interface probably wants to generate a survey to do233 * ACS (automatic channel selection).234 * Force a non-fragmented scan in that case.235 */236 if (vif && ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_AP)237 return IWL_SCAN_TYPE_WILD;238 239 ieee80211_iterate_active_interfaces_atomic(mvm->hw,240 IEEE80211_IFACE_ITER_NORMAL,241 iwl_mvm_scan_iterator,242 &data);243 244 if (!data.global_cnt)245 return IWL_SCAN_TYPE_UNASSOC;246 247 if (fw_has_api(&mvm->fw->ucode_capa,248 IWL_UCODE_TLV_API_FRAGMENTED_SCAN)) {249 if ((load == IWL_MVM_TRAFFIC_HIGH || low_latency) &&250 (!vif || vif->type != NL80211_IFTYPE_P2P_DEVICE))251 return IWL_SCAN_TYPE_FRAGMENTED;252 253 /*254 * in case of DCM with P2P GO set all scan requests as255 * fast-balance scan256 */257 if (vif && vif->type == NL80211_IFTYPE_STATION &&258 data.is_dcm_with_p2p_go)259 return IWL_SCAN_TYPE_FAST_BALANCE;260 }261 262 if (load >= IWL_MVM_TRAFFIC_MEDIUM || low_latency)263 return IWL_SCAN_TYPE_MILD;264 265 return IWL_SCAN_TYPE_WILD;266}267 268static enum269iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm,270 struct ieee80211_vif *vif)271{272 enum iwl_mvm_traffic_load load;273 bool low_latency;274 275 load = iwl_mvm_get_traffic_load(mvm);276 low_latency = iwl_mvm_low_latency(mvm);277 278 return _iwl_mvm_get_scan_type(mvm, vif, load, low_latency);279}280 281static enum282iwl_mvm_scan_type iwl_mvm_get_scan_type_band(struct iwl_mvm *mvm,283 struct ieee80211_vif *vif,284 enum nl80211_band band)285{286 enum iwl_mvm_traffic_load load;287 bool low_latency;288 289 load = iwl_mvm_get_traffic_load_band(mvm, band);290 low_latency = iwl_mvm_low_latency_band(mvm, band);291 292 return _iwl_mvm_get_scan_type(mvm, vif, load, low_latency);293}294 295static inline bool iwl_mvm_rrm_scan_needed(struct iwl_mvm *mvm)296{297 /* require rrm scan whenever the fw supports it */298 return fw_has_capa(&mvm->fw->ucode_capa,299 IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT);300}301 302static int iwl_mvm_max_scan_ie_fw_cmd_room(struct iwl_mvm *mvm)303{304 int max_probe_len;305 306 max_probe_len = SCAN_OFFLOAD_PROBE_REQ_SIZE;307 308 /* we create the 802.11 header SSID element and WFA TPC element */309 max_probe_len -= 24 + 2 + WFA_TPC_IE_LEN;310 311 /* DS parameter set element is added on 2.4GHZ band if required */312 if (iwl_mvm_rrm_scan_needed(mvm))313 max_probe_len -= 3;314 315 return max_probe_len;316}317 318int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm)319{320 int max_ie_len = iwl_mvm_max_scan_ie_fw_cmd_room(mvm);321 322 /* TODO: [BUG] This function should return the maximum allowed size of323 * scan IEs, however the LMAC scan api contains both 2GHZ and 5GHZ IEs324 * in the same command. So the correct implementation of this function325 * is just iwl_mvm_max_scan_ie_fw_cmd_room() / 2. Currently the scan326 * command has only 512 bytes and it would leave us with about 240327 * bytes for scan IEs, which is clearly not enough. So meanwhile328 * we will report an incorrect value. This may result in a failure to329 * issue a scan in unified_scan_lmac and unified_sched_scan_lmac330 * functions with -ENOBUFS, if a large enough probe will be provided.331 */332 return max_ie_len;333}334 335void iwl_mvm_rx_lmac_scan_iter_complete_notif(struct iwl_mvm *mvm,336 struct iwl_rx_cmd_buffer *rxb)337{338 struct iwl_rx_packet *pkt = rxb_addr(rxb);339 struct iwl_lmac_scan_complete_notif *notif = (void *)pkt->data;340 341 IWL_DEBUG_SCAN(mvm,342 "Scan offload iteration complete: status=0x%x scanned channels=%d\n",343 notif->status, notif->scanned_channels);344 345 if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_FOUND) {346 IWL_DEBUG_SCAN(mvm, "Pass all scheduled scan results found\n");347 ieee80211_sched_scan_results(mvm->hw);348 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED;349 }350}351 352void iwl_mvm_rx_scan_match_found(struct iwl_mvm *mvm,353 struct iwl_rx_cmd_buffer *rxb)354{355 IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");356 ieee80211_sched_scan_results(mvm->hw);357}358 359static const char *iwl_mvm_ebs_status_str(enum iwl_scan_ebs_status status)360{361 switch (status) {362 case IWL_SCAN_EBS_SUCCESS:363 return "successful";364 case IWL_SCAN_EBS_INACTIVE:365 return "inactive";366 case IWL_SCAN_EBS_FAILED:367 case IWL_SCAN_EBS_CHAN_NOT_FOUND:368 default:369 return "failed";370 }371}372 373void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm,374 struct iwl_rx_cmd_buffer *rxb)375{376 struct iwl_rx_packet *pkt = rxb_addr(rxb);377 struct iwl_periodic_scan_complete *scan_notif = (void *)pkt->data;378 bool aborted = (scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED);379 380 /* If this happens, the firmware has mistakenly sent an LMAC381 * notification during UMAC scans -- warn and ignore it.382 */383 if (WARN_ON_ONCE(fw_has_capa(&mvm->fw->ucode_capa,384 IWL_UCODE_TLV_CAPA_UMAC_SCAN)))385 return;386 387 /* scan status must be locked for proper checking */388 lockdep_assert_held(&mvm->mutex);389 390 /* We first check if we were stopping a scan, in which case we391 * just clear the stopping flag. Then we check if it was a392 * firmware initiated stop, in which case we need to inform393 * mac80211.394 * Note that we can have a stopping and a running scan395 * simultaneously, but we can't have two different types of396 * scans stopping or running at the same time (since LMAC397 * doesn't support it).398 */399 400 if (mvm->scan_status & IWL_MVM_SCAN_STOPPING_SCHED) {401 WARN_ON_ONCE(mvm->scan_status & IWL_MVM_SCAN_STOPPING_REGULAR);402 403 IWL_DEBUG_SCAN(mvm, "Scheduled scan %s, EBS status %s\n",404 aborted ? "aborted" : "completed",405 iwl_mvm_ebs_status_str(scan_notif->ebs_status));406 IWL_DEBUG_SCAN(mvm,407 "Last line %d, Last iteration %d, Time after last iteration %d\n",408 scan_notif->last_schedule_line,409 scan_notif->last_schedule_iteration,410 __le32_to_cpu(scan_notif->time_after_last_iter));411 412 mvm->scan_status &= ~IWL_MVM_SCAN_STOPPING_SCHED;413 } else if (mvm->scan_status & IWL_MVM_SCAN_STOPPING_REGULAR) {414 IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s\n",415 aborted ? "aborted" : "completed",416 iwl_mvm_ebs_status_str(scan_notif->ebs_status));417 418 mvm->scan_status &= ~IWL_MVM_SCAN_STOPPING_REGULAR;419 } else if (mvm->scan_status & IWL_MVM_SCAN_SCHED) {420 WARN_ON_ONCE(mvm->scan_status & IWL_MVM_SCAN_REGULAR);421 422 IWL_DEBUG_SCAN(mvm, "Scheduled scan %s, EBS status %s\n",423 aborted ? "aborted" : "completed",424 iwl_mvm_ebs_status_str(scan_notif->ebs_status));425 IWL_DEBUG_SCAN(mvm,426 "Last line %d, Last iteration %d, Time after last iteration %d (FW)\n",427 scan_notif->last_schedule_line,428 scan_notif->last_schedule_iteration,429 __le32_to_cpu(scan_notif->time_after_last_iter));430 431 mvm->scan_status &= ~IWL_MVM_SCAN_SCHED;432 ieee80211_sched_scan_stopped(mvm->hw);433 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;434 } else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {435 struct cfg80211_scan_info info = {436 .aborted = aborted,437 };438 439 IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n",440 aborted ? "aborted" : "completed",441 iwl_mvm_ebs_status_str(scan_notif->ebs_status));442 443 mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;444 ieee80211_scan_completed(mvm->hw, &info);445 cancel_delayed_work(&mvm->scan_timeout_dwork);446 iwl_mvm_resume_tcm(mvm);447 } else {448 IWL_ERR(mvm,449 "got scan complete notification but no scan is running\n");450 }451 452 mvm->last_ebs_successful =453 scan_notif->ebs_status == IWL_SCAN_EBS_SUCCESS ||454 scan_notif->ebs_status == IWL_SCAN_EBS_INACTIVE;455}456 457static int iwl_ssid_exist(u8 *ssid, u8 ssid_len, struct iwl_ssid_ie *ssid_list)458{459 int i;460 461 for (i = 0; i < PROBE_OPTION_MAX; i++) {462 if (!ssid_list[i].len)463 break;464 if (ssid_list[i].len == ssid_len &&465 !memcmp(ssid_list->ssid, ssid, ssid_len))466 return i;467 }468 return -1;469}470 471/* We insert the SSIDs in an inverted order, because the FW will472 * invert it back.473 */474static void iwl_scan_build_ssids(struct iwl_mvm_scan_params *params,475 struct iwl_ssid_ie *ssids,476 u32 *ssid_bitmap)477{478 int i, j;479 int index;480 u32 tmp_bitmap = 0;481 482 /*483 * copy SSIDs from match list.484 * iwl_config_sched_scan_profiles() uses the order of these ssids to485 * config match list.486 */487 for (i = 0, j = params->n_match_sets - 1;488 j >= 0 && i < PROBE_OPTION_MAX;489 i++, j--) {490 /* skip empty SSID matchsets */491 if (!params->match_sets[j].ssid.ssid_len)492 continue;493 ssids[i].id = WLAN_EID_SSID;494 ssids[i].len = params->match_sets[j].ssid.ssid_len;495 memcpy(ssids[i].ssid, params->match_sets[j].ssid.ssid,496 ssids[i].len);497 }498 499 /* add SSIDs from scan SSID list */500 for (j = params->n_ssids - 1;501 j >= 0 && i < PROBE_OPTION_MAX;502 i++, j--) {503 index = iwl_ssid_exist(params->ssids[j].ssid,504 params->ssids[j].ssid_len,505 ssids);506 if (index < 0) {507 ssids[i].id = WLAN_EID_SSID;508 ssids[i].len = params->ssids[j].ssid_len;509 memcpy(ssids[i].ssid, params->ssids[j].ssid,510 ssids[i].len);511 tmp_bitmap |= BIT(i);512 } else {513 tmp_bitmap |= BIT(index);514 }515 }516 if (ssid_bitmap)517 *ssid_bitmap = tmp_bitmap;518}519 520static int521iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,522 struct cfg80211_sched_scan_request *req)523{524 struct iwl_scan_offload_profile *profile;525 struct iwl_scan_offload_profile_cfg_v1 *profile_cfg_v1;526 struct iwl_scan_offload_blocklist *blocklist;527 struct iwl_scan_offload_profile_cfg_data *data;528 int max_profiles = iwl_umac_scan_get_max_profiles(mvm->fw);529 int profile_cfg_size = sizeof(*data) +530 sizeof(*profile) * max_profiles;531 struct iwl_host_cmd cmd = {532 .id = SCAN_OFFLOAD_UPDATE_PROFILES_CMD,533 .len[1] = profile_cfg_size,534 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,535 .dataflags[1] = IWL_HCMD_DFL_NOCOPY,536 };537 int blocklist_len;538 int i;539 int ret;540 541 if (WARN_ON(req->n_match_sets > max_profiles))542 return -EIO;543 544 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL)545 blocklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN;546 else547 blocklist_len = IWL_SCAN_MAX_BLACKLIST_LEN;548 549 blocklist = kcalloc(blocklist_len, sizeof(*blocklist), GFP_KERNEL);550 if (!blocklist)551 return -ENOMEM;552 553 profile_cfg_v1 = kzalloc(profile_cfg_size, GFP_KERNEL);554 if (!profile_cfg_v1) {555 ret = -ENOMEM;556 goto free_blocklist;557 }558 559 cmd.data[0] = blocklist;560 cmd.len[0] = sizeof(*blocklist) * blocklist_len;561 cmd.data[1] = profile_cfg_v1;562 563 /* if max_profile is MAX_PROFILES_V2, we have the new API */564 if (max_profiles == IWL_SCAN_MAX_PROFILES_V2) {565 struct iwl_scan_offload_profile_cfg *profile_cfg =566 (struct iwl_scan_offload_profile_cfg *)profile_cfg_v1;567 568 data = &profile_cfg->data;569 } else {570 data = &profile_cfg_v1->data;571 }572 573 /* No blocklist configuration */574 data->num_profiles = req->n_match_sets;575 data->active_clients = SCAN_CLIENT_SCHED_SCAN;576 data->pass_match = SCAN_CLIENT_SCHED_SCAN;577 data->match_notify = SCAN_CLIENT_SCHED_SCAN;578 579 if (!req->n_match_sets || !req->match_sets[0].ssid.ssid_len)580 data->any_beacon_notify = SCAN_CLIENT_SCHED_SCAN;581 582 for (i = 0; i < req->n_match_sets; i++) {583 profile = &profile_cfg_v1->profiles[i];584 profile->ssid_index = i;585 /* Support any cipher and auth algorithm */586 profile->unicast_cipher = 0xff;587 profile->auth_alg = IWL_AUTH_ALGO_UNSUPPORTED |588 IWL_AUTH_ALGO_NONE | IWL_AUTH_ALGO_PSK | IWL_AUTH_ALGO_8021X |589 IWL_AUTH_ALGO_SAE | IWL_AUTH_ALGO_8021X_SHA384 | IWL_AUTH_ALGO_OWE;590 profile->network_type = IWL_NETWORK_TYPE_ANY;591 profile->band_selection = IWL_SCAN_OFFLOAD_SELECT_ANY;592 profile->client_bitmap = SCAN_CLIENT_SCHED_SCAN;593 }594 595 IWL_DEBUG_SCAN(mvm, "Sending scheduled scan profile config\n");596 597 ret = iwl_mvm_send_cmd(mvm, &cmd);598 kfree(profile_cfg_v1);599free_blocklist:600 kfree(blocklist);601 602 return ret;603}604 605static bool iwl_mvm_scan_pass_all(struct iwl_mvm *mvm,606 struct cfg80211_sched_scan_request *req)607{608 if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) {609 IWL_DEBUG_SCAN(mvm,610 "Sending scheduled scan with filtering, n_match_sets %d\n",611 req->n_match_sets);612 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;613 return false;614 }615 616 IWL_DEBUG_SCAN(mvm, "Sending Scheduled scan without filtering\n");617 618 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED;619 return true;620}621 622static int iwl_mvm_lmac_scan_abort(struct iwl_mvm *mvm)623{624 int ret;625 struct iwl_host_cmd cmd = {626 .id = SCAN_OFFLOAD_ABORT_CMD,627 };628 u32 status = CAN_ABORT_STATUS;629 630 ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status);631 if (ret)632 return ret;633 634 if (status != CAN_ABORT_STATUS) {635 /*636 * The scan abort will return 1 for success or637 * 2 for "failure". A failure condition can be638 * due to simply not being in an active scan which639 * can occur if we send the scan abort before the640 * microcode has notified us that a scan is completed.641 */642 IWL_DEBUG_SCAN(mvm, "SCAN OFFLOAD ABORT ret %d.\n", status);643 ret = -ENOENT;644 }645 646 return ret;647}648 649static void iwl_mvm_scan_fill_tx_cmd(struct iwl_mvm *mvm,650 struct iwl_scan_req_tx_cmd *tx_cmd,651 bool no_cck)652{653 tx_cmd[0].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |654 TX_CMD_FLG_BT_DIS);655 tx_cmd[0].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm,656 NL80211_BAND_2GHZ,657 no_cck);658 659 if (!iwl_mvm_has_new_station_api(mvm->fw)) {660 tx_cmd[0].sta_id = mvm->aux_sta.sta_id;661 tx_cmd[1].sta_id = mvm->aux_sta.sta_id;662 663 /*664 * Fw doesn't use this sta anymore, pending deprecation via HOST API665 * change666 */667 } else {668 tx_cmd[0].sta_id = 0xff;669 tx_cmd[1].sta_id = 0xff;670 }671 672 tx_cmd[1].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |673 TX_CMD_FLG_BT_DIS);674 675 tx_cmd[1].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm,676 NL80211_BAND_5GHZ,677 no_cck);678}679 680static void681iwl_mvm_lmac_scan_cfg_channels(struct iwl_mvm *mvm,682 struct ieee80211_channel **channels,683 int n_channels, u32 ssid_bitmap,684 struct iwl_scan_req_lmac *cmd)685{686 struct iwl_scan_channel_cfg_lmac *channel_cfg = (void *)&cmd->data;687 int i;688 689 for (i = 0; i < n_channels; i++) {690 channel_cfg[i].channel_num =691 cpu_to_le16(channels[i]->hw_value);692 channel_cfg[i].iter_count = cpu_to_le16(1);693 channel_cfg[i].iter_interval = 0;694 channel_cfg[i].flags =695 cpu_to_le32(IWL_UNIFIED_SCAN_CHANNEL_PARTIAL |696 ssid_bitmap);697 }698}699 700static u8 *iwl_mvm_copy_and_insert_ds_elem(struct iwl_mvm *mvm, const u8 *ies,701 size_t len, u8 *const pos)702{703 static const u8 before_ds_params[] = {704 WLAN_EID_SSID,705 WLAN_EID_SUPP_RATES,706 WLAN_EID_REQUEST,707 WLAN_EID_EXT_SUPP_RATES,708 };709 size_t offs;710 u8 *newpos = pos;711 712 if (!iwl_mvm_rrm_scan_needed(mvm)) {713 memcpy(newpos, ies, len);714 return newpos + len;715 }716 717 offs = ieee80211_ie_split(ies, len,718 before_ds_params,719 ARRAY_SIZE(before_ds_params),720 0);721 722 memcpy(newpos, ies, offs);723 newpos += offs;724 725 /* Add a placeholder for DS Parameter Set element */726 *newpos++ = WLAN_EID_DS_PARAMS;727 *newpos++ = 1;728 *newpos++ = 0;729 730 memcpy(newpos, ies + offs, len - offs);731 newpos += len - offs;732 733 return newpos;734}735 736static void iwl_mvm_add_tpc_report_ie(u8 *pos)737{738 pos[0] = WLAN_EID_VENDOR_SPECIFIC;739 pos[1] = WFA_TPC_IE_LEN - 2;740 pos[2] = (WLAN_OUI_MICROSOFT >> 16) & 0xff;741 pos[3] = (WLAN_OUI_MICROSOFT >> 8) & 0xff;742 pos[4] = WLAN_OUI_MICROSOFT & 0xff;743 pos[5] = WLAN_OUI_TYPE_MICROSOFT_TPC;744 pos[6] = 0;745 /* pos[7] - tx power will be inserted by the FW */746 pos[7] = 0;747 pos[8] = 0;748}749 750static void751iwl_mvm_build_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,752 struct ieee80211_scan_ies *ies,753 struct iwl_mvm_scan_params *params)754{755 struct ieee80211_mgmt *frame = (void *)params->preq.buf;756 u8 *pos, *newpos;757 const u8 *mac_addr = params->flags & NL80211_SCAN_FLAG_RANDOM_ADDR ?758 params->mac_addr : NULL;759 760 /*761 * Unfortunately, right now the offload scan doesn't support randomising762 * within the firmware, so until the firmware API is ready we implement763 * it in the driver. This means that the scan iterations won't really be764 * random, only when it's restarted, but at least that helps a bit.765 */766 if (mac_addr)767 get_random_mask_addr(frame->sa, mac_addr,768 params->mac_addr_mask);769 else770 memcpy(frame->sa, vif->addr, ETH_ALEN);771 772 frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);773 eth_broadcast_addr(frame->da);774 ether_addr_copy(frame->bssid, params->bssid);775 frame->seq_ctrl = 0;776 777 pos = frame->u.probe_req.variable;778 *pos++ = WLAN_EID_SSID;779 *pos++ = 0;780 781 params->preq.mac_header.offset = 0;782 params->preq.mac_header.len = cpu_to_le16(24 + 2);783 784 /* Insert ds parameter set element on 2.4 GHz band */785 newpos = iwl_mvm_copy_and_insert_ds_elem(mvm,786 ies->ies[NL80211_BAND_2GHZ],787 ies->len[NL80211_BAND_2GHZ],788 pos);789 params->preq.band_data[0].offset = cpu_to_le16(pos - params->preq.buf);790 params->preq.band_data[0].len = cpu_to_le16(newpos - pos);791 pos = newpos;792 793 memcpy(pos, ies->ies[NL80211_BAND_5GHZ],794 ies->len[NL80211_BAND_5GHZ]);795 params->preq.band_data[1].offset = cpu_to_le16(pos - params->preq.buf);796 params->preq.band_data[1].len =797 cpu_to_le16(ies->len[NL80211_BAND_5GHZ]);798 pos += ies->len[NL80211_BAND_5GHZ];799 800 memcpy(pos, ies->ies[NL80211_BAND_6GHZ],801 ies->len[NL80211_BAND_6GHZ]);802 params->preq.band_data[2].offset = cpu_to_le16(pos - params->preq.buf);803 params->preq.band_data[2].len =804 cpu_to_le16(ies->len[NL80211_BAND_6GHZ]);805 pos += ies->len[NL80211_BAND_6GHZ];806 memcpy(pos, ies->common_ies, ies->common_ie_len);807 params->preq.common_data.offset = cpu_to_le16(pos - params->preq.buf);808 809 if (iwl_mvm_rrm_scan_needed(mvm) &&810 !fw_has_capa(&mvm->fw->ucode_capa,811 IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT)) {812 iwl_mvm_add_tpc_report_ie(pos + ies->common_ie_len);813 params->preq.common_data.len = cpu_to_le16(ies->common_ie_len +814 WFA_TPC_IE_LEN);815 } else {816 params->preq.common_data.len = cpu_to_le16(ies->common_ie_len);817 }818}819 820static void iwl_mvm_scan_lmac_dwell(struct iwl_mvm *mvm,821 struct iwl_scan_req_lmac *cmd,822 struct iwl_mvm_scan_params *params)823{824 cmd->active_dwell = IWL_SCAN_DWELL_ACTIVE;825 cmd->passive_dwell = IWL_SCAN_DWELL_PASSIVE;826 cmd->fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED;827 cmd->extended_dwell = IWL_SCAN_DWELL_EXTENDED;828 cmd->max_out_time = cpu_to_le32(scan_timing[params->type].max_out_time);829 cmd->suspend_time = cpu_to_le32(scan_timing[params->type].suspend_time);830 cmd->scan_prio = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);831}832 833static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids,834 struct ieee80211_scan_ies *ies,835 int n_channels)836{837 return ((n_ssids <= PROBE_OPTION_MAX) &&838 (n_channels <= mvm->fw->ucode_capa.n_scan_channels) &839 (ies->common_ie_len +840 ies->len[NL80211_BAND_2GHZ] + ies->len[NL80211_BAND_5GHZ] +841 ies->len[NL80211_BAND_6GHZ] <=842 iwl_mvm_max_scan_ie_fw_cmd_room(mvm)));843}844 845static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm,846 struct ieee80211_vif *vif)847{848 const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa;849 bool low_latency;850 851 if (iwl_mvm_is_cdb_supported(mvm))852 low_latency = iwl_mvm_low_latency_band(mvm, NL80211_BAND_5GHZ);853 else854 low_latency = iwl_mvm_low_latency(mvm);855 856 /* We can only use EBS if:857 * 1. the feature is supported;858 * 2. the last EBS was successful;859 * 3. if only single scan, the single scan EBS API is supported;860 * 4. it's not a p2p find operation.861 * 5. we are not in low latency mode,862 * or if fragmented ebs is supported by the FW863 * 6. the VIF is not an AP interface (scan wants survey results)864 */865 return ((capa->flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT) &&866 mvm->last_ebs_successful && IWL_MVM_ENABLE_EBS &&867 vif->type != NL80211_IFTYPE_P2P_DEVICE &&868 (!low_latency || iwl_mvm_is_frag_ebs_supported(mvm)) &&869 ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_AP);870}871 872static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params)873{874 return params->n_scan_plans == 1 &&875 params->scan_plans[0].iterations == 1;876}877 878static bool iwl_mvm_is_scan_fragmented(enum iwl_mvm_scan_type type)879{880 return (type == IWL_SCAN_TYPE_FRAGMENTED ||881 type == IWL_SCAN_TYPE_FAST_BALANCE);882}883 884static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm,885 struct iwl_mvm_scan_params *params,886 struct ieee80211_vif *vif)887{888 int flags = 0;889 890 if (params->n_ssids == 0)891 flags |= IWL_MVM_LMAC_SCAN_FLAG_PASSIVE;892 893 if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0)894 flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION;895 896 if (iwl_mvm_is_scan_fragmented(params->type))897 flags |= IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED;898 899 if (iwl_mvm_rrm_scan_needed(mvm) &&900 fw_has_capa(&mvm->fw->ucode_capa,901 IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT))902 flags |= IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED;903 904 if (params->pass_all)905 flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL;906 else907 flags |= IWL_MVM_LMAC_SCAN_FLAG_MATCH;908 909#ifdef CONFIG_IWLWIFI_DEBUGFS910 if (mvm->scan_iter_notif_enabled)911 flags |= IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE;912#endif913 914 if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED)915 flags |= IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE;916 917 if (iwl_mvm_is_regular_scan(params) &&918 vif->type != NL80211_IFTYPE_P2P_DEVICE &&919 !iwl_mvm_is_scan_fragmented(params->type))920 flags |= IWL_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL;921 922 return flags;923}924 925static void926iwl_mvm_scan_set_legacy_probe_req(struct iwl_scan_probe_req_v1 *p_req,927 struct iwl_scan_probe_req *src_p_req)928{929 int i;930 931 p_req->mac_header = src_p_req->mac_header;932 for (i = 0; i < SCAN_NUM_BAND_PROBE_DATA_V_1; i++)933 p_req->band_data[i] = src_p_req->band_data[i];934 p_req->common_data = src_p_req->common_data;935 memcpy(p_req->buf, src_p_req->buf, sizeof(p_req->buf));936}937 938static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,939 struct iwl_mvm_scan_params *params)940{941 struct iwl_scan_req_lmac *cmd = mvm->scan_cmd;942 struct iwl_scan_probe_req_v1 *preq =943 (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *944 mvm->fw->ucode_capa.n_scan_channels);945 u32 ssid_bitmap = 0;946 int i;947 u8 band;948 949 if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))950 return -EINVAL;951 952 iwl_mvm_scan_lmac_dwell(mvm, cmd, params);953 954 cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm);955 cmd->iter_num = cpu_to_le32(1);956 cmd->n_channels = (u8)params->n_channels;957 958 cmd->delay = cpu_to_le32(params->delay);959 960 cmd->scan_flags = cpu_to_le32(iwl_mvm_scan_lmac_flags(mvm, params,961 vif));962 963 band = iwl_mvm_phy_band_from_nl80211(params->channels[0]->band);964 cmd->flags = cpu_to_le32(band);965 cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP |966 MAC_FILTER_IN_BEACON);967 iwl_mvm_scan_fill_tx_cmd(mvm, cmd->tx_cmd, params->no_cck);968 iwl_scan_build_ssids(params, cmd->direct_scan, &ssid_bitmap);969 970 /* this API uses bits 1-20 instead of 0-19 */971 ssid_bitmap <<= 1;972 973 for (i = 0; i < params->n_scan_plans; i++) {974 struct cfg80211_sched_scan_plan *scan_plan =975 ¶ms->scan_plans[i];976 977 cmd->schedule[i].delay =978 cpu_to_le16(scan_plan->interval);979 cmd->schedule[i].iterations = scan_plan->iterations;980 cmd->schedule[i].full_scan_mul = 1;981 }982 983 /*984 * If the number of iterations of the last scan plan is set to985 * zero, it should run infinitely. However, this is not always the case.986 * For example, when regular scan is requested the driver sets one scan987 * plan with one iteration.988 */989 if (!cmd->schedule[i - 1].iterations)990 cmd->schedule[i - 1].iterations = 0xff;991 992 if (iwl_mvm_scan_use_ebs(mvm, vif)) {993 cmd->channel_opt[0].flags =994 cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |995 IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |996 IWL_SCAN_CHANNEL_FLAG_CACHE_ADD);997 cmd->channel_opt[0].non_ebs_ratio =998 cpu_to_le16(IWL_DENSE_EBS_SCAN_RATIO);999 cmd->channel_opt[1].flags =1000 cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |1001 IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |1002 IWL_SCAN_CHANNEL_FLAG_CACHE_ADD);1003 cmd->channel_opt[1].non_ebs_ratio =1004 cpu_to_le16(IWL_SPARSE_EBS_SCAN_RATIO);1005 }1006 1007 iwl_mvm_lmac_scan_cfg_channels(mvm, params->channels,1008 params->n_channels, ssid_bitmap, cmd);1009 1010 iwl_mvm_scan_set_legacy_probe_req(preq, ¶ms->preq);1011 1012 return 0;1013}1014 1015static int rate_to_scan_rate_flag(unsigned int rate)1016{1017 static const int rate_to_scan_rate[IWL_RATE_COUNT] = {1018 [IWL_RATE_1M_INDEX] = SCAN_CONFIG_RATE_1M,1019 [IWL_RATE_2M_INDEX] = SCAN_CONFIG_RATE_2M,1020 [IWL_RATE_5M_INDEX] = SCAN_CONFIG_RATE_5M,1021 [IWL_RATE_11M_INDEX] = SCAN_CONFIG_RATE_11M,1022 [IWL_RATE_6M_INDEX] = SCAN_CONFIG_RATE_6M,1023 [IWL_RATE_9M_INDEX] = SCAN_CONFIG_RATE_9M,1024 [IWL_RATE_12M_INDEX] = SCAN_CONFIG_RATE_12M,1025 [IWL_RATE_18M_INDEX] = SCAN_CONFIG_RATE_18M,1026 [IWL_RATE_24M_INDEX] = SCAN_CONFIG_RATE_24M,1027 [IWL_RATE_36M_INDEX] = SCAN_CONFIG_RATE_36M,1028 [IWL_RATE_48M_INDEX] = SCAN_CONFIG_RATE_48M,1029 [IWL_RATE_54M_INDEX] = SCAN_CONFIG_RATE_54M,1030 };1031 1032 return rate_to_scan_rate[rate];1033}1034 1035static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm)1036{1037 struct ieee80211_supported_band *band;1038 unsigned int rates = 0;1039 int i;1040 1041 band = &mvm->nvm_data->bands[NL80211_BAND_2GHZ];1042 for (i = 0; i < band->n_bitrates; i++)1043 rates |= rate_to_scan_rate_flag(band->bitrates[i].hw_value);1044 band = &mvm->nvm_data->bands[NL80211_BAND_5GHZ];1045 for (i = 0; i < band->n_bitrates; i++)1046 rates |= rate_to_scan_rate_flag(band->bitrates[i].hw_value);1047 1048 /* Set both basic rates and supported rates */1049 rates |= SCAN_CONFIG_SUPPORTED_RATE(rates);1050 1051 return cpu_to_le32(rates);1052}1053 1054static void iwl_mvm_fill_scan_dwell(struct iwl_mvm *mvm,1055 struct iwl_scan_dwell *dwell)1056{1057 dwell->active = IWL_SCAN_DWELL_ACTIVE;1058 dwell->passive = IWL_SCAN_DWELL_PASSIVE;1059 dwell->fragmented = IWL_SCAN_DWELL_FRAGMENTED;1060 dwell->extended = IWL_SCAN_DWELL_EXTENDED;1061}1062 1063static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels,1064 u32 max_channels)1065{1066 struct ieee80211_supported_band *band;1067 int i, j = 0;1068 1069 band = &mvm->nvm_data->bands[NL80211_BAND_2GHZ];1070 for (i = 0; i < band->n_channels && j < max_channels; i++, j++)1071 channels[j] = band->channels[i].hw_value;1072 band = &mvm->nvm_data->bands[NL80211_BAND_5GHZ];1073 for (i = 0; i < band->n_channels && j < max_channels; i++, j++)1074 channels[j] = band->channels[i].hw_value;1075}1076 1077static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,1078 u32 flags, u8 channel_flags,1079 u32 max_channels)1080{1081 enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, NULL);1082 struct iwl_scan_config_v1 *cfg = config;1083 1084 cfg->flags = cpu_to_le32(flags);1085 cfg->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));1086 cfg->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));1087 cfg->legacy_rates = iwl_mvm_scan_config_rates(mvm);1088 cfg->out_of_channel_time = cpu_to_le32(scan_timing[type].max_out_time);1089 cfg->suspend_time = cpu_to_le32(scan_timing[type].suspend_time);1090 1091 iwl_mvm_fill_scan_dwell(mvm, &cfg->dwell);1092 1093 memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);1094 1095 /* This function should not be called when using ADD_STA ver >=12 */1096 WARN_ON_ONCE(iwl_mvm_has_new_station_api(mvm->fw));1097 1098 cfg->bcast_sta_id = mvm->aux_sta.sta_id;1099 cfg->channel_flags = channel_flags;1100 1101 iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels);1102}1103 1104static void iwl_mvm_fill_scan_config_v2(struct iwl_mvm *mvm, void *config,1105 u32 flags, u8 channel_flags,1106 u32 max_channels)1107{1108 struct iwl_scan_config_v2 *cfg = config;1109 1110 cfg->flags = cpu_to_le32(flags);1111 cfg->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));1112 cfg->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));1113 cfg->legacy_rates = iwl_mvm_scan_config_rates(mvm);1114 1115 if (iwl_mvm_is_cdb_supported(mvm)) {1116 enum iwl_mvm_scan_type lb_type, hb_type;1117 1118 lb_type = iwl_mvm_get_scan_type_band(mvm, NULL,1119 NL80211_BAND_2GHZ);1120 hb_type = iwl_mvm_get_scan_type_band(mvm, NULL,1121 NL80211_BAND_5GHZ);1122 1123 cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] =1124 cpu_to_le32(scan_timing[lb_type].max_out_time);1125 cfg->suspend_time[SCAN_LB_LMAC_IDX] =1126 cpu_to_le32(scan_timing[lb_type].suspend_time);1127 1128 cfg->out_of_channel_time[SCAN_HB_LMAC_IDX] =1129 cpu_to_le32(scan_timing[hb_type].max_out_time);1130 cfg->suspend_time[SCAN_HB_LMAC_IDX] =1131 cpu_to_le32(scan_timing[hb_type].suspend_time);1132 } else {1133 enum iwl_mvm_scan_type type =1134 iwl_mvm_get_scan_type(mvm, NULL);1135 1136 cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] =1137 cpu_to_le32(scan_timing[type].max_out_time);1138 cfg->suspend_time[SCAN_LB_LMAC_IDX] =1139 cpu_to_le32(scan_timing[type].suspend_time);1140 }1141 1142 iwl_mvm_fill_scan_dwell(mvm, &cfg->dwell);1143 1144 memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);1145 1146 /* This function should not be called when using ADD_STA ver >=12 */1147 WARN_ON_ONCE(iwl_mvm_has_new_station_api(mvm->fw));1148 1149 cfg->bcast_sta_id = mvm->aux_sta.sta_id;1150 cfg->channel_flags = channel_flags;1151 1152 iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels);1153}1154 1155static int iwl_mvm_legacy_config_scan(struct iwl_mvm *mvm)1156{1157 void *cfg;1158 int ret, cmd_size;1159 struct iwl_host_cmd cmd = {1160 .id = WIDE_ID(IWL_ALWAYS_LONG_GROUP, SCAN_CFG_CMD),1161 };1162 enum iwl_mvm_scan_type type;1163 enum iwl_mvm_scan_type hb_type = IWL_SCAN_TYPE_NOT_SET;1164 int num_channels =1165 mvm->nvm_data->bands[NL80211_BAND_2GHZ].n_channels +1166 mvm->nvm_data->bands[NL80211_BAND_5GHZ].n_channels;1167 u32 flags;1168 u8 channel_flags;1169 1170 if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels))1171 num_channels = mvm->fw->ucode_capa.n_scan_channels;1172 1173 if (iwl_mvm_is_cdb_supported(mvm)) {1174 type = iwl_mvm_get_scan_type_band(mvm, NULL,1175 NL80211_BAND_2GHZ);1176 hb_type = iwl_mvm_get_scan_type_band(mvm, NULL,1177 NL80211_BAND_5GHZ);1178 if (type == mvm->scan_type && hb_type == mvm->hb_scan_type)1179 return 0;1180 } else {1181 type = iwl_mvm_get_scan_type(mvm, NULL);1182 if (type == mvm->scan_type)1183 return 0;1184 }1185 1186 if (iwl_mvm_cdb_scan_api(mvm))1187 cmd_size = sizeof(struct iwl_scan_config_v2);1188 else1189 cmd_size = sizeof(struct iwl_scan_config_v1);1190 cmd_size += mvm->fw->ucode_capa.n_scan_channels;1191 1192 cfg = kzalloc(cmd_size, GFP_KERNEL);1193 if (!cfg)1194 return -ENOMEM;1195 1196 flags = SCAN_CONFIG_FLAG_ACTIVATE |1197 SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |1198 SCAN_CONFIG_FLAG_SET_TX_CHAINS |1199 SCAN_CONFIG_FLAG_SET_RX_CHAINS |1200 SCAN_CONFIG_FLAG_SET_AUX_STA_ID |1201 SCAN_CONFIG_FLAG_SET_ALL_TIMES |1202 SCAN_CONFIG_FLAG_SET_LEGACY_RATES |1203 SCAN_CONFIG_FLAG_SET_MAC_ADDR |1204 SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS |1205 SCAN_CONFIG_N_CHANNELS(num_channels) |1206 (iwl_mvm_is_scan_fragmented(type) ?1207 SCAN_CONFIG_FLAG_SET_FRAGMENTED :1208 SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED);1209 1210 channel_flags = IWL_CHANNEL_FLAG_EBS |1211 IWL_CHANNEL_FLAG_ACCURATE_EBS |1212 IWL_CHANNEL_FLAG_EBS_ADD |1213 IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;1214 1215 /*1216 * Check for fragmented scan on LMAC2 - high band.1217 * LMAC1 - low band is checked above.1218 */1219 if (iwl_mvm_cdb_scan_api(mvm)) {1220 if (iwl_mvm_is_cdb_supported(mvm))1221 flags |= (iwl_mvm_is_scan_fragmented(hb_type)) ?1222 SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED :1223 SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED;1224 iwl_mvm_fill_scan_config_v2(mvm, cfg, flags, channel_flags,1225 num_channels);1226 } else {1227 iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags,1228 num_channels);1229 }1230 1231 cmd.data[0] = cfg;1232 cmd.len[0] = cmd_size;1233 cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;1234 1235 IWL_DEBUG_SCAN(mvm, "Sending UMAC scan config\n");1236 1237 ret = iwl_mvm_send_cmd(mvm, &cmd);1238 if (!ret) {1239 mvm->scan_type = type;1240 mvm->hb_scan_type = hb_type;1241 }1242 1243 kfree(cfg);1244 return ret;1245}1246 1247int iwl_mvm_config_scan(struct iwl_mvm *mvm)1248{1249 struct iwl_scan_config cfg;1250 struct iwl_host_cmd cmd = {1251 .id = WIDE_ID(IWL_ALWAYS_LONG_GROUP, SCAN_CFG_CMD),1252 .len[0] = sizeof(cfg),1253 .data[0] = &cfg,1254 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,1255 };1256 1257 if (!iwl_mvm_is_reduced_config_scan_supported(mvm))1258 return iwl_mvm_legacy_config_scan(mvm);1259 1260 memset(&cfg, 0, sizeof(cfg));1261 1262 if (!iwl_mvm_has_new_station_api(mvm->fw)) {1263 cfg.bcast_sta_id = mvm->aux_sta.sta_id;1264 } else if (iwl_fw_lookup_cmd_ver(mvm->fw, SCAN_CFG_CMD, 0) < 5) {1265 /*1266 * Fw doesn't use this sta anymore. Deprecated on SCAN_CFG_CMD1267 * version 5.1268 */1269 cfg.bcast_sta_id = 0xff;1270 }1271 1272 cfg.tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));1273 cfg.rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));1274 1275 IWL_DEBUG_SCAN(mvm, "Sending UMAC scan config\n");1276 1277 return iwl_mvm_send_cmd(mvm, &cmd);1278}1279 1280static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status)1281{1282 int i;1283 1284 for (i = 0; i < mvm->max_scans; i++)1285 if (mvm->scan_uid_status[i] == status)1286 return i;1287 1288 return -ENOENT;1289}1290 1291static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,1292 struct iwl_scan_req_umac *cmd,1293 struct iwl_mvm_scan_params *params)1294{1295 struct iwl_mvm_scan_timing_params *timing, *hb_timing;1296 u8 active_dwell, passive_dwell;1297 1298 timing = &scan_timing[params->type];1299 active_dwell = IWL_SCAN_DWELL_ACTIVE;1300 passive_dwell = IWL_SCAN_DWELL_PASSIVE;1301 1302 if (iwl_mvm_is_adaptive_dwell_supported(mvm)) {1303 cmd->v7.adwell_default_n_aps_social =1304 IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;1305 cmd->v7.adwell_default_n_aps =1306 IWL_SCAN_ADWELL_DEFAULT_LB_N_APS;1307 1308 if (iwl_mvm_is_adwell_hb_ap_num_supported(mvm))1309 cmd->v9.adwell_default_hb_n_aps =1310 IWL_SCAN_ADWELL_DEFAULT_HB_N_APS;1311 1312 /* if custom max budget was configured with debugfs */1313 if (IWL_MVM_ADWELL_MAX_BUDGET)1314 cmd->v7.adwell_max_budget =1315 cpu_to_le16(IWL_MVM_ADWELL_MAX_BUDGET);1316 else if (params->n_ssids && params->ssids[0].ssid_len)1317 cmd->v7.adwell_max_budget =1318 cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);1319 else1320 cmd->v7.adwell_max_budget =1321 cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN);1322 1323 cmd->v7.scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);1324 cmd->v7.max_out_time[SCAN_LB_LMAC_IDX] =1325 cpu_to_le32(timing->max_out_time);1326 cmd->v7.suspend_time[SCAN_LB_LMAC_IDX] =1327 cpu_to_le32(timing->suspend_time);1328 1329 if (iwl_mvm_is_cdb_supported(mvm)) {1330 hb_timing = &scan_timing[params->hb_type];1331 1332 cmd->v7.max_out_time[SCAN_HB_LMAC_IDX] =1333 cpu_to_le32(hb_timing->max_out_time);1334 cmd->v7.suspend_time[SCAN_HB_LMAC_IDX] =1335 cpu_to_le32(hb_timing->suspend_time);1336 }1337 1338 if (!iwl_mvm_is_adaptive_dwell_v2_supported(mvm)) {1339 cmd->v7.active_dwell = active_dwell;1340 cmd->v7.passive_dwell = passive_dwell;1341 cmd->v7.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED;1342 } else {1343 cmd->v8.active_dwell[SCAN_LB_LMAC_IDX] = active_dwell;1344 cmd->v8.passive_dwell[SCAN_LB_LMAC_IDX] = passive_dwell;1345 if (iwl_mvm_is_cdb_supported(mvm)) {1346 cmd->v8.active_dwell[SCAN_HB_LMAC_IDX] =1347 active_dwell;1348 cmd->v8.passive_dwell[SCAN_HB_LMAC_IDX] =1349 passive_dwell;1350 }1351 }1352 } else {1353 cmd->v1.extended_dwell = IWL_SCAN_DWELL_EXTENDED;1354 cmd->v1.active_dwell = active_dwell;1355 cmd->v1.passive_dwell = passive_dwell;1356 cmd->v1.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED;1357 1358 if (iwl_mvm_is_cdb_supported(mvm)) {1359 hb_timing = &scan_timing[params->hb_type];1360 1361 cmd->v6.max_out_time[SCAN_HB_LMAC_IDX] =1362 cpu_to_le32(hb_timing->max_out_time);1363 cmd->v6.suspend_time[SCAN_HB_LMAC_IDX] =1364 cpu_to_le32(hb_timing->suspend_time);1365 }1366 1367 if (iwl_mvm_cdb_scan_api(mvm)) {1368 cmd->v6.scan_priority =1369 cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);1370 cmd->v6.max_out_time[SCAN_LB_LMAC_IDX] =1371 cpu_to_le32(timing->max_out_time);1372 cmd->v6.suspend_time[SCAN_LB_LMAC_IDX] =1373 cpu_to_le32(timing->suspend_time);1374 } else {1375 cmd->v1.scan_priority =1376 cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);1377 cmd->v1.max_out_time =1378 cpu_to_le32(timing->max_out_time);1379 cmd->v1.suspend_time =1380 cpu_to_le32(timing->suspend_time);1381 }1382 }1383 1384 if (iwl_mvm_is_regular_scan(params))1385 cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);1386 else1387 cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_2);1388}1389 1390static u32 iwl_mvm_scan_umac_ooc_priority(int type)1391{1392 if (type == IWL_MVM_SCAN_REGULAR)1393 return IWL_SCAN_PRIORITY_EXT_6;1394 if (type == IWL_MVM_SCAN_INT_MLO)1395 return IWL_SCAN_PRIORITY_EXT_4;1396 1397 return IWL_SCAN_PRIORITY_EXT_2;1398}1399 1400static void1401iwl_mvm_scan_umac_dwell_v11(struct iwl_mvm *mvm,1402 struct iwl_scan_general_params_v11 *general_params,1403 struct iwl_mvm_scan_params *params)1404{1405 struct iwl_mvm_scan_timing_params *timing, *hb_timing;1406 u8 active_dwell, passive_dwell;1407 1408 timing = &scan_timing[params->type];1409 active_dwell = IWL_SCAN_DWELL_ACTIVE;1410 passive_dwell = IWL_SCAN_DWELL_PASSIVE;1411 1412 general_params->adwell_default_social_chn =1413 IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;1414 general_params->adwell_default_2g = IWL_SCAN_ADWELL_DEFAULT_LB_N_APS;1415 general_params->adwell_default_5g = IWL_SCAN_ADWELL_DEFAULT_HB_N_APS;1416 1417 /* if custom max budget was configured with debugfs */1418 if (IWL_MVM_ADWELL_MAX_BUDGET)1419 general_params->adwell_max_budget =1420 cpu_to_le16(IWL_MVM_ADWELL_MAX_BUDGET);1421 else if (params->n_ssids && params->ssids[0].ssid_len)1422 general_params->adwell_max_budget =1423 cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);1424 else1425 general_params->adwell_max_budget =1426 cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN);1427 1428 general_params->scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);1429 general_params->max_out_of_time[SCAN_LB_LMAC_IDX] =1430 cpu_to_le32(timing->max_out_time);1431 general_params->suspend_time[SCAN_LB_LMAC_IDX] =1432 cpu_to_le32(timing->suspend_time);1433 1434 hb_timing = &scan_timing[params->hb_type];1435 1436 general_params->max_out_of_time[SCAN_HB_LMAC_IDX] =1437 cpu_to_le32(hb_timing->max_out_time);1438 general_params->suspend_time[SCAN_HB_LMAC_IDX] =1439 cpu_to_le32(hb_timing->suspend_time);1440 1441 general_params->active_dwell[SCAN_LB_LMAC_IDX] = active_dwell;1442 general_params->passive_dwell[SCAN_LB_LMAC_IDX] = passive_dwell;1443 general_params->active_dwell[SCAN_HB_LMAC_IDX] = active_dwell;1444 general_params->passive_dwell[SCAN_HB_LMAC_IDX] = passive_dwell;1445}1446 1447struct iwl_mvm_scan_channel_segment {1448 u8 start_idx;1449 u8 end_idx;1450 u8 first_channel_id;1451 u8 last_channel_id;1452 u8 channel_spacing_shift;1453 u8 band;1454};1455 1456static const struct iwl_mvm_scan_channel_segment scan_channel_segments[] = {1457 {1458 .start_idx = 0,1459 .end_idx = 13,1460 .first_channel_id = 1,1461 .last_channel_id = 14,1462 .channel_spacing_shift = 0,1463 .band = PHY_BAND_241464 },1465 {1466 .start_idx = 14,1467 .end_idx = 41,1468 .first_channel_id = 36,1469 .last_channel_id = 144,1470 .channel_spacing_shift = 2,1471 .band = PHY_BAND_51472 },1473 {1474 .start_idx = 42,1475 .end_idx = 50,1476 .first_channel_id = 149,1477 .last_channel_id = 181,1478 .channel_spacing_shift = 2,1479 .band = PHY_BAND_51480 },1481 {1482 .start_idx = 51,1483 .end_idx = 111,1484 .first_channel_id = 1,1485 .last_channel_id = 241,1486 .channel_spacing_shift = 2,1487 .band = PHY_BAND_61488 },1489};1490 1491static int iwl_mvm_scan_ch_and_band_to_idx(u8 channel_id, u8 band)1492{1493 int i, index;1494 1495 if (!channel_id)1496 return -EINVAL;1497 1498 for (i = 0; i < ARRAY_SIZE(scan_channel_segments); i++) {1499 const struct iwl_mvm_scan_channel_segment *ch_segment =1500 &scan_channel_segments[i];1501 u32 ch_offset;1502 1503 if (ch_segment->band != band ||1504 ch_segment->first_channel_id > channel_id ||1505 ch_segment->last_channel_id < channel_id)1506 continue;1507 1508 ch_offset = (channel_id - ch_segment->first_channel_id) >>1509 ch_segment->channel_spacing_shift;1510 1511 index = scan_channel_segments[i].start_idx + ch_offset;1512 if (index < IWL_SCAN_NUM_CHANNELS)1513 return index;1514 1515 break;1516 }1517 1518 return -EINVAL;1519}1520 1521static const u8 p2p_go_friendly_chs[] = {1522 36, 40, 44, 48, 149, 153, 157, 161, 165,1523};1524 1525static const u8 social_chs[] = {1526 1, 6, 111527};1528 1529static void iwl_mvm_scan_ch_add_n_aps_override(enum nl80211_iftype vif_type,1530 u8 ch_id, u8 band, u8 *ch_bitmap,1531 size_t bitmap_n_entries)1532{1533 int i;1534 1535 if (vif_type != NL80211_IFTYPE_P2P_DEVICE)1536 return;1537 1538 for (i = 0; i < ARRAY_SIZE(p2p_go_friendly_chs); i++) {1539 if (p2p_go_friendly_chs[i] == ch_id) {1540 int ch_idx, bitmap_idx;1541 1542 ch_idx = iwl_mvm_scan_ch_and_band_to_idx(ch_id, band);1543 if (ch_idx < 0)1544 return;1545 1546 bitmap_idx = ch_idx / 8;1547 if (bitmap_idx >= bitmap_n_entries)1548 return;1549 1550 ch_idx = ch_idx % 8;1551 ch_bitmap[bitmap_idx] |= BIT(ch_idx);1552 1553 return;1554 }1555 }1556}1557 1558static u32 iwl_mvm_scan_ch_n_aps_flag(enum nl80211_iftype vif_type, u8 ch_id)1559{1560 int i;1561 u32 flags = 0;1562 1563 if (vif_type != NL80211_IFTYPE_P2P_DEVICE)1564 goto out;1565 1566 for (i = 0; i < ARRAY_SIZE(p2p_go_friendly_chs); i++) {1567 if (p2p_go_friendly_chs[i] == ch_id) {1568 flags |= IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY_BIT;1569 break;1570 }1571 }1572 1573 if (flags)1574 goto out;1575 1576 for (i = 0; i < ARRAY_SIZE(social_chs); i++) {1577 if (social_chs[i] == ch_id) {1578 flags |= IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS_BIT;1579 break;1580 }1581 }1582 1583out:1584 return flags;1585}1586 1587static void1588iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,1589 struct ieee80211_channel **channels,1590 int n_channels, u32 flags,1591 struct iwl_scan_channel_cfg_umac *channel_cfg)1592{1593 int i;1594 1595 for (i = 0; i < n_channels; i++) {1596 channel_cfg[i].flags = cpu_to_le32(flags);1597 channel_cfg[i].channel_num = channels[i]->hw_value;1598 if (iwl_mvm_is_scan_ext_chan_supported(mvm)) {1599 enum nl80211_band band = channels[i]->band;1600 1601 channel_cfg[i].v2.band =1602 iwl_mvm_phy_band_from_nl80211(band);1603 channel_cfg[i].v2.iter_count = 1;1604 channel_cfg[i].v2.iter_interval = 0;1605 } else {1606 channel_cfg[i].v1.iter_count = 1;1607 channel_cfg[i].v1.iter_interval = 0;1608 }1609 }1610}1611 1612static void1613iwl_mvm_umac_scan_cfg_channels_v4(struct iwl_mvm *mvm,1614 struct ieee80211_channel **channels,1615 struct iwl_scan_channel_params_v4 *cp,1616 int n_channels, u32 flags,1617 enum nl80211_iftype vif_type)1618{1619 u8 *bitmap = cp->adwell_ch_override_bitmap;1620 size_t bitmap_n_entries = ARRAY_SIZE(cp->adwell_ch_override_bitmap);1621 int i;1622 1623 for (i = 0; i < n_channels; i++) {1624 enum nl80211_band band = channels[i]->band;1625 struct iwl_scan_channel_cfg_umac *cfg =1626 &cp->channel_config[i];1627 1628 cfg->flags = cpu_to_le32(flags);1629 cfg->channel_num = channels[i]->hw_value;1630 cfg->v2.band = iwl_mvm_phy_band_from_nl80211(band);1631 cfg->v2.iter_count = 1;1632 cfg->v2.iter_interval = 0;1633 1634 iwl_mvm_scan_ch_add_n_aps_override(vif_type,1635 cfg->channel_num,1636 cfg->v2.band, bitmap,1637 bitmap_n_entries);1638 }1639}1640 1641static void1642iwl_mvm_umac_scan_cfg_channels_v7(struct iwl_mvm *mvm,1643 struct ieee80211_channel **channels,1644 struct iwl_scan_channel_params_v7 *cp,1645 int n_channels, u32 flags,1646 enum nl80211_iftype vif_type, u32 version)1647{1648 int i;1649 1650 for (i = 0; i < n_channels; i++) {1651 enum nl80211_band band = channels[i]->band;1652 struct iwl_scan_channel_cfg_umac *cfg = &cp->channel_config[i];1653 u32 n_aps_flag =1654 iwl_mvm_scan_ch_n_aps_flag(vif_type,1655 channels[i]->hw_value);1656 u8 iwl_band = iwl_mvm_phy_band_from_nl80211(band);1657 1658 cfg->flags = cpu_to_le32(flags | n_aps_flag);1659 cfg->channel_num = channels[i]->hw_value;1660 if (cfg80211_channel_is_psc(channels[i]))1661 cfg->flags = 0;1662 1663 if (band == NL80211_BAND_6GHZ) {1664 /* 6 GHz channels should only appear in a scan request1665 * that has scan_6ghz set. The only exception is MLO1666 * scan, which has to be passive.1667 */1668 WARN_ON_ONCE(cfg->flags != 0);1669 cfg->flags =1670 cpu_to_le32(IWL_UHB_CHAN_CFG_FLAG_FORCE_PASSIVE);1671 }1672 1673 cfg->v2.iter_count = 1;1674 cfg->v2.iter_interval = 0;1675 if (version < 17)1676 cfg->v2.band = iwl_band;1677 else1678 cfg->flags |= cpu_to_le32((iwl_band <<1679 IWL_CHAN_CFG_FLAGS_BAND_POS));1680 }1681}1682 1683static void1684iwl_mvm_umac_scan_fill_6g_chan_list(struct iwl_mvm *mvm,1685 struct iwl_mvm_scan_params *params,1686 struct iwl_scan_probe_params_v4 *pp)1687{1688 int j, idex_s = 0, idex_b = 0;1689 struct cfg80211_scan_6ghz_params *scan_6ghz_params =1690 params->scan_6ghz_params;1691 bool hidden_supported = fw_has_capa(&mvm->fw->ucode_capa,1692 IWL_UCODE_TLV_CAPA_HIDDEN_6GHZ_SCAN);1693 1694 for (j = 0; j < params->n_ssids && idex_s < SCAN_SHORT_SSID_MAX_SIZE;1695 j++) {1696 if (!params->ssids[j].ssid_len)1697 continue;1698 1699 pp->short_ssid[idex_s] =1700 cpu_to_le32(~crc32_le(~0, params->ssids[j].ssid,1701 params->ssids[j].ssid_len));1702 1703 if (hidden_supported) {1704 pp->direct_scan[idex_s].id = WLAN_EID_SSID;1705 pp->direct_scan[idex_s].len = params->ssids[j].ssid_len;1706 memcpy(pp->direct_scan[idex_s].ssid, params->ssids[j].ssid,1707 params->ssids[j].ssid_len);1708 }1709 idex_s++;1710 }1711 1712 /*1713 * Populate the arrays of the short SSIDs and the BSSIDs using the 6GHz1714 * collocated parameters. This might not be optimal, as this processing1715 * does not (yet) correspond to the actual channels, so it is possible1716 * that some entries would be left out.1717 *1718 * TODO: improve this logic.1719 */1720 for (j = 0; j < params->n_6ghz_params; j++) {1721 int k;1722 1723 /* First, try to place the short SSID */1724 if (scan_6ghz_params[j].short_ssid_valid) {1725 for (k = 0; k < idex_s; k++) {1726 if (pp->short_ssid[k] ==1727 cpu_to_le32(scan_6ghz_params[j].short_ssid))1728 break;1729 }1730 1731 if (k == idex_s && idex_s < SCAN_SHORT_SSID_MAX_SIZE) {1732 pp->short_ssid[idex_s++] =1733 cpu_to_le32(scan_6ghz_params[j].short_ssid);1734 }1735 }1736 1737 /* try to place BSSID for the same entry */1738 for (k = 0; k < idex_b; k++) {1739 if (!memcmp(&pp->bssid_array[k],1740 scan_6ghz_params[j].bssid, ETH_ALEN))1741 break;1742 }1743 1744 if (k == idex_b && idex_b < SCAN_BSSID_MAX_SIZE &&1745 !WARN_ONCE(!is_valid_ether_addr(scan_6ghz_params[j].bssid),1746 "scan: invalid BSSID at index %u, index_b=%u\n",1747 j, idex_b)) {1748 memcpy(&pp->bssid_array[idex_b++],1749 scan_6ghz_params[j].bssid, ETH_ALEN);1750 }1751 }1752 1753 pp->short_ssid_num = idex_s;1754 pp->bssid_num = idex_b;1755}1756 1757/* TODO: this function can be merged with iwl_mvm_scan_umac_fill_ch_p_v7 */1758static u321759iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm,1760 struct iwl_mvm_scan_params *params,1761 u32 n_channels,1762 struct iwl_scan_probe_params_v4 *pp,1763 struct iwl_scan_channel_params_v7 *cp,1764 enum nl80211_iftype vif_type,1765 u32 version)1766{1767 int i;1768 struct cfg80211_scan_6ghz_params *scan_6ghz_params =1769 params->scan_6ghz_params;1770 u32 ch_cnt;1771 1772 for (i = 0, ch_cnt = 0; i < params->n_channels; i++) {1773 struct iwl_scan_channel_cfg_umac *cfg =1774 &cp->channel_config[ch_cnt];1775 1776 u32 s_ssid_bitmap = 0, bssid_bitmap = 0, flags = 0;1777 u8 k, n_s_ssids = 0, n_bssids = 0;1778 u8 max_s_ssids, max_bssids;1779 bool force_passive = false, found = false, allow_passive = true,1780 unsolicited_probe_on_chan = false, psc_no_listen = false;1781 s8 psd_20 = IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED;1782 1783 /*1784 * Avoid performing passive scan on non PSC channels unless the1785 * scan is specifically a passive scan, i.e., no SSIDs1786 * configured in the scan command.1787 */1788 if (!cfg80211_channel_is_psc(params->channels[i]) &&1789 !params->n_6ghz_params && params->n_ssids)1790 continue;1791 1792 cfg->channel_num = params->channels[i]->hw_value;1793 if (version < 17)1794 cfg->v2.band = PHY_BAND_6;1795 else1796 cfg->flags |= cpu_to_le32(PHY_BAND_6 <<1797 IWL_CHAN_CFG_FLAGS_BAND_POS);1798 1799 cfg->v5.iter_count = 1;1800 cfg->v5.iter_interval = 0;1801 1802 for (u32 j = 0; j < params->n_6ghz_params; j++) {1803 s8 tmp_psd_20;1804 1805 if (!(scan_6ghz_params[j].channel_idx == i))1806 continue;1807 1808 unsolicited_probe_on_chan |=1809 scan_6ghz_params[j].unsolicited_probe;1810 1811 /* Use the highest PSD value allowed as advertised by1812 * APs for this channel1813 */1814 tmp_psd_20 = scan_6ghz_params[j].psd_20;1815 if (tmp_psd_20 !=1816 IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED &&1817 (psd_20 ==1818 IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED ||1819 psd_20 < tmp_psd_20))1820 psd_20 = tmp_psd_20;1821 1822 psc_no_listen |= scan_6ghz_params[j].psc_no_listen;1823 }1824 1825 /*1826 * In the following cases apply passive scan:1827 * 1. Non fragmented scan:1828 * - PSC channel with NO_LISTEN_FLAG on should be treated1829 * like non PSC channel1830 * - Non PSC channel with more than 3 short SSIDs or more1831 * than 9 BSSIDs.1832 * - Non PSC Channel with unsolicited probe response and1833 * more than 2 short SSIDs or more than 6 BSSIDs.1834 * - PSC channel with more than 2 short SSIDs or more than1835 * 6 BSSIDs.1836 * 3. Fragmented scan:1837 * - PSC channel with more than 1 SSID or 3 BSSIDs.1838 * - Non PSC channel with more than 2 SSIDs or 6 BSSIDs.1839 * - Non PSC channel with unsolicited probe response and1840 * more than 1 SSID or more than 3 BSSIDs.1841 */1842 if (!iwl_mvm_is_scan_fragmented(params->type)) {1843 if (!cfg80211_channel_is_psc(params->channels[i]) ||1844 psc_no_listen) {1845 if (unsolicited_probe_on_chan) {1846 max_s_ssids = 2;1847 max_bssids = 6;1848 } else {1849 max_s_ssids = 3;1850 max_bssids = 9;1851 }1852 } else {1853 max_s_ssids = 2;1854 max_bssids = 6;1855 }1856 } else if (cfg80211_channel_is_psc(params->channels[i])) {1857 max_s_ssids = 1;1858 max_bssids = 3;1859 } else {1860 if (unsolicited_probe_on_chan) {1861 max_s_ssids = 1;1862 max_bssids = 3;1863 } else {1864 max_s_ssids = 2;1865 max_bssids = 6;1866 }1867 }1868 1869 /*1870 * The optimize the scan time, i.e., reduce the scan dwell time1871 * on each channel, the below logic tries to set 3 direct BSSID1872 * probe requests for each broadcast probe request with a short1873 * SSID.1874 * TODO: improve this logic1875 */1876 for (u32 j = 0; j < params->n_6ghz_params; j++) {1877 if (!(scan_6ghz_params[j].channel_idx == i))1878 continue;1879 1880 found = false;1881 1882 for (k = 0;1883 k < pp->short_ssid_num && n_s_ssids < max_s_ssids;1884 k++) {1885 if (!scan_6ghz_params[j].unsolicited_probe &&1886 le32_to_cpu(pp->short_ssid[k]) ==1887 scan_6ghz_params[j].short_ssid) {1888 /* Relevant short SSID bit set */1889 if (s_ssid_bitmap & BIT(k)) {1890 found = true;1891 break;1892 }1893 1894 /*1895 * Prefer creating BSSID entries unless1896 * the short SSID probe can be done in1897 * the same channel dwell iteration.1898 *1899 * We also need to create a short SSID1900 * entry for any hidden AP.1901 */1902 if (3 * n_s_ssids > n_bssids &&1903 !pp->direct_scan[k].len)1904 break;1905 1906 /* Hidden AP, cannot do passive scan */1907 if (pp->direct_scan[k].len)1908 allow_passive = false;1909 1910 s_ssid_bitmap |= BIT(k);1911 n_s_ssids++;1912 found = true;1913 break;1914 }1915 }1916 1917 if (found)1918 continue;1919 1920 for (k = 0; k < pp->bssid_num; k++) {1921 if (!memcmp(&pp->bssid_array[k],1922 scan_6ghz_params[j].bssid,1923 ETH_ALEN)) {1924 if (!(bssid_bitmap & BIT(k))) {1925 if (n_bssids < max_bssids) {1926 bssid_bitmap |= BIT(k);1927 n_bssids++;1928 } else {1929 force_passive = TRUE;1930 }1931 }1932 break;1933 }1934 }1935 }1936 1937 if (cfg80211_channel_is_psc(params->channels[i]) &&1938 psc_no_listen)1939 flags |= IWL_UHB_CHAN_CFG_FLAG_PSC_CHAN_NO_LISTEN;1940 1941 if (unsolicited_probe_on_chan)1942 flags |= IWL_UHB_CHAN_CFG_FLAG_UNSOLICITED_PROBE_RES;1943 1944 if ((allow_passive && force_passive) ||1945 (!(bssid_bitmap | s_ssid_bitmap) &&1946 !cfg80211_channel_is_psc(params->channels[i])))1947 flags |= IWL_UHB_CHAN_CFG_FLAG_FORCE_PASSIVE;1948 else1949 flags |= bssid_bitmap | (s_ssid_bitmap << 16);1950 1951 cfg->flags |= cpu_to_le32(flags);1952 if (version >= 17)1953 cfg->v5.psd_20 = psd_20;1954 1955 ch_cnt++;1956 }1957 1958 if (params->n_channels > ch_cnt)1959 IWL_DEBUG_SCAN(mvm,1960 "6GHz: reducing number channels: (%u->%u)\n",1961 params->n_channels, ch_cnt);1962 1963 return ch_cnt;1964}1965 1966static u8 iwl_mvm_scan_umac_chan_flags_v2(struct iwl_mvm *mvm,1967 struct iwl_mvm_scan_params *params,1968 struct ieee80211_vif *vif)1969{1970 u8 flags = 0;1971 1972 flags |= IWL_SCAN_CHANNEL_FLAG_ENABLE_CHAN_ORDER;1973 1974 if (iwl_mvm_scan_use_ebs(mvm, vif))1975 flags |= IWL_SCAN_CHANNEL_FLAG_EBS |1976 IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |1977 IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;1978 1979 /* set fragmented ebs for fragmented scan on HB channels */1980 if ((!iwl_mvm_is_cdb_supported(mvm) &&1981 iwl_mvm_is_scan_fragmented(params->type)) ||1982 (iwl_mvm_is_cdb_supported(mvm) &&1983 iwl_mvm_is_scan_fragmented(params->hb_type)))1984 flags |= IWL_SCAN_CHANNEL_FLAG_EBS_FRAG;1985 1986 /*1987 * force EBS in case the scan is a fragmented and there is a need to take P2P1988 * GO operation into consideration during scan operation.1989 */1990 if ((!iwl_mvm_is_cdb_supported(mvm) &&1991 iwl_mvm_is_scan_fragmented(params->type) && params->respect_p2p_go) ||1992 (iwl_mvm_is_cdb_supported(mvm) &&1993 iwl_mvm_is_scan_fragmented(params->hb_type) &&1994 params->respect_p2p_go_hb)) {1995 IWL_DEBUG_SCAN(mvm, "Respect P2P GO. Force EBS\n");1996 flags |= IWL_SCAN_CHANNEL_FLAG_FORCE_EBS;1997 }1998 1999 return flags;2000}2001 2002static void iwl_mvm_scan_6ghz_passive_scan(struct iwl_mvm *mvm,2003 struct iwl_mvm_scan_params *params,2004 struct ieee80211_vif *vif)2005{2006 struct ieee80211_supported_band *sband =2007 &mvm->nvm_data->bands[NL80211_BAND_6GHZ];2008 u32 n_disabled, i;2009 2010 params->enable_6ghz_passive = false;2011 2012 if (params->scan_6ghz)2013 return;2014 2015 if (!fw_has_capa(&mvm->fw->ucode_capa,2016 IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN)) {2017 IWL_DEBUG_SCAN(mvm,2018 "6GHz passive scan: Not supported by FW\n");2019 return;2020 }2021 2022 /* 6GHz passive scan allowed only on station interface */2023 if (vif->type != NL80211_IFTYPE_STATION) {2024 IWL_DEBUG_SCAN(mvm,2025 "6GHz passive scan: not station interface\n");2026 return;2027 }2028 2029 /*2030 * 6GHz passive scan is allowed in a defined time interval following HW2031 * reset or resume flow, or while not associated and a large interval2032 * has passed since the last 6GHz passive scan.2033 */2034 if ((vif->cfg.assoc ||2035 time_after(mvm->last_6ghz_passive_scan_jiffies +2036 (IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT * HZ), jiffies)) &&2037 (time_before(mvm->last_reset_or_resume_time_jiffies +2038 (IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT * HZ),2039 jiffies))) {2040 IWL_DEBUG_SCAN(mvm, "6GHz passive scan: %s\n",2041 vif->cfg.assoc ? "associated" :2042 "timeout did not expire");2043 return;2044 }2045 2046 /* not enough channels in the regular scan request */2047 if (params->n_channels < IWL_MVM_6GHZ_PASSIVE_SCAN_MIN_CHANS) {2048 IWL_DEBUG_SCAN(mvm,2049 "6GHz passive scan: not enough channels\n");2050 return;2051 }2052 2053 for (i = 0; i < params->n_ssids; i++) {2054 if (!params->ssids[i].ssid_len)2055 break;2056 }2057 2058 /* not a wildcard scan, so cannot enable passive 6GHz scan */2059 if (i == params->n_ssids) {2060 IWL_DEBUG_SCAN(mvm,2061 "6GHz passive scan: no wildcard SSID\n");2062 return;2063 }2064 2065 if (!sband || !sband->n_channels) {2066 IWL_DEBUG_SCAN(mvm,2067 "6GHz passive scan: no 6GHz channels\n");2068 return;2069 }2070 2071 for (i = 0, n_disabled = 0; i < sband->n_channels; i++) {2072 if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED))2073 n_disabled++;2074 }2075 2076 /*2077 * Not all the 6GHz channels are disabled, so no need for 6GHz passive2078 * scan2079 */2080 if (n_disabled != sband->n_channels) {2081 IWL_DEBUG_SCAN(mvm,2082 "6GHz passive scan: 6GHz channels enabled\n");2083 return;2084 }2085 2086 /* all conditions to enable 6ghz passive scan are satisfied */2087 IWL_DEBUG_SCAN(mvm, "6GHz passive scan: can be enabled\n");2088 params->enable_6ghz_passive = true;2089}2090 2091static u16 iwl_mvm_scan_umac_flags_v2(struct iwl_mvm *mvm,2092 struct iwl_mvm_scan_params *params,2093 struct ieee80211_vif *vif,2094 int type)2095{2096 u16 flags = 0;2097 2098 /*2099 * If no direct SSIDs are provided perform a passive scan. Otherwise,2100 * if there is a single SSID which is not the broadcast SSID, assume2101 * that the scan is intended for roaming purposes and thus enable Rx on2102 * all chains to improve chances of hearing the beacons/probe responses.2103 */2104 if (params->n_ssids == 0)2105 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE;2106 else if (params->n_ssids == 1 && params->ssids[0].ssid_len)2107 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_USE_ALL_RX_CHAINS;2108 2109 if (iwl_mvm_is_scan_fragmented(params->type))2110 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1;2111 2112 if (iwl_mvm_is_scan_fragmented(params->hb_type))2113 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2;2114 2115 if (params->pass_all)2116 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_PASS_ALL;2117 else2118 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_MATCH;2119 2120 if (!iwl_mvm_is_regular_scan(params))2121 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_PERIODIC;2122 2123 if (params->iter_notif ||2124 mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED)2125 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_NTFY_ITER_COMPLETE;2126 2127 if (IWL_MVM_ADWELL_ENABLE)2128 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_ADAPTIVE_DWELL;2129 2130 if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT)2131 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_PREEMPTIVE;2132 2133 if ((type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT) &&2134 params->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ)2135 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_TRIGGER_UHB_SCAN;2136 2137 if (params->enable_6ghz_passive)2138 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN;2139 2140 if (iwl_mvm_is_oce_supported(mvm) &&2141 (params->flags & (NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP |2142 NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE |2143 NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME)))2144 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_OCE;2145 2146 return flags;2147}2148 2149static u8 iwl_mvm_scan_umac_flags2(struct iwl_mvm *mvm,2150 struct iwl_mvm_scan_params *params,2151 struct ieee80211_vif *vif, int type,2152 u16 gen_flags)2153{2154 u8 flags = 0;2155 2156 if (iwl_mvm_is_cdb_supported(mvm)) {2157 if (params->respect_p2p_go)2158 flags |= IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_LB;2159 if (params->respect_p2p_go_hb)2160 flags |= IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_HB;2161 } else {2162 if (params->respect_p2p_go)2163 flags = IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_LB |2164 IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_HB;2165 }2166 2167 if (params->scan_6ghz &&2168 fw_has_capa(&mvm->fw->ucode_capa,2169 IWL_UCODE_TLV_CAPA_SCAN_DONT_TOGGLE_ANT))2170 flags |= IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_DONT_TOGGLE_ANT;2171 2172 /* Passive and AP interface -> ACS (automatic channel selection) */2173 if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE &&2174 ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_AP &&2175 iwl_fw_lookup_notif_ver(mvm->fw, SCAN_GROUP, CHANNEL_SURVEY_NOTIF,2176 0) >= 1)2177 flags |= IWL_UMAC_SCAN_GEN_FLAGS2_COLLECT_CHANNEL_STATS;2178 2179 return flags;2180}2181 2182static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,2183 struct iwl_mvm_scan_params *params,2184 struct ieee80211_vif *vif)2185{2186 u16 flags = 0;2187 2188 if (params->n_ssids == 0)2189 flags = IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE;2190 2191 if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0)2192 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT;2193 2194 if (iwl_mvm_is_scan_fragmented(params->type))2195 flags |= IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED;2196 2197 if (iwl_mvm_is_cdb_supported(mvm) &&2198 iwl_mvm_is_scan_fragmented(params->hb_type))2199 flags |= IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED;2200 2201 if (iwl_mvm_rrm_scan_needed(mvm) &&2202 fw_has_capa(&mvm->fw->ucode_capa,2203 IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT))2204 flags |= IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED;2205 2206 if (params->pass_all)2207 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL;2208 else2209 flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH;2210 2211 if (!iwl_mvm_is_regular_scan(params))2212 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC;2213 2214 if (params->iter_notif)2215 flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;2216 2217#ifdef CONFIG_IWLWIFI_DEBUGFS2218 if (mvm->scan_iter_notif_enabled)2219 flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;2220#endif2221 2222 if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED)2223 flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;2224 2225 if (iwl_mvm_is_adaptive_dwell_supported(mvm) && IWL_MVM_ADWELL_ENABLE)2226 flags |= IWL_UMAC_SCAN_GEN_FLAGS_ADAPTIVE_DWELL;2227 2228 /*2229 * Extended dwell is relevant only for low band to start with, as it is2230 * being used for social channles only (1, 6, 11), so we can check2231 * only scan type on low band also for CDB.2232 */2233 if (iwl_mvm_is_regular_scan(params) &&2234 vif->type != NL80211_IFTYPE_P2P_DEVICE &&2235 !iwl_mvm_is_scan_fragmented(params->type) &&2236 !iwl_mvm_is_adaptive_dwell_supported(mvm) &&2237 !iwl_mvm_is_oce_supported(mvm))2238 flags |= IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL;2239 2240 if (iwl_mvm_is_oce_supported(mvm)) {2241 if ((params->flags &2242 NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE))2243 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PROB_REQ_HIGH_TX_RATE;2244 /* Since IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL and2245 * NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION shares2246 * the same bit, we need to make sure that we use this bit here2247 * only when IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL cannot be2248 * used. */2249 if ((params->flags &2250 NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) &&2251 !WARN_ON_ONCE(!iwl_mvm_is_adaptive_dwell_supported(mvm)))2252 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PROB_REQ_DEFER_SUPP;2253 if ((params->flags & NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME))2254 flags |= IWL_UMAC_SCAN_GEN_FLAGS_MAX_CHNL_TIME;2255 }2256 2257 return flags;2258}2259 2260static int2261iwl_mvm_fill_scan_sched_params(struct iwl_mvm_scan_params *params,2262 struct iwl_scan_umac_schedule *schedule,2263 __le16 *delay)2264{2265 int i;2266 if (WARN_ON(!params->n_scan_plans ||2267 params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))2268 return -EINVAL;2269 2270 for (i = 0; i < params->n_scan_plans; i++) {2271 struct cfg80211_sched_scan_plan *scan_plan =2272 ¶ms->scan_plans[i];2273 2274 schedule[i].iter_count = scan_plan->iterations;2275 schedule[i].interval =2276 cpu_to_le16(scan_plan->interval);2277 }2278 2279 /*2280 * If the number of iterations of the last scan plan is set to2281 * zero, it should run infinitely. However, this is not always the case.2282 * For example, when regular scan is requested the driver sets one scan2283 * plan with one iteration.2284 */2285 if (!schedule[params->n_scan_plans - 1].iter_count)2286 schedule[params->n_scan_plans - 1].iter_count = 0xff;2287 2288 *delay = cpu_to_le16(params->delay);2289 2290 return 0;2291}2292 2293static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,2294 struct iwl_mvm_scan_params *params,2295 int type, int uid)2296{2297 struct iwl_scan_req_umac *cmd = mvm->scan_cmd;2298 struct iwl_scan_umac_chan_param *chan_param;2299 void *cmd_data = iwl_mvm_get_scan_req_umac_data(mvm);2300 void *sec_part = (u8 *)cmd_data + sizeof(struct iwl_scan_channel_cfg_umac) *2301 mvm->fw->ucode_capa.n_scan_channels;2302 struct iwl_scan_req_umac_tail_v2 *tail_v2 =2303 (struct iwl_scan_req_umac_tail_v2 *)sec_part;2304 struct iwl_scan_req_umac_tail_v1 *tail_v1;2305 struct iwl_ssid_ie *direct_scan;2306 int ret = 0;2307 u32 ssid_bitmap = 0;2308 u8 channel_flags = 0;2309 u16 gen_flags;2310 struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);2311 2312 chan_param = iwl_mvm_get_scan_req_umac_channel(mvm);2313 2314 iwl_mvm_scan_umac_dwell(mvm, cmd, params);2315 2316 cmd->uid = cpu_to_le32(uid);2317 gen_flags = iwl_mvm_scan_umac_flags(mvm, params, vif);2318 cmd->general_flags = cpu_to_le16(gen_flags);2319 if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm)) {2320 if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED)2321 cmd->v8.num_of_fragments[SCAN_LB_LMAC_IDX] =2322 IWL_SCAN_NUM_OF_FRAGS;2323 if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED)2324 cmd->v8.num_of_fragments[SCAN_HB_LMAC_IDX] =2325 IWL_SCAN_NUM_OF_FRAGS;2326 2327 cmd->v8.general_flags2 =2328 IWL_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER;2329 }2330 2331 cmd->scan_start_mac_id = scan_vif->id;2332 2333 if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT)2334 cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);2335 2336 if (iwl_mvm_scan_use_ebs(mvm, vif)) {2337 channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS |2338 IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |2339 IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;2340 2341 /* set fragmented ebs for fragmented scan on HB channels */2342 if (iwl_mvm_is_frag_ebs_supported(mvm)) {2343 if (gen_flags &2344 IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED ||2345 (!iwl_mvm_is_cdb_supported(mvm) &&2346 gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED))2347 channel_flags |= IWL_SCAN_CHANNEL_FLAG_EBS_FRAG;2348 }2349 }2350 2351 chan_param->flags = channel_flags;2352 chan_param->count = params->n_channels;2353 2354 ret = iwl_mvm_fill_scan_sched_params(params, tail_v2->schedule,2355 &tail_v2->delay);2356 if (ret)2357 return ret;2358 2359 if (iwl_mvm_is_scan_ext_chan_supported(mvm)) {2360 tail_v2->preq = params->preq;2361 direct_scan = tail_v2->direct_scan;2362 } else {2363 tail_v1 = (struct iwl_scan_req_umac_tail_v1 *)sec_part;2364 iwl_mvm_scan_set_legacy_probe_req(&tail_v1->preq,2365 ¶ms->preq);2366 direct_scan = tail_v1->direct_scan;2367 }2368 iwl_scan_build_ssids(params, direct_scan, &ssid_bitmap);2369 iwl_mvm_umac_scan_cfg_channels(mvm, params->channels,2370 params->n_channels, ssid_bitmap,2371 cmd_data);2372 return 0;2373}2374 2375static void2376iwl_mvm_scan_umac_fill_general_p_v12(struct iwl_mvm *mvm,2377 struct iwl_mvm_scan_params *params,2378 struct ieee80211_vif *vif,2379 struct iwl_scan_general_params_v11 *gp,2380 u16 gen_flags, u8 gen_flags2,2381 u32 version)2382{2383 struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);2384 2385 iwl_mvm_scan_umac_dwell_v11(mvm, gp, params);2386 2387 IWL_DEBUG_SCAN(mvm, "General: flags=0x%x, flags2=0x%x\n",2388 gen_flags, gen_flags2);2389 2390 gp->flags = cpu_to_le16(gen_flags);2391 gp->flags2 = gen_flags2;2392 2393 if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1)2394 gp->num_of_fragments[SCAN_LB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS;2395 if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2)2396 gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS;2397 2398 mvm->scan_link_id = 0;2399 2400 if (version < 16) {2401 gp->scan_start_mac_or_link_id = scan_vif->id;2402 } else {2403 struct iwl_mvm_vif_link_info *link_info =2404 scan_vif->link[params->tsf_report_link_id];2405 2406 mvm->scan_link_id = params->tsf_report_link_id;2407 if (!WARN_ON(!link_info))2408 gp->scan_start_mac_or_link_id = link_info->fw_link_id;2409 }2410}2411 2412static void2413iwl_mvm_scan_umac_fill_probe_p_v3(struct iwl_mvm_scan_params *params,2414 struct iwl_scan_probe_params_v3 *pp)2415{2416 pp->preq = params->preq;2417 pp->ssid_num = params->n_ssids;2418 iwl_scan_build_ssids(params, pp->direct_scan, NULL);2419}2420 2421static void2422iwl_mvm_scan_umac_fill_probe_p_v4(struct iwl_mvm_scan_params *params,2423 struct iwl_scan_probe_params_v4 *pp,2424 u32 *bitmap_ssid)2425{2426 pp->preq = params->preq;2427 iwl_scan_build_ssids(params, pp->direct_scan, bitmap_ssid);2428}2429 2430static void2431iwl_mvm_scan_umac_fill_ch_p_v4(struct iwl_mvm *mvm,2432 struct iwl_mvm_scan_params *params,2433 struct ieee80211_vif *vif,2434 struct iwl_scan_channel_params_v4 *cp,2435 u32 channel_cfg_flags)2436{2437 cp->flags = iwl_mvm_scan_umac_chan_flags_v2(mvm, params, vif);2438 cp->count = params->n_channels;2439 cp->num_of_aps_override = IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY;2440 2441 iwl_mvm_umac_scan_cfg_channels_v4(mvm, params->channels, cp,2442 params->n_channels,2443 channel_cfg_flags,2444 vif->type);2445}2446 2447static void2448iwl_mvm_scan_umac_fill_ch_p_v7(struct iwl_mvm *mvm,2449 struct iwl_mvm_scan_params *params,2450 struct ieee80211_vif *vif,2451 struct iwl_scan_channel_params_v7 *cp,2452 u32 channel_cfg_flags,2453 u32 version)2454{2455 cp->flags = iwl_mvm_scan_umac_chan_flags_v2(mvm, params, vif);2456 cp->count = params->n_channels;2457 cp->n_aps_override[0] = IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY;2458 cp->n_aps_override[1] = IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS;2459 2460 iwl_mvm_umac_scan_cfg_channels_v7(mvm, params->channels, cp,2461 params->n_channels,2462 channel_cfg_flags,2463 vif->type, version);2464 2465 if (params->enable_6ghz_passive) {2466 struct ieee80211_supported_band *sband =2467 &mvm->nvm_data->bands[NL80211_BAND_6GHZ];2468 u32 i;2469 2470 for (i = 0; i < sband->n_channels; i++) {2471 struct ieee80211_channel *channel =2472 &sband->channels[i];2473 2474 struct iwl_scan_channel_cfg_umac *cfg =2475 &cp->channel_config[cp->count];2476 2477 if (!cfg80211_channel_is_psc(channel))2478 continue;2479 2480 cfg->channel_num = channel->hw_value;2481 cfg->v5.iter_count = 1;2482 cfg->v5.iter_interval = 0;2483 2484 if (version < 17) {2485 cfg->flags = 0;2486 cfg->v2.band = PHY_BAND_6;2487 } else {2488 cfg->flags = cpu_to_le32(PHY_BAND_6 <<2489 IWL_CHAN_CFG_FLAGS_BAND_POS);2490 cfg->v5.psd_20 =2491 IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED;2492 }2493 cp->count++;2494 }2495 }2496}2497 2498static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif,2499 struct iwl_mvm_scan_params *params, int type,2500 int uid)2501{2502 struct iwl_scan_req_umac_v12 *cmd = mvm->scan_cmd;2503 struct iwl_scan_req_params_v12 *scan_p = &cmd->scan_params;2504 int ret;2505 u16 gen_flags;2506 2507 cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(type));2508 cmd->uid = cpu_to_le32(uid);2509 2510 gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);2511 iwl_mvm_scan_umac_fill_general_p_v12(mvm, params, vif,2512 &scan_p->general_params,2513 gen_flags, 0, 12);2514 2515 ret = iwl_mvm_fill_scan_sched_params(params,2516 scan_p->periodic_params.schedule,2517 &scan_p->periodic_params.delay);2518 if (ret)2519 return ret;2520 2521 iwl_mvm_scan_umac_fill_probe_p_v3(params, &scan_p->probe_params);2522 iwl_mvm_scan_umac_fill_ch_p_v4(mvm, params, vif,2523 &scan_p->channel_params, 0);2524 2525 return 0;2526}2527 2528static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,2529 struct ieee80211_vif *vif,2530 struct iwl_mvm_scan_params *params,2531 int type, int uid, u32 version)2532{2533 struct iwl_scan_req_umac_v17 *cmd = mvm->scan_cmd;2534 struct iwl_scan_req_params_v17 *scan_p = &cmd->scan_params;2535 struct iwl_scan_channel_params_v7 *cp = &scan_p->channel_params;2536 struct iwl_scan_probe_params_v4 *pb = &scan_p->probe_params;2537 int ret;2538 u16 gen_flags;2539 u8 gen_flags2;2540 u32 bitmap_ssid = 0;2541 2542 cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(type));2543 cmd->uid = cpu_to_le32(uid);2544 2545 gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);2546 2547 if (version >= 15)2548 gen_flags2 = iwl_mvm_scan_umac_flags2(mvm, params, vif, type,2549 gen_flags);2550 else2551 gen_flags2 = 0;2552 2553 iwl_mvm_scan_umac_fill_general_p_v12(mvm, params, vif,2554 &scan_p->general_params,2555 gen_flags, gen_flags2, version);2556 2557 ret = iwl_mvm_fill_scan_sched_params(params,2558 scan_p->periodic_params.schedule,2559 &scan_p->periodic_params.delay);2560 if (ret)2561 return ret;2562 2563 if (!params->scan_6ghz) {2564 iwl_mvm_scan_umac_fill_probe_p_v4(params,2565 &scan_p->probe_params,2566 &bitmap_ssid);2567 iwl_mvm_scan_umac_fill_ch_p_v7(mvm, params, vif,2568 &scan_p->channel_params,2569 bitmap_ssid,2570 version);2571 return 0;2572 } else {2573 pb->preq = params->preq;2574 }2575 2576 cp->flags = iwl_mvm_scan_umac_chan_flags_v2(mvm, params, vif);2577 cp->n_aps_override[0] = IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY;2578 cp->n_aps_override[1] = IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS;2579 2580 iwl_mvm_umac_scan_fill_6g_chan_list(mvm, params, pb);2581 2582 cp->count = iwl_mvm_umac_scan_cfg_channels_v7_6g(mvm, params,2583 params->n_channels,2584 pb, cp, vif->type,2585 version);2586 if (!cp->count)2587 return -EINVAL;2588 2589 if (!params->n_ssids ||2590 (params->n_ssids == 1 && !params->ssids[0].ssid_len))2591 cp->flags |= IWL_SCAN_CHANNEL_FLAG_6G_PSC_NO_FILTER;2592 2593 return 0;2594}2595 2596static int iwl_mvm_scan_umac_v14(struct iwl_mvm *mvm, struct ieee80211_vif *vif,2597 struct iwl_mvm_scan_params *params, int type,2598 int uid)2599{2600 return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 14);2601}2602 2603static int iwl_mvm_scan_umac_v15(struct iwl_mvm *mvm, struct ieee80211_vif *vif,2604 struct iwl_mvm_scan_params *params, int type,2605 int uid)2606{2607 return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 15);2608}2609 2610static int iwl_mvm_scan_umac_v16(struct iwl_mvm *mvm, struct ieee80211_vif *vif,2611 struct iwl_mvm_scan_params *params, int type,2612 int uid)2613{2614 return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 16);2615}2616 2617static int iwl_mvm_scan_umac_v17(struct iwl_mvm *mvm, struct ieee80211_vif *vif,2618 struct iwl_mvm_scan_params *params, int type,2619 int uid)2620{2621 return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 17);2622}2623 2624static int iwl_mvm_num_scans(struct iwl_mvm *mvm)2625{2626 return hweight32(mvm->scan_status & IWL_MVM_SCAN_MASK);2627}2628 2629static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type)2630{2631 bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,2632 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);2633 2634 /* This looks a bit arbitrary, but the idea is that if we run2635 * out of possible simultaneous scans and the userspace is2636 * trying to run a scan type that is already running, we2637 * return -EBUSY. But if the userspace wants to start a2638 * different type of scan, we stop the opposite type to make2639 * space for the new request. The reason is backwards2640 * compatibility with old wpa_supplicant that wouldn't stop a2641 * scheduled scan before starting a normal scan.2642 */2643 2644 /* FW supports only a single periodic scan */2645 if ((type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT) &&2646 mvm->scan_status & (IWL_MVM_SCAN_SCHED | IWL_MVM_SCAN_NETDETECT))2647 return -EBUSY;2648 2649 if (iwl_mvm_num_scans(mvm) < mvm->max_scans)2650 return 0;2651 2652 /* Use a switch, even though this is a bitmask, so that more2653 * than one bits set will fall in default and we will warn.2654 */2655 switch (type) {2656 case IWL_MVM_SCAN_REGULAR:2657 if (mvm->scan_status & IWL_MVM_SCAN_REGULAR_MASK)2658 return -EBUSY;2659 return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, true);2660 case IWL_MVM_SCAN_SCHED:2661 if (mvm->scan_status & IWL_MVM_SCAN_SCHED_MASK)2662 return -EBUSY;2663 return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_REGULAR, true);2664 case IWL_MVM_SCAN_NETDETECT:2665 /* For non-unified images, there's no need to stop2666 * anything for net-detect since the firmware is2667 * restarted anyway. This way, any sched scans that2668 * were running will be restarted when we resume.2669 */2670 if (!unified_image)2671 return 0;2672 2673 /* If this is a unified image and we ran out of scans,2674 * we need to stop something. Prefer stopping regular2675 * scans, because the results are useless at this2676 * point, and we should be able to keep running2677 * another scheduled scan while suspended.2678 */2679 if (mvm->scan_status & IWL_MVM_SCAN_REGULAR_MASK)2680 return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_REGULAR,2681 true);2682 if (mvm->scan_status & IWL_MVM_SCAN_SCHED_MASK)2683 return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED,2684 true);2685 /* Something is wrong if no scan was running but we2686 * ran out of scans.2687 */2688 fallthrough;2689 default:2690 WARN_ON(1);2691 break;2692 }2693 2694 return -EIO;2695}2696 2697#define SCAN_TIMEOUT 300002698 2699void iwl_mvm_scan_timeout_wk(struct work_struct *work)2700{2701 struct delayed_work *delayed_work = to_delayed_work(work);2702 struct iwl_mvm *mvm = container_of(delayed_work, struct iwl_mvm,2703 scan_timeout_dwork);2704 2705 IWL_ERR(mvm, "regular scan timed out\n");2706 2707 iwl_force_nmi(mvm->trans);2708}2709 2710static void iwl_mvm_fill_scan_type(struct iwl_mvm *mvm,2711 struct iwl_mvm_scan_params *params,2712 struct ieee80211_vif *vif)2713{2714 if (iwl_mvm_is_cdb_supported(mvm)) {2715 params->type =2716 iwl_mvm_get_scan_type_band(mvm, vif,2717 NL80211_BAND_2GHZ);2718 params->hb_type =2719 iwl_mvm_get_scan_type_band(mvm, vif,2720 NL80211_BAND_5GHZ);2721 } else {2722 params->type = iwl_mvm_get_scan_type(mvm, vif);2723 }2724}2725 2726struct iwl_scan_umac_handler {2727 u8 version;2728 int (*handler)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,2729 struct iwl_mvm_scan_params *params, int type, int uid);2730};2731 2732#define IWL_SCAN_UMAC_HANDLER(_ver) { \2733 .version = _ver, \2734 .handler = iwl_mvm_scan_umac_v##_ver, \2735}2736 2737static const struct iwl_scan_umac_handler iwl_scan_umac_handlers[] = {2738 /* set the newest version first to shorten the list traverse time */2739 IWL_SCAN_UMAC_HANDLER(17),2740 IWL_SCAN_UMAC_HANDLER(16),2741 IWL_SCAN_UMAC_HANDLER(15),2742 IWL_SCAN_UMAC_HANDLER(14),2743 IWL_SCAN_UMAC_HANDLER(12),2744};2745 2746static void iwl_mvm_mei_scan_work(struct work_struct *wk)2747{2748 struct iwl_mei_scan_filter *scan_filter =2749 container_of(wk, struct iwl_mei_scan_filter, scan_work);2750 struct iwl_mvm *mvm =2751 container_of(scan_filter, struct iwl_mvm, mei_scan_filter);2752 struct iwl_mvm_csme_conn_info *info;2753 struct sk_buff *skb;2754 u8 bssid[ETH_ALEN];2755 2756 mutex_lock(&mvm->mutex);2757 info = iwl_mvm_get_csme_conn_info(mvm);2758 memcpy(bssid, info->conn_info.bssid, ETH_ALEN);2759 mutex_unlock(&mvm->mutex);2760 2761 while ((skb = skb_dequeue(&scan_filter->scan_res))) {2762 struct ieee80211_mgmt *mgmt = (void *)skb->data;2763 2764 if (!memcmp(mgmt->bssid, bssid, ETH_ALEN))2765 ieee80211_rx_irqsafe(mvm->hw, skb);2766 else2767 kfree_skb(skb);2768 }2769}2770 2771void iwl_mvm_mei_scan_filter_init(struct iwl_mei_scan_filter *mei_scan_filter)2772{2773 skb_queue_head_init(&mei_scan_filter->scan_res);2774 INIT_WORK(&mei_scan_filter->scan_work, iwl_mvm_mei_scan_work);2775}2776 2777/* In case CSME is connected and has link protection set, this function will2778 * override the scan request to scan only the associated channel and only for2779 * the associated SSID.2780 */2781static void iwl_mvm_mei_limited_scan(struct iwl_mvm *mvm,2782 struct iwl_mvm_scan_params *params)2783{2784 struct iwl_mvm_csme_conn_info *info = iwl_mvm_get_csme_conn_info(mvm);2785 struct iwl_mei_conn_info *conn_info;2786 struct ieee80211_channel *chan;2787 int scan_iters, i;2788 2789 if (!info) {2790 IWL_DEBUG_SCAN(mvm, "mei_limited_scan: no connection info\n");2791 return;2792 }2793 2794 conn_info = &info->conn_info;2795 if (!info->conn_info.lp_state || !info->conn_info.ssid_len)2796 return;2797 2798 if (!params->n_channels || !params->n_ssids)2799 return;2800 2801 mvm->mei_scan_filter.is_mei_limited_scan = true;2802 2803 chan = ieee80211_get_channel(mvm->hw->wiphy,2804 ieee80211_channel_to_frequency(conn_info->channel,2805 conn_info->band));2806 if (!chan) {2807 IWL_DEBUG_SCAN(mvm,2808 "Failed to get CSME channel (chan=%u band=%u)\n",2809 conn_info->channel, conn_info->band);2810 return;2811 }2812 2813 /* The mei filtered scan must find the AP, otherwise CSME will2814 * take the NIC ownership. Add several iterations on the channel to2815 * make the scan more robust.2816 */2817 scan_iters = min(IWL_MEI_SCAN_NUM_ITER, params->n_channels);2818 params->n_channels = scan_iters;2819 for (i = 0; i < scan_iters; i++)2820 params->channels[i] = chan;2821 2822 IWL_DEBUG_SCAN(mvm, "Mei scan: num iterations=%u\n", scan_iters);2823 2824 params->n_ssids = 1;2825 params->ssids[0].ssid_len = conn_info->ssid_len;2826 memcpy(params->ssids[0].ssid, conn_info->ssid, conn_info->ssid_len);2827}2828 2829static int iwl_mvm_build_scan_cmd(struct iwl_mvm *mvm,2830 struct ieee80211_vif *vif,2831 struct iwl_host_cmd *hcmd,2832 struct iwl_mvm_scan_params *params,2833 int type)2834{2835 int uid, i, err;2836 u8 scan_ver;2837 2838 lockdep_assert_held(&mvm->mutex);2839 memset(mvm->scan_cmd, 0, mvm->scan_cmd_size);2840 2841 iwl_mvm_mei_limited_scan(mvm, params);2842 2843 if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {2844 hcmd->id = SCAN_OFFLOAD_REQUEST_CMD;2845 2846 return iwl_mvm_scan_lmac(mvm, vif, params);2847 }2848 2849 uid = iwl_mvm_scan_uid_by_status(mvm, 0);2850 if (uid < 0)2851 return uid;2852 2853 hcmd->id = WIDE_ID(IWL_ALWAYS_LONG_GROUP, SCAN_REQ_UMAC);2854 2855 scan_ver = iwl_fw_lookup_cmd_ver(mvm->fw, SCAN_REQ_UMAC,2856 IWL_FW_CMD_VER_UNKNOWN);2857 2858 for (i = 0; i < ARRAY_SIZE(iwl_scan_umac_handlers); i++) {2859 const struct iwl_scan_umac_handler *ver_handler =2860 &iwl_scan_umac_handlers[i];2861 2862 if (ver_handler->version != scan_ver)2863 continue;2864 2865 err = ver_handler->handler(mvm, vif, params, type, uid);2866 return err ? : uid;2867 }2868 2869 err = iwl_mvm_scan_umac(mvm, vif, params, type, uid);2870 if (err)2871 return err;2872 2873 return uid;2874}2875 2876struct iwl_mvm_scan_respect_p2p_go_iter_data {2877 struct ieee80211_vif *current_vif;2878 bool p2p_go;2879 enum nl80211_band band;2880};2881 2882static void iwl_mvm_scan_respect_p2p_go_iter(void *_data, u8 *mac,2883 struct ieee80211_vif *vif)2884{2885 struct iwl_mvm_scan_respect_p2p_go_iter_data *data = _data;2886 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);2887 2888 /* exclude the given vif */2889 if (vif == data->current_vif)2890 return;2891 2892 if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_P2P_GO) {2893 u32 link_id;2894 2895 for (link_id = 0;2896 link_id < ARRAY_SIZE(mvmvif->link);2897 link_id++) {2898 struct iwl_mvm_vif_link_info *link =2899 mvmvif->link[link_id];2900 2901 if (link && link->phy_ctxt->id < NUM_PHY_CTX &&2902 (data->band == NUM_NL80211_BANDS ||2903 link->phy_ctxt->channel->band == data->band)) {2904 data->p2p_go = true;2905 break;2906 }2907 }2908 }2909}2910 2911static bool _iwl_mvm_get_respect_p2p_go(struct iwl_mvm *mvm,2912 struct ieee80211_vif *vif,2913 bool low_latency,2914 enum nl80211_band band)2915{2916 struct iwl_mvm_scan_respect_p2p_go_iter_data data = {2917 .current_vif = vif,2918 .p2p_go = false,2919 .band = band,2920 };2921 2922 if (!low_latency)2923 return false;2924 2925 ieee80211_iterate_active_interfaces_atomic(mvm->hw,2926 IEEE80211_IFACE_ITER_NORMAL,2927 iwl_mvm_scan_respect_p2p_go_iter,2928 &data);2929 2930 return data.p2p_go;2931}2932 2933static bool iwl_mvm_get_respect_p2p_go_band(struct iwl_mvm *mvm,2934 struct ieee80211_vif *vif,2935 enum nl80211_band band)2936{2937 bool low_latency = iwl_mvm_low_latency_band(mvm, band);2938 2939 return _iwl_mvm_get_respect_p2p_go(mvm, vif, low_latency, band);2940}2941 2942static bool iwl_mvm_get_respect_p2p_go(struct iwl_mvm *mvm,2943 struct ieee80211_vif *vif)2944{2945 bool low_latency = iwl_mvm_low_latency(mvm);2946 2947 return _iwl_mvm_get_respect_p2p_go(mvm, vif, low_latency,2948 NUM_NL80211_BANDS);2949}2950 2951static void iwl_mvm_fill_respect_p2p_go(struct iwl_mvm *mvm,2952 struct iwl_mvm_scan_params *params,2953 struct ieee80211_vif *vif)2954{2955 if (iwl_mvm_is_cdb_supported(mvm)) {2956 params->respect_p2p_go =2957 iwl_mvm_get_respect_p2p_go_band(mvm, vif,2958 NL80211_BAND_2GHZ);2959 params->respect_p2p_go_hb =2960 iwl_mvm_get_respect_p2p_go_band(mvm, vif,2961 NL80211_BAND_5GHZ);2962 } else {2963 params->respect_p2p_go = iwl_mvm_get_respect_p2p_go(mvm, vif);2964 }2965}2966 2967static int _iwl_mvm_single_scan_start(struct iwl_mvm *mvm,2968 struct ieee80211_vif *vif,2969 struct cfg80211_scan_request *req,2970 struct ieee80211_scan_ies *ies,2971 int type)2972{2973 struct iwl_host_cmd hcmd = {2974 .len = { iwl_mvm_scan_size(mvm), },2975 .data = { mvm->scan_cmd, },2976 .dataflags = { IWL_HCMD_DFL_NOCOPY, },2977 };2978 struct iwl_mvm_scan_params params = {};2979 int ret, uid;2980 struct cfg80211_sched_scan_plan scan_plan = { .iterations = 1 };2981 2982 lockdep_assert_held(&mvm->mutex);2983 2984 if (iwl_mvm_is_lar_supported(mvm) && !mvm->lar_regdom_set) {2985 IWL_ERR(mvm, "scan while LAR regdomain is not set\n");2986 return -EBUSY;2987 }2988 2989 ret = iwl_mvm_check_running_scans(mvm, type);2990 if (ret)2991 return ret;2992 2993 /* we should have failed registration if scan_cmd was NULL */2994 if (WARN_ON(!mvm->scan_cmd))2995 return -ENOMEM;2996 2997 if (!iwl_mvm_scan_fits(mvm, req->n_ssids, ies, req->n_channels))2998 return -ENOBUFS;2999 3000 params.n_ssids = req->n_ssids;3001 params.flags = req->flags;3002 params.n_channels = req->n_channels;3003 params.delay = 0;3004 params.ssids = req->ssids;3005 params.channels = req->channels;3006 params.mac_addr = req->mac_addr;3007 params.mac_addr_mask = req->mac_addr_mask;3008 params.no_cck = req->no_cck;3009 params.pass_all = true;3010 params.n_match_sets = 0;3011 params.match_sets = NULL;3012 ether_addr_copy(params.bssid, req->bssid);3013 3014 params.scan_plans = &scan_plan;3015 params.n_scan_plans = 1;3016 3017 params.n_6ghz_params = req->n_6ghz_params;3018 params.scan_6ghz_params = req->scan_6ghz_params;3019 params.scan_6ghz = req->scan_6ghz;3020 iwl_mvm_fill_scan_type(mvm, ¶ms, vif);3021 iwl_mvm_fill_respect_p2p_go(mvm, ¶ms, vif);3022 3023 if (req->duration)3024 params.iter_notif = true;3025 3026 params.tsf_report_link_id = req->tsf_report_link_id;3027 if (params.tsf_report_link_id < 0) {3028 if (vif->active_links)3029 params.tsf_report_link_id = __ffs(vif->active_links);3030 else3031 params.tsf_report_link_id = 0;3032 }3033 3034 iwl_mvm_build_scan_probe(mvm, vif, ies, ¶ms);3035 3036 iwl_mvm_scan_6ghz_passive_scan(mvm, ¶ms, vif);3037 3038 uid = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, ¶ms, type);3039 3040 if (uid < 0)3041 return uid;3042 3043 iwl_mvm_pause_tcm(mvm, false);3044 3045 ret = iwl_mvm_send_cmd(mvm, &hcmd);3046 if (ret) {3047 /* If the scan failed, it usually means that the FW was unable3048 * to allocate the time events. Warn on it, but maybe we3049 * should try to send the command again with different params.3050 */3051 IWL_ERR(mvm, "Scan failed! ret %d\n", ret);3052 iwl_mvm_resume_tcm(mvm);3053 return ret;3054 }3055 3056 IWL_DEBUG_SCAN(mvm, "Scan request send success: type=%u, uid=%u\n",3057 type, uid);3058 3059 mvm->scan_uid_status[uid] = type;3060 mvm->scan_status |= type;3061 3062 if (type == IWL_MVM_SCAN_REGULAR) {3063 mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);3064 schedule_delayed_work(&mvm->scan_timeout_dwork,3065 msecs_to_jiffies(SCAN_TIMEOUT));3066 }3067 3068 if (params.enable_6ghz_passive)3069 mvm->last_6ghz_passive_scan_jiffies = jiffies;3070 3071 return 0;3072}3073 3074int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,3075 struct cfg80211_scan_request *req,3076 struct ieee80211_scan_ies *ies)3077{3078 return _iwl_mvm_single_scan_start(mvm, vif, req, ies,3079 IWL_MVM_SCAN_REGULAR);3080}3081 3082int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,3083 struct ieee80211_vif *vif,3084 struct cfg80211_sched_scan_request *req,3085 struct ieee80211_scan_ies *ies,3086 int type)3087{3088 struct iwl_host_cmd hcmd = {3089 .len = { iwl_mvm_scan_size(mvm), },3090 .data = { mvm->scan_cmd, },3091 .dataflags = { IWL_HCMD_DFL_NOCOPY, },3092 };3093 struct iwl_mvm_scan_params params = {};3094 int ret, uid;3095 int i, j;3096 bool non_psc_included = false;3097 3098 lockdep_assert_held(&mvm->mutex);3099 3100 if (iwl_mvm_is_lar_supported(mvm) && !mvm->lar_regdom_set) {3101 IWL_ERR(mvm, "sched-scan while LAR regdomain is not set\n");3102 return -EBUSY;3103 }3104 3105 ret = iwl_mvm_check_running_scans(mvm, type);3106 if (ret)3107 return ret;3108 3109 /* we should have failed registration if scan_cmd was NULL */3110 if (WARN_ON(!mvm->scan_cmd))3111 return -ENOMEM;3112 3113 3114 params.n_ssids = req->n_ssids;3115 params.flags = req->flags;3116 params.n_channels = req->n_channels;3117 params.ssids = req->ssids;3118 params.channels = req->channels;3119 params.mac_addr = req->mac_addr;3120 params.mac_addr_mask = req->mac_addr_mask;3121 params.no_cck = false;3122 params.pass_all = iwl_mvm_scan_pass_all(mvm, req);3123 params.n_match_sets = req->n_match_sets;3124 params.match_sets = req->match_sets;3125 eth_broadcast_addr(params.bssid);3126 if (!req->n_scan_plans)3127 return -EINVAL;3128 3129 params.n_scan_plans = req->n_scan_plans;3130 params.scan_plans = req->scan_plans;3131 3132 iwl_mvm_fill_scan_type(mvm, ¶ms, vif);3133 iwl_mvm_fill_respect_p2p_go(mvm, ¶ms, vif);3134 3135 /* In theory, LMAC scans can handle a 32-bit delay, but since3136 * waiting for over 18 hours to start the scan is a bit silly3137 * and to keep it aligned with UMAC scans (which only support3138 * 16-bit delays), trim it down to 16-bits.3139 */3140 if (req->delay > U16_MAX) {3141 IWL_DEBUG_SCAN(mvm,3142 "delay value is > 16-bits, set to max possible\n");3143 params.delay = U16_MAX;3144 } else {3145 params.delay = req->delay;3146 }3147 3148 ret = iwl_mvm_config_sched_scan_profiles(mvm, req);3149 if (ret)3150 return ret;3151 3152 iwl_mvm_build_scan_probe(mvm, vif, ies, ¶ms);3153 3154 /* for 6 GHZ band only PSC channels need to be added */3155 for (i = 0; i < params.n_channels; i++) {3156 struct ieee80211_channel *channel = params.channels[i];3157 3158 if (channel->band == NL80211_BAND_6GHZ &&3159 !cfg80211_channel_is_psc(channel)) {3160 non_psc_included = true;3161 break;3162 }3163 }3164 3165 if (non_psc_included) {3166 params.channels = kmemdup(params.channels,3167 sizeof(params.channels[0]) *3168 params.n_channels,3169 GFP_KERNEL);3170 if (!params.channels)3171 return -ENOMEM;3172 3173 for (i = j = 0; i < params.n_channels; i++) {3174 if (params.channels[i]->band == NL80211_BAND_6GHZ &&3175 !cfg80211_channel_is_psc(params.channels[i]))3176 continue;3177 params.channels[j++] = params.channels[i];3178 }3179 params.n_channels = j;3180 }3181 3182 if (!iwl_mvm_scan_fits(mvm, req->n_ssids, ies, params.n_channels)) {3183 ret = -ENOBUFS;3184 goto out;3185 }3186 3187 uid = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, ¶ms, type);3188 if (uid < 0) {3189 ret = uid;3190 goto out;3191 }3192 3193 ret = iwl_mvm_send_cmd(mvm, &hcmd);3194 if (!ret) {3195 IWL_DEBUG_SCAN(mvm,3196 "Sched scan request send success: type=%u, uid=%u\n",3197 type, uid);3198 mvm->scan_uid_status[uid] = type;3199 mvm->scan_status |= type;3200 } else {3201 /* If the scan failed, it usually means that the FW was unable3202 * to allocate the time events. Warn on it, but maybe we3203 * should try to send the command again with different params.3204 */3205 IWL_ERR(mvm, "Sched scan failed! ret %d\n", ret);3206 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;3207 }3208 3209out:3210 if (non_psc_included)3211 kfree(params.channels);3212 return ret;3213}3214 3215void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,3216 struct iwl_rx_cmd_buffer *rxb)3217{3218 struct iwl_rx_packet *pkt = rxb_addr(rxb);3219 struct iwl_umac_scan_complete *notif = (void *)pkt->data;3220 u32 uid = __le32_to_cpu(notif->uid);3221 bool aborted = (notif->status == IWL_SCAN_OFFLOAD_ABORTED);3222 bool select_links = false;3223 3224 mvm->mei_scan_filter.is_mei_limited_scan = false;3225 3226 IWL_DEBUG_SCAN(mvm,3227 "Scan completed: uid=%u type=%u, status=%s, EBS=%s\n",3228 uid, mvm->scan_uid_status[uid],3229 notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?3230 "completed" : "aborted",3231 iwl_mvm_ebs_status_str(notif->ebs_status));3232 3233 IWL_DEBUG_SCAN(mvm, "Scan completed: scan_status=0x%x\n",3234 mvm->scan_status);3235 3236 IWL_DEBUG_SCAN(mvm,3237 "Scan completed: line=%u, iter=%u, elapsed time=%u\n",3238 notif->last_schedule, notif->last_iter,3239 __le32_to_cpu(notif->time_from_last_iter));3240 3241 if (WARN_ON(!(mvm->scan_uid_status[uid] & mvm->scan_status)))3242 return;3243 3244 /* if the scan is already stopping, we don't need to notify mac80211 */3245 if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) {3246 struct cfg80211_scan_info info = {3247 .aborted = aborted,3248 .scan_start_tsf = mvm->scan_start,3249 };3250 struct iwl_mvm_vif *scan_vif = mvm->scan_vif;3251 struct iwl_mvm_vif_link_info *link_info =3252 scan_vif->link[mvm->scan_link_id];3253 3254 /* It is possible that by the time the scan is complete the link3255 * was already removed and is not valid.3256 */3257 if (link_info)3258 memcpy(info.tsf_bssid, link_info->bssid, ETH_ALEN);3259 else3260 IWL_DEBUG_SCAN(mvm, "Scan link is no longer valid\n");3261 3262 ieee80211_scan_completed(mvm->hw, &info);3263 mvm->scan_vif = NULL;3264 cancel_delayed_work(&mvm->scan_timeout_dwork);3265 iwl_mvm_resume_tcm(mvm);3266 } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {3267 ieee80211_sched_scan_stopped(mvm->hw);3268 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;3269 } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_INT_MLO) {3270 IWL_DEBUG_SCAN(mvm, "Internal MLO scan completed\n");3271 /*3272 * Other scan types won't necessarily scan for the MLD links channels.3273 * Therefore, only select links after successful internal scan.3274 */3275 select_links = notif->status == IWL_SCAN_OFFLOAD_COMPLETED;3276 }3277 3278 mvm->scan_status &= ~mvm->scan_uid_status[uid];3279 3280 IWL_DEBUG_SCAN(mvm, "Scan completed: after update: scan_status=0x%x\n",3281 mvm->scan_status);3282 3283 if (notif->ebs_status != IWL_SCAN_EBS_SUCCESS &&3284 notif->ebs_status != IWL_SCAN_EBS_INACTIVE)3285 mvm->last_ebs_successful = false;3286 3287 mvm->scan_uid_status[uid] = 0;3288 3289 if (select_links)3290 wiphy_work_queue(mvm->hw->wiphy, &mvm->trig_link_selection_wk);3291}3292 3293void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,3294 struct iwl_rx_cmd_buffer *rxb)3295{3296 struct iwl_rx_packet *pkt = rxb_addr(rxb);3297 struct iwl_umac_scan_iter_complete_notif *notif = (void *)pkt->data;3298 3299 mvm->scan_start = le64_to_cpu(notif->start_tsf);3300 3301 IWL_DEBUG_SCAN(mvm,3302 "UMAC Scan iteration complete: status=0x%x scanned_channels=%d\n",3303 notif->status, notif->scanned_channels);3304 3305 if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_FOUND) {3306 IWL_DEBUG_SCAN(mvm, "Pass all scheduled scan results found\n");3307 ieee80211_sched_scan_results(mvm->hw);3308 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED;3309 }3310 3311 IWL_DEBUG_SCAN(mvm,3312 "UMAC Scan iteration complete: scan started at %llu (TSF)\n",3313 mvm->scan_start);3314}3315 3316static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type, bool *wait)3317{3318 struct iwl_umac_scan_abort abort_cmd = {};3319 struct iwl_host_cmd cmd = {3320 .id = WIDE_ID(IWL_ALWAYS_LONG_GROUP, SCAN_ABORT_UMAC),3321 .len = { sizeof(abort_cmd), },3322 .data = { &abort_cmd, },3323 .flags = CMD_SEND_IN_RFKILL,3324 };3325 3326 int uid, ret;3327 u32 status = IWL_UMAC_SCAN_ABORT_STATUS_NOT_FOUND;3328 3329 lockdep_assert_held(&mvm->mutex);3330 3331 *wait = true;3332 3333 /* We should always get a valid index here, because we already3334 * checked that this type of scan was running in the generic3335 * code.3336 */3337 uid = iwl_mvm_scan_uid_by_status(mvm, type);3338 if (WARN_ON_ONCE(uid < 0))3339 return uid;3340 3341 abort_cmd.uid = cpu_to_le32(uid);3342 3343 IWL_DEBUG_SCAN(mvm, "Sending scan abort, uid %u\n", uid);3344 3345 ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status);3346 3347 IWL_DEBUG_SCAN(mvm, "Scan abort: ret=%d, status=%u\n", ret, status);3348 if (!ret)3349 mvm->scan_uid_status[uid] = type << IWL_MVM_SCAN_STOPPING_SHIFT;3350 3351 /* Handle the case that the FW is no longer familiar with the scan that3352 * is to be stopped. In such a case, it is expected that the scan3353 * complete notification was already received but not yet processed.3354 * In such a case, there is no need to wait for a scan complete3355 * notification and the flow should continue similar to the case that3356 * the scan was really aborted.3357 */3358 if (status == IWL_UMAC_SCAN_ABORT_STATUS_NOT_FOUND) {3359 mvm->scan_uid_status[uid] = type << IWL_MVM_SCAN_STOPPING_SHIFT;3360 *wait = false;3361 }3362 3363 return ret;3364}3365 3366static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type)3367{3368 struct iwl_notification_wait wait_scan_done;3369 static const u16 scan_done_notif[] = { SCAN_COMPLETE_UMAC,3370 SCAN_OFFLOAD_COMPLETE, };3371 int ret;3372 bool wait = true;3373 3374 lockdep_assert_held(&mvm->mutex);3375 3376 iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done,3377 scan_done_notif,3378 ARRAY_SIZE(scan_done_notif),3379 NULL, NULL);3380 3381 IWL_DEBUG_SCAN(mvm, "Preparing to stop scan, type %x\n", type);3382 3383 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN))3384 ret = iwl_mvm_umac_scan_abort(mvm, type, &wait);3385 else3386 ret = iwl_mvm_lmac_scan_abort(mvm);3387 3388 if (ret) {3389 IWL_DEBUG_SCAN(mvm, "couldn't stop scan type %d\n", type);3390 iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);3391 return ret;3392 } else if (!wait) {3393 IWL_DEBUG_SCAN(mvm, "no need to wait for scan type %d\n", type);3394 iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);3395 return 0;3396 }3397 3398 return iwl_wait_notification(&mvm->notif_wait, &wait_scan_done,3399 1 * HZ);3400}3401 3402static size_t iwl_scan_req_umac_get_size(u8 scan_ver)3403{3404 switch (scan_ver) {3405 case 12:3406 return sizeof(struct iwl_scan_req_umac_v12);3407 case 14:3408 case 15:3409 case 16:3410 case 17:3411 return sizeof(struct iwl_scan_req_umac_v17);3412 }3413 3414 return 0;3415}3416 3417size_t iwl_mvm_scan_size(struct iwl_mvm *mvm)3418{3419 int base_size, tail_size;3420 u8 scan_ver = iwl_fw_lookup_cmd_ver(mvm->fw, SCAN_REQ_UMAC,3421 IWL_FW_CMD_VER_UNKNOWN);3422 3423 base_size = iwl_scan_req_umac_get_size(scan_ver);3424 if (base_size)3425 return base_size;3426 3427 3428 if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm))3429 base_size = IWL_SCAN_REQ_UMAC_SIZE_V8;3430 else if (iwl_mvm_is_adaptive_dwell_supported(mvm))3431 base_size = IWL_SCAN_REQ_UMAC_SIZE_V7;3432 else if (iwl_mvm_cdb_scan_api(mvm))3433 base_size = IWL_SCAN_REQ_UMAC_SIZE_V6;3434 else3435 base_size = IWL_SCAN_REQ_UMAC_SIZE_V1;3436 3437 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {3438 if (iwl_mvm_is_scan_ext_chan_supported(mvm))3439 tail_size = sizeof(struct iwl_scan_req_umac_tail_v2);3440 else3441 tail_size = sizeof(struct iwl_scan_req_umac_tail_v1);3442 3443 return base_size +3444 sizeof(struct iwl_scan_channel_cfg_umac) *3445 mvm->fw->ucode_capa.n_scan_channels +3446 tail_size;3447 }3448 return sizeof(struct iwl_scan_req_lmac) +3449 sizeof(struct iwl_scan_channel_cfg_lmac) *3450 mvm->fw->ucode_capa.n_scan_channels +3451 sizeof(struct iwl_scan_probe_req_v1);3452}3453 3454/*3455 * This function is used in nic restart flow, to inform mac80211 about scans3456 * that was aborted by restart flow or by an assert.3457 */3458void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)3459{3460 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {3461 int uid, i;3462 3463 uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_REGULAR);3464 if (uid >= 0) {3465 struct cfg80211_scan_info info = {3466 .aborted = true,3467 };3468 3469 cancel_delayed_work(&mvm->scan_timeout_dwork);3470 3471 ieee80211_scan_completed(mvm->hw, &info);3472 mvm->scan_uid_status[uid] = 0;3473 }3474 uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED);3475 if (uid >= 0) {3476 /* Sched scan will be restarted by mac80211 in3477 * restart_hw, so do not report if FW is about to be3478 * restarted.3479 */3480 if (!mvm->fw_restart)3481 ieee80211_sched_scan_stopped(mvm->hw);3482 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;3483 mvm->scan_uid_status[uid] = 0;3484 }3485 uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_INT_MLO);3486 if (uid >= 0) {3487 IWL_DEBUG_SCAN(mvm, "Internal MLO scan aborted\n");3488 mvm->scan_uid_status[uid] = 0;3489 }3490 3491 uid = iwl_mvm_scan_uid_by_status(mvm,3492 IWL_MVM_SCAN_STOPPING_REGULAR);3493 if (uid >= 0)3494 mvm->scan_uid_status[uid] = 0;3495 3496 uid = iwl_mvm_scan_uid_by_status(mvm,3497 IWL_MVM_SCAN_STOPPING_SCHED);3498 if (uid >= 0)3499 mvm->scan_uid_status[uid] = 0;3500 3501 uid = iwl_mvm_scan_uid_by_status(mvm,3502 IWL_MVM_SCAN_STOPPING_INT_MLO);3503 if (uid >= 0)3504 mvm->scan_uid_status[uid] = 0;3505 3506 /* We shouldn't have any UIDs still set. Loop over all the3507 * UIDs to make sure there's nothing left there and warn if3508 * any is found.3509 */3510 for (i = 0; i < mvm->max_scans; i++) {3511 if (WARN_ONCE(mvm->scan_uid_status[i],3512 "UMAC scan UID %d status was not cleaned\n",3513 i))3514 mvm->scan_uid_status[i] = 0;3515 }3516 } else {3517 if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {3518 struct cfg80211_scan_info info = {3519 .aborted = true,3520 };3521 3522 cancel_delayed_work(&mvm->scan_timeout_dwork);3523 ieee80211_scan_completed(mvm->hw, &info);3524 }3525 3526 /* Sched scan will be restarted by mac80211 in3527 * restart_hw, so do not report if FW is about to be3528 * restarted.3529 */3530 if ((mvm->scan_status & IWL_MVM_SCAN_SCHED) &&3531 !mvm->fw_restart) {3532 ieee80211_sched_scan_stopped(mvm->hw);3533 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;3534 }3535 }3536}3537 3538int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify)3539{3540 int ret;3541 3542 IWL_DEBUG_SCAN(mvm,3543 "Request to stop scan: type=0x%x, status=0x%x\n",3544 type, mvm->scan_status);3545 3546 if (!(mvm->scan_status & type))3547 return 0;3548 3549 if (!test_bit(STATUS_DEVICE_ENABLED, &mvm->trans->status)) {3550 ret = 0;3551 goto out;3552 }3553 3554 ret = iwl_mvm_scan_stop_wait(mvm, type);3555 if (!ret)3556 mvm->scan_status |= type << IWL_MVM_SCAN_STOPPING_SHIFT;3557 else3558 IWL_DEBUG_SCAN(mvm, "Failed to stop scan\n");3559 3560out:3561 /* Clear the scan status so the next scan requests will3562 * succeed and mark the scan as stopping, so that the Rx3563 * handler doesn't do anything, as the scan was stopped from3564 * above.3565 */3566 mvm->scan_status &= ~type;3567 3568 if (type == IWL_MVM_SCAN_REGULAR) {3569 cancel_delayed_work(&mvm->scan_timeout_dwork);3570 if (notify) {3571 struct cfg80211_scan_info info = {3572 .aborted = true,3573 };3574 3575 ieee80211_scan_completed(mvm->hw, &info);3576 }3577 } else if (notify) {3578 ieee80211_sched_scan_stopped(mvm->hw);3579 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;3580 }3581 3582 return ret;3583}3584 3585static int iwl_mvm_int_mlo_scan_start(struct iwl_mvm *mvm,3586 struct ieee80211_vif *vif,3587 struct ieee80211_channel **channels,3588 size_t n_channels)3589{3590 struct cfg80211_scan_request *req = NULL;3591 struct ieee80211_scan_ies ies = {};3592 size_t size, i;3593 int ret;3594 3595 lockdep_assert_held(&mvm->mutex);3596 3597 IWL_DEBUG_SCAN(mvm, "Starting Internal MLO scan: n_channels=%zu\n",3598 n_channels);3599 3600 if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))3601 return -EINVAL;3602 3603 size = struct_size(req, channels, n_channels);3604 req = kzalloc(size, GFP_KERNEL);3605 if (!req)3606 return -ENOMEM;3607 3608 /* set the requested channels */3609 for (i = 0; i < n_channels; i++)3610 req->channels[i] = channels[i];3611 3612 req->n_channels = n_channels;3613 3614 /* set the rates */3615 for (i = 0; i < NUM_NL80211_BANDS; i++)3616 if (mvm->hw->wiphy->bands[i])3617 req->rates[i] =3618 (1 << mvm->hw->wiphy->bands[i]->n_bitrates) - 1;3619 3620 req->wdev = ieee80211_vif_to_wdev(vif);3621 req->wiphy = mvm->hw->wiphy;3622 req->scan_start = jiffies;3623 req->tsf_report_link_id = -1;3624 3625 ret = _iwl_mvm_single_scan_start(mvm, vif, req, &ies,3626 IWL_MVM_SCAN_INT_MLO);3627 kfree(req);3628 3629 IWL_DEBUG_SCAN(mvm, "Internal MLO scan: ret=%d\n", ret);3630 return ret;3631}3632 3633int iwl_mvm_int_mlo_scan(struct iwl_mvm *mvm, struct ieee80211_vif *vif)3634{3635 struct ieee80211_channel *channels[IEEE80211_MLD_MAX_NUM_LINKS];3636 unsigned long usable_links = ieee80211_vif_usable_links(vif);3637 size_t n_channels = 0;3638 u8 link_id;3639 3640 lockdep_assert_held(&mvm->mutex);3641 3642 if (mvm->scan_status & IWL_MVM_SCAN_INT_MLO) {3643 IWL_DEBUG_SCAN(mvm, "Internal MLO scan is already running\n");3644 return -EBUSY;3645 }3646 3647 rcu_read_lock();3648 3649 for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {3650 struct ieee80211_bss_conf *link_conf =3651 rcu_dereference(vif->link_conf[link_id]);3652 3653 if (WARN_ON_ONCE(!link_conf))3654 continue;3655 3656 channels[n_channels++] = link_conf->chanreq.oper.chan;3657 }3658 3659 rcu_read_unlock();3660 3661 if (!n_channels)3662 return -EINVAL;3663 3664 return iwl_mvm_int_mlo_scan_start(mvm, vif, channels, n_channels);3665}3666 3667static int iwl_mvm_chanidx_from_phy(struct iwl_mvm *mvm,3668 enum nl80211_band band,3669 u16 phy_chan_num)3670{3671 struct ieee80211_supported_band *sband = mvm->hw->wiphy->bands[band];3672 int chan_idx;3673 3674 if (WARN_ON_ONCE(!sband))3675 return -EINVAL;3676 3677 for (chan_idx = 0; chan_idx < sband->n_channels; chan_idx++) {3678 struct ieee80211_channel *channel = &sband->channels[chan_idx];3679 3680 if (channel->hw_value == phy_chan_num)3681 return chan_idx;3682 }3683 3684 return -EINVAL;3685}3686 3687static u32 iwl_mvm_div_by_db(u32 value, u8 db)3688{3689 /*3690 * 2^32 * 10**(i / 10) for i = [1, 10], skipping 0 and simply stopping3691 * at 10 dB and looping instead of using a much larger table.3692 *3693 * Using 64 bit math is overkill, but means the helper does not require3694 * a limit on the input range.3695 */3696 static const u32 db_to_val[] = {3697 0xcb59185e, 0xa1866ba8, 0x804dce7a, 0x65ea59fe, 0x50f44d89,3698 0x404de61f, 0x331426af, 0x2892c18b, 0x203a7e5b, 0x1999999a,3699 };3700 3701 while (value && db > 0) {3702 u8 change = min_t(u8, db, ARRAY_SIZE(db_to_val));3703 3704 value = (((u64)value) * db_to_val[change - 1]) >> 32;3705 3706 db -= change;3707 }3708 3709 return value;3710}3711 3712VISIBLE_IF_IWLWIFI_KUNIT s83713iwl_mvm_average_dbm_values(const struct iwl_umac_scan_channel_survey_notif *notif)3714{3715 s8 average_magnitude;3716 u32 average_factor;3717 s8 sum_magnitude = -128;3718 u32 sum_factor = 0;3719 int i, count = 0;3720 3721 /*3722 * To properly average the decibel values (signal values given in dBm)3723 * we need to do the math in linear space. Doing a linear average of3724 * dB (dBm) values is a bit annoying though due to the large range of3725 * at least -10 to -110 dBm that will not fit into a 32 bit integer.3726 *3727 * A 64 bit integer should be sufficient, but then we still have the3728 * problem that there are no directly usable utility functions3729 * available.3730 *3731 * So, lets not deal with that and instead do much of the calculation3732 * with a 16.16 fixed point integer along with a base in dBm. 16.16 bit3733 * gives us plenty of head-room for adding up a few values and even3734 * doing some math on it. And the tail should be accurate enough too3735 * (1/2^16 is somewhere around -48 dB, so effectively zero).3736 *3737 * i.e. the real value of sum is:3738 * sum = sum_factor / 2^16 * 10^(sum_magnitude / 10) mW3739 *3740 * However, that does mean we need to be able to bring two values to3741 * a common base, so we need a helper for that.3742 *3743 * Note that this function takes an input with unsigned negative dBm3744 * values but returns a signed dBm (i.e. a negative value).3745 */3746 3747 for (i = 0; i < ARRAY_SIZE(notif->noise); i++) {3748 s8 val_magnitude;3749 u32 val_factor;3750 3751 if (notif->noise[i] == 0xff)3752 continue;3753 3754 val_factor = 0x10000;3755 val_magnitude = -notif->noise[i];3756 3757 if (val_magnitude <= sum_magnitude) {3758 u8 div_db = sum_magnitude - val_magnitude;3759 3760 val_factor = iwl_mvm_div_by_db(val_factor, div_db);3761 val_magnitude = sum_magnitude;3762 } else {3763 u8 div_db = val_magnitude - sum_magnitude;3764 3765 sum_factor = iwl_mvm_div_by_db(sum_factor, div_db);3766 sum_magnitude = val_magnitude;3767 }3768 3769 sum_factor += val_factor;3770 count++;3771 }3772 3773 /* No valid noise measurement, return a very high noise level */3774 if (count == 0)3775 return 0;3776 3777 average_magnitude = sum_magnitude;3778 average_factor = sum_factor / count;3779 3780 /*3781 * average_factor will be a number smaller than 1.0 (0x10000) at this3782 * point. What we need to do now is to adjust average_magnitude so that3783 * average_factor is between -0.5 dB and 0.5 dB.3784 *3785 * Just do -1 dB steps and find the point where3786 * -0.5 dB * -i dB = 0x10000 * 10^(-0.5/10) / i dB3787 * = div_by_db(0xe429, i)3788 * is smaller than average_factor.3789 */3790 for (i = 0; average_factor < iwl_mvm_div_by_db(0xe429, i); i++) {3791 /* nothing */3792 }3793 3794 return average_magnitude - i;3795}3796EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_average_dbm_values);3797 3798void iwl_mvm_rx_channel_survey_notif(struct iwl_mvm *mvm,3799 struct iwl_rx_cmd_buffer *rxb)3800{3801 struct iwl_rx_packet *pkt = rxb_addr(rxb);3802 const struct iwl_umac_scan_channel_survey_notif *notif =3803 (void *)pkt->data;3804 struct iwl_mvm_acs_survey_channel *info;3805 enum nl80211_band band;3806 int chan_idx;3807 3808 lockdep_assert_held(&mvm->mutex);3809 3810 if (!mvm->acs_survey) {3811 size_t n_channels = 0;3812 3813 for (band = 0; band < NUM_NL80211_BANDS; band++) {3814 if (!mvm->hw->wiphy->bands[band])3815 continue;3816 3817 n_channels += mvm->hw->wiphy->bands[band]->n_channels;3818 }3819 3820 mvm->acs_survey = kzalloc(struct_size(mvm->acs_survey,3821 channels, n_channels),3822 GFP_KERNEL);3823 3824 if (!mvm->acs_survey)3825 return;3826 3827 mvm->acs_survey->n_channels = n_channels;3828 n_channels = 0;3829 for (band = 0; band < NUM_NL80211_BANDS; band++) {3830 if (!mvm->hw->wiphy->bands[band])3831 continue;3832 3833 mvm->acs_survey->bands[band] =3834 &mvm->acs_survey->channels[n_channels];3835 n_channels += mvm->hw->wiphy->bands[band]->n_channels;3836 }3837 }3838 3839 band = iwl_mvm_nl80211_band_from_phy(le32_to_cpu(notif->band));3840 chan_idx = iwl_mvm_chanidx_from_phy(mvm, band,3841 le32_to_cpu(notif->channel));3842 if (WARN_ON_ONCE(chan_idx < 0))3843 return;3844 3845 IWL_DEBUG_SCAN(mvm, "channel survey received for freq %d\n",3846 mvm->hw->wiphy->bands[band]->channels[chan_idx].center_freq);3847 3848 info = &mvm->acs_survey->bands[band][chan_idx];3849 3850 /* Times are all in ms */3851 info->time = le32_to_cpu(notif->active_time);3852 info->time_busy = le32_to_cpu(notif->busy_time);3853 info->time_rx = le32_to_cpu(notif->rx_time);3854 info->time_tx = le32_to_cpu(notif->tx_time);3855 info->noise = iwl_mvm_average_dbm_values(notif);3856}3857