Commit b66b5817 authored by Sara Sharon's avatar Sara Sharon Committed by Luca Coelho

iwlwifi: mvm: detect low latency and traffic load per band

Detect low latency and traffic load per band.  Add support for
deciding on scan type and timings per band.
Signed-off-by: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent b0ffe455
...@@ -1093,6 +1093,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) ...@@ -1093,6 +1093,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) { if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
mvm->scan_type = IWL_SCAN_TYPE_NOT_SET; mvm->scan_type = IWL_SCAN_TYPE_NOT_SET;
mvm->hb_scan_type = IWL_SCAN_TYPE_NOT_SET;
ret = iwl_mvm_config_scan(mvm); ret = iwl_mvm_config_scan(mvm);
if (ret) if (ret)
goto error; goto error;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -35,6 +36,7 @@ ...@@ -35,6 +36,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -638,6 +640,7 @@ struct iwl_mvm_tcm { ...@@ -638,6 +640,7 @@ struct iwl_mvm_tcm {
u32 elapsed; /* milliseconds for this TCM period */ u32 elapsed; /* milliseconds for this TCM period */
u32 airtime[NUM_MAC_INDEX_DRIVER]; u32 airtime[NUM_MAC_INDEX_DRIVER];
enum iwl_mvm_traffic_load load[NUM_MAC_INDEX_DRIVER]; enum iwl_mvm_traffic_load load[NUM_MAC_INDEX_DRIVER];
enum iwl_mvm_traffic_load band_load[NUM_NL80211_BANDS];
enum iwl_mvm_traffic_load global_load; enum iwl_mvm_traffic_load global_load;
bool low_latency[NUM_MAC_INDEX_DRIVER]; bool low_latency[NUM_MAC_INDEX_DRIVER];
bool change[NUM_MAC_INDEX_DRIVER]; bool change[NUM_MAC_INDEX_DRIVER];
...@@ -879,7 +882,10 @@ struct iwl_mvm { ...@@ -879,7 +882,10 @@ struct iwl_mvm {
unsigned int scan_status; unsigned int scan_status;
void *scan_cmd; void *scan_cmd;
struct iwl_mcast_filter_cmd *mcast_filter_cmd; struct iwl_mcast_filter_cmd *mcast_filter_cmd;
/* For CDB this is low band scan type, for non-CDB - type. */
enum iwl_mvm_scan_type scan_type; enum iwl_mvm_scan_type scan_type;
enum iwl_mvm_scan_type hb_scan_type;
enum iwl_mvm_sched_scan_pass_all_states sched_scan_pass_all; enum iwl_mvm_sched_scan_pass_all_states sched_scan_pass_all;
struct delayed_work scan_timeout_dwork; struct delayed_work scan_timeout_dwork;
...@@ -1828,6 +1834,8 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -1828,6 +1834,8 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum iwl_mvm_low_latency_cause cause); enum iwl_mvm_low_latency_cause cause);
/* get SystemLowLatencyMode - only needed for beacon threshold? */ /* get SystemLowLatencyMode - only needed for beacon threshold? */
bool iwl_mvm_low_latency(struct iwl_mvm *mvm); bool iwl_mvm_low_latency(struct iwl_mvm *mvm);
bool iwl_mvm_low_latency_band(struct iwl_mvm *mvm, enum nl80211_band band);
/* get VMACLowLatencyMode */ /* get VMACLowLatencyMode */
static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif)
{ {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -19,9 +20,7 @@ ...@@ -19,9 +20,7 @@
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
* *
* The full GNU General Public License is included in this distribution * The full GNU General Public License is included in this distribution
* in the file called COPYING. * in the file called COPYING.
...@@ -117,7 +116,9 @@ static struct iwl_mvm_scan_timing_params scan_timing[] = { ...@@ -117,7 +116,9 @@ static struct iwl_mvm_scan_timing_params scan_timing[] = {
}; };
struct iwl_mvm_scan_params { struct iwl_mvm_scan_params {
/* For CDB this is low band scan type, for non-CDB - type. */
enum iwl_mvm_scan_type type; enum iwl_mvm_scan_type type;
enum iwl_mvm_scan_type hb_type;
u32 n_channels; u32 n_channels;
u16 delay; u16 delay;
int n_ssids; int n_ssids;
...@@ -231,12 +232,18 @@ static enum iwl_mvm_traffic_load iwl_mvm_get_traffic_load(struct iwl_mvm *mvm) ...@@ -231,12 +232,18 @@ static enum iwl_mvm_traffic_load iwl_mvm_get_traffic_load(struct iwl_mvm *mvm)
return mvm->tcm.result.global_load; return mvm->tcm.result.global_load;
} }
static enum iwl_mvm_traffic_load
iwl_mvm_get_traffic_load_band(struct iwl_mvm *mvm, enum nl80211_band band)
{
return mvm->tcm.result.band_load[band];
}
static enum static enum
iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device) iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device,
enum iwl_mvm_traffic_load load,
bool low_latency)
{ {
int global_cnt = 0; int global_cnt = 0;
enum iwl_mvm_traffic_load load;
bool low_latency;
ieee80211_iterate_active_interfaces_atomic(mvm->hw, ieee80211_iterate_active_interfaces_atomic(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL, IEEE80211_IFACE_ITER_NORMAL,
...@@ -245,9 +252,6 @@ iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device) ...@@ -245,9 +252,6 @@ iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device)
if (!global_cnt) if (!global_cnt)
return IWL_SCAN_TYPE_UNASSOC; return IWL_SCAN_TYPE_UNASSOC;
load = iwl_mvm_get_traffic_load(mvm);
low_latency = iwl_mvm_low_latency(mvm);
if ((load == IWL_MVM_TRAFFIC_HIGH || low_latency) && !p2p_device && if ((load == IWL_MVM_TRAFFIC_HIGH || low_latency) && !p2p_device &&
fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_FRAGMENTED_SCAN)) fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_FRAGMENTED_SCAN))
return IWL_SCAN_TYPE_FRAGMENTED; return IWL_SCAN_TYPE_FRAGMENTED;
...@@ -258,25 +262,57 @@ iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device) ...@@ -258,25 +262,57 @@ iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device)
return IWL_SCAN_TYPE_WILD; return IWL_SCAN_TYPE_WILD;
} }
static enum
iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device)
{
enum iwl_mvm_traffic_load load;
bool low_latency;
load = iwl_mvm_get_traffic_load(mvm);
low_latency = iwl_mvm_low_latency(mvm);
return _iwl_mvm_get_scan_type(mvm, p2p_device, load, low_latency);
}
static enum
iwl_mvm_scan_type iwl_mvm_get_scan_type_band(struct iwl_mvm *mvm,
bool p2p_device,
enum nl80211_band band)
{
enum iwl_mvm_traffic_load load;
bool low_latency;
load = iwl_mvm_get_traffic_load_band(mvm, band);
low_latency = iwl_mvm_low_latency_band(mvm, band);
return _iwl_mvm_get_scan_type(mvm, p2p_device, load, low_latency);
}
static int static int
iwl_mvm_get_measurement_dwell(struct iwl_mvm *mvm, iwl_mvm_get_measurement_dwell(struct iwl_mvm *mvm,
struct cfg80211_scan_request *req, struct cfg80211_scan_request *req,
struct iwl_mvm_scan_params *params) struct iwl_mvm_scan_params *params)
{ {
u32 duration = scan_timing[params->type].max_out_time;
if (!req->duration) if (!req->duration)
return 0; return 0;
if (req->duration_mandatory && if (iwl_mvm_is_cdb_supported(mvm)) {
req->duration > scan_timing[params->type].max_out_time) { u32 hb_time = scan_timing[params->hb_type].max_out_time;
duration = min_t(u32, duration, hb_time);
}
if (req->duration_mandatory && req->duration > duration) {
IWL_DEBUG_SCAN(mvm, IWL_DEBUG_SCAN(mvm,
"Measurement scan - too long dwell %hu (max out time %u)\n", "Measurement scan - too long dwell %hu (max out time %u)\n",
req->duration, req->duration,
scan_timing[params->type].max_out_time); duration);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
return min_t(u32, (u32)req->duration, return min_t(u32, (u32)req->duration, duration);
scan_timing[params->type].max_out_time);
} }
static inline bool iwl_mvm_rrm_scan_needed(struct iwl_mvm *mvm) static inline bool iwl_mvm_rrm_scan_needed(struct iwl_mvm *mvm)
...@@ -1025,22 +1061,38 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config, ...@@ -1025,22 +1061,38 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config, static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
u32 flags, u8 channel_flags) u32 flags, u8 channel_flags)
{ {
enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, false);
struct iwl_scan_config *cfg = config; struct iwl_scan_config *cfg = config;
cfg->flags = cpu_to_le32(flags); cfg->flags = cpu_to_le32(flags);
cfg->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm)); cfg->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
cfg->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm)); cfg->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));
cfg->legacy_rates = iwl_mvm_scan_config_rates(mvm); cfg->legacy_rates = iwl_mvm_scan_config_rates(mvm);
cfg->out_of_channel_time[0] =
cpu_to_le32(scan_timing[type].max_out_time);
cfg->suspend_time[0] = cpu_to_le32(scan_timing[type].suspend_time);
if (iwl_mvm_is_cdb_supported(mvm)) { if (iwl_mvm_is_cdb_supported(mvm)) {
cfg->suspend_time[1] = enum iwl_mvm_scan_type lb_type, hb_type;
cpu_to_le32(scan_timing[type].suspend_time);
cfg->out_of_channel_time[1] = lb_type = iwl_mvm_get_scan_type_band(mvm, false,
NL80211_BAND_2GHZ);
hb_type = iwl_mvm_get_scan_type_band(mvm, false,
NL80211_BAND_5GHZ);
cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] =
cpu_to_le32(scan_timing[lb_type].max_out_time);
cfg->suspend_time[SCAN_LB_LMAC_IDX] =
cpu_to_le32(scan_timing[lb_type].suspend_time);
cfg->out_of_channel_time[SCAN_HB_LMAC_IDX] =
cpu_to_le32(scan_timing[hb_type].max_out_time);
cfg->suspend_time[SCAN_HB_LMAC_IDX] =
cpu_to_le32(scan_timing[hb_type].suspend_time);
} else {
enum iwl_mvm_scan_type type =
iwl_mvm_get_scan_type(mvm, false);
cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] =
cpu_to_le32(scan_timing[type].max_out_time); cpu_to_le32(scan_timing[type].max_out_time);
cfg->suspend_time[SCAN_LB_LMAC_IDX] =
cpu_to_le32(scan_timing[type].suspend_time);
} }
iwl_mvm_fill_scan_dwell(mvm, &cfg->dwell); iwl_mvm_fill_scan_dwell(mvm, &cfg->dwell);
...@@ -1060,7 +1112,8 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) ...@@ -1060,7 +1112,8 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
struct iwl_host_cmd cmd = { struct iwl_host_cmd cmd = {
.id = iwl_cmd_id(SCAN_CFG_CMD, IWL_ALWAYS_LONG_GROUP, 0), .id = iwl_cmd_id(SCAN_CFG_CMD, IWL_ALWAYS_LONG_GROUP, 0),
}; };
enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, false); enum iwl_mvm_scan_type type;
enum iwl_mvm_scan_type hb_type = IWL_SCAN_TYPE_NOT_SET;
int num_channels = int num_channels =
mvm->nvm_data->bands[NL80211_BAND_2GHZ].n_channels + mvm->nvm_data->bands[NL80211_BAND_2GHZ].n_channels +
mvm->nvm_data->bands[NL80211_BAND_5GHZ].n_channels; mvm->nvm_data->bands[NL80211_BAND_5GHZ].n_channels;
...@@ -1070,8 +1123,18 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) ...@@ -1070,8 +1123,18 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels)) if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels))
return -ENOBUFS; return -ENOBUFS;
if (type == mvm->scan_type) if (iwl_mvm_is_cdb_supported(mvm)) {
return 0; type = iwl_mvm_get_scan_type_band(mvm, false,
NL80211_BAND_2GHZ);
hb_type = iwl_mvm_get_scan_type_band(mvm, false,
NL80211_BAND_5GHZ);
if (type == mvm->scan_type && hb_type == mvm->hb_scan_type)
return 0;
} else {
type = iwl_mvm_get_scan_type(mvm, false);
if (type == mvm->scan_type)
return 0;
}
if (iwl_mvm_has_new_tx_api(mvm)) if (iwl_mvm_has_new_tx_api(mvm))
cmd_size = sizeof(struct iwl_scan_config); cmd_size = sizeof(struct iwl_scan_config);
...@@ -1102,10 +1165,15 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) ...@@ -1102,10 +1165,15 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
IWL_CHANNEL_FLAG_EBS_ADD | IWL_CHANNEL_FLAG_EBS_ADD |
IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE; IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;
/*
* Check for fragmented scan on LMAC2 - high band.
* LMAC1 - low band is checked above.
*/
if (iwl_mvm_has_new_tx_api(mvm)) { if (iwl_mvm_has_new_tx_api(mvm)) {
flags |= (type == IWL_SCAN_TYPE_FRAGMENTED) ? if (iwl_mvm_is_cdb_supported(mvm))
SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED : flags |= (hb_type == IWL_SCAN_TYPE_FRAGMENTED) ?
SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED; SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED :
SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED;
iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags); iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags);
} else { } else {
iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags); iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags);
...@@ -1118,8 +1186,10 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) ...@@ -1118,8 +1186,10 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
IWL_DEBUG_SCAN(mvm, "Sending UMAC scan config\n"); IWL_DEBUG_SCAN(mvm, "Sending UMAC scan config\n");
ret = iwl_mvm_send_cmd(mvm, &cmd); ret = iwl_mvm_send_cmd(mvm, &cmd);
if (!ret) if (!ret) {
mvm->scan_type = type; mvm->scan_type = type;
mvm->hb_scan_type = hb_type;
}
kfree(cfg); kfree(cfg);
return ret; return ret;
...@@ -1173,7 +1243,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, ...@@ -1173,7 +1243,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
cpu_to_le32(timing->suspend_time); cpu_to_le32(timing->suspend_time);
if (iwl_mvm_is_cdb_supported(mvm)) { if (iwl_mvm_is_cdb_supported(mvm)) {
hb_timing = &scan_timing[params->type]; hb_timing = &scan_timing[params->hb_type];
cmd->v7.max_out_time[SCAN_HB_LMAC_IDX] = cmd->v7.max_out_time[SCAN_HB_LMAC_IDX] =
cpu_to_le32(hb_timing->max_out_time); cpu_to_le32(hb_timing->max_out_time);
...@@ -1203,7 +1273,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, ...@@ -1203,7 +1273,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
cmd->v1.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED; cmd->v1.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED;
if (iwl_mvm_is_cdb_supported(mvm)) { if (iwl_mvm_is_cdb_supported(mvm)) {
hb_timing = &scan_timing[params->type]; hb_timing = &scan_timing[params->hb_type];
cmd->v6.max_out_time[SCAN_HB_LMAC_IDX] = cmd->v6.max_out_time[SCAN_HB_LMAC_IDX] =
cpu_to_le32(hb_timing->max_out_time); cpu_to_le32(hb_timing->max_out_time);
...@@ -1212,8 +1282,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, ...@@ -1212,8 +1282,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
} }
if (iwl_mvm_has_new_tx_api(mvm)) { if (iwl_mvm_has_new_tx_api(mvm)) {
cmd->v6.scan_priority = cmd->v6.scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);
cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);
cmd->v6.max_out_time[SCAN_LB_LMAC_IDX] = cmd->v6.max_out_time[SCAN_LB_LMAC_IDX] =
cpu_to_le32(timing->max_out_time); cpu_to_le32(timing->max_out_time);
cmd->v6.suspend_time[SCAN_LB_LMAC_IDX] = cmd->v6.suspend_time[SCAN_LB_LMAC_IDX] =
...@@ -1257,11 +1326,12 @@ static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, ...@@ -1257,11 +1326,12 @@ static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0) if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0)
flags |= IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT; flags |= IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT;
if (params->type == IWL_SCAN_TYPE_FRAGMENTED) { if (params->type == IWL_SCAN_TYPE_FRAGMENTED)
flags |= IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED; flags |= IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED;
if (iwl_mvm_is_cdb_supported(mvm))
flags |= IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED; if (iwl_mvm_is_cdb_supported(mvm) &&
} params->hb_type == IWL_SCAN_TYPE_FRAGMENTED)
flags |= IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED;
if (iwl_mvm_rrm_scan_needed(mvm) && if (iwl_mvm_rrm_scan_needed(mvm) &&
fw_has_capa(&mvm->fw->ucode_capa, fw_has_capa(&mvm->fw->ucode_capa,
...@@ -1492,6 +1562,21 @@ void iwl_mvm_scan_timeout_wk(struct work_struct *work) ...@@ -1492,6 +1562,21 @@ void iwl_mvm_scan_timeout_wk(struct work_struct *work)
iwl_force_nmi(mvm->trans); iwl_force_nmi(mvm->trans);
} }
static void iwl_mvm_fill_scan_type(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
bool p2p)
{
if (iwl_mvm_is_cdb_supported(mvm)) {
params->type =
iwl_mvm_get_scan_type_band(mvm, p2p,
NL80211_BAND_2GHZ);
params->hb_type =
iwl_mvm_get_scan_type_band(mvm, p2p,
NL80211_BAND_5GHZ);
} else {
params->type = iwl_mvm_get_scan_type(mvm, p2p);
}
}
int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct cfg80211_scan_request *req, struct cfg80211_scan_request *req,
struct ieee80211_scan_ies *ies) struct ieee80211_scan_ies *ies)
...@@ -1539,9 +1624,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -1539,9 +1624,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
params.scan_plans = &scan_plan; params.scan_plans = &scan_plan;
params.n_scan_plans = 1; params.n_scan_plans = 1;
params.type = iwl_mvm_fill_scan_type(mvm, &params,
iwl_mvm_get_scan_type(mvm, vif->type == NL80211_IFTYPE_P2P_DEVICE);
vif->type == NL80211_IFTYPE_P2P_DEVICE);
ret = iwl_mvm_get_measurement_dwell(mvm, req, &params); ret = iwl_mvm_get_measurement_dwell(mvm, req, &params);
if (ret < 0) if (ret < 0)
...@@ -1636,9 +1720,8 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, ...@@ -1636,9 +1720,8 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
params.n_scan_plans = req->n_scan_plans; params.n_scan_plans = req->n_scan_plans;
params.scan_plans = req->scan_plans; params.scan_plans = req->scan_plans;
params.type = iwl_mvm_fill_scan_type(mvm, &params,
iwl_mvm_get_scan_type(mvm, vif->type == NL80211_IFTYPE_P2P_DEVICE);
vif->type == NL80211_IFTYPE_P2P_DEVICE);
/* In theory, LMAC scans can handle a 32-bit delay, but since /* 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 * waiting for over 18 hours to start the scan is a bit silly
......
...@@ -1074,23 +1074,48 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -1074,23 +1074,48 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return iwl_mvm_power_update_mac(mvm); return iwl_mvm_power_update_mac(mvm);
} }
struct iwl_mvm_low_latency_iter {
bool result;
bool result_per_band[NUM_NL80211_BANDS];
};
static void iwl_mvm_ll_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) static void iwl_mvm_ll_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
{ {
bool *result = _data; struct iwl_mvm_low_latency_iter *result = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
enum nl80211_band band;
if (iwl_mvm_vif_low_latency(mvmvif)) {
result->result = true;
if (!mvmvif->phy_ctxt)
return;
if (iwl_mvm_vif_low_latency(iwl_mvm_vif_from_mac80211(vif))) band = mvmvif->phy_ctxt->channel->band;
*result = true; result->result_per_band[band] = true;
}
} }
bool iwl_mvm_low_latency(struct iwl_mvm *mvm) bool iwl_mvm_low_latency(struct iwl_mvm *mvm)
{ {
bool result = false; struct iwl_mvm_low_latency_iter data = {};
ieee80211_iterate_active_interfaces_atomic( ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL, mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_ll_iter, &result); iwl_mvm_ll_iter, &data);
return result; return data.result;
}
bool iwl_mvm_low_latency_band(struct iwl_mvm *mvm, enum nl80211_band band)
{
struct iwl_mvm_low_latency_iter data = {};
ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_ll_iter, &data);
return data.result_per_band[band];
} }
struct iwl_bss_iter_data { struct iwl_bss_iter_data {
...@@ -1599,6 +1624,18 @@ static void iwl_mvm_check_uapsd_agg_expected_tpt(struct iwl_mvm *mvm, ...@@ -1599,6 +1624,18 @@ static void iwl_mvm_check_uapsd_agg_expected_tpt(struct iwl_mvm *mvm,
iwl_mvm_uapsd_agg_disconnect_iter, &mac); iwl_mvm_uapsd_agg_disconnect_iter, &mac);
} }
static void iwl_mvm_tcm_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 *band = _data;
if (!mvmvif->phy_ctxt)
return;
band[mvmvif->id] = mvmvif->phy_ctxt->channel->band;
}
static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm, static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
unsigned long ts, unsigned long ts,
bool handle_uapsd) bool handle_uapsd)
...@@ -1607,9 +1644,11 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm, ...@@ -1607,9 +1644,11 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
unsigned int uapsd_elapsed = unsigned int uapsd_elapsed =
jiffies_to_msecs(ts - mvm->tcm.uapsd_nonagg_ts); jiffies_to_msecs(ts - mvm->tcm.uapsd_nonagg_ts);
u32 total_airtime = 0; u32 total_airtime = 0;
int ac, mac; u32 band_airtime[NUM_NL80211_BANDS] = {0};
u32 band[NUM_MAC_INDEX_DRIVER] = {0};
int ac, mac, i;
bool low_latency = false; bool low_latency = false;
enum iwl_mvm_traffic_load load; enum iwl_mvm_traffic_load load, band_load;
bool handle_ll = time_after(ts, mvm->tcm.ll_ts + MVM_LL_PERIOD); bool handle_ll = time_after(ts, mvm->tcm.ll_ts + MVM_LL_PERIOD);
if (handle_ll) if (handle_ll)
...@@ -1619,12 +1658,18 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm, ...@@ -1619,12 +1658,18 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
mvm->tcm.result.elapsed = elapsed; mvm->tcm.result.elapsed = elapsed;
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_tcm_iterator,
&band);
for (mac = 0; mac < NUM_MAC_INDEX_DRIVER; mac++) { for (mac = 0; mac < NUM_MAC_INDEX_DRIVER; mac++) {
struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[mac]; struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[mac];
u32 vo_vi_pkts = 0; u32 vo_vi_pkts = 0;
u32 airtime = mdata->rx.airtime + mdata->tx.airtime; u32 airtime = mdata->rx.airtime + mdata->tx.airtime;
total_airtime += airtime; total_airtime += airtime;
band_airtime[band[mac]] += airtime;
load = iwl_mvm_tcm_load(mvm, airtime, elapsed); load = iwl_mvm_tcm_load(mvm, airtime, elapsed);
mvm->tcm.result.change[mac] = load != mvm->tcm.result.load[mac]; mvm->tcm.result.change[mac] = load != mvm->tcm.result.load[mac];
...@@ -1662,6 +1707,11 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm, ...@@ -1662,6 +1707,11 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
mvm->tcm.result.global_change = load != mvm->tcm.result.global_load; mvm->tcm.result.global_change = load != mvm->tcm.result.global_load;
mvm->tcm.result.global_load = load; mvm->tcm.result.global_load = load;
for (i = 0; i < NUM_NL80211_BANDS; i++) {
band_load = iwl_mvm_tcm_load(mvm, band_airtime[i], elapsed);
mvm->tcm.result.band_load[i] = band_load;
}
/* /*
* If the current load isn't low we need to force re-evaluation * If the current load isn't low we need to force re-evaluation
* in the TCM period, so that we can return to low load if there * in the TCM period, so that we can return to low load if there
......
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