summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/mvm
diff options
context:
space:
mode:
authorTova Mussai <tova.mussai@intel.com>2019-11-15 09:27:48 +0200
committerKalle Valo <kvalo@codeaurora.org>2019-11-15 09:32:30 +0200
commit19ff9b2c6e3cdf1363ef0ec58e2089d750594d60 (patch)
tree43e37df8ee47b88117af32747225008b150ac073 /drivers/net/wireless/intel/iwlwifi/mvm
parent51698293e3230796e38cd92c49e69650cacf66e5 (diff)
iwlwifi: scan: adapt the code to use api ver 11
FW scan api ver 11 adds support for some new features, in this version the fw did also some cleanup in the api, which causes the driver not to be able to use the current scan req struct. Therefore, in this patch the driver has new version for the scan command code Signed-off-by: Tova Mussai <tova.mussai@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c202
2 files changed, 205 insertions, 6 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 735436f5253f..e300ea267b66 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1422,6 +1422,15 @@ static inline bool iwl_mvm_is_band_in_rx_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_API_BAND_IN_RX_DATA);
}
+static inline bool iwl_mvm_is_scan_ext_band_supported(struct iwl_mvm *mvm)
+{
+ u8 cmd_ver = iwl_mvm_lookup_cmd_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
+ SCAN_REQ_UMAC);
+ if (cmd_ver == IWL_FW_CMD_VER_UNKNOWN)
+ return false;
+ return (cmd_ver >= 11);
+}
+
static inline bool iwl_mvm_has_new_rx_stats_api(struct iwl_mvm *mvm)
{
return fw_has_api(&mvm->fw->ucode_capa,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 3e5455cef0ee..1745f92490ed 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -539,6 +539,7 @@ static void iwl_scan_build_ssids(struct iwl_mvm_scan_params *params,
{
int i, j;
int index;
+ u32 tmp_bitmap = 0;
/*
* copy SSIDs from match list.
@@ -558,7 +559,6 @@ static void iwl_scan_build_ssids(struct iwl_mvm_scan_params *params,
}
/* add SSIDs from scan SSID list */
- *ssid_bitmap = 0;
for (j = params->n_ssids - 1;
j >= 0 && i < PROBE_OPTION_MAX;
i++, j--) {
@@ -570,11 +570,13 @@ static void iwl_scan_build_ssids(struct iwl_mvm_scan_params *params,
ssids[i].len = params->ssids[j].ssid_len;
memcpy(ssids[i].ssid, params->ssids[j].ssid,
ssids[i].len);
- *ssid_bitmap |= BIT(i);
+ tmp_bitmap |= BIT(i);
} else {
- *ssid_bitmap |= BIT(index);
+ tmp_bitmap |= BIT(index);
}
}
+ if (ssid_bitmap)
+ *ssid_bitmap = tmp_bitmap;
}
static int
@@ -1405,16 +1407,76 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_2);
}
+static void iwl_mvm_scan_umac_dwell_v2(struct iwl_mvm *mvm,
+ struct iwl_scan_umac_req_v2 *cmd,
+ struct iwl_mvm_scan_params *params)
+{
+ struct iwl_mvm_scan_timing_params *timing, *hb_timing;
+ u8 active_dwell, passive_dwell;
+
+ timing = &scan_timing[params->type];
+ active_dwell = params->measurement_dwell ?
+ params->measurement_dwell : IWL_SCAN_DWELL_ACTIVE;
+ passive_dwell = params->measurement_dwell ?
+ params->measurement_dwell : IWL_SCAN_DWELL_PASSIVE;
+
+ cmd->scan_params.general_params.adwell_default_social_chn =
+ IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;
+ cmd->scan_params.general_params.adwell_default_2g =
+ IWL_SCAN_ADWELL_DEFAULT_LB_N_APS;
+ cmd->scan_params.general_params.adwell_default_5g =
+ IWL_SCAN_ADWELL_DEFAULT_HB_N_APS;
+
+ /* if custom max budget was configured with debugfs */
+ if (IWL_MVM_ADWELL_MAX_BUDGET)
+ cmd->scan_params.general_params.adwell_max_budget =
+ cpu_to_le16(IWL_MVM_ADWELL_MAX_BUDGET);
+ else if (params->ssids && params->ssids[0].ssid_len)
+ cmd->scan_params.general_params.adwell_max_budget =
+ cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);
+ else
+ cmd->scan_params.general_params.adwell_max_budget =
+ cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN);
+
+ cmd->scan_params.general_params.scan_priority =
+ cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);
+ cmd->scan_params.general_params.max_out_of_time[SCAN_LB_LMAC_IDX] =
+ cpu_to_le32(timing->max_out_time);
+ cmd->scan_params.general_params.suspend_time[SCAN_LB_LMAC_IDX] =
+ cpu_to_le32(timing->suspend_time);
+
+ hb_timing = &scan_timing[params->hb_type];
+
+ cmd->scan_params.general_params.max_out_of_time[SCAN_HB_LMAC_IDX] =
+ cpu_to_le32(hb_timing->max_out_time);
+ cmd->scan_params.general_params.suspend_time[SCAN_HB_LMAC_IDX] =
+ cpu_to_le32(hb_timing->suspend_time);
+
+ cmd->scan_params.general_params.active_dwell[SCAN_LB_LMAC_IDX] =
+ active_dwell;
+ cmd->scan_params.general_params.passive_dwell[SCAN_LB_LMAC_IDX] =
+ passive_dwell;
+ cmd->scan_params.general_params.active_dwell[SCAN_HB_LMAC_IDX] =
+ active_dwell;
+ cmd->scan_params.general_params.passive_dwell[SCAN_HB_LMAC_IDX] =
+ passive_dwell;
+
+ if (iwl_mvm_is_regular_scan(params))
+ cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);
+ else
+ cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_2);
+}
+
static void
iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
struct ieee80211_channel **channels,
- int n_channels, u32 ssid_bitmap,
+ int n_channels, u32 flags,
struct iwl_scan_channel_cfg_umac *channel_cfg)
{
int i;
for (i = 0; i < n_channels; i++) {
- channel_cfg[i].flags = cpu_to_le32(ssid_bitmap);
+ channel_cfg[i].flags = cpu_to_le32(flags);
channel_cfg[i].v1.channel_num = channels[i]->hw_value;
if (iwl_mvm_is_scan_ext_chan_supported(mvm)) {
enum nl80211_band band = channels[i]->band;
@@ -1430,6 +1492,64 @@ iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
}
}
+static u8 iwl_mvm_scan_umac_chan_flags_v2(struct iwl_mvm *mvm,
+ struct iwl_mvm_scan_params *params,
+ struct ieee80211_vif *vif)
+{
+ u8 flags = 0;
+
+ flags |= IWL_SCAN_CHANNEL_FLAG_ENABLE_CHAN_ORDER;
+
+ if (iwl_mvm_scan_use_ebs(mvm, vif))
+ flags |= IWL_SCAN_CHANNEL_FLAG_EBS |
+ IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
+ IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
+
+ /* set fragmented ebs for fragmented scan on HB channels */
+ if (iwl_mvm_is_scan_fragmented(params->hb_type))
+ flags |= IWL_SCAN_CHANNEL_FLAG_EBS_FRAG;
+
+ return flags;
+}
+
+static u16 iwl_mvm_scan_umac_flags_v2(struct iwl_mvm *mvm,
+ struct iwl_mvm_scan_params *params,
+ struct ieee80211_vif *vif,
+ int type)
+{
+ u16 flags = 0;
+
+ if (params->n_ssids == 0)
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE;
+
+ if (iwl_mvm_is_scan_fragmented(params->type))
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1;
+
+ if (iwl_mvm_is_scan_fragmented(params->hb_type))
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2;
+
+ if (params->pass_all)
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_PASS_ALL;
+ else
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_MATCH;
+
+ if (!iwl_mvm_is_regular_scan(params))
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_PERIODIC;
+
+ if (params->measurement_dwell ||
+ mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED)
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_NTFY_ITER_COMPLETE;
+
+ if (IWL_MVM_ADWELL_ENABLE &&
+ vif->type != NL80211_IFTYPE_P2P_DEVICE)
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_ADAPTIVE_DWELL;
+
+ if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT)
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_PREEMPTIVE;
+
+ return flags;
+}
+
static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
struct ieee80211_vif *vif)
@@ -1634,6 +1754,71 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return 0;
}
+static int iwl_mvm_scan_umac_v2(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct iwl_mvm_scan_params *params,
+ int type)
+{
+ struct iwl_scan_umac_req_v2 *cmd = mvm->scan_cmd;
+ int uid, ret = 0;
+ u8 channel_flags = 0;
+ u16 gen_flags;
+ struct iwl_scan_req_params *scan_params;
+ struct iwl_scan_periodic_parms *periodic_params;
+ struct iwl_scan_channel_params *channel_params;
+
+ struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);
+
+ scan_params = &cmd->scan_params;
+ periodic_params = &scan_params->periodic_params;
+ channel_params = &scan_params->channel_params;
+ lockdep_assert_held(&mvm->mutex);
+
+ uid = iwl_mvm_scan_uid_by_status(mvm, 0);
+ if (uid < 0)
+ return uid;
+
+ memset(cmd, 0, ksize(cmd));
+
+ iwl_mvm_scan_umac_dwell_v2(mvm, cmd, params);
+
+ mvm->scan_uid_status[uid] = type;
+
+ cmd->uid = cpu_to_le32(uid);
+
+ gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
+ scan_params->general_params.flags = cpu_to_le16(gen_flags);
+
+ if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1)
+ scan_params->general_params.num_of_fragments[SCAN_LB_LMAC_IDX] =
+ IWL_SCAN_NUM_OF_FRAGS;
+ if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2)
+ scan_params->general_params.num_of_fragments[SCAN_HB_LMAC_IDX] =
+ IWL_SCAN_NUM_OF_FRAGS;
+
+ scan_params->general_params.scan_start_mac_id = scan_vif->id;
+
+ channel_flags = iwl_mvm_scan_umac_chan_flags_v2(mvm, params, vif);
+ channel_params->flags = channel_flags;
+
+ channel_params->count = params->n_channels;
+
+ ret = iwl_mvm_fill_scan_sched_params(params,
+ periodic_params->schedule,
+ &periodic_params->delay);
+ if (ret)
+ return ret;
+
+ scan_params->probe_params.preq = params->preq;
+ scan_params->probe_params.ssid_num = params->n_ssids;
+ iwl_scan_build_ssids(params, scan_params->probe_params.direct_scan,
+ NULL);
+
+ iwl_mvm_umac_scan_cfg_channels(mvm, params->channels,
+ params->n_channels, 0,
+ channel_params->channel_config);
+ return 0;
+}
+
static int iwl_mvm_num_scans(struct iwl_mvm *mvm)
{
return hweight32(mvm->scan_status & IWL_MVM_SCAN_MASK);
@@ -1744,7 +1929,9 @@ static int iwl_mvm_build_scan_cmd(struct iwl_mvm *mvm,
{
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
hcmd->id = iwl_cmd_id(SCAN_REQ_UMAC, IWL_ALWAYS_LONG_GROUP, 0);
- return iwl_mvm_scan_umac(mvm, vif, params, type);
+ if (iwl_mvm_is_scan_ext_band_supported(mvm))
+ return iwl_mvm_scan_umac_v2(mvm, vif, params, type);
+ return iwl_mvm_scan_umac(mvm, vif, params, type);
}
hcmd->id = SCAN_OFFLOAD_REQUEST_CMD;
return iwl_mvm_scan_lmac(mvm, vif, params);
@@ -2062,6 +2249,9 @@ int iwl_mvm_scan_size(struct iwl_mvm *mvm)
int base_size = IWL_SCAN_REQ_UMAC_SIZE_V1;
int tail_size;
+ if (iwl_mvm_is_scan_ext_band_supported(mvm))
+ return sizeof(struct iwl_scan_umac_req_v2);
+
if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm))
base_size = IWL_SCAN_REQ_UMAC_SIZE_V8;
else if (iwl_mvm_is_adaptive_dwell_supported(mvm))