iwlwifi: scan: support FW APIs with variable number of profiles

The FW changed the maximum number of scan offload profiles to 8 in new
APIs.  Support it by changing the scan_offload_profile_cfg struct to be
more dynamic, so we can reuse most of the code and only change size of
the profiles array.

Change-Id: I65210cf541af46e2675a8c764d5871f7f5b070d6
Signed-off-by: Tova Mussai <tova.mussai@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
Tova Mussai 2019-11-05 12:56:14 +02:00 committed by Luca Coelho
parent e8b61560ef
commit 5d1234ba25
5 changed files with 65 additions and 23 deletions

View File

@ -95,6 +95,7 @@ struct iwl_ssid_ie {
#define IWL_SCAN_MAX_BLACKLIST_LEN 64
#define IWL_SCAN_SHORT_BLACKLIST_LEN 16
#define IWL_SCAN_MAX_PROFILES 11
#define IWL_SCAN_MAX_PROFILES_V2 8
#define SCAN_OFFLOAD_PROBE_REQ_SIZE 512
#define SCAN_NUM_BAND_PROBE_DATA_V_1 2
#define SCAN_NUM_BAND_PROBE_DATA_V_2 3
@ -160,8 +161,7 @@ struct iwl_scan_offload_profile {
} __packed;
/**
* struct iwl_scan_offload_profile_cfg - SCAN_OFFLOAD_PROFILES_CFG_API_S_VER_1
* @profiles: profiles to search for match
* struct iwl_scan_offload_profile_cfg_data
* @blacklist_len: length of blacklist
* @num_profiles: num of profiles in the list
* @match_notify: clients waiting for match found notification
@ -170,8 +170,7 @@ struct iwl_scan_offload_profile {
* @any_beacon_notify: clients waiting for match notification without match
* @reserved: reserved
*/
struct iwl_scan_offload_profile_cfg {
struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES];
struct iwl_scan_offload_profile_cfg_data {
u8 blacklist_len;
u8 num_profiles;
u8 match_notify;
@ -181,6 +180,26 @@ struct iwl_scan_offload_profile_cfg {
u8 reserved[2];
} __packed;
/**
* struct iwl_scan_offload_profile_cfg
* @profiles: profiles to search for match
* @data: the rest of the data for profile_cfg
*/
struct iwl_scan_offload_profile_cfg_v1 {
struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES];
struct iwl_scan_offload_profile_cfg_data data;
} __packed; /* SCAN_OFFLOAD_PROFILES_CFG_API_S_VER_1-2*/
/**
* struct iwl_scan_offload_profile_cfg
* @profiles: profiles to search for match
* @data: the rest of the data for profile_cfg
*/
struct iwl_scan_offload_profile_cfg {
struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES_V2];
struct iwl_scan_offload_profile_cfg_data data;
} __packed; /* SCAN_OFFLOAD_PROFILES_CFG_API_S_VER_3*/
/**
* struct iwl_scan_schedule_lmac - schedule of scan offload
* @delay: delay between iterations, in seconds.
@ -1169,7 +1188,7 @@ struct iwl_scan_offload_profiles_query_v1 {
u8 resume_while_scanning;
u8 self_recovery;
__le16 reserved;
struct iwl_scan_offload_profile_match_v1 matches[IWL_SCAN_MAX_PROFILES];
struct iwl_scan_offload_profile_match_v1 matches[0];
} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */
/**
@ -1213,7 +1232,7 @@ struct iwl_scan_offload_profiles_query {
u8 resume_while_scanning;
u8 self_recovery;
__le16 reserved;
struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES];
struct iwl_scan_offload_profile_match matches[0];
} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_3 */
/**

View File

@ -1709,6 +1709,7 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
};
int ret, len;
size_t query_len, matches_len;
int max_profiles = iwl_umac_scan_get_max_profiles(mvm->fw);
ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret) {
@ -1720,11 +1721,11 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
query_len = sizeof(struct iwl_scan_offload_profiles_query);
matches_len = sizeof(struct iwl_scan_offload_profile_match) *
IWL_SCAN_MAX_PROFILES;
max_profiles;
} else {
query_len = sizeof(struct iwl_scan_offload_profiles_query_v1);
matches_len = sizeof(struct iwl_scan_offload_profile_match_v1) *
IWL_SCAN_MAX_PROFILES;
max_profiles;
}
len = iwl_rx_packet_payload_len(cmd.resp_pkt);

View File

@ -617,7 +617,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->max_sched_scan_reqs = 1;
hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
hw->wiphy->max_match_sets = iwl_umac_scan_get_max_profiles(mvm->fw);
/* we create the 802.11 header and zero length SSID IE. */
hw->wiphy->max_sched_scan_ie_len =
SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
@ -705,7 +705,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
mvm->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS;
mvm->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN;
mvm->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN;
mvm->wowlan.max_nd_match_sets = IWL_SCAN_MAX_PROFILES;
mvm->wowlan.max_nd_match_sets =
iwl_umac_scan_get_max_profiles(mvm->fw);
hw->wiphy->wowlan = &mvm->wowlan;
}
#endif

