From: Benjamin Berg <benjamin.berg@xxxxxxxxx> When scanning on 6 GHz we allocate a set of short-SSIDs and BSSIDs to probe. However, when we need to do an active scan because of a hidden SSID, then we could add too many entries for probing causing an assertion in the firmware input validation. Reshuffle the code a bit to first calculate the maximum number of short-SSIDs and BSSIDs that are permitted for the channel. Then ensure that we do not set more than the permitted number of bits in the bitmasks and turn on force_passive when we have surpassed the limit. While at it, also change the logic so that allow_passive is always disabled in case a hidden SSID is included. Previously, we might not have done so if we added the short-SSID based on the number of BSSIDs already in the request. Signed-off-by: Benjamin Berg <benjamin.berg@xxxxxxxxx> Reviewed-by: Ilan Peer <ilan.peer@xxxxxxxxx> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@xxxxxxxxx> --- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 155 ++++++++++-------- 1 file changed, 89 insertions(+), 66 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index ea05957fbcec..459adba41ca6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -1750,8 +1750,9 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm, &cp->channel_config[ch_cnt]; u32 s_ssid_bitmap = 0, bssid_bitmap = 0, flags = 0; - u8 j, k, s_max = 0, b_max = 0, n_used_bssid_entries; - bool force_passive, found = false, allow_passive = true, + u8 j, k, n_s_ssids = 0, n_bssids = 0; + u8 max_s_ssids, max_bssids; + bool force_passive = false, found = false, allow_passive = true, unsolicited_probe_on_chan = false, psc_no_listen = false; s8 psd_20 = IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED; @@ -1774,20 +1775,15 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm, cfg->v5.iter_count = 1; cfg->v5.iter_interval = 0; - /* - * The optimize the scan time, i.e., reduce the scan dwell time - * on each channel, the below logic tries to set 3 direct BSSID - * probe requests for each broadcast probe request with a short - * SSID. - * TODO: improve this logic - */ - n_used_bssid_entries = 3; for (j = 0; j < params->n_6ghz_params; j++) { s8 tmp_psd_20; if (!(scan_6ghz_params[j].channel_idx == i)) continue; + unsolicited_probe_on_chan |= + scan_6ghz_params[j].unsolicited_probe; + /* Use the highest PSD value allowed as advertised by * APs for this channel */ @@ -1799,12 +1795,69 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm, psd_20 < tmp_psd_20)) psd_20 = tmp_psd_20; - found = false; - unsolicited_probe_on_chan |= - scan_6ghz_params[j].unsolicited_probe; psc_no_listen |= scan_6ghz_params[j].psc_no_listen; + } + + /* + * In the following cases apply passive scan: + * 1. Non fragmented scan: + * - PSC channel with NO_LISTEN_FLAG on should be treated + * like non PSC channel + * - Non PSC channel with more than 3 short SSIDs or more + * than 9 BSSIDs. + * - Non PSC Channel with unsolicited probe response and + * more than 2 short SSIDs or more than 6 BSSIDs. + * - PSC channel with more than 2 short SSIDs or more than + * 6 BSSIDs. + * 3. Fragmented scan: + * - PSC channel with more than 1 SSID or 3 BSSIDs. + * - Non PSC channel with more than 2 SSIDs or 6 BSSIDs. + * - Non PSC channel with unsolicited probe response and + * more than 1 SSID or more than 3 BSSIDs. + */ + if (!iwl_mvm_is_scan_fragmented(params->type)) { + if (!cfg80211_channel_is_psc(params->channels[i]) || + flags & IWL_UHB_CHAN_CFG_FLAG_PSC_CHAN_NO_LISTEN) { + if (unsolicited_probe_on_chan) { + max_s_ssids = 2; + max_bssids = 6; + } else { + max_s_ssids = 3; + max_bssids = 9; + } + } else { + max_s_ssids = 2; + max_bssids = 6; + } + } else if (cfg80211_channel_is_psc(params->channels[i])) { + max_s_ssids = 1; + max_bssids = 3; + } else { + if (unsolicited_probe_on_chan) { + max_s_ssids = 1; + max_bssids = 3; + } else { + max_s_ssids = 2; + max_bssids = 6; + } + } + + /* + * The optimize the scan time, i.e., reduce the scan dwell time + * on each channel, the below logic tries to set 3 direct BSSID + * probe requests for each broadcast probe request with a short + * SSID. + * TODO: improve this logic + */ + for (j = 0; j < params->n_6ghz_params; j++) { + if (!(scan_6ghz_params[j].channel_idx == i)) + continue; + + found = false; - for (k = 0; k < pp->short_ssid_num; k++) { + for (k = 0; + k < pp->short_ssid_num && n_s_ssids < max_s_ssids; + k++) { if (!scan_6ghz_params[j].unsolicited_probe && le32_to_cpu(pp->short_ssid[k]) == scan_6ghz_params[j].short_ssid) { @@ -1815,25 +1868,25 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm, } /* - * Use short SSID only to create a new - * iteration during channel dwell or in - * case that the short SSID has a - * matching SSID, i.e., scan for hidden - * APs. + * Prefer creating BSSID entries unless + * the short SSID probe can be done in + * the same channel dwell iteration. + * + * We also need to create a short SSID + * entry for any hidden AP. */ - if (n_used_bssid_entries >= 3) { - s_ssid_bitmap |= BIT(k); - s_max++; - n_used_bssid_entries -= 3; - found = true; + if (3 * n_s_ssids > n_bssids && + !pp->direct_scan[k].len) break; - } else if (pp->direct_scan[k].len) { - s_ssid_bitmap |= BIT(k); - s_max++; - found = true; + + /* Hidden AP, cannot do passive scan */ + if (pp->direct_scan[k].len) allow_passive = false; - break; - } + + s_ssid_bitmap |= BIT(k); + n_s_ssids++; + found = true; + break; } } @@ -1845,9 +1898,12 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm, scan_6ghz_params[j].bssid, ETH_ALEN)) { if (!(bssid_bitmap & BIT(k))) { - bssid_bitmap |= BIT(k); - b_max++; - n_used_bssid_entries++; + if (n_bssids < max_bssids) { + bssid_bitmap |= BIT(k); + n_bssids++; + } else { + force_passive = TRUE; + } } break; } @@ -1861,39 +1917,6 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm, if (unsolicited_probe_on_chan) flags |= IWL_UHB_CHAN_CFG_FLAG_UNSOLICITED_PROBE_RES; - /* - * In the following cases apply passive scan: - * 1. Non fragmented scan: - * - PSC channel with NO_LISTEN_FLAG on should be treated - * like non PSC channel - * - Non PSC channel with more than 3 short SSIDs or more - * than 9 BSSIDs. - * - Non PSC Channel with unsolicited probe response and - * more than 2 short SSIDs or more than 6 BSSIDs. - * - PSC channel with more than 2 short SSIDs or more than - * 6 BSSIDs. - * 3. Fragmented scan: - * - PSC channel with more than 1 SSID or 3 BSSIDs. - * - Non PSC channel with more than 2 SSIDs or 6 BSSIDs. - * - Non PSC channel with unsolicited probe response and - * more than 1 SSID or more than 3 BSSIDs. - */ - if (!iwl_mvm_is_scan_fragmented(params->type)) { - if (!cfg80211_channel_is_psc(params->channels[i]) || - flags & IWL_UHB_CHAN_CFG_FLAG_PSC_CHAN_NO_LISTEN) { - force_passive = (s_max > 3 || b_max > 9); - force_passive |= (unsolicited_probe_on_chan && - (s_max > 2 || b_max > 6)); - } else { - force_passive = (s_max > 2 || b_max > 6); - } - } else if (cfg80211_channel_is_psc(params->channels[i])) { - force_passive = (s_max > 1 || b_max > 3); - } else { - force_passive = (s_max > 2 || b_max > 6); - force_passive |= (unsolicited_probe_on_chan && - (s_max > 1 || b_max > 3)); - } if ((allow_passive && force_passive) || (!(bssid_bitmap | s_ssid_bitmap) && !cfg80211_channel_is_psc(params->channels[i]))) -- 2.34.1