iwl-power.c revision 298df1f62aa69881528bf0f1c3c14395bc447846
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/version.h> 335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include <linux/init.h> 345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 355da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include <net/mac80211.h> 365da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 375da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-eeprom.h" 383e0d4cb12f6fd97193a455b49125398b2231c87cTomas Winkler#include "iwl-dev.h" 395da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-core.h" 405a36ba0e412a0e12a8bf2648a075226c1dd7870dTomas Winkler#include "iwl-commands.h" 415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-debug.h" 425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-power.h" 435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#include "iwl-helpers.h" 445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 455da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* 465da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Setting power level allow the card to go to sleep when not busy 475da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * there are three factor that decide the power level to go to, they 485da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * are list here with its priority 495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 1- critical_power_setting this will be set according to card temperature. 505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 2- system_power_setting this will be set by system PM manager. 515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 3- user_power_setting this will be set by user either by writing to sys or 525da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * mac80211 535da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 545da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * if system_power_setting and user_power_setting is set to auto 555da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * the power level will be decided according to association status and battery 565da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * status. 575da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * 585da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 595da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 605da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define MSEC_TO_USEC 1024 615da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_RANGE_0_MAX (2) 625da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_RANGE_1_MAX (10) 635da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 645da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 655da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define NOSLP __constant_cpu_to_le16(0), 0, 0 665da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 675da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define SLP_TOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC) 685da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \ 695da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas __constant_cpu_to_le32(X1), \ 705da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas __constant_cpu_to_le32(X2), \ 715da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas __constant_cpu_to_le32(X3), \ 725da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas __constant_cpu_to_le32(X4)} 735da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_ON_BATTERY IWL_POWER_INDEX_5 755da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_ON_AC_DISASSOC IWL_POWER_MODE_CAM 765da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_POWER_ON_AC_ASSOC IWL_POWER_MODE_CAM 775da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 785da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 795da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_CT_KILL_TEMPERATURE 110 805da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_MIN_POWER_TEMPERATURE 100 815da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas#define IWL_REDUCED_POWER_TEMPERATURE 95 825da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 835da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* default power management (not Tx power) table values */ 845da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* for tim 0-10 */ 85298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummerstatic struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = { 865da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, 875da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 885da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0}, 905da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1}, 915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 2, 4, 6, 0xFF)}, 2} 925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}; 935da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 945da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 955da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* for tim = 3-10 */ 96298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummerstatic struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = { 975da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, 985da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, 995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, 1005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0}, 1015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1}, 1025da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} 1035da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}; 1045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* for tim > 11 */ 106298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummerstatic struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = { 1075da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, 1085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, 1095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, 1105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, 1115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, 1125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} 1135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas}; 1145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 115ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas/* set card power command */ 116ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbasstatic int iwl_set_power(struct iwl_priv *priv, void *cmd) 117ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas{ 118ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas return iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD, 119ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas sizeof(struct iwl_powertable_cmd), 120ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas cmd, NULL); 121ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas} 1225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* decide the right power level according to association status 1235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * and battery status 1245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 1255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasstatic u16 iwl_get_auto_power_mode(struct iwl_priv *priv) 1265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 127298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer u16 mode; 1285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas switch (priv->power_data.user_power_setting) { 1305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas case IWL_POWER_AUTO: 1315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas /* if running on battery */ 1325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (priv->power_data.is_battery_active) 1335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas mode = IWL_POWER_ON_BATTERY; 1345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else if (iwl_is_associated(priv)) 1355da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas mode = IWL_POWER_ON_AC_ASSOC; 1365da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else 1375da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas mode = IWL_POWER_ON_AC_DISASSOC; 1385da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas break; 139298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer /* FIXME: remove battery and ac from here */ 1405da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas case IWL_POWER_BATTERY: 1415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas mode = IWL_POWER_INDEX_3; 1425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas break; 1435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas case IWL_POWER_AC: 1445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas mode = IWL_POWER_MODE_CAM; 1455da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas break; 146298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer default: 147298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer mode = priv->power_data.user_power_setting; 148298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer break; 1495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 1505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return mode; 1515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 1525da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1535da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* initialize to default */ 1545da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasstatic int iwl_power_init_handle(struct iwl_priv *priv) 1555da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 1565da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0, i; 1575da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas struct iwl_power_mgr *pow_data; 158298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX; 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 1715da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas ret = pci_read_config_word(priv->pci_dev, 1725da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas PCI_LINK_CTRL, &pci_pm); 1735da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (ret != 0) 1745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return 0; 1755da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else { 176ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas struct iwl_powertable_cmd *cmd; 1775da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1785da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas IWL_DEBUG_POWER("adjust power command flags\n"); 1795da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 180298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer for (i = 0; i < IWL_POWER_MAX; i++) { 1815da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd = &pow_data->pwr_range_0[i].cmd; 1825da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1835da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (pci_pm & 0x1) 1845da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd->flags &= ~IWL_POWER_PCI_PM_MSK; 1855da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else 1865da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd->flags |= IWL_POWER_PCI_PM_MSK; 1875da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 1885da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 1895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 1905da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 1915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 1925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* adjust power command according to dtim period and power level*/ 1935da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasstatic int iwl_update_power_command(struct iwl_priv *priv, 194ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas struct iwl_powertable_cmd *cmd, 1955da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u16 mode) 1965da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 1975da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0, i; 1985da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u8 skip; 1995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u32 max_sleep = 0; 2005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas struct iwl_power_vec_entry *range; 2015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u8 period = 0; 2025da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas struct iwl_power_mgr *pow_data; 2035da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (mode > IWL_POWER_INDEX_5) { 2055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas IWL_DEBUG_POWER("Error invalid power mode \n"); 2065da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return -1; 2075da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 2085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas pow_data = &(priv->power_data); 2095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (pow_data->dtim_period <= IWL_POWER_RANGE_0_MAX) 2115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas range = &pow_data->pwr_range_0[0]; 2125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else if (pow_data->dtim_period <= IWL_POWER_RANGE_1_MAX) 2135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas range = &pow_data->pwr_range_1[0]; 2145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else 2155da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas range = &pow_data->pwr_range_2[0]; 2165da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2175da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas period = pow_data->dtim_period; 218ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd)); 2195da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2205da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (period == 0) { 2215da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas period = 1; 2225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas skip = 0; 2235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } else 2245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas skip = range[mode].no_dtim; 2255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (skip == 0) { 2275da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas max_sleep = period; 2285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; 2295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } else { 2305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]; 2315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas max_sleep = le32_to_cpu(slp_itrvl); 2325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (max_sleep == 0xFF) 2335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas max_sleep = period * (skip + 1); 2345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else if (max_sleep > period) 2355da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas max_sleep = (le32_to_cpu(slp_itrvl) / period) * period; 2365da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; 2375da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 2385da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2395da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas for (i = 0; i < IWL_POWER_VEC_SIZE; i++) { 2405da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) 2415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd->sleep_interval[i] = cpu_to_le32(max_sleep); 2425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 2435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags); 2455da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); 2465da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas IWL_DEBUG_POWER("Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); 2475da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas IWL_DEBUG_POWER("Sleep interval vector = { %d , %d , %d , %d , %d }\n", 2485da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[0]), 2495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[1]), 2505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[2]), 2515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[3]), 2525da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas le32_to_cpu(cmd->sleep_interval[4])); 2535da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2545da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 2555da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 2565da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2575da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2585da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* 2595da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * calucaute the final power mode index 2605da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 2615da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_update_mode(struct iwl_priv *priv, u8 refresh) 2625da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 2635da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas struct iwl_power_mgr *setting = &(priv->power_data); 2645da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0; 2655da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u16 uninitialized_var(final_mode); 2665da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2675da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas /* If on battery, set to 3, 2685da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * if plugged into AC power, set to CAM ("continuously aware mode"), 2695da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * else user level */ 2705da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2715da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas switch (setting->system_power_setting) { 272298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer case IWL_POWER_SYS_AUTO: 2735da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas final_mode = iwl_get_auto_power_mode(priv); 2745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas break; 275298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer case IWL_POWER_SYS_BATTERY: 2765da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas final_mode = IWL_POWER_INDEX_3; 2775da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas break; 278298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer case IWL_POWER_SYS_AC: 2795da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas final_mode = IWL_POWER_MODE_CAM; 2805da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas break; 2815da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas default: 282298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer final_mode = IWL_POWER_INDEX_3; 283298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer WARN_ON(1); 2845da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 2855da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2865da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (setting->critical_power_setting > final_mode) 2875da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas final_mode = setting->critical_power_setting; 2885da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas /* driver only support CAM for non STA network */ 2905da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (priv->iw_mode != IEEE80211_IF_TYPE_STA) 2915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas final_mode = IWL_POWER_MODE_CAM; 2925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2935da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (!iwl_is_rfkill(priv) && !setting->power_disabled && 2945da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas ((setting->power_mode != final_mode) || refresh)) { 295ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas struct iwl_powertable_cmd cmd; 2965da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 2975da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (final_mode != IWL_POWER_MODE_CAM) 2985da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas set_bit(STATUS_POWER_PMI, &priv->status); 2995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas iwl_update_power_command(priv, &cmd, final_mode); 3015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd.keep_alive_beacons = 0; 3025da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3035da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (final_mode == IWL_POWER_INDEX_5) 3045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas cmd.flags |= IWL_POWER_FAST_PD; 3055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 306ca579617d81baf5865498eb5fae58e453ee77c2cMohamed Abbas ret = iwl_set_power(priv, &cmd); 3075da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (final_mode == IWL_POWER_MODE_CAM) 3095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas clear_bit(STATUS_POWER_PMI, &priv->status); 3105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else 3115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas set_bit(STATUS_POWER_PMI, &priv->status); 3125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (priv->cfg->ops->lib->update_chain_flags) 3145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->cfg->ops->lib->update_chain_flags(priv); 3155da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3165da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (!ret) 3175da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas setting->power_mode = final_mode; 3185da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas } 3195da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3205da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 3215da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 3225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_update_mode); 3235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* Allow other iwl code to disable/enable power management active 3255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * this will be usefull for rate scale to disable PM during heavy 3265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * Tx/Rx activities 3275da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 3285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_disable_management(struct iwl_priv *priv) 3295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 3305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u16 prev_mode; 3315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0; 3325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (priv->power_data.power_disabled) 3345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return -EBUSY; 3355da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3365da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas prev_mode = priv->power_data.user_power_setting; 3375da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.user_power_setting = IWL_POWER_MODE_CAM; 3385da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas ret = iwl_power_update_mode(priv, 0); 3395da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.power_disabled = 1; 3405da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.user_power_setting = prev_mode; 3415da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3425da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 3435da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 3445da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_disable_management); 3455da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3465da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* Allow other iwl code to disable/enable power management active 3475da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * this will be usefull for rate scale to disable PM during hight 3485da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * valume activities 3495da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 3505da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_enable_management(struct iwl_priv *priv) 3515da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 3525da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0; 3535da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3545da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.power_disabled = 0; 3555da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas ret = iwl_power_update_mode(priv, 0); 3565da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 3575da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 3585da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_enable_management); 3595da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3605da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* set user_power_setting */ 3615da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode) 3625da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 3635da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0; 3645da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3655da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (mode > IWL_POWER_LIMIT) 3665da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return -EINVAL; 3675da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3685da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.user_power_setting = mode; 3695da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3705da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas ret = iwl_power_update_mode(priv, 0); 3715da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3725da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 3735da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 3745da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_set_user_mode); 3755da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3765da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3775da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* set system_power_setting. This should be set by over all 3785da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas * PM application. 3795da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas */ 3805da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode) 3815da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 3825da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0; 3835da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3845da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (mode > IWL_POWER_LIMIT) 3855da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return -EINVAL; 3865da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3875da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.system_power_setting = mode; 3885da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3895da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas ret = iwl_power_update_mode(priv, 0); 3905da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3915da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 3925da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 3935da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_set_system_mode); 3945da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3955da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* initilize to default */ 3965da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasvoid iwl_power_initialize(struct iwl_priv *priv) 3975da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 3985da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 3995da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas iwl_power_init_handle(priv); 4005da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.user_power_setting = IWL_POWER_AUTO; 4015da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.power_disabled = 0; 402298df1f62aa69881528bf0f1c3c14395bc447846Esti Kummer priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO; 4035da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.is_battery_active = 0; 4045da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.power_disabled = 0; 4055da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.critical_power_setting = 0; 4065da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 4075da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_initialize); 4085da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 4095da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas/* set critical_power_setting according to temperature value */ 4105da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbasint iwl_power_temperature_change(struct iwl_priv *priv) 4115da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas{ 4125da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas int ret = 0; 4135da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas u16 new_critical = priv->power_data.critical_power_setting; 4145da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas s32 temperature = KELVIN_TO_CELSIUS(priv->last_temperature); 4155da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 4165da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (temperature > IWL_CT_KILL_TEMPERATURE) 4175da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return 0; 4185da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else if (temperature > IWL_MIN_POWER_TEMPERATURE) 4195da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas new_critical = IWL_POWER_INDEX_5; 4205da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else if (temperature > IWL_REDUCED_POWER_TEMPERATURE) 4215da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas new_critical = IWL_POWER_INDEX_3; 4225da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas else 4235da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas new_critical = IWL_POWER_MODE_CAM; 4245da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 4255da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (new_critical != priv->power_data.critical_power_setting) 4265da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.critical_power_setting = new_critical; 4275da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 4285da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas if (priv->power_data.critical_power_setting > 4295da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas priv->power_data.power_mode) 4305da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas ret = iwl_power_update_mode(priv, 0); 4315da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas 4325da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas return ret; 4335da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed Abbas} 4345da4b55f78fb2ed40926b775d4f7c791594ecbd7Mohamed AbbasEXPORT_SYMBOL(iwl_power_temperature_change); 435