iwlwifi: mvm: Add support for two scheduled scan plans
Add support for two scan plans for scheduled scan. The first plan will run for a limited number of iterations, then the second plan will run infinitely. Signed-off-by: Avraham Stern <avraham.stern@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>hifive-unleashed-5.1
parent
5888a40c50
commit
cd55ccea59
|
@ -101,6 +101,7 @@ struct iwl_ssid_ie {
|
|||
|
||||
#define IWL_FULL_SCAN_MULTIPLIER 5
|
||||
#define IWL_FAST_SCHED_SCAN_ITERATIONS 3
|
||||
#define IWL_MAX_SCHED_SCAN_PLANS 2
|
||||
|
||||
enum scan_framework_client {
|
||||
SCAN_CLIENT_SCHED_SCAN = BIT(0),
|
||||
|
@ -359,7 +360,7 @@ struct iwl_scan_req_lmac {
|
|||
/* SCAN_REQ_PERIODIC_PARAMS_API_S */
|
||||
__le32 iter_num;
|
||||
__le32 delay;
|
||||
struct iwl_scan_schedule_lmac schedule[2];
|
||||
struct iwl_scan_schedule_lmac schedule[IWL_MAX_SCHED_SCAN_PLANS];
|
||||
struct iwl_scan_channel_opt channel_opt[2];
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
@ -582,7 +583,7 @@ struct iwl_scan_umac_schedule {
|
|||
*/
|
||||
struct iwl_scan_req_umac_tail {
|
||||
/* SCAN_PERIODIC_PARAMS_API_S_VER_1 */
|
||||
struct iwl_scan_umac_schedule schedule[2];
|
||||
struct iwl_scan_umac_schedule schedule[IWL_MAX_SCHED_SCAN_PLANS];
|
||||
__le16 delay;
|
||||
__le16 reserved;
|
||||
/* SCAN_PROBE_PARAMS_API_S_VER_1 */
|
||||
|
|
|
@ -572,6 +572,14 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
/* 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;
|
||||
hw->wiphy->max_sched_scan_plans = IWL_MAX_SCHED_SCAN_PLANS;
|
||||
hw->wiphy->max_sched_scan_plan_interval = U16_MAX;
|
||||
|
||||
/*
|
||||
* the firmware uses u8 for num of iterations, but 0xff is saved for
|
||||
* infinite loop, so the maximum number of iterations is actually 254.
|
||||
*/
|
||||
hw->wiphy->max_sched_scan_plan_iterations = 254;
|
||||
|
||||
hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN |
|
||||
NL80211_FEATURE_LOW_PRIORITY_SCAN |
|
||||
|
|
|
@ -131,7 +131,6 @@ struct iwl_mvm_scan_params {
|
|||
int n_ssids;
|
||||
struct cfg80211_ssid *ssids;
|
||||
struct ieee80211_channel **channels;
|
||||
u16 interval; /* interval between scans (in secs) */
|
||||
u32 flags;
|
||||
u8 *mac_addr;
|
||||
u8 *mac_addr_mask;
|
||||
|
@ -140,7 +139,8 @@ struct iwl_mvm_scan_params {
|
|||
int n_match_sets;
|
||||
struct iwl_scan_probe_req preq;
|
||||
struct cfg80211_match_set *match_sets;
|
||||
u8 iterations[2];
|
||||
int n_scan_plans;
|
||||
struct cfg80211_sched_scan_plan *scan_plans;
|
||||
};
|
||||
|
||||
static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)
|
||||
|
@ -737,8 +737,7 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids,
|
|||
}
|
||||
|
||||
static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
int n_iterations)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa;
|
||||
|
||||
|
@ -753,11 +752,6 @@ static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm,
|
|||
vif->type != NL80211_IFTYPE_P2P_DEVICE);
|
||||
}
|
||||
|
||||
static int iwl_mvm_scan_total_iterations(struct iwl_mvm_scan_params *params)
|
||||
{
|
||||
return params->iterations[0] + params->iterations[1];
|
||||
}
|
||||
|
||||
static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_scan_params *params)
|
||||
{
|
||||
|
@ -796,12 +790,15 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
(void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *
|
||||
mvm->fw->ucode_capa.n_scan_channels);
|
||||
u32 ssid_bitmap = 0;
|
||||
int n_iterations = iwl_mvm_scan_total_iterations(params);
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
memset(cmd, 0, ksize(cmd));
|
||||
|
||||
if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))
|
||||
return -EINVAL;
|
||||
|
||||
iwl_mvm_scan_lmac_dwell(mvm, cmd, params);
|
||||
|
||||
cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm);
|
||||
|
@ -821,14 +818,33 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
/* this API uses bits 1-20 instead of 0-19 */
|
||||
ssid_bitmap <<= 1;
|
||||
|
||||
cmd->schedule[0].delay = cpu_to_le16(params->interval);
|
||||
cmd->schedule[0].iterations = params->iterations[0];
|
||||
cmd->schedule[0].full_scan_mul = 1;
|
||||
cmd->schedule[1].delay = cpu_to_le16(params->interval);
|
||||
cmd->schedule[1].iterations = params->iterations[1];
|
||||
cmd->schedule[1].full_scan_mul = 1;
|
||||
for (i = 0; i < params->n_scan_plans; i++) {
|
||||
struct wiphy *wiphy = mvm->hw->wiphy;
|
||||
struct cfg80211_sched_scan_plan *scan_plan =
|
||||
¶ms->scan_plans[i];
|
||||
|
||||
if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) {
|
||||
if (WARN_ON(scan_plan->iterations >
|
||||
wiphy->max_sched_scan_plan_iterations ||
|
||||
scan_plan->interval >
|
||||
wiphy->max_sched_scan_plan_interval))
|
||||
return -EINVAL;
|
||||
|
||||
cmd->schedule[i].delay =
|
||||
cpu_to_le16(scan_plan->interval);
|
||||
cmd->schedule[i].iterations = scan_plan->iterations;
|
||||
cmd->schedule[i].full_scan_mul = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the number of iterations of the last scan plan is set to
|
||||
* zero, it should run infinitely. However, this is not always the case.
|
||||
* For example, when regular scan is requested the driver sets one scan
|
||||
* plan with one iteration.
|
||||
*/
|
||||
if (!cmd->schedule[i - 1].iterations)
|
||||
cmd->schedule[i - 1].iterations = 0xff;
|
||||
|
||||
if (iwl_mvm_scan_use_ebs(mvm, vif)) {
|
||||
cmd->channel_opt[0].flags =
|
||||
cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |
|
||||
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
|
||||
|
@ -968,6 +984,12 @@ static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params)
|
||||
{
|
||||
return params->n_scan_plans == 1 &&
|
||||
params->scan_plans[0].iterations == 1;
|
||||
}
|
||||
|
||||
static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
|
||||
struct iwl_scan_req_umac *cmd,
|
||||
struct iwl_mvm_scan_params *params)
|
||||
|
@ -980,7 +1002,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
|
|||
cmd->scan_priority =
|
||||
iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
|
||||
|
||||
if (iwl_mvm_scan_total_iterations(params) == 1)
|
||||
if (iwl_mvm_is_regular_scan(params))
|
||||
cmd->ooc_priority =
|
||||
iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
|
||||
else
|
||||
|
@ -1027,7 +1049,7 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
|
|||
else
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH;
|
||||
|
||||
if (iwl_mvm_scan_total_iterations(params) > 1)
|
||||
if (!iwl_mvm_is_regular_scan(params))
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
|
@ -1045,12 +1067,14 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data +
|
||||
sizeof(struct iwl_scan_channel_cfg_umac) *
|
||||
mvm->fw->ucode_capa.n_scan_channels;
|
||||
int uid;
|
||||
int uid, i;
|
||||
u32 ssid_bitmap = 0;
|
||||
int n_iterations = iwl_mvm_scan_total_iterations(params);
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))
|
||||
return -EINVAL;
|
||||
|
||||
uid = iwl_mvm_scan_uid_by_status(mvm, 0);
|
||||
if (uid < 0)
|
||||
return uid;
|
||||
|
@ -1067,7 +1091,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
if (type == IWL_MVM_SCAN_SCHED)
|
||||
cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);
|
||||
|
||||
if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations))
|
||||
if (iwl_mvm_scan_use_ebs(mvm, vif))
|
||||
cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS |
|
||||
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
|
||||
IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
|
||||
|
@ -1079,12 +1103,30 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
iwl_mvm_umac_scan_cfg_channels(mvm, params->channels,
|
||||
params->n_channels, ssid_bitmap, cmd);
|
||||
|
||||
/* With UMAC we use only one schedule for now, so use the sum
|
||||
* of the iterations (with a a maximum of 255).
|
||||
for (i = 0; i < params->n_scan_plans; i++) {
|
||||
struct wiphy *wiphy = mvm->hw->wiphy;
|
||||
struct cfg80211_sched_scan_plan *scan_plan =
|
||||
¶ms->scan_plans[i];
|
||||
|
||||
if (WARN_ON(scan_plan->iterations >
|
||||
wiphy->max_sched_scan_plan_iterations ||
|
||||
scan_plan->interval >
|
||||
wiphy->max_sched_scan_plan_interval))
|
||||
return -EINVAL;
|
||||
|
||||
sec_part->schedule[i].iter_count = scan_plan->iterations;
|
||||
sec_part->schedule[i].interval =
|
||||
cpu_to_le16(scan_plan->interval);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the number of iterations of the last scan plan is set to
|
||||
* zero, it should run infinitely. However, this is not always the case.
|
||||
* For example, when regular scan is requested the driver sets one scan
|
||||
* plan with one iteration.
|
||||
*/
|
||||
sec_part->schedule[0].iter_count =
|
||||
(n_iterations > 255) ? 255 : n_iterations;
|
||||
sec_part->schedule[0].interval = cpu_to_le16(params->interval);
|
||||
if (!sec_part->schedule[i - 1].iter_count)
|
||||
sec_part->schedule[i - 1].iter_count = 0xff;
|
||||
|
||||
sec_part->delay = cpu_to_le16(params->delay);
|
||||
sec_part->preq = params->preq;
|
||||
|
@ -1150,6 +1192,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
};
|
||||
struct iwl_mvm_scan_params params = {};
|
||||
int ret;
|
||||
struct cfg80211_sched_scan_plan scan_plan = { .iterations = 1 };
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
|
@ -1175,7 +1218,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
params.flags = req->flags;
|
||||
params.n_channels = req->n_channels;
|
||||
params.delay = 0;
|
||||
params.interval = 0;
|
||||
params.ssids = req->ssids;
|
||||
params.channels = req->channels;
|
||||
params.mac_addr = req->mac_addr;
|
||||
|
@ -1185,8 +1227,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
params.n_match_sets = 0;
|
||||
params.match_sets = NULL;
|
||||
|
||||
params.iterations[0] = 1;
|
||||
params.iterations[1] = 0;
|
||||
params.scan_plans = &scan_plan;
|
||||
params.n_scan_plans = 1;
|
||||
|
||||
params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms);
|
||||
|
||||
|
@ -1265,20 +1307,14 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
|
|||
params.pass_all = iwl_mvm_scan_pass_all(mvm, req);
|
||||
params.n_match_sets = req->n_match_sets;
|
||||
params.match_sets = req->match_sets;
|
||||
if (!req->n_scan_plans)
|
||||
return -EINVAL;
|
||||
|
||||
params.iterations[0] = 0;
|
||||
params.iterations[1] = 0xff;
|
||||
params.n_scan_plans = req->n_scan_plans;
|
||||
params.scan_plans = req->scan_plans;
|
||||
|
||||
params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms);
|
||||
|
||||
if (req->scan_plans[0].interval > U16_MAX) {
|
||||
IWL_DEBUG_SCAN(mvm,
|
||||
"interval value is > 16-bits, set to max possible\n");
|
||||
params.interval = U16_MAX;
|
||||
} else {
|
||||
params.interval = req->scan_plans[0].interval;
|
||||
}
|
||||
|
||||
/* In theory, LMAC scans can handle a 32-bit delay, but since
|
||||
* waiting for over 18 hours to start the scan is a bit silly
|
||||
* and to keep it aligned with UMAC scans (which only support
|
||||
|
|
Loading…
Reference in New Issue