iwl-power.c revision a96a27f97f2bbfc1fca54bc3c0b0d41484152740
15da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/****************************************************************************** 25da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 35da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Copyright(c) 2007 - 2008 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: 255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * James P. Ketrenos <ipw2100-admin@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" 395a36ba0e412a0e12a8bf2648a075226c1dd7870dTomas Winkler#include "iwl-commands.h" 405da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-debug.h" 415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-power.h" 425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-helpers.h" 435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* 455da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Setting power level allow the card to go to sleep when not busy 465da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * there are three factor that decide the power level to go to, they 475da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * are list here with its priority 485da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 1- critical_power_setting this will be set according to card temperature. 495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 2- system_power_setting this will be set by system PM manager. 505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 3- user_power_setting this will be set by user either by writing to sys or 515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * mac80211 525da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 535da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * if system_power_setting and user_power_setting is set to auto 545da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * the power level will be decided according to association status and battery 555da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * status. 565da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 575da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 585da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 595da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define MSEC_TO_USEC 1024 605da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_RANGE_0_MAX (2) 615da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_RANGE_1_MAX (10) 625da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 635da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 645da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define NOSLP __constant_cpu_to_le16(0), 0, 0 655da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 665da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define SLP_TOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC) 675da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \ 685da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas __constant_cpu_to_le32(X1), \ 695da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas __constant_cpu_to_le32(X2), \ 705da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas __constant_cpu_to_le32(X3), \ 715da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas __constant_cpu_to_le32(X4)} 725da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 735da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_ON_BATTERY IWL_POWER_INDEX_5 745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_ON_AC_DISASSOC IWL_POWER_MODE_CAM 755da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_ON_AC_ASSOC IWL_POWER_MODE_CAM 765da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 775da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 785da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_CT_KILL_TEMPERATURE 110 795da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_MIN_POWER_TEMPERATURE 100 805da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_REDUCED_POWER_TEMPERATURE 95 815da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 825da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* default power management (not Tx power) table values */ 83a96a27f97f2bbfc1fca54bc3c0b0d41484152740Tomas Winkler/* for TIM 0-10 */ 84298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummerstatic struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = { 855da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, 865da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 875da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 885da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0}, 895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1}, 905da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 2, 4, 6, 0xFF)}, 2} 915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}; 925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 935da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 94a96a27f97f2bbfc1fca54bc3c0b0d41484152740Tomas Winkler/* for TIM = 3-10 */ 95298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummerstatic struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = { 965da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, 975da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, 985da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, 995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0}, 1005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1}, 1015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} 1025da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}; 1035da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 104a96a27f97f2bbfc1fca54bc3c0b0d41484152740Tomas Winkler/* for TIM > 11 */ 105298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummerstatic struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = { 1065da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, 1075da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, 1085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, 1095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, 1105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, 1115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} 1125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}; 1135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 114ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas/* set card power command */ 115ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbasstatic int iwl_set_power(struct iwl_priv *priv, void *cmd) 116ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas{ 117ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas return iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD, 118ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas sizeof(struct iwl_powertable_cmd), 119ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas cmd, NULL); 120ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas} 1215da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* decide the right power level according to association status 1225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * and battery status 1235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 1245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasstatic u16 iwl_get_auto_power_mode(struct iwl_priv *priv) 1255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 126298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer u16 mode; 1275da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas switch (priv->power_data.user_power_setting) { 1295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas case IWL_POWER_AUTO: 1305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas /* if running on battery */ 1315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (priv->power_data.is_battery_active) 1325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas mode = IWL_POWER_ON_BATTERY; 1335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else if (iwl_is_associated(priv)) 1345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas mode = IWL_POWER_ON_AC_ASSOC; 1355da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else 1365da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas mode = IWL_POWER_ON_AC_DISASSOC; 1375da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas break; 138298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer /* FIXME: remove battery and ac from here */ 1395da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas case IWL_POWER_BATTERY: 1405da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas mode = IWL_POWER_INDEX_3; 1415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas break; 1425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas case IWL_POWER_AC: 1435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas mode = IWL_POWER_MODE_CAM; 1445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas break; 145298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer default: 146298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer mode = priv->power_data.user_power_setting; 147298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer break; 1485da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 1495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return mode; 1505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 1515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1525da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* initialize to default */ 1535da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasstatic int iwl_power_init_handle(struct iwl_priv *priv) 1545da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 1555da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas struct iwl_power_mgr *pow_data; 156298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX; 157e7b635814b640c6fd9dca1c254dc22fac6fb9a1aTomas Winkler struct iwl_powertable_cmd *cmd; 158e7b635814b640c6fd9dca1c254dc22fac6fb9a1aTomas Winkler int i; 1595da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u16 pci_pm; 1605da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1615da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas IWL_DEBUG_POWER("Initialize power \n"); 1625da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1635da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas pow_data = &(priv->power_data); 1645da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1655da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas memset(pow_data, 0, sizeof(*pow_data)); 1665da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1675da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas memcpy(&pow_data->pwr_range_0[0], &range_0[0], size); 1685da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas memcpy(&pow_data->pwr_range_1[0], &range_1[0], size); 1695da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas memcpy(&pow_data->pwr_range_2[0], &range_2[0], size); 1705da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 171e7b635814b640c6fd9dca1c254dc22fac6fb9a1aTomas Winkler pci_read_config_word(priv->pci_dev, PCI_CFG_LINK_CTRL, &pci_pm); 1725da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 173e7b635814b640c6fd9dca1c254dc22fac6fb9a1aTomas Winkler IWL_DEBUG_POWER("adjust power command flags\n"); 1745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 175e7b635814b640c6fd9dca1c254dc22fac6fb9a1aTomas Winkler for (i = 0; i < IWL_POWER_MAX; i++) { 176e7b635814b640c6fd9dca1c254dc22fac6fb9a1aTomas Winkler cmd = &pow_data->pwr_range_0[i].cmd; 1775da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 178e7b635814b640c6fd9dca1c254dc22fac6fb9a1aTomas Winkler if (pci_pm & PCI_CFG_LINK_CTRL_VAL_L0S_EN) 179e7b635814b640c6fd9dca1c254dc22fac6fb9a1aTomas Winkler cmd->flags &= ~IWL_POWER_PCI_PM_MSK; 180e7b635814b640c6fd9dca1c254dc22fac6fb9a1aTomas Winkler else 181e7b635814b640c6fd9dca1c254dc22fac6fb9a1aTomas Winkler cmd->flags |= IWL_POWER_PCI_PM_MSK; 1825da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 183e7b635814b640c6fd9dca1c254dc22fac6fb9a1aTomas Winkler return 0; 1845da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 1855da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 186a96a27f97f2bbfc1fca54bc3c0b0d41484152740Tomas Winkler/* adjust power command according to DTIM period and power level*/ 1875da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasstatic int iwl_update_power_command(struct iwl_priv *priv, 188ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas struct iwl_powertable_cmd *cmd, 1895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u16 mode) 1905da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 1915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0, i; 1925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u8 skip; 1935da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u32 max_sleep = 0; 1945da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas struct iwl_power_vec_entry *range; 1955da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u8 period = 0; 1965da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas struct iwl_power_mgr *pow_data; 1975da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1985da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (mode > IWL_POWER_INDEX_5) { 1995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas IWL_DEBUG_POWER("Error invalid power mode \n"); 2005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return -1; 2015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 2025da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas pow_data = &(priv->power_data); 2035da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (pow_data->dtim_period <= IWL_POWER_RANGE_0_MAX) 2055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas range = &pow_data->pwr_range_0[0]; 2065da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else if (pow_data->dtim_period <= IWL_POWER_RANGE_1_MAX) 2075da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas range = &pow_data->pwr_range_1[0]; 2085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else 2095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas range = &pow_data->pwr_range_2[0]; 2105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas period = pow_data->dtim_period; 212ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd)); 2135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (period == 0) { 2155da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas period = 1; 2165da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas skip = 0; 2175da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } else 2185da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas skip = range[mode].no_dtim; 2195da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2205da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (skip == 0) { 2215da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas max_sleep = period; 2225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; 2235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } else { 2245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]; 2255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas max_sleep = le32_to_cpu(slp_itrvl); 2265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (max_sleep == 0xFF) 2275da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas max_sleep = period * (skip + 1); 2285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else if (max_sleep > period) 2295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas max_sleep = (le32_to_cpu(slp_itrvl) / period) * period; 2305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; 2315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 2325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas for (i = 0; i < IWL_POWER_VEC_SIZE; i++) { 2345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) 2355da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd->sleep_interval[i] = cpu_to_le32(max_sleep); 2365da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 2375da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2385da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags); 2395da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); 2405da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas IWL_DEBUG_POWER("Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); 2415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas IWL_DEBUG_POWER("Sleep interval vector = { %d , %d , %d , %d , %d }\n", 2425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[0]), 2435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[1]), 2445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[2]), 2455da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[3]), 2465da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[4])); 2475da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2485da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 2495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 2505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2525da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* 253a33c2f47bd4618b0483d5ec4c5bc793e6d02c1f7Emmanuel Grumbach * compute the final power mode index 2545da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 25504816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuelint iwl_power_update_mode(struct iwl_priv *priv, bool force) 2565da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 2575da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas struct iwl_power_mgr *setting = &(priv->power_data); 2585da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0; 2595da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u16 uninitialized_var(final_mode); 2605da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 26104816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel /* Don't update the RX chain when chain noise calibration is running */ 26204816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel if (priv->chain_noise_data.state != IWL_CHAIN_NOISE_DONE && 26304816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel priv->chain_noise_data.state != IWL_CHAIN_NOISE_ALIVE) { 26404816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel IWL_DEBUG_POWER("Cannot update the power, chain noise " 26504816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel "calibration running: %d\n", 26604816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel priv->chain_noise_data.state); 26704816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel return -EAGAIN; 26804816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel } 26904816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel 270a33c2f47bd4618b0483d5ec4c5bc793e6d02c1f7Emmanuel Grumbach /* If on battery, set to 3, 271a33c2f47bd4618b0483d5ec4c5bc793e6d02c1f7Emmanuel Grumbach * if plugged into AC power, set to CAM ("continuously aware mode"), 272a33c2f47bd4618b0483d5ec4c5bc793e6d02c1f7Emmanuel Grumbach * else user level */ 2735da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas switch (setting->system_power_setting) { 275298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer case IWL_POWER_SYS_AUTO: 2765da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas final_mode = iwl_get_auto_power_mode(priv); 2775da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas break; 278298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer case IWL_POWER_SYS_BATTERY: 2795da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas final_mode = IWL_POWER_INDEX_3; 2805da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas break; 281298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer case IWL_POWER_SYS_AC: 2825da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas final_mode = IWL_POWER_MODE_CAM; 2835da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas break; 2845da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas default: 285298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer final_mode = IWL_POWER_INDEX_3; 286298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer WARN_ON(1); 2875da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 2885da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (setting->critical_power_setting > final_mode) 2905da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas final_mode = setting->critical_power_setting; 2915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas /* driver only support CAM for non STA network */ 29305c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg if (priv->iw_mode != NL80211_IFTYPE_STATION) 2945da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas final_mode = IWL_POWER_MODE_CAM; 2955da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2965da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (!iwl_is_rfkill(priv) && !setting->power_disabled && 29704816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel ((setting->power_mode != final_mode) || force)) { 298ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas struct iwl_powertable_cmd cmd; 2995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (final_mode != IWL_POWER_MODE_CAM) 3015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas set_bit(STATUS_POWER_PMI, &priv->status); 3025da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3035da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas iwl_update_power_command(priv, &cmd, final_mode); 3045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd.keep_alive_beacons = 0; 3055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3065da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (final_mode == IWL_POWER_INDEX_5) 3075da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd.flags |= IWL_POWER_FAST_PD; 3085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 309ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas ret = iwl_set_power(priv, &cmd); 3105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (final_mode == IWL_POWER_MODE_CAM) 3125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas clear_bit(STATUS_POWER_PMI, &priv->status); 3135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else 3145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas set_bit(STATUS_POWER_PMI, &priv->status); 3155da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3165da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (priv->cfg->ops->lib->update_chain_flags) 3175da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->cfg->ops->lib->update_chain_flags(priv); 3185da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3195da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (!ret) 3205da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas setting->power_mode = final_mode; 3215da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 3225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 3245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 3255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_update_mode); 3265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3275da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* Allow other iwl code to disable/enable power management active 328a96a27f97f2bbfc1fca54bc3c0b0d41484152740Tomas Winkler * this will be useful for rate scale to disable PM during heavy 3295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Tx/Rx activities 3305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 331c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbachint iwl_power_disable_management(struct iwl_priv *priv, u32 ms) 3325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 3335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u16 prev_mode; 3345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0; 3355da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3365da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (priv->power_data.power_disabled) 3375da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return -EBUSY; 3385da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3395da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas prev_mode = priv->power_data.user_power_setting; 3405da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.user_power_setting = IWL_POWER_MODE_CAM; 3415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas ret = iwl_power_update_mode(priv, 0); 3425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.power_disabled = 1; 3435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.user_power_setting = prev_mode; 344c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach cancel_delayed_work(&priv->set_power_save); 345c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach if (ms) 346c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach queue_delayed_work(priv->workqueue, &priv->set_power_save, 347c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach msecs_to_jiffies(ms)); 348c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach 3495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 3515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 3525da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_disable_management); 3535da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3545da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* Allow other iwl code to disable/enable power management active 355a96a27f97f2bbfc1fca54bc3c0b0d41484152740Tomas Winkler * this will be useful for rate scale to disable PM during high 356a96a27f97f2bbfc1fca54bc3c0b0d41484152740Tomas Winkler * volume activities 3575da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 3585da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_enable_management(struct iwl_priv *priv) 3595da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 3605da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0; 3615da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3625da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.power_disabled = 0; 3635da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas ret = iwl_power_update_mode(priv, 0); 3645da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 3655da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 3665da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_enable_management); 3675da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3685da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* set user_power_setting */ 3695da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode) 3705da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 3715da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (mode > IWL_POWER_LIMIT) 3725da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return -EINVAL; 3735da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.user_power_setting = mode; 3755da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 37604816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel return iwl_power_update_mode(priv, 0); 3775da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 3785da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_set_user_mode); 3795da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3805da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* set system_power_setting. This should be set by over all 3815da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * PM application. 3825da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 3835da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode) 3845da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 3855da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (mode > IWL_POWER_LIMIT) 3865da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return -EINVAL; 3875da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3885da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.system_power_setting = mode; 3895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 39004816448d8b77551834c9ea01e407ef5f0042f0fGrumbach, Emmanuel return iwl_power_update_mode(priv, 0); 3915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 3925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_set_system_mode); 3935da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 394a96a27f97f2bbfc1fca54bc3c0b0d41484152740Tomas Winkler/* initialize to default */ 3955da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasvoid iwl_power_initialize(struct iwl_priv *priv) 3965da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 3975da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3985da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas iwl_power_init_handle(priv); 3995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.user_power_setting = IWL_POWER_AUTO; 4005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.power_disabled = 0; 401298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO; 4025da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.is_battery_active = 0; 4035da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.power_disabled = 0; 4045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.critical_power_setting = 0; 4055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 4065da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_initialize); 4075da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 4085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* set critical_power_setting according to temperature value */ 4095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_temperature_change(struct iwl_priv *priv) 4105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 4115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0; 4125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u16 new_critical = priv->power_data.critical_power_setting; 4135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas s32 temperature = KELVIN_TO_CELSIUS(priv->last_temperature); 4145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 4155da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (temperature > IWL_CT_KILL_TEMPERATURE) 4165da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return 0; 4175da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else if (temperature > IWL_MIN_POWER_TEMPERATURE) 4185da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas new_critical = IWL_POWER_INDEX_5; 4195da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else if (temperature > IWL_REDUCED_POWER_TEMPERATURE) 4205da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas new_critical = IWL_POWER_INDEX_3; 4215da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else 4225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas new_critical = IWL_POWER_MODE_CAM; 4235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 4245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (new_critical != priv->power_data.critical_power_setting) 4255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.critical_power_setting = new_critical; 4265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 4275da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (priv->power_data.critical_power_setting > 4285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.power_mode) 4295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas ret = iwl_power_update_mode(priv, 0); 4305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 4315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 4325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 4335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_temperature_change); 434c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach 435c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbachstatic void iwl_bg_set_power_save(struct work_struct *work) 436c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach{ 437c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach struct iwl_priv *priv = container_of(work, 438c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach struct iwl_priv, set_power_save.work); 439c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach IWL_DEBUG(IWL_DL_STATE, "update power\n"); 440c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach 441c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 442c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach return; 443c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach 444c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach mutex_lock(&priv->mutex); 445c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach 446a96a27f97f2bbfc1fca54bc3c0b0d41484152740Tomas Winkler /* on starting association we disable power management 447c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach * until association, if association failed then this 448c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach * timer will expire and enable PM again. 449c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach */ 450c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach if (!iwl_is_associated(priv)) 451c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach iwl_power_enable_management(priv); 452c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach 453c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach mutex_unlock(&priv->mutex); 454c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach} 455c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbachvoid iwl_setup_power_deferred_work(struct iwl_priv *priv) 456c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach{ 457c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach INIT_DELAYED_WORK(&priv->set_power_save, iwl_bg_set_power_save); 458c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach} 459c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel GrumbachEXPORT_SYMBOL(iwl_setup_power_deferred_work); 460c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach 461c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbachvoid iwl_power_cancel_timeout(struct iwl_priv *priv) 462c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach{ 463c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach cancel_delayed_work(&priv->set_power_save); 464c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel Grumbach} 465c90a74bae10dc2a4677d1bd06b6400db229d3e1eEmmanuel GrumbachEXPORT_SYMBOL(iwl_power_cancel_timeout); 466