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 (12086B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/******************************************************************************
      3 *
      4 * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
      5 * Copyright (C) 2019 Intel Corporation
      6 *
      7 * Portions of this file are derived from the ipw3945 project, as well
      8 * as portions of the ieee80211 subsystem header files.
      9 *****************************************************************************/
     10
     11
     12#include <linux/kernel.h>
     13#include <linux/module.h>
     14#include <linux/slab.h>
     15#include <net/mac80211.h>
     16#include "iwl-io.h"
     17#include "iwl-debug.h"
     18#include "iwl-trans.h"
     19#include "iwl-modparams.h"
     20#include "dev.h"
     21#include "agn.h"
     22#include "commands.h"
     23#include "power.h"
     24
     25static bool force_cam = true;
     26module_param(force_cam, bool, 0644);
     27MODULE_PARM_DESC(force_cam, "force continuously aware mode (no power saving at all)");
     28
     29/*
     30 * Setting power level allows the card to go to sleep when not busy.
     31 *
     32 * We calculate a sleep command based on the required latency, which
     33 * we get from mac80211. In order to handle thermal throttling, we can
     34 * also use pre-defined power levels.
     35 */
     36
     37/*
     38 * This defines the old power levels. They are still used by default
     39 * (level 1) and for thermal throttle (levels 3 through 5)
     40 */
     41
     42struct iwl_power_vec_entry {
     43	struct iwl_powertable_cmd cmd;
     44	u8 no_dtim;	/* number of skip dtim */
     45};
     46
     47#define IWL_DTIM_RANGE_0_MAX	2
     48#define IWL_DTIM_RANGE_1_MAX	10
     49
     50#define NOSLP cpu_to_le16(0), 0, 0
     51#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
     52#define ASLP (IWL_POWER_POWER_SAVE_ENA_MSK |	\
     53		IWL_POWER_POWER_MANAGEMENT_ENA_MSK | \
     54		IWL_POWER_ADVANCE_PM_ENA_MSK)
     55#define ASLP_TOUT(T) cpu_to_le32(T)
     56#define TU_TO_USEC 1024
     57#define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC)
     58#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \
     59				     cpu_to_le32(X1), \
     60				     cpu_to_le32(X2), \
     61				     cpu_to_le32(X3), \
     62				     cpu_to_le32(X4)}
     63/* default power management (not Tx power) table values */
     64/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */
     65/* DTIM 0 - 2 */
     66static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
     67	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 1, 2, 2, 0xFF)}, 0},
     68	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
     69	{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0},
     70	{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1},
     71	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 2, 4, 6, 0xFF)}, 2}
     72};
     73
     74
     75/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
     76/* DTIM 3 - 10 */
     77static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
     78	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
     79	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
     80	{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0},
     81	{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1},
     82	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 6, 10, 10)}, 2}
     83};
     84
     85/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
     86/* DTIM 11 - */
     87static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
     88	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
     89	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
     90	{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
     91	{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
     92	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
     93};
     94
     95/* advance power management */
     96/* DTIM 0 - 2 */
     97static const struct iwl_power_vec_entry apm_range_0[IWL_POWER_NUM] = {
     98	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
     99		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
    100	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    101		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
    102	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    103		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
    104	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    105		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
    106	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    107		SLP_VEC(1, 2, 6, 8, 0xFF), ASLP_TOUT(2)}, 2}
    108};
    109
    110
    111/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
    112/* DTIM 3 - 10 */
    113static const struct iwl_power_vec_entry apm_range_1[IWL_POWER_NUM] = {
    114	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    115		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
    116	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    117		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
    118	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    119		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
    120	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    121		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
    122	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    123		SLP_VEC(1, 2, 6, 8, 0xFF), 0}, 2}
    124};
    125
    126/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
    127/* DTIM 11 - */
    128static const struct iwl_power_vec_entry apm_range_2[IWL_POWER_NUM] = {
    129	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    130		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
    131	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    132		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
    133	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    134		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
    135	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    136		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
    137	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
    138		SLP_VEC(1, 2, 6, 8, 0xFF), ASLP_TOUT(2)}, 2}
    139};
    140
    141static void iwl_static_sleep_cmd(struct iwl_priv *priv,
    142				 struct iwl_powertable_cmd *cmd,
    143				 enum iwl_power_level lvl, int period)
    144{
    145	const struct iwl_power_vec_entry *table;
    146	int max_sleep[IWL_POWER_VEC_SIZE] = { 0 };
    147	int i;
    148	u8 skip;
    149	u32 slp_itrvl;
    150
    151	if (priv->lib->adv_pm) {
    152		table = apm_range_2;
    153		if (period <= IWL_DTIM_RANGE_1_MAX)
    154			table = apm_range_1;
    155		if (period <= IWL_DTIM_RANGE_0_MAX)
    156			table = apm_range_0;
    157	} else {
    158		table = range_2;
    159		if (period <= IWL_DTIM_RANGE_1_MAX)
    160			table = range_1;
    161		if (period <= IWL_DTIM_RANGE_0_MAX)
    162			table = range_0;
    163	}
    164
    165	if (WARN_ON(lvl < 0 || lvl >= IWL_POWER_NUM))
    166		memset(cmd, 0, sizeof(*cmd));
    167	else
    168		*cmd = table[lvl].cmd;
    169
    170	if (period == 0) {
    171		skip = 0;
    172		period = 1;
    173		for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
    174			max_sleep[i] =  1;
    175
    176	} else {
    177		skip = table[lvl].no_dtim;
    178		for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
    179			max_sleep[i] = le32_to_cpu(cmd->sleep_interval[i]);
    180		max_sleep[IWL_POWER_VEC_SIZE - 1] = skip + 1;
    181	}
    182
    183	slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
    184	/* figure out the listen interval based on dtim period and skip */
    185	if (slp_itrvl == 0xFF)
    186		cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
    187			cpu_to_le32(period * (skip + 1));
    188
    189	slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
    190	if (slp_itrvl > period)
    191		cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
    192			cpu_to_le32((slp_itrvl / period) * period);
    193
    194	if (skip)
    195		cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
    196	else
    197		cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
    198
    199	if (priv->trans->trans_cfg->base_params->shadow_reg_enable)
    200		cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
    201	else
    202		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
    203
    204	if (iwl_advanced_bt_coexist(priv)) {
    205		if (!priv->lib->bt_params->bt_sco_disable)
    206			cmd->flags |= IWL_POWER_BT_SCO_ENA;
    207		else
    208			cmd->flags &= ~IWL_POWER_BT_SCO_ENA;
    209	}
    210
    211
    212	slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
    213	if (slp_itrvl > IWL_CONN_MAX_LISTEN_INTERVAL)
    214		cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
    215			cpu_to_le32(IWL_CONN_MAX_LISTEN_INTERVAL);
    216
    217	/* enforce max sleep interval */
    218	for (i = IWL_POWER_VEC_SIZE - 1; i >= 0 ; i--) {
    219		if (le32_to_cpu(cmd->sleep_interval[i]) >
    220		    (max_sleep[i] * period))
    221			cmd->sleep_interval[i] =
    222				cpu_to_le32(max_sleep[i] * period);
    223		if (i != (IWL_POWER_VEC_SIZE - 1)) {
    224			if (le32_to_cpu(cmd->sleep_interval[i]) >
    225			    le32_to_cpu(cmd->sleep_interval[i+1]))
    226				cmd->sleep_interval[i] =
    227					cmd->sleep_interval[i+1];
    228		}
    229	}
    230
    231	if (priv->power_data.bus_pm)
    232		cmd->flags |= IWL_POWER_PCI_PM_MSK;
    233	else
    234		cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
    235
    236	IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n",
    237			skip, period);
    238	/* The power level here is 0-4 (used as array index), but user expects
    239	to see 1-5 (according to spec). */
    240	IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
    241}
    242
    243static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
    244				    struct iwl_powertable_cmd *cmd)
    245{
    246	memset(cmd, 0, sizeof(*cmd));
    247
    248	if (priv->power_data.bus_pm)
    249		cmd->flags |= IWL_POWER_PCI_PM_MSK;
    250
    251	IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
    252}
    253
    254static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
    255{
    256	IWL_DEBUG_POWER(priv, "Sending power/sleep command\n");
    257	IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags);
    258	IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
    259	IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout));
    260	IWL_DEBUG_POWER(priv, "Sleep interval vector = { %d , %d , %d , %d , %d }\n",
    261			le32_to_cpu(cmd->sleep_interval[0]),
    262			le32_to_cpu(cmd->sleep_interval[1]),
    263			le32_to_cpu(cmd->sleep_interval[2]),
    264			le32_to_cpu(cmd->sleep_interval[3]),
    265			le32_to_cpu(cmd->sleep_interval[4]));
    266
    267	return iwl_dvm_send_cmd_pdu(priv, POWER_TABLE_CMD, 0,
    268				sizeof(struct iwl_powertable_cmd), cmd);
    269}
    270
    271static void iwl_power_build_cmd(struct iwl_priv *priv,
    272				struct iwl_powertable_cmd *cmd)
    273{
    274	bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
    275	int dtimper;
    276
    277	if (force_cam) {
    278		iwl_power_sleep_cam_cmd(priv, cmd);
    279		return;
    280	}
    281
    282	dtimper = priv->hw->conf.ps_dtim_period ?: 1;
    283
    284	if (priv->wowlan)
    285		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
    286	else if (!priv->lib->no_idle_support &&
    287		 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
    288		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
    289	else if (iwl_tt_is_low_power_state(priv)) {
    290		/* in thermal throttling low power state */
    291		iwl_static_sleep_cmd(priv, cmd,
    292		    iwl_tt_current_power_mode(priv), dtimper);
    293	} else if (!enabled)
    294		iwl_power_sleep_cam_cmd(priv, cmd);
    295	else if (priv->power_data.debug_sleep_level_override >= 0)
    296		iwl_static_sleep_cmd(priv, cmd,
    297				     priv->power_data.debug_sleep_level_override,
    298				     dtimper);
    299	else {
    300		/* Note that the user parameter is 1-5 (according to spec),
    301		but we pass 0-4 because it acts as an array index. */
    302		if (iwlwifi_mod_params.power_level > IWL_POWER_INDEX_1 &&
    303		    iwlwifi_mod_params.power_level <= IWL_POWER_NUM)
    304			iwl_static_sleep_cmd(priv, cmd,
    305				iwlwifi_mod_params.power_level - 1, dtimper);
    306		else
    307			iwl_static_sleep_cmd(priv, cmd,
    308				IWL_POWER_INDEX_1, dtimper);
    309	}
    310}
    311
    312int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
    313		       bool force)
    314{
    315	int ret;
    316	bool update_chains;
    317
    318	lockdep_assert_held(&priv->mutex);
    319
    320	/* Don't update the RX chain when chain noise calibration is running */
    321	update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
    322			priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
    323
    324	if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
    325		return 0;
    326
    327	if (!iwl_is_ready_rf(priv))
    328		return -EIO;
    329
    330	/* scan complete use sleep_power_next, need to be updated */
    331	memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
    332	if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
    333		IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
    334		return 0;
    335	}
    336
    337	if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
    338		iwl_dvm_set_pmi(priv, true);
    339
    340	ret = iwl_set_power(priv, cmd);
    341	if (!ret) {
    342		if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
    343			iwl_dvm_set_pmi(priv, false);
    344
    345		if (update_chains)
    346			iwl_update_chain_flags(priv);
    347		else
    348			IWL_DEBUG_POWER(priv,
    349					"Cannot update the power, chain noise "
    350					"calibration running: %d\n",
    351					priv->chain_noise_data.state);
    352
    353		memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd));
    354	} else
    355		IWL_ERR(priv, "set power fail, ret = %d\n", ret);
    356
    357	return ret;
    358}
    359
    360int iwl_power_update_mode(struct iwl_priv *priv, bool force)
    361{
    362	struct iwl_powertable_cmd cmd;
    363
    364	iwl_power_build_cmd(priv, &cmd);
    365	return iwl_power_set_mode(priv, &cmd, force);
    366}
    367
    368/* initialize to default */
    369void iwl_power_initialize(struct iwl_priv *priv)
    370{
    371	priv->power_data.bus_pm = priv->trans->pm_support;
    372
    373	priv->power_data.debug_sleep_level_override = -1;
    374
    375	memset(&priv->power_data.sleep_cmd, 0,
    376		sizeof(priv->power_data.sleep_cmd));
    377}