2020-12-10 00:06:03 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
|
|
|
/*
|
2024-02-06 18:02:10 +02:00
|
|
|
* Copyright (C) 2012-2014, 2018-2019, 2021-2024 Intel Corporation
|
2020-12-10 00:06:03 +02:00
|
|
|
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
|
|
|
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
|
|
|
*/
|
2013-01-24 14:25:36 +01:00
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/slab.h>
|
2015-03-02 19:54:49 -08:00
|
|
|
#include <linux/etherdevice.h>
|
2013-01-24 14:25:36 +01:00
|
|
|
|
|
|
|
#include <net/mac80211.h>
|
|
|
|
|
|
|
|
#include "iwl-debug.h"
|
|
|
|
#include "mvm.h"
|
|
|
|
#include "iwl-modparams.h"
|
2017-06-02 15:15:53 +02:00
|
|
|
#include "fw/api/power.h"
|
2013-01-24 14:25:36 +01:00
|
|
|
|
|
|
|
#define POWER_KEEP_ALIVE_PERIOD_SEC 25
|
|
|
|
|
2014-01-26 12:58:24 +02:00
|
|
|
static
|
2013-03-10 15:29:44 +02:00
|
|
|
int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
|
2024-02-06 18:02:10 +02:00
|
|
|
struct iwl_beacon_filter_cmd *cmd)
|
2013-05-06 13:03:59 +03:00
|
|
|
{
|
2018-10-28 17:16:44 +02:00
|
|
|
u16 len;
|
|
|
|
|
2014-01-26 12:58:24 +02:00
|
|
|
IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
|
|
|
|
le32_to_cpu(cmd->ba_enable_beacon_abort));
|
|
|
|
IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
|
|
|
|
le32_to_cpu(cmd->ba_escape_timer));
|
|
|
|
IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
|
|
|
|
le32_to_cpu(cmd->bf_debug_flag));
|
|
|
|
IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
|
|
|
|
le32_to_cpu(cmd->bf_enable_beacon_filter));
|
|
|
|
IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
|
|
|
|
le32_to_cpu(cmd->bf_energy_delta));
|
|
|
|
IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
|
|
|
|
le32_to_cpu(cmd->bf_escape_timer));
|
|
|
|
IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
|
|
|
|
le32_to_cpu(cmd->bf_roaming_energy_delta));
|
|
|
|
IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
|
|
|
|
le32_to_cpu(cmd->bf_roaming_state));
|
|
|
|
IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n",
|
|
|
|
le32_to_cpu(cmd->bf_temp_threshold));
|
|
|
|
IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n",
|
|
|
|
le32_to_cpu(cmd->bf_temp_fast_filter));
|
|
|
|
IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
|
|
|
|
le32_to_cpu(cmd->bf_temp_slow_filter));
|
2018-10-28 17:16:44 +02:00
|
|
|
IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_low is: %d, %d\n",
|
|
|
|
le32_to_cpu(cmd->bf_threshold_absolute_low[0]),
|
|
|
|
le32_to_cpu(cmd->bf_threshold_absolute_low[1]));
|
|
|
|
|
|
|
|
IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_high is: %d, %d\n",
|
|
|
|
le32_to_cpu(cmd->bf_threshold_absolute_high[0]),
|
|
|
|
le32_to_cpu(cmd->bf_threshold_absolute_high[1]));
|
|
|
|
|
|
|
|
if (fw_has_api(&mvm->fw->ucode_capa,
|
|
|
|
IWL_UCODE_TLV_API_BEACON_FILTER_V4))
|
|
|
|
len = sizeof(struct iwl_beacon_filter_cmd);
|
|
|
|
else
|
|
|
|
len = offsetof(struct iwl_beacon_filter_cmd,
|
|
|
|
bf_threshold_absolute_low);
|
2014-01-26 12:58:24 +02:00
|
|
|
|
2024-02-06 18:02:10 +02:00
|
|
|
return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, 0,
|
2018-10-28 17:16:44 +02:00
|
|
|
len, cmd);
|
2013-05-06 13:03:59 +03:00
|
|
|
}
|
|
|
|
|
2013-07-21 17:23:59 +03:00
|
|
|
static
|
|
|
|
void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
|
|
|
|
struct ieee80211_vif *vif,
|
2019-06-06 11:03:01 +03:00
|
|
|
struct iwl_beacon_filter_cmd *cmd)
|
2013-07-21 17:23:59 +03:00
|
|
|
{
|
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
|
|
2019-06-06 11:03:01 +03:00
|
|
|
if (vif->bss_conf.cqm_rssi_thold) {
|
2013-07-21 17:23:59 +03:00
|
|
|
cmd->bf_energy_delta =
|
|
|
|
cpu_to_le32(vif->bss_conf.cqm_rssi_hyst);
|
|
|
|
/* fw uses an absolute value for this */
|
|
|
|
cmd->bf_roaming_state =
|
|
|
|
cpu_to_le32(-vif->bss_conf.cqm_rssi_thold);
|
|
|
|
}
|
2024-03-11 08:28:04 +02:00
|
|
|
cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->ba_enabled);
|
2013-07-21 17:23:59 +03:00
|
|
|
}
|
|
|
|
|
2013-03-05 14:08:23 +02:00
|
|
|
static void iwl_mvm_power_log(struct iwl_mvm *mvm,
|
2013-03-10 15:29:44 +02:00
|
|
|
struct iwl_mac_power_cmd *cmd)
|
2013-03-05 14:08:23 +02:00
|
|
|
{
|
|
|
|
IWL_DEBUG_POWER(mvm,
|
2013-03-10 15:29:44 +02:00
|
|
|
"Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
|
|
|
|
cmd->id_and_color, iwlmvm_mod_params.power_scheme,
|
2013-03-05 14:08:23 +02:00
|
|
|
le16_to_cpu(cmd->flags));
|
2013-03-10 15:29:44 +02:00
|
|
|
IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n",
|
|
|
|
le16_to_cpu(cmd->keep_alive_seconds));
|
2013-03-05 14:08:23 +02:00
|
|
|
|
2013-04-07 14:08:59 +03:00
|
|
|
if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) {
|
|
|
|
IWL_DEBUG_POWER(mvm, "Disable power management\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
|
|
|
|
le32_to_cpu(cmd->rx_data_timeout));
|
|
|
|
IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
|
|
|
|
le32_to_cpu(cmd->tx_data_timeout));
|
|
|
|
if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
|
|
|
|
IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
|
|
|
|
cmd->skip_dtim_periods);
|
|
|
|
if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
|
|
|
|
IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
|
|
|
|
cmd->lprx_rssi_threshold);
|
|
|
|
if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
|
|
|
|
IWL_DEBUG_POWER(mvm, "uAPSD enabled\n");
|
|
|
|
IWL_DEBUG_POWER(mvm, "Rx timeout (uAPSD) = %u usec\n",
|
|
|
|
le32_to_cpu(cmd->rx_data_timeout_uapsd));
|
|
|
|
IWL_DEBUG_POWER(mvm, "Tx timeout (uAPSD) = %u usec\n",
|
|
|
|
le32_to_cpu(cmd->tx_data_timeout_uapsd));
|
|
|
|
IWL_DEBUG_POWER(mvm, "QNDP TID = %d\n", cmd->qndp_tid);
|
|
|
|
IWL_DEBUG_POWER(mvm, "ACs flags = 0x%x\n", cmd->uapsd_ac_flags);
|
|
|
|
IWL_DEBUG_POWER(mvm, "Max SP = %d\n", cmd->uapsd_max_sp);
|
2013-03-05 14:08:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-14 20:59:37 +03:00
|
|
|
static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
|
|
|
|
struct ieee80211_vif *vif,
|
|
|
|
struct iwl_mac_power_cmd *cmd)
|
|
|
|
{
|
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
|
enum ieee80211_ac_numbers ac;
|
|
|
|
bool tid_found = false;
|
|
|
|
|
2021-10-17 16:59:46 +03:00
|
|
|
if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ||
|
|
|
|
cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
|
|
|
|
cmd->rx_data_timeout_uapsd =
|
|
|
|
cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
|
|
|
|
cmd->tx_data_timeout_uapsd =
|
|
|
|
cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
|
|
|
|
} else {
|
|
|
|
cmd->rx_data_timeout_uapsd =
|
|
|
|
cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
|
|
|
|
cmd->tx_data_timeout_uapsd =
|
|
|
|
cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
|
|
|
|
}
|
|
|
|
|
2016-10-26 14:21:27 +03:00
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
|
|
|
/* set advanced pm flag with no uapsd ACs to enable ps-poll */
|
|
|
|
if (mvmvif->dbgfs_pm.use_ps_poll) {
|
|
|
|
cmd->flags |= cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-04-14 20:59:37 +03:00
|
|
|
for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
|
wifi: iwlwifi: mvm: vif preparation for MLO
In MLO, some fields of iwl_mvm_vif should be defined in the
context of a link. Define a separate structure for these fields and
add a deflink object to hold it as part of iwl_mvm_vif. Non-MLO legacy
code will use only deflink object while MLO related code will use the
corresponding link from the link array.
It follows the strategy applied in mac80211 for introducing MLO
changes.
The below spatch takes care of updating all driver code to access
fields separated into MLD specific data structure via deflink (need
to convert all references to the fields listed in var to deflink.var
and also to take care of calls like iwl_mvm_vif_from_mac80211(vif)->field).
@iwl_mld_vif@
struct iwl_mvm_vif *v;
struct ieee80211_vif *vv;
identifier fn;
identifier var = {bssid, ap_sta_id, bcast_sta, mcast_sta,
beacon_stats, smps_requests, probe_resp_data,
he_ru_2mhz_block, cab_queue, phy_ctxt,
queue_params};
@@
(
v->
- var
+ deflink.var
|
fn(vv)->
- var
+ deflink.var
)
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104948.4896576f0a9f.Ifaf0187c96b9fe52b24bd629331165831a877691@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2023-03-28 10:58:41 +03:00
|
|
|
if (!mvmvif->deflink.queue_params[ac].uapsd)
|
2013-04-14 20:59:37 +03:00
|
|
|
continue;
|
|
|
|
|
2019-09-30 14:45:54 +02:00
|
|
|
if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
|
2013-04-14 20:59:37 +03:00
|
|
|
cmd->flags |=
|
|
|
|
cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
|
|
|
|
|
|
|
|
cmd->uapsd_ac_flags |= BIT(ac);
|
|
|
|
|
|
|
|
/* QNDP TID - the highest TID with no admission control */
|
wifi: iwlwifi: mvm: vif preparation for MLO
In MLO, some fields of iwl_mvm_vif should be defined in the
context of a link. Define a separate structure for these fields and
add a deflink object to hold it as part of iwl_mvm_vif. Non-MLO legacy
code will use only deflink object while MLO related code will use the
corresponding link from the link array.
It follows the strategy applied in mac80211 for introducing MLO
changes.
The below spatch takes care of updating all driver code to access
fields separated into MLD specific data structure via deflink (need
to convert all references to the fields listed in var to deflink.var
and also to take care of calls like iwl_mvm_vif_from_mac80211(vif)->field).
@iwl_mld_vif@
struct iwl_mvm_vif *v;
struct ieee80211_vif *vv;
identifier fn;
identifier var = {bssid, ap_sta_id, bcast_sta, mcast_sta,
beacon_stats, smps_requests, probe_resp_data,
he_ru_2mhz_block, cab_queue, phy_ctxt,
queue_params};
@@
(
v->
- var
+ deflink.var
|
fn(vv)->
- var
+ deflink.var
)
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104948.4896576f0a9f.Ifaf0187c96b9fe52b24bd629331165831a877691@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2023-03-28 10:58:41 +03:00
|
|
|
if (!tid_found && !mvmvif->deflink.queue_params[ac].acm) {
|
2013-04-14 20:59:37 +03:00
|
|
|
tid_found = true;
|
|
|
|
switch (ac) {
|
|
|
|
case IEEE80211_AC_VO:
|
|
|
|
cmd->qndp_tid = 6;
|
|
|
|
break;
|
|
|
|
case IEEE80211_AC_VI:
|
|
|
|
cmd->qndp_tid = 5;
|
|
|
|
break;
|
|
|
|
case IEEE80211_AC_BE:
|
|
|
|
cmd->qndp_tid = 0;
|
|
|
|
break;
|
|
|
|
case IEEE80211_AC_BK:
|
|
|
|
cmd->qndp_tid = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd->flags |= cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK);
|
|
|
|
|
|
|
|
if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
|
|
|
|
BIT(IEEE80211_AC_VI) |
|
|
|
|
BIT(IEEE80211_AC_BE) |
|
|
|
|
BIT(IEEE80211_AC_BK))) {
|
|
|
|
cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
|
|
|
|
cmd->snooze_interval = cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL);
|
2017-06-02 11:56:58 +02:00
|
|
|
cmd->snooze_window =
|
2019-09-30 14:45:54 +02:00
|
|
|
test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ?
|
2017-06-02 11:56:58 +02:00
|
|
|
cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) :
|
|
|
|
cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW);
|
2013-04-14 20:59:37 +03:00
|
|
|
}
|
|
|
|
|
2016-03-15 11:12:20 +02:00
|
|
|
cmd->uapsd_max_sp = mvm->hw->uapsd_max_sp_len;
|
2013-04-14 20:59:37 +03:00
|
|
|
|
|
|
|
if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
|
|
|
|
cmd->heavy_tx_thld_packets =
|
|
|
|
IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS;
|
|
|
|
cmd->heavy_rx_thld_packets =
|
|
|
|
IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS;
|
|
|
|
} else {
|
|
|
|
cmd->heavy_tx_thld_packets =
|
|
|
|
IWL_MVM_PS_HEAVY_TX_THLD_PACKETS;
|
|
|
|
cmd->heavy_rx_thld_packets =
|
|
|
|
IWL_MVM_PS_HEAVY_RX_THLD_PACKETS;
|
|
|
|
}
|
|
|
|
cmd->heavy_tx_thld_percentage =
|
|
|
|
IWL_MVM_PS_HEAVY_TX_THLD_PERCENT;
|
|
|
|
cmd->heavy_rx_thld_percentage =
|
|
|
|
IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
|
|
|
|
}
|
|
|
|
|
2015-11-25 13:17:10 +02:00
|
|
|
static void iwl_mvm_p2p_standalone_iterator(void *_data, u8 *mac,
|
|
|
|
struct ieee80211_vif *vif)
|
|
|
|
{
|
|
|
|
bool *is_p2p_standalone = _data;
|
|
|
|
|
|
|
|
switch (ieee80211_vif_type_p2p(vif)) {
|
|
|
|
case NL80211_IFTYPE_P2P_GO:
|
|
|
|
case NL80211_IFTYPE_AP:
|
|
|
|
*is_p2p_standalone = false;
|
|
|
|
break;
|
|
|
|
case NL80211_IFTYPE_STATION:
|
wifi: mac80211: move interface config to new struct
We'll use bss_conf for per-link configuration later, so
move out all the non-link-specific data out into a new
struct ieee80211_vif_cfg used in the vif.
Some adjustments were done with the following spatch:
@@
expression sdata;
struct ieee80211_vif *vifp;
identifier var = { assoc, ibss_joined, aid, arp_addr_list, arp_addr_cnt, ssid, ssid_len, s1g, ibss_creator };
@@
(
-sdata->vif.bss_conf.var
+sdata->vif.cfg.var
|
-vifp->bss_conf.var
+vifp->cfg.var
)
@bss_conf@
struct ieee80211_bss_conf *bss_conf;
identifier var = { assoc, ibss_joined, aid, arp_addr_list, arp_addr_cnt, ssid, ssid_len, s1g, ibss_creator };
@@
-bss_conf->var
+vif_cfg->var
(though more manual fixups were needed, e.g. replacing
"vif_cfg->" by "vif->cfg." in many files.)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2022-05-10 17:05:04 +02:00
|
|
|
if (vif->cfg.assoc)
|
2015-11-25 13:17:10 +02:00
|
|
|
*is_p2p_standalone = false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-01 12:08:13 +03:00
|
|
|
static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
|
|
|
|
struct ieee80211_vif *vif)
|
|
|
|
{
|
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
|
|
2023-06-14 12:41:34 +03:00
|
|
|
if (ether_addr_equal(mvmvif->uapsd_misbehaving_ap_addr,
|
|
|
|
vif->cfg.ap_addr))
|
2014-04-01 12:08:13 +03:00
|
|
|
return false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Avoid using uAPSD if P2P client is associated to GO that uses
|
|
|
|
* opportunistic power save. This is due to current FW limitation.
|
|
|
|
*/
|
|
|
|
if (vif->p2p &&
|
|
|
|
(vif->bss_conf.p2p_noa_attr.oppps_ctwindow &
|
|
|
|
IEEE80211_P2P_OPPPS_ENABLE_BIT))
|
|
|
|
return false;
|
|
|
|
|
2014-05-08 10:06:01 +03:00
|
|
|
/*
|
|
|
|
* Avoid using uAPSD if client is in DCM -
|
|
|
|
* low latency issue in Miracast
|
|
|
|
*/
|
2014-05-15 11:44:40 +03:00
|
|
|
if (iwl_mvm_phy_ctx_count(mvm) >= 2)
|
2014-05-08 10:06:01 +03:00
|
|
|
return false;
|
|
|
|
|
2015-11-25 13:17:10 +02:00
|
|
|
if (vif->p2p) {
|
|
|
|
/* Allow U-APSD only if p2p is stand alone */
|
|
|
|
bool is_p2p_standalone = true;
|
|
|
|
|
2016-04-20 09:29:18 +03:00
|
|
|
if (!iwl_mvm_is_p2p_scm_uapsd_supported(mvm))
|
2015-11-25 13:17:10 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
|
|
|
IEEE80211_IFACE_ITER_NORMAL,
|
|
|
|
iwl_mvm_p2p_standalone_iterator,
|
|
|
|
&is_p2p_standalone);
|
|
|
|
|
|
|
|
if (!is_p2p_standalone)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-04-01 12:08:13 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-08-27 19:58:56 +03:00
|
|
|
static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
|
|
|
|
{
|
|
|
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
2023-03-29 10:05:15 +03:00
|
|
|
struct ieee80211_bss_conf *link_conf;
|
2014-08-27 19:58:56 +03:00
|
|
|
bool radar_detect = false;
|
2023-03-29 10:05:15 +03:00
|
|
|
unsigned int link_id;
|
2014-08-27 19:58:56 +03:00
|
|
|
|
|
|
|
rcu_read_lock();
|
2023-03-29 10:05:15 +03:00
|
|
|
for_each_vif_active_link(vif, link_conf, link_id) {
|
|
|
|
chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
|
2023-03-29 10:05:26 +03:00
|
|
|
/* this happens on link switching, just ignore inactive ones */
|
|
|
|
if (!chanctx_conf)
|
2023-03-29 10:05:15 +03:00
|
|
|
continue;
|
|
|
|
|
|
|
|
radar_detect = !!(chanctx_conf->def.chan->flags &
|
|
|
|
IEEE80211_CHAN_RADAR);
|
|
|
|
if (radar_detect)
|
|
|
|
goto out;
|
2014-08-27 19:58:56 +03:00
|
|
|
}
|
|
|
|
|
2023-03-29 10:05:15 +03:00
|
|
|
out:
|
|
|
|
rcu_read_unlock();
|
2014-08-27 19:58:56 +03:00
|
|
|
return radar_detect;
|
|
|
|
}
|
|
|
|
|
2015-09-01 14:15:17 +02:00
|
|
|
static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm,
|
|
|
|
struct ieee80211_vif *vif,
|
2019-09-30 14:45:54 +02:00
|
|
|
struct iwl_mac_power_cmd *cmd)
|
2015-09-01 14:15:17 +02:00
|
|
|
{
|
|
|
|
int dtimper = vif->bss_conf.dtim_period ?: 1;
|
|
|
|
int skip;
|
|
|
|
|
|
|
|
/* disable, in case we're supposed to override */
|
|
|
|
cmd->skip_dtim_periods = 0;
|
|
|
|
cmd->flags &= ~cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
|
|
|
|
|
|
|
if (iwl_mvm_power_is_radar(vif))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (dtimper >= 10)
|
|
|
|
return;
|
|
|
|
|
2019-09-30 14:45:54 +02:00
|
|
|
if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) {
|
2015-09-01 14:15:17 +02:00
|
|
|
if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP)
|
|
|
|
return;
|
|
|
|
skip = 2;
|
|
|
|
} else {
|
|
|
|
int dtimper_tu = dtimper * vif->bss_conf.beacon_int;
|
|
|
|
|
|
|
|
if (WARN_ON(!dtimper_tu))
|
|
|
|
return;
|
2023-06-20 13:04:04 +03:00
|
|
|
/* configure skip over dtim up to 900 TU DTIM interval */
|
|
|
|
skip = max_t(u8, 1, 900 / dtimper_tu);
|
2015-09-01 14:15:17 +02:00
|
|
|
}
|
|
|
|
|
2023-06-20 13:04:04 +03:00
|
|
|
cmd->skip_dtim_periods = skip;
|
2015-09-01 14:15:17 +02:00
|
|
|
cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
|
|
|
}
|
|
|
|
|
2013-03-10 15:29:44 +02:00
|
|
|
static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
|
|
|
|
struct ieee80211_vif *vif,
|
2019-09-30 14:45:54 +02:00
|
|
|
struct iwl_mac_power_cmd *cmd)
|
2013-01-24 14:25:36 +01:00
|
|
|
{
|
2014-11-11 07:29:59 +02:00
|
|
|
int dtimper, bi;
|
2013-01-24 14:25:36 +01:00
|
|
|
int keep_alive;
|
2013-05-21 14:49:09 +03:00
|
|
|
struct iwl_mvm_vif *mvmvif __maybe_unused =
|
|
|
|
iwl_mvm_vif_from_mac80211(vif);
|
2013-01-24 14:25:36 +01:00
|
|
|
|
2013-03-10 15:29:44 +02:00
|
|
|
cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
|
|
|
mvmvif->color));
|
2014-07-31 14:39:40 +03:00
|
|
|
dtimper = vif->bss_conf.dtim_period;
|
2014-10-02 19:46:16 +02:00
|
|
|
bi = vif->bss_conf.beacon_int;
|
2013-03-10 15:29:44 +02:00
|
|
|
|
2013-03-05 14:01:27 +02:00
|
|
|
/*
|
|
|
|
* Regardless of power management state the driver must set
|
|
|
|
* keep alive period. FW will use it for sending keep alive NDPs
|
2013-03-10 15:29:44 +02:00
|
|
|
* immediately after association. Check that keep alive period
|
|
|
|
* is at least 3 * DTIM
|
2013-03-05 14:01:27 +02:00
|
|
|
*/
|
2014-11-11 07:29:59 +02:00
|
|
|
keep_alive = DIV_ROUND_UP(ieee80211_tu_to_usec(3 * dtimper * bi),
|
|
|
|
USEC_PER_SEC);
|
|
|
|
keep_alive = max(keep_alive, POWER_KEEP_ALIVE_PERIOD_SEC);
|
2013-03-10 15:29:44 +02:00
|
|
|
cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
|
2013-03-05 14:01:27 +02:00
|
|
|
|
2014-01-27 16:57:33 +02:00
|
|
|
if (mvm->ps_disabled)
|
2013-01-24 14:25:36 +01:00
|
|
|
return;
|
|
|
|
|
2013-03-05 12:54:00 +02:00
|
|
|
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
|
|
|
|
2022-06-24 15:02:16 +02:00
|
|
|
if (!vif->cfg.ps || !mvmvif->pm_enabled)
|
2015-10-06 14:07:44 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
|
|
|
|
(!fw_has_capa(&mvm->fw->ucode_capa,
|
|
|
|
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) ||
|
|
|
|
!IWL_MVM_P2P_LOWLATENCY_PS_ENABLE))
|
2013-03-05 12:54:00 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
|
2013-01-24 14:25:36 +01:00
|
|
|
|
2013-03-21 17:14:14 +02:00
|
|
|
if (vif->bss_conf.beacon_rate &&
|
|
|
|
(vif->bss_conf.beacon_rate->bitrate == 10 ||
|
|
|
|
vif->bss_conf.beacon_rate->bitrate == 60)) {
|
|
|
|
cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
|
2013-03-10 15:29:44 +02:00
|
|
|
cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
|
2013-03-21 17:14:14 +02:00
|
|
|
}
|
|
|
|
|
2019-09-30 14:45:54 +02:00
|
|
|
iwl_mvm_power_config_skip_dtim(mvm, vif, cmd);
|
2013-01-24 14:25:36 +01:00
|
|
|
|
2019-09-30 14:45:54 +02:00
|
|
|
if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) {
|
2013-06-14 13:36:21 +02:00
|
|
|
cmd->rx_data_timeout =
|
2015-10-06 14:07:44 +02:00
|
|
|
cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
|
2013-06-14 13:36:21 +02:00
|
|
|
cmd->tx_data_timeout =
|
2015-10-06 14:07:44 +02:00
|
|
|
cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
|
|
|
|
} else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
|
|
|
|
fw_has_capa(&mvm->fw->ucode_capa,
|
|
|
|
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) {
|
|
|
|
cmd->tx_data_timeout =
|
|
|
|
cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT);
|
|
|
|
cmd->rx_data_timeout =
|
|
|
|
cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT);
|
2013-04-23 13:52:10 +03:00
|
|
|
} else {
|
2013-06-14 13:36:21 +02:00
|
|
|
cmd->rx_data_timeout =
|
2015-10-06 14:07:44 +02:00
|
|
|
cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
|
2013-06-14 13:36:21 +02:00
|
|
|
cmd->tx_data_timeout =
|
2015-10-06 14:07:44 +02:00
|
|
|
cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
|
2013-04-23 13:52:10 +03:00
|
|
|
}
|
2013-05-21 14:49:09 +03:00
|
|
|
|
2014-04-01 12:08:13 +03:00
|
|
|
if (iwl_mvm_power_allow_uapsd(mvm, vif))
|
2013-04-14 20:59:37 +03:00
|
|
|
iwl_mvm_power_configure_uapsd(mvm, vif, cmd);
|
2013-04-07 14:08:59 +03:00
|
|
|
|
2013-05-21 14:49:09 +03:00
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
|
|
|
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
|
2013-03-10 15:29:44 +02:00
|
|
|
cmd->keep_alive_seconds =
|
|
|
|
cpu_to_le16(mvmvif->dbgfs_pm.keep_alive_seconds);
|
2013-05-21 14:49:09 +03:00
|
|
|
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
|
|
|
|
if (mvmvif->dbgfs_pm.skip_over_dtim)
|
|
|
|
cmd->flags |=
|
|
|
|
cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
|
|
|
else
|
|
|
|
cmd->flags &=
|
|
|
|
cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
|
|
|
}
|
|
|
|
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
|
|
|
|
cmd->rx_data_timeout =
|
|
|
|
cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
|
|
|
|
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
|
|
|
|
cmd->tx_data_timeout =
|
|
|
|
cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
|
|
|
|
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
|
2013-03-10 15:29:44 +02:00
|
|
|
cmd->skip_dtim_periods = mvmvif->dbgfs_pm.skip_dtim_periods;
|
2013-03-21 17:14:14 +02:00
|
|
|
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
|
|
|
|
if (mvmvif->dbgfs_pm.lprx_ena)
|
|
|
|
cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
|
|
|
|
else
|
|
|
|
cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
|
|
|
|
}
|
|
|
|
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
|
2013-03-10 15:29:44 +02:00
|
|
|
cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold;
|
2013-08-04 17:52:23 +03:00
|
|
|
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SNOOZE_ENABLE) {
|
|
|
|
if (mvmvif->dbgfs_pm.snooze_ena)
|
|
|
|
cmd->flags |=
|
|
|
|
cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
|
|
|
|
else
|
|
|
|
cmd->flags &=
|
|
|
|
cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK);
|
|
|
|
}
|
2013-12-04 10:13:24 +02:00
|
|
|
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_UAPSD_MISBEHAVING) {
|
|
|
|
u16 flag = POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK;
|
|
|
|
if (mvmvif->dbgfs_pm.uapsd_misbehaving)
|
|
|
|
cmd->flags |= cpu_to_le16(flag);
|
|
|
|
else
|
|
|
|
cmd->flags &= cpu_to_le16(flag);
|
|
|
|
}
|
2013-05-21 14:49:09 +03:00
|
|
|
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
2013-01-24 14:25:36 +01:00
|
|
|
}
|
|
|
|
|
2014-01-27 16:57:33 +02:00
|
|
|
static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
|
2013-03-10 15:29:44 +02:00
|
|
|
struct ieee80211_vif *vif)
|
2013-01-24 14:25:36 +01:00
|
|
|
{
|
2013-03-10 15:29:44 +02:00
|
|
|
struct iwl_mac_power_cmd cmd = {};
|
2013-01-24 14:25:36 +01:00
|
|
|
|
2019-09-30 14:45:54 +02:00
|
|
|
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
|
2013-03-05 14:08:23 +02:00
|
|
|
iwl_mvm_power_log(mvm, &cmd);
|
2014-01-28 09:13:04 +02:00
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
|
|
|
memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));
|
|
|
|
#endif
|
2013-01-24 14:25:36 +01:00
|
|
|
|
2014-05-12 11:36:41 +03:00
|
|
|
return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, 0,
|
2014-01-27 08:09:23 +02:00
|
|
|
sizeof(cmd), &cmd);
|
|
|
|
}
|
|
|
|
|
2014-01-27 16:57:33 +02:00
|
|
|
int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
|
2013-09-03 14:18:03 +03:00
|
|
|
{
|
|
|
|
struct iwl_device_power_cmd cmd = {
|
2015-09-04 11:27:25 +02:00
|
|
|
.flags = 0,
|
2013-09-03 14:18:03 +03:00
|
|
|
};
|
|
|
|
|
2014-01-27 16:57:33 +02:00
|
|
|
if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
|
|
|
|
mvm->ps_disabled = true;
|
|
|
|
|
2015-09-04 11:27:25 +02:00
|
|
|
if (!mvm->ps_disabled)
|
|
|
|
cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
2013-09-03 14:18:03 +03:00
|
|
|
|
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
2019-09-30 14:45:54 +02:00
|
|
|
if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ?
|
2017-06-02 11:56:58 +02:00
|
|
|
mvm->disable_power_off_d3 : mvm->disable_power_off)
|
2013-09-03 14:18:03 +03:00
|
|
|
cmd.flags &=
|
|
|
|
cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
|
|
|
#endif
|
2019-01-02 12:52:20 +02:00
|
|
|
if (mvm->ext_clock_valid)
|
|
|
|
cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK);
|
|
|
|
|
2023-09-13 14:56:48 +03:00
|
|
|
if (iwl_fw_lookup_cmd_ver(mvm->fw, POWER_TABLE_CMD, 0) >= 7 &&
|
|
|
|
test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
|
|
|
|
cmd.flags |=
|
|
|
|
cpu_to_le16(DEVICE_POWER_FLAGS_NO_SLEEP_TILL_D3_MSK);
|
|
|
|
|
2013-09-03 14:18:03 +03:00
|
|
|
IWL_DEBUG_POWER(mvm,
|
|
|
|
"Sending device power command with flags = 0x%X\n",
|
|
|
|
cmd.flags);
|
|
|
|
|
2014-05-12 11:36:41 +03:00
|
|
|
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, 0, sizeof(cmd),
|
2013-09-03 14:18:03 +03:00
|
|
|
&cmd);
|
|
|
|
}
|
|
|
|
|
2013-04-14 20:59:37 +03:00
|
|
|
void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|
|
|
{
|
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
|
|
2023-06-14 12:41:34 +03:00
|
|
|
if (!ether_addr_equal(mvmvif->uapsd_misbehaving_ap_addr,
|
|
|
|
vif->cfg.ap_addr))
|
|
|
|
eth_zero_addr(mvmvif->uapsd_misbehaving_ap_addr);
|
2013-04-14 20:59:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
|
|
|
|
struct ieee80211_vif *vif)
|
|
|
|
{
|
|
|
|
u8 *ap_sta_id = _data;
|
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
2023-06-14 12:41:34 +03:00
|
|
|
struct ieee80211_bss_conf *link_conf;
|
|
|
|
unsigned int link_id;
|
2013-04-14 20:59:37 +03:00
|
|
|
|
2023-06-14 12:41:34 +03:00
|
|
|
rcu_read_lock();
|
|
|
|
for_each_vif_active_link(vif, link_conf, link_id) {
|
|
|
|
struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
|
|
|
|
|
|
|
|
/* The ap_sta_id is not expected to change during current
|
|
|
|
* association so no explicit protection is needed
|
|
|
|
*/
|
|
|
|
if (link_info->ap_sta_id == *ap_sta_id) {
|
|
|
|
ether_addr_copy(mvmvif->uapsd_misbehaving_ap_addr,
|
|
|
|
vif->cfg.ap_addr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
2013-04-14 20:59:37 +03:00
|
|
|
}
|
|
|
|
|
2015-06-23 21:22:09 +02:00
|
|
|
void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
|
|
|
|
struct iwl_rx_cmd_buffer *rxb)
|
2013-04-14 20:59:37 +03:00
|
|
|
{
|
|
|
|
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
|
|
|
struct iwl_uapsd_misbehaving_ap_notif *notif = (void *)pkt->data;
|
|
|
|
u8 ap_sta_id = le32_to_cpu(notif->sta_id);
|
|
|
|
|
|
|
|
ieee80211_iterate_active_interfaces_atomic(
|
|
|
|
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
|
|
|
|
iwl_mvm_power_uapsd_misbehav_ap_iterator, &ap_sta_id);
|
|
|
|
}
|
|
|
|
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
struct iwl_power_vifs {
|
2014-05-15 18:59:32 +03:00
|
|
|
struct iwl_mvm *mvm;
|
2014-01-27 16:57:33 +02:00
|
|
|
struct ieee80211_vif *bss_vif;
|
2014-02-20 13:28:57 +02:00
|
|
|
struct ieee80211_vif *p2p_vif;
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
struct ieee80211_vif *ap_vif;
|
|
|
|
struct ieee80211_vif *monitor_vif;
|
|
|
|
bool p2p_active;
|
|
|
|
bool bss_active;
|
|
|
|
bool ap_active;
|
|
|
|
bool monitor_active;
|
2014-01-27 08:09:23 +02:00
|
|
|
};
|
|
|
|
|
2014-08-08 18:36:22 +03:00
|
|
|
static void iwl_mvm_power_disable_pm_iterator(void *_data, u8* mac,
|
|
|
|
struct ieee80211_vif *vif)
|
2013-08-27 20:31:48 +03:00
|
|
|
{
|
2014-01-27 08:09:23 +02:00
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
2014-01-27 16:57:33 +02:00
|
|
|
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
mvmvif->pm_enabled = false;
|
2014-08-08 18:36:22 +03:00
|
|
|
}
|
|
|
|
|
2014-08-08 19:50:46 +03:00
|
|
|
static void iwl_mvm_power_ps_disabled_iterator(void *_data, u8* mac,
|
|
|
|
struct ieee80211_vif *vif)
|
|
|
|
{
|
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
|
bool *disable_ps = _data;
|
|
|
|
|
2023-03-28 10:58:58 +03:00
|
|
|
if (iwl_mvm_vif_is_active(mvmvif))
|
2016-11-20 13:50:39 +02:00
|
|
|
*disable_ps |= mvmvif->ps_disabled;
|
2014-08-08 19:50:46 +03:00
|
|
|
}
|
|
|
|
|
2014-08-08 18:36:22 +03:00
|
|
|
static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
|
|
|
|
struct ieee80211_vif *vif)
|
|
|
|
{
|
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
|
struct iwl_power_vifs *power_iterator = _data;
|
2023-03-28 10:58:58 +03:00
|
|
|
bool active;
|
2014-08-08 18:36:22 +03:00
|
|
|
|
2022-05-17 12:05:09 +03:00
|
|
|
if (!mvmvif->uploaded)
|
|
|
|
return;
|
|
|
|
|
2023-03-28 10:58:58 +03:00
|
|
|
active = iwl_mvm_vif_is_active(mvmvif);
|
|
|
|
|
2014-01-27 16:57:33 +02:00
|
|
|
switch (ieee80211_vif_type_p2p(vif)) {
|
|
|
|
case NL80211_IFTYPE_P2P_DEVICE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NL80211_IFTYPE_P2P_GO:
|
|
|
|
case NL80211_IFTYPE_AP:
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
/* only a single MAC of the same type */
|
|
|
|
WARN_ON(power_iterator->ap_vif);
|
|
|
|
power_iterator->ap_vif = vif;
|
2016-11-20 13:50:39 +02:00
|
|
|
if (active)
|
|
|
|
power_iterator->ap_active = true;
|
2014-01-27 16:57:33 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NL80211_IFTYPE_MONITOR:
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
/* only a single MAC of the same type */
|
|
|
|
WARN_ON(power_iterator->monitor_vif);
|
|
|
|
power_iterator->monitor_vif = vif;
|
2016-11-20 13:50:39 +02:00
|
|
|
if (active)
|
|
|
|
power_iterator->monitor_active = true;
|
2014-01-27 16:57:33 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NL80211_IFTYPE_P2P_CLIENT:
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
/* only a single MAC of the same type */
|
2014-02-20 13:28:57 +02:00
|
|
|
WARN_ON(power_iterator->p2p_vif);
|
|
|
|
power_iterator->p2p_vif = vif;
|
2016-11-20 13:50:39 +02:00
|
|
|
if (active)
|
|
|
|
power_iterator->p2p_active = true;
|
2014-01-27 16:57:33 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NL80211_IFTYPE_STATION:
|
|
|
|
power_iterator->bss_vif = vif;
|
2016-11-20 13:50:39 +02:00
|
|
|
if (active)
|
|
|
|
power_iterator->bss_active = true;
|
2014-01-27 16:57:33 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-08-27 20:31:48 +03:00
|
|
|
|
2014-08-08 17:12:07 +03:00
|
|
|
static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
|
|
|
|
struct iwl_power_vifs *vifs)
|
2014-01-27 16:57:33 +02:00
|
|
|
{
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
struct iwl_mvm_vif *bss_mvmvif = NULL;
|
|
|
|
struct iwl_mvm_vif *p2p_mvmvif = NULL;
|
|
|
|
struct iwl_mvm_vif *ap_mvmvif = NULL;
|
|
|
|
bool client_same_channel = false;
|
|
|
|
bool ap_same_channel = false;
|
2014-01-27 16:57:33 +02:00
|
|
|
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
lockdep_assert_held(&mvm->mutex);
|
2014-01-27 08:09:23 +02:00
|
|
|
|
2014-08-08 18:36:22 +03:00
|
|
|
/* set pm_enable to false */
|
2014-01-27 16:57:33 +02:00
|
|
|
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
2014-08-08 18:36:22 +03:00
|
|
|
IEEE80211_IFACE_ITER_NORMAL,
|
|
|
|
iwl_mvm_power_disable_pm_iterator,
|
|
|
|
NULL);
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
|
|
|
|
if (vifs->bss_vif)
|
|
|
|
bss_mvmvif = iwl_mvm_vif_from_mac80211(vifs->bss_vif);
|
|
|
|
|
|
|
|
if (vifs->p2p_vif)
|
|
|
|
p2p_mvmvif = iwl_mvm_vif_from_mac80211(vifs->p2p_vif);
|
|
|
|
|
|
|
|
if (vifs->ap_vif)
|
|
|
|
ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
|
|
|
|
|
2015-02-22 19:15:04 +02:00
|
|
|
/* don't allow PM if any TDLS stations exist */
|
|
|
|
if (iwl_mvm_tdls_sta_count(mvm, NULL))
|
|
|
|
return;
|
|
|
|
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
/* enable PM on bss if bss stand alone */
|
2023-06-14 15:50:08 +03:00
|
|
|
if (bss_mvmvif && vifs->bss_active && !vifs->p2p_active &&
|
|
|
|
!vifs->ap_active) {
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
bss_mvmvif->pm_enabled = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* enable PM on p2p if p2p stand alone */
|
2023-06-14 15:50:08 +03:00
|
|
|
if (p2p_mvmvif && vifs->p2p_active && !vifs->bss_active &&
|
|
|
|
!vifs->ap_active) {
|
2016-09-12 16:03:30 +03:00
|
|
|
p2p_mvmvif->pm_enabled = true;
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-06-14 15:50:08 +03:00
|
|
|
if (p2p_mvmvif && bss_mvmvif && vifs->bss_active && vifs->p2p_active)
|
2023-03-28 10:58:58 +03:00
|
|
|
client_same_channel =
|
|
|
|
iwl_mvm_have_links_same_channel(bss_mvmvif, p2p_mvmvif);
|
|
|
|
|
2023-06-14 15:50:08 +03:00
|
|
|
if (bss_mvmvif && ap_mvmvif && vifs->bss_active && vifs->ap_active)
|
2023-03-28 10:58:58 +03:00
|
|
|
ap_same_channel =
|
|
|
|
iwl_mvm_have_links_same_channel(bss_mvmvif, ap_mvmvif);
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
|
2014-04-02 07:54:07 +03:00
|
|
|
/* clients are not stand alone: enable PM if DCM */
|
2016-09-12 16:03:30 +03:00
|
|
|
if (!(client_same_channel || ap_same_channel)) {
|
2023-06-14 15:50:08 +03:00
|
|
|
if (bss_mvmvif && vifs->bss_active)
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
bss_mvmvif->pm_enabled = true;
|
2023-06-14 15:50:08 +03:00
|
|
|
if (p2p_mvmvif && vifs->p2p_active)
|
2014-04-02 07:54:07 +03:00
|
|
|
p2p_mvmvif->pm_enabled = true;
|
|
|
|
return;
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* There is only one channel in the system and there are only
|
|
|
|
* bss and p2p clients that share it
|
|
|
|
*/
|
2016-09-12 16:03:30 +03:00
|
|
|
if (client_same_channel && !vifs->ap_active) {
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
/* share same channel*/
|
|
|
|
bss_mvmvif->pm_enabled = true;
|
2016-09-12 16:03:30 +03:00
|
|
|
p2p_mvmvif->pm_enabled = true;
|
iwlwifi: mvm: Handle power management constraints for additional use-cases
Today, the driver logic looks for the conditions to disable
power management albeit power management should be enabled
in a very few distinct cases.
This patch changes the driver logic to enable power
management once the required conditions met.
While at it, make some housekeeping and support a few
additional use cases:
a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client
MAC only if the firmware supports it (TLV flag is set).
Instead we used the DCM flag, therefore we didn't cover
use cases that did not include the DCM flag.
b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there
are no other active vifs in the system, power management
should be enabled only if the firmware supports this
(TLV flag is set).
c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable
power management for all the vifs altogether.
Actually, the correct behavior is to enable power
management on a client if on a different channel
(based on the firmware capabilities).
d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is
scattered across several functions, specifically in the
iterator. For the sake of both readability and
scalability, we moved this logic to its applicable
function, leaving the iterator gather information only.
Furthermore, as power management is a MAC-related
attribute, we moved the power management member to the
iwl_mvm_vif structure.
Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
2014-03-19 07:25:06 +02:00
|
|
|
}
|
2013-08-27 20:31:48 +03:00
|
|
|
}
|
|
|
|
|
2013-05-21 14:49:09 +03:00
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
2014-01-28 10:17:18 +02:00
|
|
|
int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
|
|
|
|
struct ieee80211_vif *vif, char *buf,
|
|
|
|
int bufsz)
|
2013-03-10 15:29:44 +02:00
|
|
|
{
|
2014-01-28 09:13:04 +02:00
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
2013-03-10 15:29:44 +02:00
|
|
|
struct iwl_mac_power_cmd cmd = {};
|
|
|
|
int pos = 0;
|
|
|
|
|
2014-01-28 09:13:04 +02:00
|
|
|
mutex_lock(&mvm->mutex);
|
|
|
|
memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd));
|
|
|
|
mutex_unlock(&mvm->mutex);
|
2013-03-10 15:29:44 +02:00
|
|
|
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
|
|
|
|
iwlmvm_mod_params.power_scheme);
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
|
|
|
|
le16_to_cpu(cmd.flags));
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
|
|
|
|
le16_to_cpu(cmd.keep_alive_seconds));
|
|
|
|
|
2013-04-14 20:59:37 +03:00
|
|
|
if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)))
|
|
|
|
return pos;
|
|
|
|
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
|
|
|
|
(cmd.flags &
|
|
|
|
cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? 1 : 0);
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
|
|
|
|
cmd.skip_dtim_periods);
|
|
|
|
if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
|
|
|
|
le32_to_cpu(cmd.rx_data_timeout));
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
|
|
|
|
le32_to_cpu(cmd.tx_data_timeout));
|
2013-03-10 15:29:44 +02:00
|
|
|
}
|
2013-04-14 20:59:37 +03:00
|
|
|
if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos,
|
|
|
|
"lprx_rssi_threshold = %d\n",
|
|
|
|
cmd.lprx_rssi_threshold);
|
|
|
|
|
|
|
|
if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)))
|
|
|
|
return pos;
|
|
|
|
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout_uapsd = %d\n",
|
|
|
|
le32_to_cpu(cmd.rx_data_timeout_uapsd));
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout_uapsd = %d\n",
|
|
|
|
le32_to_cpu(cmd.tx_data_timeout_uapsd));
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n", cmd.qndp_tid);
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "uapsd_ac_flags = 0x%x\n",
|
|
|
|
cmd.uapsd_ac_flags);
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "uapsd_max_sp = %d\n",
|
|
|
|
cmd.uapsd_max_sp);
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_packets = %d\n",
|
|
|
|
cmd.heavy_tx_thld_packets);
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_packets = %d\n",
|
|
|
|
cmd.heavy_rx_thld_packets);
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_percentage = %d\n",
|
|
|
|
cmd.heavy_tx_thld_percentage);
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_percentage = %d\n",
|
|
|
|
cmd.heavy_rx_thld_percentage);
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "uapsd_misbehaving_enable = %d\n",
|
|
|
|
(cmd.flags &
|
|
|
|
cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK)) ?
|
|
|
|
1 : 0);
|
|
|
|
|
|
|
|
if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)))
|
|
|
|
return pos;
|
|
|
|
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "snooze_interval = %d\n",
|
|
|
|
cmd.snooze_interval);
|
|
|
|
pos += scnprintf(buf+pos, bufsz-pos, "snooze_window = %d\n",
|
|
|
|
cmd.snooze_window);
|
|
|
|
|
2013-03-10 15:29:44 +02:00
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
2013-05-21 14:49:09 +03:00
|
|
|
void
|
|
|
|
iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
|
|
|
|
struct iwl_beacon_filter_cmd *cmd)
|
|
|
|
{
|
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
|
struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
|
|
|
|
|
|
|
|
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
|
2013-07-16 11:15:35 +03:00
|
|
|
cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta);
|
2013-05-21 14:49:09 +03:00
|
|
|
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
|
|
|
|
cmd->bf_roaming_energy_delta =
|
2013-07-16 11:15:35 +03:00
|
|
|
cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta);
|
2013-05-21 14:49:09 +03:00
|
|
|
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
|
2013-07-16 11:15:35 +03:00
|
|
|
cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state);
|
|
|
|
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD)
|
|
|
|
cmd->bf_temp_threshold =
|
|
|
|
cpu_to_le32(dbgfs_bf->bf_temp_threshold);
|
|
|
|
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER)
|
|
|
|
cmd->bf_temp_fast_filter =
|
|
|
|
cpu_to_le32(dbgfs_bf->bf_temp_fast_filter);
|
|
|
|
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER)
|
|
|
|
cmd->bf_temp_slow_filter =
|
|
|
|
cpu_to_le32(dbgfs_bf->bf_temp_slow_filter);
|
2013-05-21 14:49:09 +03:00
|
|
|
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
|
2013-07-16 11:15:35 +03:00
|
|
|
cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag);
|
2013-05-21 14:49:09 +03:00
|
|
|
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
|
|
|
|
cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
|
|
|
|
if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
|
|
|
|
cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
|
|
|
|
if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
|
2013-07-16 11:15:35 +03:00
|
|
|
cmd->ba_enable_beacon_abort =
|
|
|
|
cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort);
|
2013-05-21 14:49:09 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-01-07 14:00:24 +02:00
|
|
|
static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
|
|
|
|
struct ieee80211_vif *vif,
|
2024-02-06 18:02:10 +02:00
|
|
|
struct iwl_beacon_filter_cmd *cmd)
|
2012-12-12 11:16:19 +02:00
|
|
|
{
|
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
2013-05-06 13:03:59 +03:00
|
|
|
int ret;
|
2012-12-12 11:16:19 +02:00
|
|
|
|
2014-05-20 08:03:24 +03:00
|
|
|
if (mvmvif != mvm->bf_allowed_vif || !vif->bss_conf.dtim_period ||
|
2012-12-12 11:16:19 +02:00
|
|
|
vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
|
|
|
return 0;
|
|
|
|
|
2019-06-06 11:03:01 +03:00
|
|
|
iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd);
|
|
|
|
iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
|
2024-02-06 18:02:10 +02:00
|
|
|
ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd);
|
2013-05-06 13:03:59 +03:00
|
|
|
|
2019-06-06 11:03:01 +03:00
|
|
|
if (!ret)
|
2024-03-11 08:28:04 +02:00
|
|
|
mvmvif->bf_enabled = true;
|
2013-05-06 13:03:59 +03:00
|
|
|
|
|
|
|
return ret;
|
2012-12-12 11:16:19 +02:00
|
|
|
}
|
|
|
|
|
2014-01-07 14:00:24 +02:00
|
|
|
int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
|
2024-02-06 18:02:10 +02:00
|
|
|
struct ieee80211_vif *vif)
|
2014-01-07 14:00:24 +02:00
|
|
|
{
|
|
|
|
struct iwl_beacon_filter_cmd cmd = {
|
|
|
|
IWL_BF_CMD_CONFIG_DEFAULTS,
|
|
|
|
.bf_enable_beacon_filter = cpu_to_le32(1),
|
|
|
|
};
|
|
|
|
|
2024-02-06 18:02:10 +02:00
|
|
|
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd);
|
2014-01-07 14:00:24 +02:00
|
|
|
}
|
|
|
|
|
2015-12-29 11:07:15 +02:00
|
|
|
static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
|
2024-02-06 18:02:10 +02:00
|
|
|
struct ieee80211_vif *vif)
|
2012-12-12 11:16:19 +02:00
|
|
|
{
|
2013-05-06 13:03:59 +03:00
|
|
|
struct iwl_beacon_filter_cmd cmd = {};
|
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
|
int ret;
|
2012-12-12 11:16:19 +02:00
|
|
|
|
2014-03-30 08:57:30 +03:00
|
|
|
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
2012-12-12 11:16:19 +02:00
|
|
|
return 0;
|
|
|
|
|
2024-02-06 18:02:10 +02:00
|
|
|
ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
|
2013-05-06 13:03:59 +03:00
|
|
|
|
2019-06-06 11:03:01 +03:00
|
|
|
if (!ret)
|
2024-03-11 08:28:04 +02:00
|
|
|
mvmvif->bf_enabled = false;
|
2013-05-06 13:03:59 +03:00
|
|
|
|
|
|
|
return ret;
|
2012-12-12 11:16:19 +02:00
|
|
|
}
|
2013-03-10 15:29:44 +02:00
|
|
|
|
2015-12-29 11:07:15 +02:00
|
|
|
int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
|
2024-02-06 18:02:10 +02:00
|
|
|
struct ieee80211_vif *vif)
|
2015-12-29 11:07:15 +02:00
|
|
|
{
|
2024-02-06 18:02:10 +02:00
|
|
|
return _iwl_mvm_disable_beacon_filter(mvm, vif);
|
2015-12-29 11:07:15 +02:00
|
|
|
}
|
|
|
|
|
2014-08-08 19:50:46 +03:00
|
|
|
static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm)
|
2014-05-20 11:28:18 +03:00
|
|
|
{
|
2014-08-08 18:36:22 +03:00
|
|
|
bool disable_ps;
|
2014-05-20 11:28:18 +03:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* disable PS if CAM */
|
2014-08-08 17:12:07 +03:00
|
|
|
disable_ps = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);
|
2014-08-08 19:50:46 +03:00
|
|
|
/* ...or if any of the vifs require PS to be off */
|
|
|
|
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
|
|
|
IEEE80211_IFACE_ITER_NORMAL,
|
|
|
|
iwl_mvm_power_ps_disabled_iterator,
|
|
|
|
&disable_ps);
|
2014-08-08 17:12:07 +03:00
|
|
|
|
|
|
|
/* update device power state if it has changed */
|
|
|
|
if (mvm->ps_disabled != disable_ps) {
|
|
|
|
bool old_ps_disabled = mvm->ps_disabled;
|
|
|
|
|
|
|
|
mvm->ps_disabled = disable_ps;
|
|
|
|
ret = iwl_mvm_power_update_device(mvm);
|
|
|
|
if (ret) {
|
|
|
|
mvm->ps_disabled = old_ps_disabled;
|
|
|
|
return ret;
|
2014-05-20 11:28:18 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-08 18:36:22 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-08 19:18:35 +03:00
|
|
|
static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
|
2016-01-24 15:18:59 +02:00
|
|
|
struct ieee80211_vif *vif)
|
2014-08-08 18:36:22 +03:00
|
|
|
{
|
2016-01-24 15:18:59 +02:00
|
|
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
2016-01-24 15:56:11 +02:00
|
|
|
struct iwl_beacon_filter_cmd cmd = {
|
|
|
|
IWL_BF_CMD_CONFIG_DEFAULTS,
|
|
|
|
.bf_enable_beacon_filter = cpu_to_le32(1),
|
|
|
|
};
|
2014-08-08 19:18:35 +03:00
|
|
|
|
2024-03-11 08:28:04 +02:00
|
|
|
if (!mvmvif->bf_enabled)
|
2014-08-08 19:18:35 +03:00
|
|
|
return 0;
|
|
|
|
|
2019-09-30 14:45:54 +02:00
|
|
|
if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
|
2016-01-24 15:56:11 +02:00
|
|
|
cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
|
|
|
|
|
2024-03-11 08:28:04 +02:00
|
|
|
mvmvif->ba_enabled = !(!mvmvif->pm_enabled ||
|
|
|
|
mvm->ps_disabled ||
|
|
|
|
!vif->cfg.ps ||
|
|
|
|
iwl_mvm_vif_low_latency(mvmvif));
|
2014-08-08 19:18:35 +03:00
|
|
|
|
2024-02-06 18:02:10 +02:00
|
|
|
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd);
|
2014-08-08 19:18:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int iwl_mvm_power_update_ps(struct iwl_mvm *mvm)
|
|
|
|
{
|
|
|
|
struct iwl_power_vifs vifs = {
|
|
|
|
.mvm = mvm,
|
|
|
|
};
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
|
|
/* get vifs info */
|
|
|
|
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
|
|
|
IEEE80211_IFACE_ITER_NORMAL,
|
|
|
|
iwl_mvm_power_get_vifs_iterator, &vifs);
|
|
|
|
|
2014-08-08 19:50:46 +03:00
|
|
|
ret = iwl_mvm_power_set_ps(mvm);
|
2014-08-08 19:18:35 +03:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2016-01-24 15:18:59 +02:00
|
|
|
if (vifs.bss_vif)
|
|
|
|
return iwl_mvm_power_set_ba(mvm, vifs.bss_vif);
|
|
|
|
|
|
|
|
return 0;
|
2014-08-08 19:18:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
|
|
|
|
{
|
2014-08-08 18:36:22 +03:00
|
|
|
struct iwl_power_vifs vifs = {
|
|
|
|
.mvm = mvm,
|
|
|
|
};
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
|
|
/* get vifs info */
|
|
|
|
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
|
|
|
IEEE80211_IFACE_ITER_NORMAL,
|
|
|
|
iwl_mvm_power_get_vifs_iterator, &vifs);
|
|
|
|
|
|
|
|
iwl_mvm_power_set_pm(mvm, &vifs);
|
|
|
|
|
2014-08-08 19:50:46 +03:00
|
|
|
ret = iwl_mvm_power_set_ps(mvm);
|
2014-08-08 18:36:22 +03:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2014-05-20 11:28:18 +03:00
|
|
|
if (vifs.bss_vif) {
|
|
|
|
ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vifs.p2p_vif) {
|
|
|
|
ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-01-24 15:18:59 +02:00
|
|
|
if (vifs.bss_vif)
|
|
|
|
return iwl_mvm_power_set_ba(mvm, vifs.bss_vif);
|
|
|
|
|
|
|
|
return 0;
|
2014-05-20 11:28:18 +03:00
|
|
|
}
|