iwlwifi: mvm: Add support for hidden network scan on 6GHz band

Add support for discovery of hidden networks on the 6GHz band,
by including the scan request direct SSIDs in the FW scan request
command:

- In case a short SSID matches one of the direct SSIDs in the scan
  request command, add the matching SSID in the same offset in the
  'direct_ssids' array.
- Otherwise, add the SSID in one of the available slots.

Additionally, as a preparation to handle hidden APs, refactor
iwl_mvm_umac_scan_cfg_channels_v6_6g() the function.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210802170640.ffb540a70212.Ia2bb9bc9435b833820bcc7dc30adcedb5a5a9869@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
Ilan Peer 2021-08-02 17:09:43 +03:00 committed by Luca Coelho
parent deedf9b97c
commit 16cff731a3
2 changed files with 76 additions and 15 deletions
drivers/net/wireless/intel/iwlwifi

View File

@ -414,6 +414,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_PROTECTED_TWT = (__force iwl_ucode_tlv_capa_t)56,
IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE = (__force iwl_ucode_tlv_capa_t)57,
IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN = (__force iwl_ucode_tlv_capa_t)58,
IWL_UCODE_TLV_CAPA_HIDDEN_6GHZ_SCAN = (__force iwl_ucode_tlv_capa_t)59,
IWL_UCODE_TLV_CAPA_BROADCAST_TWT = (__force iwl_ucode_tlv_capa_t)60,
/* set 2 */

View File

@ -1724,9 +1724,8 @@ iwl_mvm_umac_scan_fill_6g_chan_list(struct iwl_mvm_scan_params *params,
/* TODO: this function can be merged with iwl_mvm_scan_umac_fill_ch_p_v6 */
static void
iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
u32 n_channels, __le32 *cmd_short_ssid,
u8 *cmd_bssid, u8 scan_ssid_num,
u8 bssid_num,
u32 n_channels,
struct iwl_scan_probe_params_v4 *pp,
struct iwl_scan_channel_params_v6 *cp,
enum nl80211_iftype vif_type)
{
@ -1741,7 +1740,7 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
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,
bool force_passive, found = false, allow_passive = true,
unsolicited_probe_on_chan = false, psc_no_listen = false;
cfg->v1.channel_num = params->channels[i]->hw_value;
@ -1766,9 +1765,9 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
scan_6ghz_params[j].unsolicited_probe;
psc_no_listen |= scan_6ghz_params[j].psc_no_listen;
for (k = 0; k < scan_ssid_num; k++) {
for (k = 0; k < pp->short_ssid_num; k++) {
if (!scan_6ghz_params[j].unsolicited_probe &&
le32_to_cpu(cmd_short_ssid[k]) ==
le32_to_cpu(pp->short_ssid[k]) ==
scan_6ghz_params[j].short_ssid) {
/* Relevant short SSID bit set */
if (s_ssid_bitmap & BIT(k)) {
@ -1778,7 +1777,10 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
/*
* Use short SSID only to create a new
* iteration during channel dwell.
* iteration during channel dwell or in
* case that the short SSID has a
* matching SSID, i.e., scan for hidden
* APs.
*/
if (n_used_bssid_entries >= 3) {
s_ssid_bitmap |= BIT(k);
@ -1786,6 +1788,12 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
n_used_bssid_entries -= 3;
found = true;
break;
} else if (pp->direct_scan[k].len) {
s_ssid_bitmap |= BIT(k);
s_max++;
found = true;
allow_passive = false;
break;
}
}
}
@ -1793,8 +1801,8 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
if (found)
continue;
for (k = 0; k < bssid_num; k++) {
if (!memcmp(&cmd_bssid[ETH_ALEN * k],
for (k = 0; k < pp->bssid_num; k++) {
if (!memcmp(&pp->bssid_array[k],
scan_6ghz_params[j].bssid,
ETH_ALEN)) {
if (!(bssid_bitmap & BIT(k))) {
@ -1849,7 +1857,7 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
force_passive |= (unsolicited_probe_on_chan &&
(s_max > 1 || b_max > 3));
}
if (force_passive ||
if ((allow_passive && force_passive) ||
(!flags && !cfg80211_channel_is_psc(params->channels[i])))
flags |= IWL_UHB_CHAN_CFG_FLAG_FORCE_PASSIVE;
@ -1857,6 +1865,60 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
}
}
static void
iwl_mvm_umac_scan_cfg_6g_direct_ssids(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
struct iwl_scan_probe_params_v4 *pp)
{
u8 next_free_idx = pp->short_ssid_num;
int i;
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_HIDDEN_6GHZ_SCAN)) {
IWL_DEBUG_SCAN(mvm,
"6GHz hidden scan: Not supported by FW\n");
return;
}
for (i = params->n_ssids - 1; i >= 0; i--) {
__le32 short_ssid;
u8 ssid_idx, j;
if (!params->ssids[i].ssid_len)
continue;
short_ssid = cpu_to_le32(~crc32_le(~0, params->ssids[i].ssid,
params->ssids[i].ssid_len));
for (j = 0; j < pp->short_ssid_num; j++)
if (short_ssid == pp->short_ssid[j])
break;
if (j == pp->short_ssid_num) {
/*
* If there are no available slots for the short SSID, do not
* place it.
*/
if (next_free_idx < SCAN_SHORT_SSID_MAX_SIZE)
ssid_idx = next_free_idx++;
else
continue;
} else {
ssid_idx = j;
}
if (ssid_idx >= PROBE_OPTION_MAX)
continue;
pp->direct_scan[ssid_idx].id = WLAN_EID_SSID;
pp->direct_scan[ssid_idx].len = params->ssids[i].ssid_len;
memcpy(pp->direct_scan[ssid_idx].ssid, params->ssids[i].ssid,
params->ssids[i].ssid_len);
}
pp->short_ssid_num = next_free_idx;
}
static u8 iwl_mvm_scan_umac_chan_flags_v2(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
struct ieee80211_vif *vif)
@ -2390,13 +2452,11 @@ static int iwl_mvm_scan_umac_v14(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (ret)
return ret;
iwl_mvm_umac_scan_cfg_6g_direct_ssids(mvm, params, pb);
iwl_mvm_umac_scan_cfg_channels_v6_6g(params,
params->n_channels,
pb->short_ssid,
pb->bssid_array[0],
pb->short_ssid_num,
pb->bssid_num, cp,
vif->type);
pb, cp, vif->type);
cp->count = params->n_channels;
if (!params->n_ssids ||
(params->n_ssids == 1 && !params->ssids[0].ssid_len))