Commit 5d1234ba authored by Tova Mussai's avatar Tova Mussai Committed by Luca Coelho
Browse files

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: default avatarTova Mussai <tova.mussai@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent e8b61560
Loading
Loading
Loading
Loading
+25 −6
Original line number Diff line number Diff line
@@ -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 */

/**
+3 −2
Original line number Diff line number Diff line
@@ -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);
+3 −2
Original line number Diff line number Diff line
@@ -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
+7 −0
Original line number Diff line number Diff line
@@ -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__ */
+27 −13
Original line number Diff line number Diff line
@@ -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);