View File

@ -2147,4 +2147,11 @@ iwl_mvm_set_chan_info_chandef(struct iwl_mvm *mvm,
iwl_mvm_get_ctrl_pos(chandef));
}
static inline int iwl_umac_scan_get_max_profiles(const struct iwl_fw *fw)
{
u8 ver = iwl_mvm_lookup_cmd_ver(fw, IWL_ALWAYS_LONG_GROUP,
SCAN_OFFLOAD_UPDATE_PROFILES_CMD);
return (ver == IWL_FW_CMD_VER_UNKNOWN || ver < 3) ?
IWL_SCAN_MAX_PROFILES : IWL_SCAN_MAX_PROFILES_V2;
}
#endif /* __IWL_MVM_H__ */

View File

@ -594,11 +594,15 @@ iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req)
{
struct iwl_scan_offload_profile *profile;
struct iwl_scan_offload_profile_cfg *profile_cfg;
struct iwl_scan_offload_profile_cfg_v1 *profile_cfg_v1;
struct iwl_scan_offload_blacklist *blacklist;
struct iwl_scan_offload_profile_cfg_data *data;
int max_profiles = iwl_umac_scan_get_max_profiles(mvm->fw);
int profile_cfg_size = sizeof(*data) +
sizeof(*profile) * max_profiles;
struct iwl_host_cmd cmd = {
.id = SCAN_OFFLOAD_UPDATE_PROFILES_CMD,
.len[1] = sizeof(*profile_cfg),
.len[1] = profile_cfg_size,
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
.dataflags[1] = IWL_HCMD_DFL_NOCOPY,
};
@ -606,7 +610,7 @@ iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
int i;
int ret;
if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES))
if (WARN_ON(req->n_match_sets > max_profiles))
return -EIO;
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL)
@ -618,27 +622,37 @@ iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
if (!blacklist)
return -ENOMEM;
profile_cfg = kzalloc(sizeof(*profile_cfg), GFP_KERNEL);
if (!profile_cfg) {
profile_cfg_v1 = kzalloc(profile_cfg_size, GFP_KERNEL);
if (!profile_cfg_v1) {
ret = -ENOMEM;
goto free_blacklist;
}
cmd.data[0] = blacklist;
cmd.len[0] = sizeof(*blacklist) * blacklist_len;
cmd.data[1] = profile_cfg;
cmd.data[1] = profile_cfg_v1;
/* if max_profile is MAX_PROFILES_V2, we have the new API */
if (max_profiles == IWL_SCAN_MAX_PROFILES_V2) {
struct iwl_scan_offload_profile_cfg *profile_cfg =
(struct iwl_scan_offload_profile_cfg *)profile_cfg_v1;
data = &profile_cfg->data;
} else {
data = &profile_cfg_v1->data;
}
/* No blacklist configuration */
data->num_profiles = req->n_match_sets;
data->active_clients = SCAN_CLIENT_SCHED_SCAN;
data->pass_match = SCAN_CLIENT_SCHED_SCAN;
data->match_notify = SCAN_CLIENT_SCHED_SCAN;
profile_cfg->num_profiles = req->n_match_sets;
profile_cfg->active_clients = SCAN_CLIENT_SCHED_SCAN;
profile_cfg->pass_match = SCAN_CLIENT_SCHED_SCAN;
profile_cfg->match_notify = SCAN_CLIENT_SCHED_SCAN;
if (!req->n_match_sets || !req->match_sets[0].ssid.ssid_len)
profile_cfg->any_beacon_notify = SCAN_CLIENT_SCHED_SCAN;
data->any_beacon_notify = SCAN_CLIENT_SCHED_SCAN;
for (i = 0; i < req->n_match_sets; i++) {
profile = &profile_cfg->profiles[i];
profile = &profile_cfg_v1->profiles[i];
profile->ssid_index = i;
/* Support any cipher and auth algorithm */
profile->unicast_cipher = 0xff;
@ -651,7 +665,7 @@ iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
IWL_DEBUG_SCAN(mvm, "Sending scheduled scan profile config\n");
ret = iwl_mvm_send_cmd(mvm, &cmd);
kfree(profile_cfg);
kfree(profile_cfg_v1);
free_blacklist:
kfree(blacklist);