iwl-power.c revision 570af86e0ab7e7b42b2562ff3209c16ab1ebd5f8
15da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/****************************************************************************** 25da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 301f8162a854df7f9c259c839ad3c1168ac13b7b8Reinette Chatre * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. 45da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 55da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Portions of this file are derived from the ipw3945 project, as well 65da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * as portions of the ieee80211 subsystem header files. 75da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 85da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * This program is free software; you can redistribute it and/or modify it 95da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * under the terms of version 2 of the GNU General Public License as 105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * published by the Free Software Foundation. 115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * This program is distributed in the hope that it will be useful, but WITHOUT 135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 155da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * more details. 165da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 175da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * You should have received a copy of the GNU General Public License along with 185da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * this program; if not, write to the Free Software Foundation, Inc., 195da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 205da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 215da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * The full GNU General Public License is included in this distribution in the 225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * file called LICENSE. 235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Contact Information: 25759ef89fb096c4a6ef078d3cfd5682ac037bd789Winkler, Tomas * Intel Linux Wireless <ilw@linux.intel.com> 265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 275da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas *****************************************************************************/ 285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include <linux/kernel.h> 315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include <linux/module.h> 325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include <linux/init.h> 335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include <net/mac80211.h> 355da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 365da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-eeprom.h" 373e0d4cb12f6fd97193a455b49125398b2231c87cTomas Winkler#include "iwl-dev.h" 385da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-core.h" 3939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy#include "iwl-io.h" 405a36ba0e412a0e12a8bf2648a075226c1dd7870dTomas Winkler#include "iwl-commands.h" 415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-debug.h" 425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-power.h" 435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* 45e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * Setting power level allows the card to go to sleep when not busy. 465da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 47e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * We calculate a sleep command based on the required latency, which 48e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * we get from mac80211. In order to handle thermal throttling, we can 49e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * also use pre-defined power levels. 505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 52e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg/* 53e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * For now, keep using power level 1 instead of automatically 54e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * adjusting ... 55e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg */ 56e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Bergbool no_sleep_autoadjust = true; 57e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Bergmodule_param(no_sleep_autoadjust, bool, S_IRUGO); 58e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes BergMODULE_PARM_DESC(no_sleep_autoadjust, 59e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg "don't automatically adjust sleep level " 60e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg "according to maximum network latency"); 615da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 62e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg/* 63e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * This defines the old power levels. They are still used by default 64e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * (level 1) and for thermal throttle (levels 3 through 5) 65e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg */ 66e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 67e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Bergstruct iwl_power_vec_entry { 68e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg struct iwl_powertable_cmd cmd; 694ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy u8 no_dtim; /* number of skip dtim */ 70e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg}; 71e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 72e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg#define IWL_DTIM_RANGE_0_MAX 2 73e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg#define IWL_DTIM_RANGE_1_MAX 10 745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 757af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Berg#define NOSLP cpu_to_le16(0), 0, 0 767af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Berg#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 777af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Berg#define TU_TO_USEC 1024 787af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Berg#define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC) 797af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Berg#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \ 807af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Berg cpu_to_le32(X1), \ 817af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Berg cpu_to_le32(X2), \ 827af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Berg cpu_to_le32(X3), \ 837af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Berg cpu_to_le32(X4)} 845da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* default power management (not Tx power) table values */ 85e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */ 864ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy/* DTIM 0 - 2 */ 877af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Bergstatic const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { 884ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 1, 2, 2, 0xFF)}, 0}, 895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 905da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0}, 915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1}, 925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 2, 4, 6, 0xFF)}, 2} 935da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}; 945da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 955da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 96e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */ 974ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy/* DTIM 3 - 10 */ 987af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Bergstatic const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = { 995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, 1005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, 1015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0}, 1025da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1}, 1034ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 6, 10, 10)}, 2} 1045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}; 1055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 106e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg/* for DTIM period > IWL_DTIM_RANGE_1_MAX */ 1074ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy/* DTIM 11 - */ 1087af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Bergstatic const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { 1095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, 1105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, 1115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, 1125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, 1135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} 1145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}; 1155da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 116e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Bergstatic void iwl_static_sleep_cmd(struct iwl_priv *priv, 117e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg struct iwl_powertable_cmd *cmd, 118e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg enum iwl_power_level lvl, int period) 119e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg{ 120e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg const struct iwl_power_vec_entry *table; 1214ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy int max_sleep[IWL_POWER_VEC_SIZE] = { 0 }; 1224ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy int i; 1234ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy u8 skip; 1244ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy u32 slp_itrvl; 125e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 126e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg table = range_2; 1274ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy if (period <= IWL_DTIM_RANGE_1_MAX) 128e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg table = range_1; 1294ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy if (period <= IWL_DTIM_RANGE_0_MAX) 130e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg table = range_0; 131e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 132e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); 133e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 134e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg *cmd = table[lvl].cmd; 135e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 136e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg if (period == 0) { 1374ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy skip = 0; 138e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg period = 1; 1394ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy for (i = 0; i < IWL_POWER_VEC_SIZE; i++) 1404ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy max_sleep[i] = 1; 1414ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy 142e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg } else { 1434ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy skip = table[lvl].no_dtim; 1444ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy for (i = 0; i < IWL_POWER_VEC_SIZE; i++) 1454ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy max_sleep[i] = le32_to_cpu(cmd->sleep_interval[i]); 1464ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy max_sleep[IWL_POWER_VEC_SIZE - 1] = skip + 1; 147e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg } 148e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 1494ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]); 1504ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy /* figure out the listen interval based on dtim period and skip */ 1514ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy if (slp_itrvl == 0xFF) 1524ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] = 1534ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy cpu_to_le32(period * (skip + 1)); 1544ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy 1554ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]); 1564ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy if (slp_itrvl > period) 1574ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] = 1584ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy cpu_to_le32((slp_itrvl / period) * period); 1594ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy 1604ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy if (skip) 161e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; 1624ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy else 163e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; 164e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 1654ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]); 166570af86e0ab7e7b42b2562ff3209c16ab1ebd5f8Wey-Yi Guy if (slp_itrvl > IWL_CONN_MAX_LISTEN_INTERVAL) 1674ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] = 168570af86e0ab7e7b42b2562ff3209c16ab1ebd5f8Wey-Yi Guy cpu_to_le32(IWL_CONN_MAX_LISTEN_INTERVAL); 1694ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy 1704ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy /* enforce max sleep interval */ 1714ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy for (i = IWL_POWER_VEC_SIZE - 1; i >= 0 ; i--) { 1724ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy if (le32_to_cpu(cmd->sleep_interval[i]) > 1734ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy (max_sleep[i] * period)) 1744ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy cmd->sleep_interval[i] = 1754ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy cpu_to_le32(max_sleep[i] * period); 1764ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy if (i != (IWL_POWER_VEC_SIZE - 1)) { 1774ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy if (le32_to_cpu(cmd->sleep_interval[i]) > 1784ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy le32_to_cpu(cmd->sleep_interval[i+1])) 1794ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy cmd->sleep_interval[i] = 1804ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy cmd->sleep_interval[i+1]; 1814ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy } 1824ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy } 183e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 184e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg if (priv->power_data.pci_pm) 185e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg cmd->flags |= IWL_POWER_PCI_PM_MSK; 186e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg else 187e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg cmd->flags &= ~IWL_POWER_PCI_PM_MSK; 188e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 1894ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n", 1904ad177b5c860dc0b1083eccc55957daf4a116b90Wey-Yi Guy skip, period); 191e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); 192e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg} 193e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 19446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy/* default Thermal Throttling transaction table 19546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * Current state | Throttling Down | Throttling Up 19646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy *============================================================================= 19746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * Condition Nxt State Condition Nxt State Condition Nxt State 19846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy *----------------------------------------------------------------------------- 1997812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A 2007812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 2017812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 20246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 20346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy *============================================================================= 20446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy */ 20546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guystatic const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { 20646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, 2077812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1}, 2087812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} 20946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy}; 21046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guystatic const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { 21146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, 2127812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1}, 2137812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} 21446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy}; 21546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guystatic const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { 21646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, 2177812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}, 2187812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} 21946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy}; 22046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guystatic const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { 22146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, 22246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, 22346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX} 22446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy}; 22546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 22646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy/* Advance Thermal Throttling default restriction table */ 22746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guystatic const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = { 2283ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true }, 2293ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true }, 2303ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false }, 2313ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false } 23246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy}; 233d25aabb0a1a2f659206ba21f6ac8ec28047e5595Winkler, Tomas 2345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 235e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Bergstatic void iwl_power_sleep_cam_cmd(struct iwl_priv *priv, 236e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg struct iwl_powertable_cmd *cmd) 2375da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 238e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg memset(cmd, 0, sizeof(*cmd)); 2395da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 240e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg if (priv->power_data.pci_pm) 241e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg cmd->flags |= IWL_POWER_PCI_PM_MSK; 2425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 243e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg IWL_DEBUG_POWER(priv, "Sleep command for CAM\n"); 2445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 2455da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 246e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Bergstatic void iwl_power_fill_sleep_cmd(struct iwl_priv *priv, 247e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg struct iwl_powertable_cmd *cmd, 248e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg int dynps_ms, int wakeup_period) 2495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 2504c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg /* 2514c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg * These are the original power level 3 sleep successions. The 2524c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg * device may behave better with such succession and was also 2534c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg * only tested with that. Just like the original sleep commands, 2544c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg * also adjust the succession here to the wakeup_period below. 2554c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg * The ranges are the same as for the sleep commands, 0-2, 3-9 2564c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg * and >10, which is selected based on the DTIM interval for 2574c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg * the sleep index but here we use the wakeup period since that 2584c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg * is what we need to do for the latency requirements. 2594c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg */ 2604c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg static const u8 slp_succ_r0[IWL_POWER_VEC_SIZE] = { 2, 2, 2, 2, 2 }; 2614c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg static const u8 slp_succ_r1[IWL_POWER_VEC_SIZE] = { 2, 4, 6, 7, 9 }; 2624c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg static const u8 slp_succ_r2[IWL_POWER_VEC_SIZE] = { 2, 7, 9, 9, 0xFF }; 2634c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg const u8 *slp_succ = slp_succ_r0; 2645cd19c5f15f4bd3354cc7f8f8b1125018a84a25cWinkler, Tomas int i; 2655da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2664c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg if (wakeup_period > IWL_DTIM_RANGE_0_MAX) 2674c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg slp_succ = slp_succ_r1; 2684c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg if (wakeup_period > IWL_DTIM_RANGE_1_MAX) 2694c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg slp_succ = slp_succ_r2; 2704c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg 271e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg memset(cmd, 0, sizeof(*cmd)); 2725cd19c5f15f4bd3354cc7f8f8b1125018a84a25cWinkler, Tomas 273e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK | 274e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg IWL_POWER_FAST_PD; /* no use seeing frames for others */ 2755da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 276e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg if (priv->power_data.pci_pm) 277e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg cmd->flags |= IWL_POWER_PCI_PM_MSK; 2785da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 279e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg cmd->rx_data_timeout = cpu_to_le32(1000 * dynps_ms); 280e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms); 2815da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2825cd19c5f15f4bd3354cc7f8f8b1125018a84a25cWinkler, Tomas for (i = 0; i < IWL_POWER_VEC_SIZE; i++) 2834c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg cmd->sleep_interval[i] = 2844c561a02291326c50f9b1f647eae891af9d1f3b2Johannes Berg cpu_to_le32(min_t(int, slp_succ[i], wakeup_period)); 285e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 286e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg IWL_DEBUG_POWER(priv, "Automatic sleep command\n"); 287e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg} 2885da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 289e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Bergstatic int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) 290e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg{ 291e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg IWL_DEBUG_POWER(priv, "Sending power/sleep command\n"); 292e1623446bb1de1834ff1c57b3e8ed341d5d4a927Tomas Winkler IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags); 293e1623446bb1de1834ff1c57b3e8ed341d5d4a927Tomas Winkler IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); 294e1623446bb1de1834ff1c57b3e8ed341d5d4a927Tomas Winkler IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); 295e1623446bb1de1834ff1c57b3e8ed341d5d4a927Tomas Winkler IWL_DEBUG_POWER(priv, "Sleep interval vector = { %d , %d , %d , %d , %d }\n", 2965da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[0]), 2975da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[1]), 2985da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[2]), 2995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[3]), 3005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[4])); 3015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 302e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, 303e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg sizeof(struct iwl_powertable_cmd), cmd); 3045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 3055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3065da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 30704816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuelint iwl_power_update_mode(struct iwl_priv *priv, bool force) 3085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 3095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0; 3103ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 311e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) && 312e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg (priv->hw->conf.flags & IEEE80211_CONF_PS); 313a71c8f62d46e4496011182658dc058303960c068Winkler, Tomas bool update_chains; 314e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg struct iwl_powertable_cmd cmd; 315e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg int dtimper; 3165da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 31704816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel /* Don't update the RX chain when chain noise calibration is running */ 318a71c8f62d46e4496011182658dc058303960c068Winkler, Tomas update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || 319a71c8f62d46e4496011182658dc058303960c068Winkler, Tomas priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; 32004816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel 321e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg if (priv->vif) 322e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg dtimper = priv->vif->bss_conf.dtim_period; 323e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg else 324e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg dtimper = 1; 325e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 326559a4741b8a5b4551b8c7e8e0de7f3e41a79bb5aJohannes Berg if (priv->cfg->broken_powersave) 327559a4741b8a5b4551b8c7e8e0de7f3e41a79bb5aJohannes Berg iwl_power_sleep_cam_cmd(priv, &cmd); 32878f5fb7fc6c2c668a12fd6892c18baa20e4ffd27Johannes Berg else if (priv->cfg->supports_idle && 32978f5fb7fc6c2c668a12fd6892c18baa20e4ffd27Johannes Berg priv->hw->conf.flags & IEEE80211_CONF_IDLE) 33078f5fb7fc6c2c668a12fd6892c18baa20e4ffd27Johannes Berg iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); 331559a4741b8a5b4551b8c7e8e0de7f3e41a79bb5aJohannes Berg else if (tt->state >= IWL_TI_1) 332e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); 333e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg else if (!enabled) 334e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg iwl_power_sleep_cam_cmd(priv, &cmd); 335e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg else if (priv->power_data.debug_sleep_level_override >= 0) 336e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg iwl_static_sleep_cmd(priv, &cmd, 337e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg priv->power_data.debug_sleep_level_override, 338e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg dtimper); 339e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg else if (no_sleep_autoadjust) 340e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper); 341e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg else 342e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg iwl_power_fill_sleep_cmd(priv, &cmd, 343e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg priv->hw->conf.dynamic_ps_timeout, 344e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg priv->hw->conf.max_sleep_period); 3455da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3467af2c460789a78d9c0d4dc7776fcb87acdc71052Johannes Berg if (iwl_is_ready_rf(priv) && 347e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg (memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) { 348e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) 3495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas set_bit(STATUS_POWER_PMI, &priv->status); 3505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 351ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas ret = iwl_set_power(priv, &cmd); 3523a780d25428a0a391a8ba6c888cf4e89ac3fdbb1Wey-Yi Guy if (!ret) { 353e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) 3543a780d25428a0a391a8ba6c888cf4e89ac3fdbb1Wey-Yi Guy clear_bit(STATUS_POWER_PMI, &priv->status); 3553a780d25428a0a391a8ba6c888cf4e89ac3fdbb1Wey-Yi Guy 3563a780d25428a0a391a8ba6c888cf4e89ac3fdbb1Wey-Yi Guy if (priv->cfg->ops->lib->update_chain_flags && 3573a780d25428a0a391a8ba6c888cf4e89ac3fdbb1Wey-Yi Guy update_chains) 3583a780d25428a0a391a8ba6c888cf4e89ac3fdbb1Wey-Yi Guy priv->cfg->ops->lib->update_chain_flags(priv); 359b57d46aa0db87b6349737e7b110ebe48ee14c143Reinette Chatre else if (priv->cfg->ops->lib->update_chain_flags) 3603a780d25428a0a391a8ba6c888cf4e89ac3fdbb1Wey-Yi Guy IWL_DEBUG_POWER(priv, 3613a780d25428a0a391a8ba6c888cf4e89ac3fdbb1Wey-Yi Guy "Cannot update the power, chain noise " 362a71c8f62d46e4496011182658dc058303960c068Winkler, Tomas "calibration running: %d\n", 363a71c8f62d46e4496011182658dc058303960c068Winkler, Tomas priv->chain_noise_data.state); 364e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)); 3653a780d25428a0a391a8ba6c888cf4e89ac3fdbb1Wey-Yi Guy } else 3663a780d25428a0a391a8ba6c888cf4e89ac3fdbb1Wey-Yi Guy IWL_ERR(priv, "set power fail, ret = %d", ret); 3675da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 3685da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3695da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 3705da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 3715da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_update_mode); 3725da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 37346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guybool iwl_ht_enabled(struct iwl_priv *priv) 37446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy{ 3753ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 37646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy struct iwl_tt_restriction *restriction; 37746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 3783ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg if (!priv->thermal_throttle.advanced_tt) 37946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy return true; 38046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy restriction = tt->restriction + tt->state; 38146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy return restriction->is_ht; 38246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy} 38346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi GuyEXPORT_SYMBOL(iwl_ht_enabled); 38446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 3857812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guybool iwl_within_ct_kill_margin(struct iwl_priv *priv) 3867812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy{ 3877812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ 3887812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy bool within_margin = false; 3897812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy 3907812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) 3917812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy temp = KELVIN_TO_CELSIUS(priv->temperature); 3927812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy 3937812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if (!priv->thermal_throttle.advanced_tt) 3947812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= 3957812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy CT_KILL_THRESHOLD_LEGACY) ? true : false; 3967812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy else 3977812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= 3987812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy CT_KILL_THRESHOLD) ? true : false; 3997812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy return within_margin; 4007812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy} 4017812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy 4023ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Bergenum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) 40346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy{ 4043ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 40546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy struct iwl_tt_restriction *restriction; 40646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 4073ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg if (!priv->thermal_throttle.advanced_tt) 4083ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg return IWL_ANT_OK_MULTI; 40946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy restriction = tt->restriction + tt->state; 41046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy return restriction->tx_stream; 41146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy} 41246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi GuyEXPORT_SYMBOL(iwl_tx_ant_restriction); 41346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 4143ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Bergenum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv) 41546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy{ 4163ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 41746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy struct iwl_tt_restriction *restriction; 41846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 4193ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg if (!priv->thermal_throttle.advanced_tt) 4203ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg return IWL_ANT_OK_MULTI; 42146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy restriction = tt->restriction + tt->state; 42246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy return restriction->rx_stream; 42346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy} 42446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 42539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ 4267812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy#define CT_KILL_WAITING_DURATION (300) /* 300ms duration */ 42739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 42839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy/* 42939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * toggle the bit to wake up uCode and check the temperature 43039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * if the temperature is below CT, uCode will stay awake and send card 43139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * state notification with CT_KILL bit clear to inform Thermal Throttling 43239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * Management to change state. Otherwise, uCode will go back to sleep 43339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * without doing anything, driver should continue the 5 seconds timer 43439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * to wake up uCode for temperature check until temperature drop below CT 43539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy */ 43639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guystatic void iwl_tt_check_exit_ct_kill(unsigned long data) 43739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy{ 43839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy struct iwl_priv *priv = (struct iwl_priv *)data; 4393ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 44039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy unsigned long flags; 44139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 44239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 44339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy return; 44439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 44539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if (tt->state == IWL_TI_CT_KILL) { 4463ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg if (priv->thermal_throttle.ct_kill_toggle) { 44739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, 44839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); 4493ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg priv->thermal_throttle.ct_kill_toggle = false; 45039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy } else { 45139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, 45239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); 4533ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg priv->thermal_throttle.ct_kill_toggle = true; 45439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy } 45539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy iwl_read32(priv, CSR_UCODE_DRV_GP1); 45639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy spin_lock_irqsave(&priv->reg_lock, flags); 45739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if (!iwl_grab_nic_access(priv)) 45839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy iwl_release_nic_access(priv); 45939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy spin_unlock_irqrestore(&priv->reg_lock, flags); 46039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 46139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy /* Reschedule the ct_kill timer to occur in 46239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * CT_KILL_EXIT_DURATION seconds to ensure we get a 46339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * thermal update */ 4647812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n"); 4653ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + 46639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy CT_KILL_EXIT_DURATION * HZ); 46739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy } 46839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy} 46939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 47039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guystatic void iwl_perform_ct_kill_task(struct iwl_priv *priv, 47139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy bool stop) 47239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy{ 47339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if (stop) { 47439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy IWL_DEBUG_POWER(priv, "Stop all queues\n"); 47539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if (priv->mac80211_registered) 47639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy ieee80211_stop_queues(priv->hw); 47739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy IWL_DEBUG_POWER(priv, 47839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy "Schedule 5 seconds CT_KILL Timer\n"); 4793ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + 48039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy CT_KILL_EXIT_DURATION * HZ); 48139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy } else { 48239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy IWL_DEBUG_POWER(priv, "Wake all queues\n"); 48339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if (priv->mac80211_registered) 48439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy ieee80211_wake_queues(priv->hw); 48539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy } 48639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy} 48739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 4887812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guystatic void iwl_tt_ready_for_ct_kill(unsigned long data) 4897812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy{ 4907812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy struct iwl_priv *priv = (struct iwl_priv *)data; 4917812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 4927812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy 4937812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 4947812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy return; 4957812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy 4967812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy /* temperature timer expired, ready to go into CT_KILL state */ 4977812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if (tt->state != IWL_TI_CT_KILL) { 4987812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n"); 4997812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy tt->state = IWL_TI_CT_KILL; 5007812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy set_bit(STATUS_CT_KILL, &priv->status); 5017812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_perform_ct_kill_task(priv, true); 5027812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy } 5037812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy} 5047812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy 5057812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guystatic void iwl_prepare_ct_kill_task(struct iwl_priv *priv) 5067812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy{ 5077812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); 5087812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy /* make request to retrieve statistics information */ 5097812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_send_statistics_request(priv, 0); 5107812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy /* Reschedule the ct_kill wait timer */ 5117812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, 5127812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); 5137812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy} 5147812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy 51539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) 51639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) 51739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) 51839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 51939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy/* 52039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * Legacy thermal throttling 52139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * 1) Avoid NIC destruction due to high temperatures 52239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * Chip will identify dangerously high temperatures that can 52339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * harm the device and will power down 52439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * 2) Avoid the NIC power down due to high temperature 52539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * Throttle early enough to lower the power consumption before 52639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * drastic steps are needed 52739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy */ 5287812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guystatic void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) 52939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy{ 5303ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 531ee9f29894fc3819c1bd639fc3a886326bb809266Wey-Yi Guy enum iwl_tt_state old_state; 53239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 53339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy#ifdef CONFIG_IWLWIFI_DEBUG 53439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if ((tt->tt_previous_temp) && 53539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy (temp > tt->tt_previous_temp) && 53639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy ((temp - tt->tt_previous_temp) > 53739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy IWL_TT_INCREASE_MARGIN)) { 53839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy IWL_DEBUG_POWER(priv, 53939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy "Temperature increase %d degree Celsius\n", 54039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy (temp - tt->tt_previous_temp)); 54139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy } 54239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy#endif 543ee9f29894fc3819c1bd639fc3a886326bb809266Wey-Yi Guy old_state = tt->state; 54439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy /* in Celsius */ 54539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if (temp >= IWL_MINIMAL_POWER_THRESHOLD) 546ee9f29894fc3819c1bd639fc3a886326bb809266Wey-Yi Guy tt->state = IWL_TI_CT_KILL; 54739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2) 548ee9f29894fc3819c1bd639fc3a886326bb809266Wey-Yi Guy tt->state = IWL_TI_2; 54939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1) 550ee9f29894fc3819c1bd639fc3a886326bb809266Wey-Yi Guy tt->state = IWL_TI_1; 55139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy else 552ee9f29894fc3819c1bd639fc3a886326bb809266Wey-Yi Guy tt->state = IWL_TI_0; 55339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 55439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy#ifdef CONFIG_IWLWIFI_DEBUG 55539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy tt->tt_previous_temp = temp; 55639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy#endif 5577812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy /* stop ct_kill_waiting_tm timer */ 5587812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); 559ee9f29894fc3819c1bd639fc3a886326bb809266Wey-Yi Guy if (tt->state != old_state) { 560ee9f29894fc3819c1bd639fc3a886326bb809266Wey-Yi Guy switch (tt->state) { 56139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy case IWL_TI_0: 562e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg /* 563e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * When the system is ready to go back to IWL_TI_0 564e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * we only have to call iwl_power_update_mode() to 565e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * do so. 56639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy */ 56739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy break; 56839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy case IWL_TI_1: 56939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy tt->tt_power_mode = IWL_POWER_INDEX_3; 57039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy break; 57139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy case IWL_TI_2: 57239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy tt->tt_power_mode = IWL_POWER_INDEX_4; 57339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy break; 57439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy default: 57539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy tt->tt_power_mode = IWL_POWER_INDEX_5; 57639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy break; 57739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy } 578a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy mutex_lock(&priv->mutex); 5797812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if (old_state == IWL_TI_CT_KILL) 5807812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy clear_bit(STATUS_CT_KILL, &priv->status); 5817812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if (tt->state != IWL_TI_CT_KILL && 5827812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_power_update_mode(priv, true)) { 58339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy /* TT state not updated 58439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * try again during next temperature read 58539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy */ 5867812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if (old_state == IWL_TI_CT_KILL) 5877812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy set_bit(STATUS_CT_KILL, &priv->status); 588ee9f29894fc3819c1bd639fc3a886326bb809266Wey-Yi Guy tt->state = old_state; 58939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy IWL_ERR(priv, "Cannot update power mode, " 59039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy "TT state not updated\n"); 59139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy } else { 5927812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if (tt->state == IWL_TI_CT_KILL) { 5937812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if (force) { 5947812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy set_bit(STATUS_CT_KILL, &priv->status); 5957812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_perform_ct_kill_task(priv, true); 5967812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy } else { 5977812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_prepare_ct_kill_task(priv); 5987812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy tt->state = old_state; 5997812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy } 6007812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy } else if (old_state == IWL_TI_CT_KILL && 601ee9f29894fc3819c1bd639fc3a886326bb809266Wey-Yi Guy tt->state != IWL_TI_CT_KILL) 60239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy iwl_perform_ct_kill_task(priv, false); 60339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", 60439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy tt->state); 60539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy IWL_DEBUG_POWER(priv, "Power Index change to %u\n", 60639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy tt->tt_power_mode); 60739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy } 608a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy mutex_unlock(&priv->mutex); 60939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy } 61039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy} 61139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 61246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy/* 61346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * Advance thermal throttling 61446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * 1) Avoid NIC destruction due to high temperatures 61546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * Chip will identify dangerously high temperatures that can 61646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * harm the device and will power down 61746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * 2) Avoid the NIC power down due to high temperature 61846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * Throttle early enough to lower the power consumption before 61946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * drastic steps are needed 62046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * Actions include relaxing the power down sleep thresholds and 62146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * decreasing the number of TX streams 62246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * 3) Avoid throughput performance impact as much as possible 62346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * 62446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy *============================================================================= 62546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * Condition Nxt State Condition Nxt State Condition Nxt State 62646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy *----------------------------------------------------------------------------- 6277812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A 6287812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 6297812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 63046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 63146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy *============================================================================= 63246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy */ 6337812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guystatic void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) 63446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy{ 6353ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 63646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy int i; 63746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy bool changed = false; 63846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy enum iwl_tt_state old_state; 63946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy struct iwl_tt_trans *transaction; 64046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 64146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy old_state = tt->state; 64246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) { 64346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy /* based on the current TT state, 64446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * find the curresponding transaction table 64546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * each table has (IWL_TI_STATE_MAX - 1) entries 64646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1)) 64746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * will advance to the correct table. 64846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * then based on the current temperature 64946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * find the next state need to transaction to 65046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * go through all the possible (IWL_TI_STATE_MAX - 1) entries 65146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * in the current table to see if transaction is needed 65246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy */ 65346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy transaction = tt->transaction + 65446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy ((old_state * (IWL_TI_STATE_MAX - 1)) + i); 65546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy if (temp >= transaction->tt_low && 65646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy temp <= transaction->tt_high) { 65746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy#ifdef CONFIG_IWLWIFI_DEBUG 65846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy if ((tt->tt_previous_temp) && 65946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy (temp > tt->tt_previous_temp) && 66046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy ((temp - tt->tt_previous_temp) > 66146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy IWL_TT_INCREASE_MARGIN)) { 66246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy IWL_DEBUG_POWER(priv, 66346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy "Temperature increase %d " 66446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy "degree Celsius\n", 66546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy (temp - tt->tt_previous_temp)); 66646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } 66746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->tt_previous_temp = temp; 66846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy#endif 66946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy if (old_state != 67046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy transaction->next_state) { 67146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy changed = true; 67246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->state = 67346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy transaction->next_state; 67446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } 67546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy break; 67646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } 67746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } 6787812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy /* stop ct_kill_waiting_tm timer */ 6797812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); 68046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy if (changed) { 68146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy struct iwl_rxon_cmd *rxon = &priv->staging_rxon; 68246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 68346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy if (tt->state >= IWL_TI_1) { 68446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ 68546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->tt_power_mode = IWL_POWER_INDEX_5; 68646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy if (!iwl_ht_enabled(priv)) 68746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy /* disable HT */ 68846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | 68946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | 6907aafef1c6e2e24f9a10dc2972bf0ee70624ccc47Wey-Yi Guy RXON_FLG_HT40_PROT_MSK | 69146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy RXON_FLG_HT_PROT_MSK); 69246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy else { 69346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy /* check HT capability and set 69446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * according to the system HT capability 69546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * in case get disabled before */ 69646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy iwl_set_rxon_ht(priv, &priv->current_ht_config); 69746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } 69846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 69946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } else { 700e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg /* 701e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * restore system power setting -- it will be 702e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg * recalculated automatically. 70346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy */ 704e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 70546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy /* check HT capability and set 70646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * according to the system HT capability 70746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * in case get disabled before */ 70846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy iwl_set_rxon_ht(priv, &priv->current_ht_config); 70946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } 710a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy mutex_lock(&priv->mutex); 7117812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if (old_state == IWL_TI_CT_KILL) 7127812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy clear_bit(STATUS_CT_KILL, &priv->status); 7137812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if (tt->state != IWL_TI_CT_KILL && 7147812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_power_update_mode(priv, true)) { 71546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy /* TT state not updated 71646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * try again during next temperature read 71746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy */ 71846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy IWL_ERR(priv, "Cannot update power mode, " 71946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy "TT state not updated\n"); 7207812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if (old_state == IWL_TI_CT_KILL) 7217812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy set_bit(STATUS_CT_KILL, &priv->status); 72246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->state = old_state; 72346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } else { 72446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy IWL_DEBUG_POWER(priv, 72546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy "Thermal Throttling to new state: %u\n", 72646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->state); 72746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy if (old_state != IWL_TI_CT_KILL && 72846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->state == IWL_TI_CT_KILL) { 7297812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy if (force) { 7307812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy IWL_DEBUG_POWER(priv, 7317812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy "Enter IWL_TI_CT_KILL\n"); 7327812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy set_bit(STATUS_CT_KILL, &priv->status); 7337812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_perform_ct_kill_task(priv, true); 7347812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy } else { 7357812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_prepare_ct_kill_task(priv); 7367812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy tt->state = old_state; 7377812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy } 73846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } else if (old_state == IWL_TI_CT_KILL && 73946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->state != IWL_TI_CT_KILL) { 74046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); 74146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy iwl_perform_ct_kill_task(priv, false); 74246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } 74346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } 744a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy mutex_unlock(&priv->mutex); 74546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } 74646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy} 74746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 74839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy/* Card State Notification indicated reach critical temperature 74939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * if PSP not enable, no Thermal Throttling function will be performed 75039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * just set the GP1 bit to acknowledge the event 75139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * otherwise, go into IWL_TI_CT_KILL state 75239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * since Card State Notification will not provide any temperature reading 75346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * for Legacy mode 75439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * so just pass the CT_KILL temperature to iwl_legacy_tt_handler() 75546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * for advance mode 75646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state 75739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy */ 758a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guystatic void iwl_bg_ct_enter(struct work_struct *work) 75939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy{ 760a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); 7613ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 76239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 76339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 76439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy return; 76539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 766a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy if (!iwl_is_ready(priv)) 767a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy return; 768a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy 76939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if (tt->state != IWL_TI_CT_KILL) { 77039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy IWL_ERR(priv, "Device reached critical temperature " 77139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy "- ucode going to sleep!\n"); 7723ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg if (!priv->thermal_throttle.advanced_tt) 77346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy iwl_legacy_tt_handler(priv, 7747812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy IWL_MINIMAL_POWER_THRESHOLD, 7757812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy true); 77646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy else 77746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy iwl_advance_tt_handler(priv, 7787812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy CT_KILL_THRESHOLD + 1, true); 77939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy } 78039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy} 78139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 78239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy/* Card State Notification indicated out of critical temperature 78339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * since Card State Notification will not provide any temperature reading 78439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature 78539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state 78639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy */ 787a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guystatic void iwl_bg_ct_exit(struct work_struct *work) 78839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy{ 789a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); 7903ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 79139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 79239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 79339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy return; 79439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 795a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy if (!iwl_is_ready(priv)) 796a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy return; 797a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy 79839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy /* stop ct_kill_exit_tm timer */ 7993ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); 80039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 80139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if (tt->state == IWL_TI_CT_KILL) { 80239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy IWL_ERR(priv, 80339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy "Device temperature below critical" 80439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy "- ucode awake!\n"); 8057812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy /* 8067812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy * exit from CT_KILL state 8077812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy * reset the current temperature reading 8087812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy */ 8097812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy priv->temperature = 0; 8103ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg if (!priv->thermal_throttle.advanced_tt) 81146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy iwl_legacy_tt_handler(priv, 8127812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy IWL_REDUCED_PERFORMANCE_THRESHOLD_2, 8137812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy true); 81446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy else 8157812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD, 8167812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy true); 81739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy } 81839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy} 819a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy 820a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guyvoid iwl_tt_enter_ct_kill(struct iwl_priv *priv) 821a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy{ 822a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 823a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy return; 824a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy 825a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n"); 826a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy queue_work(priv->workqueue, &priv->ct_enter); 827a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy} 828a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi GuyEXPORT_SYMBOL(iwl_tt_enter_ct_kill); 829a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy 830a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guyvoid iwl_tt_exit_ct_kill(struct iwl_priv *priv) 831a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy{ 832a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 833a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy return; 834a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy 835a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n"); 836a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy queue_work(priv->workqueue, &priv->ct_exit); 837a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy} 83839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi GuyEXPORT_SYMBOL(iwl_tt_exit_ct_kill); 83939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 840a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guystatic void iwl_bg_tt_work(struct work_struct *work) 84139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy{ 842a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); 84339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ 84439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 84539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 84639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy return; 84739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 84839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) 84939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy temp = KELVIN_TO_CELSIUS(priv->temperature); 85039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 8513ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg if (!priv->thermal_throttle.advanced_tt) 8527812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_legacy_tt_handler(priv, temp, false); 85346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy else 8547812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_advance_tt_handler(priv, temp, false); 85539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy} 856a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy 857a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guyvoid iwl_tt_handler(struct iwl_priv *priv) 858a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy{ 859a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 860a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy return; 861a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy 862a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n"); 863a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy queue_work(priv->workqueue, &priv->tt_work); 864a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy} 86539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi GuyEXPORT_SYMBOL(iwl_tt_handler); 86639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 86739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy/* Thermal throttling initialization 86846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * For advance thermal throttling: 86946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * Initialize Thermal Index and temperature threshold table 87046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy * Initialize thermal throttling restriction table 87139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy */ 87239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guyvoid iwl_tt_initialize(struct iwl_priv *priv) 87339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy{ 8743ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 87546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); 87646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy struct iwl_tt_trans *transaction; 87739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 87839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling \n"); 87939b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 88039b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy memset(tt, 0, sizeof(struct iwl_tt_mgmt)); 88139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 88239b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy tt->state = IWL_TI_0; 8833ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg init_timer(&priv->thermal_throttle.ct_kill_exit_tm); 8843ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; 8857812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy priv->thermal_throttle.ct_kill_exit_tm.function = 8867812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_tt_check_exit_ct_kill; 8877812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy init_timer(&priv->thermal_throttle.ct_kill_waiting_tm); 8887812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv; 8897812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy priv->thermal_throttle.ct_kill_waiting_tm.function = 8907812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy iwl_tt_ready_for_ct_kill; 891a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy /* setup deferred ct kill work */ 892a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy INIT_WORK(&priv->tt_work, iwl_bg_tt_work); 893a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); 894a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); 895a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy 8966047b4f939682ae9bf839fd00c80029cb8f073bbWey-Yi Guy if (priv->cfg->adv_thermal_throttle) { 89746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); 89846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * 89946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy IWL_TI_STATE_MAX, GFP_KERNEL); 90046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * 90146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1), 90246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy GFP_KERNEL); 90346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy if (!tt->restriction || !tt->transaction) { 90446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy IWL_ERR(priv, "Fallback to Legacy Throttling\n"); 9053ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg priv->thermal_throttle.advanced_tt = false; 90646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy kfree(tt->restriction); 90746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->restriction = NULL; 90846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy kfree(tt->transaction); 90946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->transaction = NULL; 91046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } else { 91146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy transaction = tt->transaction + 91246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy (IWL_TI_0 * (IWL_TI_STATE_MAX - 1)); 91346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy memcpy(transaction, &tt_range_0[0], size); 91446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy transaction = tt->transaction + 91546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy (IWL_TI_1 * (IWL_TI_STATE_MAX - 1)); 91646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy memcpy(transaction, &tt_range_1[0], size); 91746f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy transaction = tt->transaction + 91846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy (IWL_TI_2 * (IWL_TI_STATE_MAX - 1)); 91946f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy memcpy(transaction, &tt_range_2[0], size); 92046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy transaction = tt->transaction + 92146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1)); 92246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy memcpy(transaction, &tt_range_3[0], size); 92346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy size = sizeof(struct iwl_tt_restriction) * 92446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy IWL_TI_STATE_MAX; 92546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy memcpy(tt->restriction, 92646f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy &restriction_range[0], size); 9273ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg priv->thermal_throttle.advanced_tt = true; 92846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } 9296047b4f939682ae9bf839fd00c80029cb8f073bbWey-Yi Guy } else { 93046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); 9313ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg priv->thermal_throttle.advanced_tt = false; 93246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } 93339b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy} 93439b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi GuyEXPORT_SYMBOL(iwl_tt_initialize); 93539b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 93639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy/* cleanup thermal throttling management related memory and timer */ 93739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guyvoid iwl_tt_exit(struct iwl_priv *priv) 93839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy{ 9393ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 94046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 94139b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy /* stop ct_kill_exit_tm timer if activated */ 9423ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); 9437812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy /* stop ct_kill_waiting_tm timer if activated */ 9447812b16730ccebce71a3b2228ac08dd4f8b39469Wey-Yi Guy del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); 945a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy cancel_work_sync(&priv->tt_work); 946a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy cancel_work_sync(&priv->ct_enter); 947a28027cd7f169edc399fe4b76d3a33b0203049a1Wey-Yi Guy cancel_work_sync(&priv->ct_exit); 94846f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy 9493ad3b92a5517c043ef30e4b95c4c39a35bbc36beJohannes Berg if (priv->thermal_throttle.advanced_tt) { 95046f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy /* free advance thermal throttling memory */ 95146f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy kfree(tt->restriction); 95246f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->restriction = NULL; 95346f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy kfree(tt->transaction); 95446f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy tt->transaction = NULL; 95546f9381aa3fb62f6a141bfd41dcbeda1ec5fa26eWey-Yi Guy } 95639b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy} 95739b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi GuyEXPORT_SYMBOL(iwl_tt_exit); 95839b73fb15e4704fd4d1e33688135810637f5f3fbWey-Yi Guy 959a96a27f97f2bbfc1fca54bc3c0b0d41484152740Tomas Winkler/* initialize to default */ 9605da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasvoid iwl_power_initialize(struct iwl_priv *priv) 9615da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 962e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg u16 lctl = iwl_pcie_link_ctl(priv); 963e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 964e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN); 965e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 966e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg priv->power_data.debug_sleep_level_override = -1; 967e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg 968e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg memset(&priv->power_data.sleep_cmd, 0, 969e312c24cf8229f9b6e76dbfd5d99eefe21f4ac0aJohannes Berg sizeof(priv->power_data.sleep_cmd)); 9705da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 9715da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_initialize); 972