Commit 16cff731 authored by Ilan Peer's avatar Ilan Peer Committed by Luca Coelho

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: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210802170640.ffb540a70212.Ia2bb9bc9435b833820bcc7dc30adcedb5a5a9869@changeidSigned-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent deedf9b9
...@@ -414,6 +414,7 @@ enum iwl_ucode_tlv_capa { ...@@ -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_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_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_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, IWL_UCODE_TLV_CAPA_BROADCAST_TWT = (__force iwl_ucode_tlv_capa_t)60,
/* set 2 */ /* set 2 */
......
...@@ -1724,9 +1724,8 @@ iwl_mvm_umac_scan_fill_6g_chan_list(struct iwl_mvm_scan_params *params, ...@@ -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 */ /* TODO: this function can be merged with iwl_mvm_scan_umac_fill_ch_p_v6 */
static void static void
iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params, iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
u32 n_channels, __le32 *cmd_short_ssid, u32 n_channels,
u8 *cmd_bssid, u8 scan_ssid_num, struct iwl_scan_probe_params_v4 *pp,
u8 bssid_num,
struct iwl_scan_channel_params_v6 *cp, struct iwl_scan_channel_params_v6 *cp,
enum nl80211_iftype vif_type) enum nl80211_iftype vif_type)
{ {
...@@ -1741,7 +1740,7 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params, ...@@ -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; u32 s_ssid_bitmap = 0, bssid_bitmap = 0, flags = 0;
u8 j, k, s_max = 0, b_max = 0, n_used_bssid_entries; 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; unsolicited_probe_on_chan = false, psc_no_listen = false;
cfg->v1.channel_num = params->channels[i]->hw_value; 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, ...@@ -1766,9 +1765,9 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
scan_6ghz_params[j].unsolicited_probe; scan_6ghz_params[j].unsolicited_probe;
psc_no_listen |= scan_6ghz_params[j].psc_no_listen; 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 && 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) { scan_6ghz_params[j].short_ssid) {
/* Relevant short SSID bit set */ /* Relevant short SSID bit set */
if (s_ssid_bitmap & BIT(k)) { if (s_ssid_bitmap & BIT(k)) {
...@@ -1778,7 +1777,10 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params, ...@@ -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 * 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) { if (n_used_bssid_entries >= 3) {
s_ssid_bitmap |= BIT(k); s_ssid_bitmap |= BIT(k);
...@@ -1786,6 +1788,12 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params, ...@@ -1786,6 +1788,12 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
n_used_bssid_entries -= 3; n_used_bssid_entries -= 3;
found = true; found = true;
break; 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, ...@@ -1793,8 +1801,8 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
if (found) if (found)
continue; continue;
for (k = 0; k < bssid_num; k++) { for (k = 0; k < pp->bssid_num; k++) {
if (!memcmp(&cmd_bssid[ETH_ALEN * k], if (!memcmp(&pp->bssid_array[k],
scan_6ghz_params[j].bssid, scan_6ghz_params[j].bssid,
ETH_ALEN)) { ETH_ALEN)) {
if (!(bssid_bitmap & BIT(k))) { if (!(bssid_bitmap & BIT(k))) {
...@@ -1849,7 +1857,7 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params, ...@@ -1849,7 +1857,7 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm_scan_params *params,
force_passive |= (unsolicited_probe_on_chan && force_passive |= (unsolicited_probe_on_chan &&
(s_max > 1 || b_max > 3)); (s_max > 1 || b_max > 3));
} }
if (force_passive || if ((allow_passive && force_passive) ||
(!flags && !cfg80211_channel_is_psc(params->channels[i]))) (!flags && !cfg80211_channel_is_psc(params->channels[i])))
flags |= IWL_UHB_CHAN_CFG_FLAG_FORCE_PASSIVE; 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, ...@@ -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, static u8 iwl_mvm_scan_umac_chan_flags_v2(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params, struct iwl_mvm_scan_params *params,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
...@@ -2390,13 +2452,11 @@ static int iwl_mvm_scan_umac_v14(struct iwl_mvm *mvm, 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) if (ret)
return ret; return ret;
iwl_mvm_umac_scan_cfg_6g_direct_ssids(mvm, params, pb);
iwl_mvm_umac_scan_cfg_channels_v6_6g(params, iwl_mvm_umac_scan_cfg_channels_v6_6g(params,
params->n_channels, params->n_channels,
pb->short_ssid, pb, cp, vif->type);
pb->bssid_array[0],
pb->short_ssid_num,
pb->bssid_num, cp,
vif->type);
cp->count = params->n_channels; cp->count = params->n_channels;
if (!params->n_ssids || if (!params->n_ssids ||
(params->n_ssids == 1 && !params->ssids[0].ssid_len)) (params->n_ssids == 1 && !params->ssids[0].ssid_len))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment