cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

power.c (28138B)


      1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
      2/*
      3 * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
      4 * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
      5 * Copyright (C) 2015-2017 Intel Deutschland GmbH
      6 */
      7#include <linux/kernel.h>
      8#include <linux/module.h>
      9#include <linux/slab.h>
     10#include <linux/etherdevice.h>
     11
     12#include <net/mac80211.h>
     13
     14#include "iwl-debug.h"
     15#include "mvm.h"
     16#include "iwl-modparams.h"
     17#include "fw/api/power.h"
     18
     19#define POWER_KEEP_ALIVE_PERIOD_SEC    25
     20
     21static
     22int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
     23				   struct iwl_beacon_filter_cmd *cmd,
     24				   u32 flags)
     25{
     26	u16 len;
     27
     28	IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
     29			le32_to_cpu(cmd->ba_enable_beacon_abort));
     30	IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
     31			le32_to_cpu(cmd->ba_escape_timer));
     32	IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
     33			le32_to_cpu(cmd->bf_debug_flag));
     34	IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
     35			le32_to_cpu(cmd->bf_enable_beacon_filter));
     36	IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
     37			le32_to_cpu(cmd->bf_energy_delta));
     38	IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
     39			le32_to_cpu(cmd->bf_escape_timer));
     40	IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
     41			le32_to_cpu(cmd->bf_roaming_energy_delta));
     42	IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
     43			le32_to_cpu(cmd->bf_roaming_state));
     44	IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n",
     45			le32_to_cpu(cmd->bf_temp_threshold));
     46	IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n",
     47			le32_to_cpu(cmd->bf_temp_fast_filter));
     48	IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
     49			le32_to_cpu(cmd->bf_temp_slow_filter));
     50	IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_low is: %d, %d\n",
     51			le32_to_cpu(cmd->bf_threshold_absolute_low[0]),
     52			le32_to_cpu(cmd->bf_threshold_absolute_low[1]));
     53
     54	IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_high is: %d, %d\n",
     55			le32_to_cpu(cmd->bf_threshold_absolute_high[0]),
     56			le32_to_cpu(cmd->bf_threshold_absolute_high[1]));
     57
     58	if (fw_has_api(&mvm->fw->ucode_capa,
     59		       IWL_UCODE_TLV_API_BEACON_FILTER_V4))
     60		len = sizeof(struct iwl_beacon_filter_cmd);
     61	else
     62		len = offsetof(struct iwl_beacon_filter_cmd,
     63			       bf_threshold_absolute_low);
     64
     65	return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, flags,
     66				    len, cmd);
     67}
     68
     69static
     70void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
     71					  struct ieee80211_vif *vif,
     72					  struct iwl_beacon_filter_cmd *cmd)
     73{
     74	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
     75
     76	if (vif->bss_conf.cqm_rssi_thold) {
     77		cmd->bf_energy_delta =
     78			cpu_to_le32(vif->bss_conf.cqm_rssi_hyst);
     79		/* fw uses an absolute value for this */
     80		cmd->bf_roaming_state =
     81			cpu_to_le32(-vif->bss_conf.cqm_rssi_thold);
     82	}
     83	cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->bf_data.ba_enabled);
     84}
     85
     86static void iwl_mvm_power_log(struct iwl_mvm *mvm,
     87			      struct iwl_mac_power_cmd *cmd)
     88{
     89	IWL_DEBUG_POWER(mvm,
     90			"Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
     91			cmd->id_and_color, iwlmvm_mod_params.power_scheme,
     92			le16_to_cpu(cmd->flags));
     93	IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n",
     94			le16_to_cpu(cmd->keep_alive_seconds));
     95
     96	if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) {
     97		IWL_DEBUG_POWER(mvm, "Disable power management\n");
     98		return;
     99	}
    100
    101	IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
    102			le32_to_cpu(cmd->rx_data_timeout));
    103	IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
    104			le32_to_cpu(cmd->tx_data_timeout));
    105	if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
    106		IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
    107				cmd->skip_dtim_periods);
    108	if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
    109		IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
    110				cmd->lprx_rssi_threshold);
    111	if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
    112		IWL_DEBUG_POWER(mvm, "uAPSD enabled\n");
    113		IWL_DEBUG_POWER(mvm, "Rx timeout (uAPSD) = %u usec\n",
    114				le32_to_cpu(cmd->rx_data_timeout_uapsd));
    115		IWL_DEBUG_POWER(mvm, "Tx timeout (uAPSD) = %u usec\n",
    116				le32_to_cpu(cmd->tx_data_timeout_uapsd));
    117		IWL_DEBUG_POWER(mvm, "QNDP TID = %d\n", cmd->qndp_tid);
    118		IWL_DEBUG_POWER(mvm, "ACs flags = 0x%x\n", cmd->uapsd_ac_flags);
    119		IWL_DEBUG_POWER(mvm, "Max SP = %d\n", cmd->uapsd_max_sp);
    120	}
    121}
    122
    123static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
    124					  struct ieee80211_vif *vif,
    125					  struct iwl_mac_power_cmd *cmd)
    126{
    127	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    128	enum ieee80211_ac_numbers ac;
    129	bool tid_found = false;
    130
    131	if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ||
    132	    cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
    133		cmd->rx_data_timeout_uapsd =
    134			cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
    135		cmd->tx_data_timeout_uapsd =
    136			cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
    137	} else {
    138		cmd->rx_data_timeout_uapsd =
    139			cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
    140		cmd->tx_data_timeout_uapsd =
    141			cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
    142	}
    143
    144#ifdef CONFIG_IWLWIFI_DEBUGFS
    145	/* set advanced pm flag with no uapsd ACs to enable ps-poll */
    146	if (mvmvif->dbgfs_pm.use_ps_poll) {
    147		cmd->flags |= cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
    148		return;
    149	}
    150#endif
    151
    152	for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
    153		if (!mvmvif->queue_params[ac].uapsd)
    154			continue;
    155
    156		if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
    157			cmd->flags |=
    158				cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
    159
    160		cmd->uapsd_ac_flags |= BIT(ac);
    161
    162		/* QNDP TID - the highest TID with no admission control */
    163		if (!tid_found && !mvmvif->queue_params[ac].acm) {
    164			tid_found = true;
    165			switch (ac) {
    166			case IEEE80211_AC_VO:
    167				cmd->qndp_tid = 6;
    168				break;
    169			case IEEE80211_AC_VI:
    170				cmd->qndp_tid = 5;
    171				break;
    172			case IEEE80211_AC_BE:
    173				cmd->qndp_tid = 0;
    174				break;
    175			case IEEE80211_AC_BK:
    176				cmd->qndp_tid = 1;
    177				break;
    178			}
    179		}
    180	}
    181
    182	cmd->flags |= cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK);
    183
    184	if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
    185				    BIT(IEEE80211_AC_VI) |
    186				    BIT(IEEE80211_AC_BE) |
    187				    BIT(IEEE80211_AC_BK))) {
    188		cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
    189		cmd->snooze_interval = cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL);
    190		cmd->snooze_window =
    191			test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ?
    192				cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) :
    193				cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW);
    194	}
    195
    196	cmd->uapsd_max_sp = mvm->hw->uapsd_max_sp_len;
    197
    198	if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
    199		cmd->heavy_tx_thld_packets =
    200			IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS;
    201		cmd->heavy_rx_thld_packets =
    202			IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS;
    203	} else {
    204		cmd->heavy_tx_thld_packets =
    205			IWL_MVM_PS_HEAVY_TX_THLD_PACKETS;
    206		cmd->heavy_rx_thld_packets =
    207			IWL_MVM_PS_HEAVY_RX_THLD_PACKETS;
    208	}
    209	cmd->heavy_tx_thld_percentage =
    210		IWL_MVM_PS_HEAVY_TX_THLD_PERCENT;
    211	cmd->heavy_rx_thld_percentage =
    212		IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
    213}
    214
    215static void iwl_mvm_p2p_standalone_iterator(void *_data, u8 *mac,
    216					    struct ieee80211_vif *vif)
    217{
    218	bool *is_p2p_standalone = _data;
    219
    220	switch (ieee80211_vif_type_p2p(vif)) {
    221	case NL80211_IFTYPE_P2P_GO:
    222	case NL80211_IFTYPE_AP:
    223		*is_p2p_standalone = false;
    224		break;
    225	case NL80211_IFTYPE_STATION:
    226		if (vif->bss_conf.assoc)
    227			*is_p2p_standalone = false;
    228		break;
    229
    230	default:
    231		break;
    232	}
    233}
    234
    235static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
    236				       struct ieee80211_vif *vif)
    237{
    238	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    239
    240	if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
    241		    ETH_ALEN))
    242		return false;
    243
    244	/*
    245	 * Avoid using uAPSD if P2P client is associated to GO that uses
    246	 * opportunistic power save. This is due to current FW limitation.
    247	 */
    248	if (vif->p2p &&
    249	    (vif->bss_conf.p2p_noa_attr.oppps_ctwindow &
    250	    IEEE80211_P2P_OPPPS_ENABLE_BIT))
    251		return false;
    252
    253	/*
    254	 * Avoid using uAPSD if client is in DCM -
    255	 * low latency issue in Miracast
    256	 */
    257	if (iwl_mvm_phy_ctx_count(mvm) >= 2)
    258		return false;
    259
    260	if (vif->p2p) {
    261		/* Allow U-APSD only if p2p is stand alone */
    262		bool is_p2p_standalone = true;
    263
    264		if (!iwl_mvm_is_p2p_scm_uapsd_supported(mvm))
    265			return false;
    266
    267		ieee80211_iterate_active_interfaces_atomic(mvm->hw,
    268					IEEE80211_IFACE_ITER_NORMAL,
    269					iwl_mvm_p2p_standalone_iterator,
    270					&is_p2p_standalone);
    271
    272		if (!is_p2p_standalone)
    273			return false;
    274	}
    275
    276	return true;
    277}
    278
    279static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
    280{
    281	struct ieee80211_chanctx_conf *chanctx_conf;
    282	struct ieee80211_channel *chan;
    283	bool radar_detect = false;
    284
    285	rcu_read_lock();
    286	chanctx_conf = rcu_dereference(vif->chanctx_conf);
    287	WARN_ON(!chanctx_conf);
    288	if (chanctx_conf) {
    289		chan = chanctx_conf->def.chan;
    290		radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
    291	}
    292	rcu_read_unlock();
    293
    294	return radar_detect;
    295}
    296
    297static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm,
    298					   struct ieee80211_vif *vif,
    299					   struct iwl_mac_power_cmd *cmd)
    300{
    301	int dtimper = vif->bss_conf.dtim_period ?: 1;
    302	int skip;
    303
    304	/* disable, in case we're supposed to override */
    305	cmd->skip_dtim_periods = 0;
    306	cmd->flags &= ~cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
    307
    308	if (iwl_mvm_power_is_radar(vif))
    309		return;
    310
    311	if (dtimper >= 10)
    312		return;
    313
    314	if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) {
    315		if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP)
    316			return;
    317		skip = 2;
    318	} else {
    319		int dtimper_tu = dtimper * vif->bss_conf.beacon_int;
    320
    321		if (WARN_ON(!dtimper_tu))
    322			return;
    323		/* configure skip over dtim up to 306TU - 314 msec */
    324		skip = max_t(u8, 1, 306 / dtimper_tu);
    325	}
    326
    327	/* the firmware really expects "look at every X DTIMs", so add 1 */
    328	cmd->skip_dtim_periods = 1 + skip;
    329	cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
    330}
    331
    332static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
    333				    struct ieee80211_vif *vif,
    334				    struct iwl_mac_power_cmd *cmd)
    335{
    336	int dtimper, bi;
    337	int keep_alive;
    338	struct iwl_mvm_vif *mvmvif __maybe_unused =
    339		iwl_mvm_vif_from_mac80211(vif);
    340
    341	cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
    342							    mvmvif->color));
    343	dtimper = vif->bss_conf.dtim_period;
    344	bi = vif->bss_conf.beacon_int;
    345
    346	/*
    347	 * Regardless of power management state the driver must set
    348	 * keep alive period. FW will use it for sending keep alive NDPs
    349	 * immediately after association. Check that keep alive period
    350	 * is at least 3 * DTIM
    351	 */
    352	keep_alive = DIV_ROUND_UP(ieee80211_tu_to_usec(3 * dtimper * bi),
    353				  USEC_PER_SEC);
    354	keep_alive = max(keep_alive, POWER_KEEP_ALIVE_PERIOD_SEC);
    355	cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
    356
    357	if (mvm->ps_disabled)
    358		return;
    359
    360	cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
    361
    362	if (!vif->bss_conf.ps || !mvmvif->pm_enabled)
    363		return;
    364
    365	if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
    366	    (!fw_has_capa(&mvm->fw->ucode_capa,
    367			 IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) ||
    368	     !IWL_MVM_P2P_LOWLATENCY_PS_ENABLE))
    369		return;
    370
    371	cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
    372
    373	if (vif->bss_conf.beacon_rate &&
    374	    (vif->bss_conf.beacon_rate->bitrate == 10 ||
    375	     vif->bss_conf.beacon_rate->bitrate == 60)) {
    376		cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
    377		cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
    378	}
    379
    380	iwl_mvm_power_config_skip_dtim(mvm, vif, cmd);
    381
    382	if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) {
    383		cmd->rx_data_timeout =
    384			cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
    385		cmd->tx_data_timeout =
    386			cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
    387	} else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
    388		   fw_has_capa(&mvm->fw->ucode_capa,
    389			       IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) {
    390		cmd->tx_data_timeout =
    391			cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT);
    392		cmd->rx_data_timeout =
    393			cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT);
    394	} else {
    395		cmd->rx_data_timeout =
    396			cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
    397		cmd->tx_data_timeout =
    398			cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
    399	}
    400
    401	if (iwl_mvm_power_allow_uapsd(mvm, vif))
    402		iwl_mvm_power_configure_uapsd(mvm, vif, cmd);
    403
    404#ifdef CONFIG_IWLWIFI_DEBUGFS
    405	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
    406		cmd->keep_alive_seconds =
    407			cpu_to_le16(mvmvif->dbgfs_pm.keep_alive_seconds);
    408	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
    409		if (mvmvif->dbgfs_pm.skip_over_dtim)
    410			cmd->flags |=
    411				cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
    412		else
    413			cmd->flags &=
    414				cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
    415	}
    416	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
    417		cmd->rx_data_timeout =
    418			cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
    419	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
    420		cmd->tx_data_timeout =
    421			cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
    422	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
    423		cmd->skip_dtim_periods = mvmvif->dbgfs_pm.skip_dtim_periods;
    424	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
    425		if (mvmvif->dbgfs_pm.lprx_ena)
    426			cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
    427		else
    428			cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
    429	}
    430	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
    431		cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold;
    432	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SNOOZE_ENABLE) {
    433		if (mvmvif->dbgfs_pm.snooze_ena)
    434			cmd->flags |=
    435				cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
    436		else
    437			cmd->flags &=
    438				cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK);
    439	}
    440	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_UAPSD_MISBEHAVING) {
    441		u16 flag = POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK;
    442		if (mvmvif->dbgfs_pm.uapsd_misbehaving)
    443			cmd->flags |= cpu_to_le16(flag);
    444		else
    445			cmd->flags &= cpu_to_le16(flag);
    446	}
    447#endif /* CONFIG_IWLWIFI_DEBUGFS */
    448}
    449
    450static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
    451					 struct ieee80211_vif *vif)
    452{
    453	struct iwl_mac_power_cmd cmd = {};
    454
    455	iwl_mvm_power_build_cmd(mvm, vif, &cmd);
    456	iwl_mvm_power_log(mvm, &cmd);
    457#ifdef CONFIG_IWLWIFI_DEBUGFS
    458	memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));
    459#endif
    460
    461	return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, 0,
    462				    sizeof(cmd), &cmd);
    463}
    464
    465int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
    466{
    467	struct iwl_device_power_cmd cmd = {
    468		.flags = 0,
    469	};
    470
    471	if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
    472		mvm->ps_disabled = true;
    473
    474	if (!mvm->ps_disabled)
    475		cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
    476
    477#ifdef CONFIG_IWLWIFI_DEBUGFS
    478	if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ?
    479			mvm->disable_power_off_d3 : mvm->disable_power_off)
    480		cmd.flags &=
    481			cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
    482#endif
    483	if (mvm->ext_clock_valid)
    484		cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK);
    485
    486	IWL_DEBUG_POWER(mvm,
    487			"Sending device power command with flags = 0x%X\n",
    488			cmd.flags);
    489
    490	return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, 0, sizeof(cmd),
    491				    &cmd);
    492}
    493
    494void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
    495{
    496	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    497
    498	if (memcmp(vif->bss_conf.bssid, mvmvif->uapsd_misbehaving_bssid,
    499		   ETH_ALEN))
    500		eth_zero_addr(mvmvif->uapsd_misbehaving_bssid);
    501}
    502
    503static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
    504						     struct ieee80211_vif *vif)
    505{
    506	u8 *ap_sta_id = _data;
    507	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    508
    509	/* The ap_sta_id is not expected to change during current association
    510	 * so no explicit protection is needed
    511	 */
    512	if (mvmvif->ap_sta_id == *ap_sta_id)
    513		memcpy(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
    514		       ETH_ALEN);
    515}
    516
    517void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
    518					      struct iwl_rx_cmd_buffer *rxb)
    519{
    520	struct iwl_rx_packet *pkt = rxb_addr(rxb);
    521	struct iwl_uapsd_misbehaving_ap_notif *notif = (void *)pkt->data;
    522	u8 ap_sta_id = le32_to_cpu(notif->sta_id);
    523
    524	ieee80211_iterate_active_interfaces_atomic(
    525		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
    526		iwl_mvm_power_uapsd_misbehav_ap_iterator, &ap_sta_id);
    527}
    528
    529struct iwl_power_vifs {
    530	struct iwl_mvm *mvm;
    531	struct ieee80211_vif *bss_vif;
    532	struct ieee80211_vif *p2p_vif;
    533	struct ieee80211_vif *ap_vif;
    534	struct ieee80211_vif *monitor_vif;
    535	bool p2p_active;
    536	bool bss_active;
    537	bool ap_active;
    538	bool monitor_active;
    539};
    540
    541static void iwl_mvm_power_disable_pm_iterator(void *_data, u8* mac,
    542					      struct ieee80211_vif *vif)
    543{
    544	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    545
    546	mvmvif->pm_enabled = false;
    547}
    548
    549static void iwl_mvm_power_ps_disabled_iterator(void *_data, u8* mac,
    550					       struct ieee80211_vif *vif)
    551{
    552	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    553	bool *disable_ps = _data;
    554
    555	if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX)
    556		*disable_ps |= mvmvif->ps_disabled;
    557}
    558
    559static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
    560					    struct ieee80211_vif *vif)
    561{
    562	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    563	struct iwl_power_vifs *power_iterator = _data;
    564	bool active = mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX;
    565
    566	if (!mvmvif->uploaded)
    567		return;
    568
    569	switch (ieee80211_vif_type_p2p(vif)) {
    570	case NL80211_IFTYPE_P2P_DEVICE:
    571		break;
    572
    573	case NL80211_IFTYPE_P2P_GO:
    574	case NL80211_IFTYPE_AP:
    575		/* only a single MAC of the same type */
    576		WARN_ON(power_iterator->ap_vif);
    577		power_iterator->ap_vif = vif;
    578		if (active)
    579			power_iterator->ap_active = true;
    580		break;
    581
    582	case NL80211_IFTYPE_MONITOR:
    583		/* only a single MAC of the same type */
    584		WARN_ON(power_iterator->monitor_vif);
    585		power_iterator->monitor_vif = vif;
    586		if (active)
    587			power_iterator->monitor_active = true;
    588		break;
    589
    590	case NL80211_IFTYPE_P2P_CLIENT:
    591		/* only a single MAC of the same type */
    592		WARN_ON(power_iterator->p2p_vif);
    593		power_iterator->p2p_vif = vif;
    594		if (active)
    595			power_iterator->p2p_active = true;
    596		break;
    597
    598	case NL80211_IFTYPE_STATION:
    599		power_iterator->bss_vif = vif;
    600		if (active)
    601			power_iterator->bss_active = true;
    602		break;
    603
    604	default:
    605		break;
    606	}
    607}
    608
    609static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
    610				 struct iwl_power_vifs *vifs)
    611{
    612	struct iwl_mvm_vif *bss_mvmvif = NULL;
    613	struct iwl_mvm_vif *p2p_mvmvif = NULL;
    614	struct iwl_mvm_vif *ap_mvmvif = NULL;
    615	bool client_same_channel = false;
    616	bool ap_same_channel = false;
    617
    618	lockdep_assert_held(&mvm->mutex);
    619
    620	/* set pm_enable to false */
    621	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
    622					IEEE80211_IFACE_ITER_NORMAL,
    623					iwl_mvm_power_disable_pm_iterator,
    624					NULL);
    625
    626	if (vifs->bss_vif)
    627		bss_mvmvif = iwl_mvm_vif_from_mac80211(vifs->bss_vif);
    628
    629	if (vifs->p2p_vif)
    630		p2p_mvmvif = iwl_mvm_vif_from_mac80211(vifs->p2p_vif);
    631
    632	if (vifs->ap_vif)
    633		ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
    634
    635	/* don't allow PM if any TDLS stations exist */
    636	if (iwl_mvm_tdls_sta_count(mvm, NULL))
    637		return;
    638
    639	/* enable PM on bss if bss stand alone */
    640	if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) {
    641		bss_mvmvif->pm_enabled = true;
    642		return;
    643	}
    644
    645	/* enable PM on p2p if p2p stand alone */
    646	if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) {
    647		p2p_mvmvif->pm_enabled = true;
    648		return;
    649	}
    650
    651	if (vifs->bss_active && vifs->p2p_active)
    652		client_same_channel = (bss_mvmvif->phy_ctxt->id ==
    653				       p2p_mvmvif->phy_ctxt->id);
    654	if (vifs->bss_active && vifs->ap_active)
    655		ap_same_channel = (bss_mvmvif->phy_ctxt->id ==
    656				   ap_mvmvif->phy_ctxt->id);
    657
    658	/* clients are not stand alone: enable PM if DCM */
    659	if (!(client_same_channel || ap_same_channel)) {
    660		if (vifs->bss_active)
    661			bss_mvmvif->pm_enabled = true;
    662		if (vifs->p2p_active)
    663			p2p_mvmvif->pm_enabled = true;
    664		return;
    665	}
    666
    667	/*
    668	 * There is only one channel in the system and there are only
    669	 * bss and p2p clients that share it
    670	 */
    671	if (client_same_channel && !vifs->ap_active) {
    672		/* share same channel*/
    673		bss_mvmvif->pm_enabled = true;
    674		p2p_mvmvif->pm_enabled = true;
    675	}
    676}
    677
    678#ifdef CONFIG_IWLWIFI_DEBUGFS
    679int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
    680				 struct ieee80211_vif *vif, char *buf,
    681				 int bufsz)
    682{
    683	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    684	struct iwl_mac_power_cmd cmd = {};
    685	int pos = 0;
    686
    687	mutex_lock(&mvm->mutex);
    688	memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd));
    689	mutex_unlock(&mvm->mutex);
    690
    691	pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
    692			 iwlmvm_mod_params.power_scheme);
    693	pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
    694			 le16_to_cpu(cmd.flags));
    695	pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
    696			 le16_to_cpu(cmd.keep_alive_seconds));
    697
    698	if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)))
    699		return pos;
    700
    701	pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
    702			 (cmd.flags &
    703			 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? 1 : 0);
    704	pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
    705			 cmd.skip_dtim_periods);
    706	if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
    707		pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
    708				 le32_to_cpu(cmd.rx_data_timeout));
    709		pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
    710				 le32_to_cpu(cmd.tx_data_timeout));
    711	}
    712	if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
    713		pos += scnprintf(buf+pos, bufsz-pos,
    714				 "lprx_rssi_threshold = %d\n",
    715				 cmd.lprx_rssi_threshold);
    716
    717	if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)))
    718		return pos;
    719
    720	pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout_uapsd = %d\n",
    721			 le32_to_cpu(cmd.rx_data_timeout_uapsd));
    722	pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout_uapsd = %d\n",
    723			 le32_to_cpu(cmd.tx_data_timeout_uapsd));
    724	pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n", cmd.qndp_tid);
    725	pos += scnprintf(buf+pos, bufsz-pos, "uapsd_ac_flags = 0x%x\n",
    726			 cmd.uapsd_ac_flags);
    727	pos += scnprintf(buf+pos, bufsz-pos, "uapsd_max_sp = %d\n",
    728			 cmd.uapsd_max_sp);
    729	pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_packets = %d\n",
    730			 cmd.heavy_tx_thld_packets);
    731	pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_packets = %d\n",
    732			 cmd.heavy_rx_thld_packets);
    733	pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_percentage = %d\n",
    734			 cmd.heavy_tx_thld_percentage);
    735	pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_percentage = %d\n",
    736			 cmd.heavy_rx_thld_percentage);
    737	pos += scnprintf(buf+pos, bufsz-pos, "uapsd_misbehaving_enable = %d\n",
    738			 (cmd.flags &
    739			  cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK)) ?
    740			 1 : 0);
    741
    742	if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)))
    743		return pos;
    744
    745	pos += scnprintf(buf+pos, bufsz-pos, "snooze_interval = %d\n",
    746			 cmd.snooze_interval);
    747	pos += scnprintf(buf+pos, bufsz-pos, "snooze_window = %d\n",
    748			 cmd.snooze_window);
    749
    750	return pos;
    751}
    752
    753void
    754iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
    755					 struct iwl_beacon_filter_cmd *cmd)
    756{
    757	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    758	struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
    759
    760	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
    761		cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta);
    762	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
    763		cmd->bf_roaming_energy_delta =
    764				cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta);
    765	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
    766		cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state);
    767	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD)
    768		cmd->bf_temp_threshold =
    769				cpu_to_le32(dbgfs_bf->bf_temp_threshold);
    770	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER)
    771		cmd->bf_temp_fast_filter =
    772				cpu_to_le32(dbgfs_bf->bf_temp_fast_filter);
    773	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER)
    774		cmd->bf_temp_slow_filter =
    775				cpu_to_le32(dbgfs_bf->bf_temp_slow_filter);
    776	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
    777		cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag);
    778	if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
    779		cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
    780	if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
    781		cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
    782	if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
    783		cmd->ba_enable_beacon_abort =
    784				cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort);
    785}
    786#endif
    787
    788static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
    789					 struct ieee80211_vif *vif,
    790					 struct iwl_beacon_filter_cmd *cmd,
    791					 u32 cmd_flags)
    792{
    793	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    794	int ret;
    795
    796	if (mvmvif != mvm->bf_allowed_vif || !vif->bss_conf.dtim_period ||
    797	    vif->type != NL80211_IFTYPE_STATION || vif->p2p)
    798		return 0;
    799
    800	iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd);
    801	iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
    802	ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags);
    803
    804	if (!ret)
    805		mvmvif->bf_data.bf_enabled = true;
    806
    807	return ret;
    808}
    809
    810int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
    811				 struct ieee80211_vif *vif,
    812				 u32 flags)
    813{
    814	struct iwl_beacon_filter_cmd cmd = {
    815		IWL_BF_CMD_CONFIG_DEFAULTS,
    816		.bf_enable_beacon_filter = cpu_to_le32(1),
    817	};
    818
    819	return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags);
    820}
    821
    822static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
    823					  struct ieee80211_vif *vif,
    824					  u32 flags)
    825{
    826	struct iwl_beacon_filter_cmd cmd = {};
    827	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    828	int ret;
    829
    830	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
    831		return 0;
    832
    833	ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags);
    834
    835	if (!ret)
    836		mvmvif->bf_data.bf_enabled = false;
    837
    838	return ret;
    839}
    840
    841int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
    842				  struct ieee80211_vif *vif,
    843				  u32 flags)
    844{
    845	return _iwl_mvm_disable_beacon_filter(mvm, vif, flags);
    846}
    847
    848static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm)
    849{
    850	bool disable_ps;
    851	int ret;
    852
    853	/* disable PS if CAM */
    854	disable_ps = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);
    855	/* ...or if any of the vifs require PS to be off */
    856	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
    857					IEEE80211_IFACE_ITER_NORMAL,
    858					iwl_mvm_power_ps_disabled_iterator,
    859					&disable_ps);
    860
    861	/* update device power state if it has changed */
    862	if (mvm->ps_disabled != disable_ps) {
    863		bool old_ps_disabled = mvm->ps_disabled;
    864
    865		mvm->ps_disabled = disable_ps;
    866		ret = iwl_mvm_power_update_device(mvm);
    867		if (ret) {
    868			mvm->ps_disabled = old_ps_disabled;
    869			return ret;
    870		}
    871	}
    872
    873	return 0;
    874}
    875
    876static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
    877				struct ieee80211_vif *vif)
    878{
    879	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    880	struct iwl_beacon_filter_cmd cmd = {
    881		IWL_BF_CMD_CONFIG_DEFAULTS,
    882		.bf_enable_beacon_filter = cpu_to_le32(1),
    883	};
    884
    885	if (!mvmvif->bf_data.bf_enabled)
    886		return 0;
    887
    888	if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
    889		cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
    890
    891	mvmvif->bf_data.ba_enabled = !(!mvmvif->pm_enabled ||
    892				       mvm->ps_disabled ||
    893				       !vif->bss_conf.ps ||
    894				       iwl_mvm_vif_low_latency(mvmvif));
    895
    896	return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0);
    897}
    898
    899int iwl_mvm_power_update_ps(struct iwl_mvm *mvm)
    900{
    901	struct iwl_power_vifs vifs = {
    902		.mvm = mvm,
    903	};
    904	int ret;
    905
    906	lockdep_assert_held(&mvm->mutex);
    907
    908	/* get vifs info */
    909	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
    910					IEEE80211_IFACE_ITER_NORMAL,
    911					iwl_mvm_power_get_vifs_iterator, &vifs);
    912
    913	ret = iwl_mvm_power_set_ps(mvm);
    914	if (ret)
    915		return ret;
    916
    917	if (vifs.bss_vif)
    918		return iwl_mvm_power_set_ba(mvm, vifs.bss_vif);
    919
    920	return 0;
    921}
    922
    923int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
    924{
    925	struct iwl_power_vifs vifs = {
    926		.mvm = mvm,
    927	};
    928	int ret;
    929
    930	lockdep_assert_held(&mvm->mutex);
    931
    932	/* get vifs info */
    933	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
    934					IEEE80211_IFACE_ITER_NORMAL,
    935					iwl_mvm_power_get_vifs_iterator, &vifs);
    936
    937	iwl_mvm_power_set_pm(mvm, &vifs);
    938
    939	ret = iwl_mvm_power_set_ps(mvm);
    940	if (ret)
    941		return ret;
    942
    943	if (vifs.bss_vif) {
    944		ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);
    945		if (ret)
    946			return ret;
    947	}
    948
    949	if (vifs.p2p_vif) {
    950		ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif);
    951		if (ret)
    952			return ret;
    953	}
    954
    955	if (vifs.bss_vif)
    956		return iwl_mvm_power_set_ba(mvm, vifs.bss_vif);
    957
    958	return 0;
    959}