Commit a615323f authored by Benjamin Berg's avatar Benjamin Berg Committed by Johannes Berg
Browse files

wifi: iwlwifi: mvm: always apply 6 GHz probe limitations



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: default avatarBenjamin Berg <benjamin.berg@intel.com>
Reviewed-by: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240319100755.e0b114b68d1d.Ib86afccdb955f0d221ef5d7b8afdc1d67c3542ef@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 8f892e22
Loading
Loading
Loading
Loading
+89 −66
Original line number Diff line number Diff line
@@ -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;

			for (k = 0; k < pp->short_ssid_num; k++) {
			found = false;

			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,27 +1868,27 @@ 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) {

					/* Hidden AP, cannot do passive scan */
					if (pp->direct_scan[k].len)
						allow_passive = false;

					s_ssid_bitmap |= BIT(k);
						s_max++;
					n_s_ssids++;
					found = true;
						allow_passive = false;
					break;
				}
			}
			}

			if (found)
				continue;
@@ -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))) {
						if (n_bssids < max_bssids) {
							bssid_bitmap |= BIT(k);
						b_max++;
						n_used_bssid_entries++;
							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])))