mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-10 07:44:23 +08:00
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: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
parent
b0ffe455bc
commit
b66b5817a0
@ -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)) {
|
||||
mvm->scan_type = IWL_SCAN_TYPE_NOT_SET;
|
||||
mvm->hb_scan_type = IWL_SCAN_TYPE_NOT_SET;
|
||||
ret = iwl_mvm_config_scan(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -8,6 +8,7 @@
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications 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
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -35,6 +36,7 @@
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -638,6 +640,7 @@ struct iwl_mvm_tcm {
|
||||
u32 elapsed; /* milliseconds for this TCM period */
|
||||
u32 airtime[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;
|
||||
bool low_latency[NUM_MAC_INDEX_DRIVER];
|
||||
bool change[NUM_MAC_INDEX_DRIVER];
|
||||
@ -879,7 +882,10 @@ struct iwl_mvm {
|
||||
unsigned int scan_status;
|
||||
void *scan_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 hb_scan_type;
|
||||
|
||||
enum iwl_mvm_sched_scan_pass_all_states sched_scan_pass_all;
|
||||
struct delayed_work scan_timeout_dwork;
|
||||
|
||||
@ -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);
|
||||
/* get SystemLowLatencyMode - only needed for beacon threshold? */
|
||||
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 */
|
||||
static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif)
|
||||
{
|
||||
|
@ -8,6 +8,7 @@
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications 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
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -19,9 +20,7 @@
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
* along with this program
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called COPYING.
|
||||
@ -117,7 +116,9 @@ static struct iwl_mvm_scan_timing_params scan_timing[] = {
|
||||
};
|
||||
|
||||
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 hb_type;
|
||||
u32 n_channels;
|
||||
u16 delay;
|
||||
int n_ssids;
|
||||
@ -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;
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
enum iwl_mvm_traffic_load load;
|
||||
bool low_latency;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
@ -245,9 +252,6 @@ iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device)
|
||||
if (!global_cnt)
|
||||
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 &&
|
||||
fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_FRAGMENTED_SCAN))
|
||||
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)
|
||||
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
|
||||
iwl_mvm_get_measurement_dwell(struct iwl_mvm *mvm,
|
||||
struct cfg80211_scan_request *req,
|
||||
struct iwl_mvm_scan_params *params)
|
||||
{
|
||||
u32 duration = scan_timing[params->type].max_out_time;
|
||||
|
||||
if (!req->duration)
|
||||
return 0;
|
||||
|
||||
if (req->duration_mandatory &&
|
||||
req->duration > scan_timing[params->type].max_out_time) {
|
||||
if (iwl_mvm_is_cdb_supported(mvm)) {
|
||||
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,
|
||||
"Measurement scan - too long dwell %hu (max out time %u)\n",
|
||||
req->duration,
|
||||
scan_timing[params->type].max_out_time);
|
||||
duration);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return min_t(u32, (u32)req->duration,
|
||||
scan_timing[params->type].max_out_time);
|
||||
return min_t(u32, (u32)req->duration, duration);
|
||||
}
|
||||
|
||||
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,
|
||||
static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
|
||||
u32 flags, u8 channel_flags)
|
||||
{
|
||||
enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, false);
|
||||
struct iwl_scan_config *cfg = config;
|
||||
|
||||
cfg->flags = cpu_to_le32(flags);
|
||||
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->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)) {
|
||||
cfg->suspend_time[1] =
|
||||
cpu_to_le32(scan_timing[type].suspend_time);
|
||||
cfg->out_of_channel_time[1] =
|
||||
enum iwl_mvm_scan_type lb_type, hb_type;
|
||||
|
||||
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);
|
||||
cfg->suspend_time[SCAN_LB_LMAC_IDX] =
|
||||
cpu_to_le32(scan_timing[type].suspend_time);
|
||||
}
|
||||
|
||||
iwl_mvm_fill_scan_dwell(mvm, &cfg->dwell);
|
||||
@ -1060,7 +1112,8 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
|
||||
struct iwl_host_cmd cmd = {
|
||||
.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 =
|
||||
mvm->nvm_data->bands[NL80211_BAND_2GHZ].n_channels +
|
||||
mvm->nvm_data->bands[NL80211_BAND_5GHZ].n_channels;
|
||||
@ -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))
|
||||
return -ENOBUFS;
|
||||
|
||||
if (type == mvm->scan_type)
|
||||
return 0;
|
||||
if (iwl_mvm_is_cdb_supported(mvm)) {
|
||||
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))
|
||||
cmd_size = sizeof(struct iwl_scan_config);
|
||||
@ -1102,10 +1165,15 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
|
||||
IWL_CHANNEL_FLAG_EBS_ADD |
|
||||
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)) {
|
||||
flags |= (type == IWL_SCAN_TYPE_FRAGMENTED) ?
|
||||
SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED :
|
||||
SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED;
|
||||
if (iwl_mvm_is_cdb_supported(mvm))
|
||||
flags |= (hb_type == IWL_SCAN_TYPE_FRAGMENTED) ?
|
||||
SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED :
|
||||
SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED;
|
||||
iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags);
|
||||
} else {
|
||||
iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags);
|
||||
@ -1118,8 +1186,10 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
|
||||
IWL_DEBUG_SCAN(mvm, "Sending UMAC scan config\n");
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
mvm->scan_type = type;
|
||||
mvm->hb_scan_type = hb_type;
|
||||
}
|
||||
|
||||
kfree(cfg);
|
||||
return ret;
|
||||
@ -1173,7 +1243,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
|
||||
cpu_to_le32(timing->suspend_time);
|
||||
|
||||
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] =
|
||||
cpu_to_le32(hb_timing->max_out_time);
|
||||
@ -1203,7 +1273,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
|
||||
cmd->v1.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED;
|
||||
|
||||
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] =
|
||||
cpu_to_le32(hb_timing->max_out_time);
|
||||
@ -1212,8 +1282,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
|
||||
}
|
||||
|
||||
if (iwl_mvm_has_new_tx_api(mvm)) {
|
||||
cmd->v6.scan_priority =
|
||||
cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);
|
||||
cmd->v6.scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);
|
||||
cmd->v6.max_out_time[SCAN_LB_LMAC_IDX] =
|
||||
cpu_to_le32(timing->max_out_time);
|
||||
cmd->v6.suspend_time[SCAN_LB_LMAC_IDX] =
|
||||
@ -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)
|
||||
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;
|
||||
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) &&
|
||||
fw_has_capa(&mvm->fw->ucode_capa,
|
||||
@ -1492,6 +1562,21 @@ void iwl_mvm_scan_timeout_wk(struct work_struct *work)
|
||||
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,
|
||||
struct cfg80211_scan_request *req,
|
||||
struct ieee80211_scan_ies *ies)
|
||||
@ -1539,9 +1624,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
params.scan_plans = &scan_plan;
|
||||
params.n_scan_plans = 1;
|
||||
|
||||
params.type =
|
||||
iwl_mvm_get_scan_type(mvm,
|
||||
vif->type == NL80211_IFTYPE_P2P_DEVICE);
|
||||
iwl_mvm_fill_scan_type(mvm, ¶ms,
|
||||
vif->type == NL80211_IFTYPE_P2P_DEVICE);
|
||||
|
||||
ret = iwl_mvm_get_measurement_dwell(mvm, req, ¶ms);
|
||||
if (ret < 0)
|
||||
@ -1636,9 +1720,8 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
|
||||
params.n_scan_plans = req->n_scan_plans;
|
||||
params.scan_plans = req->scan_plans;
|
||||
|
||||
params.type =
|
||||
iwl_mvm_get_scan_type(mvm,
|
||||
vif->type == NL80211_IFTYPE_P2P_DEVICE);
|
||||
iwl_mvm_fill_scan_type(mvm, ¶ms,
|
||||
vif->type == NL80211_IFTYPE_P2P_DEVICE);
|
||||
|
||||
/* 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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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(iwl_mvm_vif_from_mac80211(vif)))
|
||||
*result = true;
|
||||
if (iwl_mvm_vif_low_latency(mvmvif)) {
|
||||
result->result = true;
|
||||
|
||||
if (!mvmvif->phy_ctxt)
|
||||
return;
|
||||
|
||||
band = mvmvif->phy_ctxt->channel->band;
|
||||
result->result_per_band[band] = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool iwl_mvm_low_latency(struct iwl_mvm *mvm)
|
||||
{
|
||||
bool result = false;
|
||||
struct iwl_mvm_low_latency_iter data = {};
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
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 {
|
||||
@ -1599,6 +1624,18 @@ static void iwl_mvm_check_uapsd_agg_expected_tpt(struct iwl_mvm *mvm,
|
||||
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,
|
||||
unsigned long ts,
|
||||
bool handle_uapsd)
|
||||
@ -1607,9 +1644,11 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
|
||||
unsigned int uapsd_elapsed =
|
||||
jiffies_to_msecs(ts - mvm->tcm.uapsd_nonagg_ts);
|
||||
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;
|
||||
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);
|
||||
|
||||
if (handle_ll)
|
||||
@ -1619,12 +1658,18 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
|
||||
|
||||
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++) {
|
||||
struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[mac];
|
||||
u32 vo_vi_pkts = 0;
|
||||
u32 airtime = mdata->rx.airtime + mdata->tx.airtime;
|
||||
|
||||
total_airtime += airtime;
|
||||
band_airtime[band[mac]] += airtime;
|
||||
|
||||
load = iwl_mvm_tcm_load(mvm, airtime, elapsed);
|
||||
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,
|
||||
mvm->tcm.result.global_change = load != mvm->tcm.result.global_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
|
||||
* in the TCM period, so that we can return to low load if there
|
||||
|
Loading…
Reference in New Issue
Block a user