aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-power.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-power.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c242
1 files changed, 179 insertions, 63 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 60be976afff8..548dac2f6a96 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project, as well 5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files. 6 * as portions of the ieee80211 subsystem header files.
@@ -29,6 +29,7 @@
29 29
30#include <linux/kernel.h> 30#include <linux/kernel.h>
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/slab.h>
32#include <linux/init.h> 33#include <linux/init.h>
33 34
34#include <net/mac80211.h> 35#include <net/mac80211.h>
@@ -66,7 +67,7 @@ MODULE_PARM_DESC(no_sleep_autoadjust,
66 67
67struct iwl_power_vec_entry { 68struct iwl_power_vec_entry {
68 struct iwl_powertable_cmd cmd; 69 struct iwl_powertable_cmd cmd;
69 u8 no_dtim; 70 u8 no_dtim; /* number of skip dtim */
70}; 71};
71 72
72#define IWL_DTIM_RANGE_0_MAX 2 73#define IWL_DTIM_RANGE_0_MAX 2
@@ -83,8 +84,9 @@ struct iwl_power_vec_entry {
83 cpu_to_le32(X4)} 84 cpu_to_le32(X4)}
84/* default power management (not Tx power) table values */ 85/* default power management (not Tx power) table values */
85/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */ 86/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */
87/* DTIM 0 - 2 */
86static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { 88static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
87 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 89 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 1, 2, 2, 0xFF)}, 0},
88 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 90 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
89 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0}, 91 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0},
90 {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1}, 92 {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1},
@@ -93,15 +95,17 @@ static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
93 95
94 96
95/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */ 97/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
98/* DTIM 3 - 10 */
96static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = { 99static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
97 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, 100 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
98 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, 101 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
99 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0}, 102 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0},
100 {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1}, 103 {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1},
101 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} 104 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 6, 10, 10)}, 2}
102}; 105};
103 106
104/* for DTIM period > IWL_DTIM_RANGE_1_MAX */ 107/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
108/* DTIM 11 - */
105static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { 109static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
106 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, 110 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
107 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, 111 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
@@ -115,13 +119,15 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
115 enum iwl_power_level lvl, int period) 119 enum iwl_power_level lvl, int period)
116{ 120{
117 const struct iwl_power_vec_entry *table; 121 const struct iwl_power_vec_entry *table;
118 int max_sleep, i; 122 int max_sleep[IWL_POWER_VEC_SIZE] = { 0 };
119 bool skip; 123 int i;
124 u8 skip;
125 u32 slp_itrvl;
120 126
121 table = range_2; 127 table = range_2;
122 if (period < IWL_DTIM_RANGE_1_MAX) 128 if (period <= IWL_DTIM_RANGE_1_MAX)
123 table = range_1; 129 table = range_1;
124 if (period < IWL_DTIM_RANGE_0_MAX) 130 if (period <= IWL_DTIM_RANGE_0_MAX)
125 table = range_0; 131 table = range_0;
126 132
127 BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); 133 BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM);
@@ -129,34 +135,60 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
129 *cmd = table[lvl].cmd; 135 *cmd = table[lvl].cmd;
130 136
131 if (period == 0) { 137 if (period == 0) {
132 skip = false; 138 skip = 0;
133 period = 1; 139 period = 1;
140 for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
141 max_sleep[i] = 1;
142
134 } else { 143 } else {
135 skip = !!table[lvl].no_dtim; 144 skip = table[lvl].no_dtim;
145 for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
146 max_sleep[i] = le32_to_cpu(cmd->sleep_interval[i]);
147 max_sleep[IWL_POWER_VEC_SIZE - 1] = skip + 1;
136 } 148 }
137 149
138 if (skip) { 150 slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
139 __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]; 151 /* figure out the listen interval based on dtim period and skip */
140 max_sleep = le32_to_cpu(slp_itrvl); 152 if (slp_itrvl == 0xFF)
141 if (max_sleep == 0xFF) 153 cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
142 max_sleep = period * (skip + 1); 154 cpu_to_le32(period * (skip + 1));
143 else if (max_sleep > period) 155
144 max_sleep = (le32_to_cpu(slp_itrvl) / period) * period; 156 slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
157 if (slp_itrvl > period)
158 cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
159 cpu_to_le32((slp_itrvl / period) * period);
160
161 if (skip)
145 cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; 162 cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
146 } else { 163 else
147 max_sleep = period;
148 cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; 164 cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
149 }
150 165
151 for (i = 0; i < IWL_POWER_VEC_SIZE; i++) 166 slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
152 if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) 167 if (slp_itrvl > IWL_CONN_MAX_LISTEN_INTERVAL)
153 cmd->sleep_interval[i] = cpu_to_le32(max_sleep); 168 cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
169 cpu_to_le32(IWL_CONN_MAX_LISTEN_INTERVAL);
170
171 /* enforce max sleep interval */
172 for (i = IWL_POWER_VEC_SIZE - 1; i >= 0 ; i--) {
173 if (le32_to_cpu(cmd->sleep_interval[i]) >
174 (max_sleep[i] * period))
175 cmd->sleep_interval[i] =
176 cpu_to_le32(max_sleep[i] * period);
177 if (i != (IWL_POWER_VEC_SIZE - 1)) {
178 if (le32_to_cpu(cmd->sleep_interval[i]) >
179 le32_to_cpu(cmd->sleep_interval[i+1]))
180 cmd->sleep_interval[i] =
181 cmd->sleep_interval[i+1];
182 }
183 }
154 184
155 if (priv->power_data.pci_pm) 185 if (priv->power_data.pci_pm)
156 cmd->flags |= IWL_POWER_PCI_PM_MSK; 186 cmd->flags |= IWL_POWER_PCI_PM_MSK;
157 else 187 else
158 cmd->flags &= ~IWL_POWER_PCI_PM_MSK; 188 cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
159 189
190 IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n",
191 skip, period);
160 IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); 192 IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
161} 193}
162 194
@@ -165,26 +197,26 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
165 *============================================================================= 197 *=============================================================================
166 * Condition Nxt State Condition Nxt State Condition Nxt State 198 * Condition Nxt State Condition Nxt State Condition Nxt State
167 *----------------------------------------------------------------------------- 199 *-----------------------------------------------------------------------------
168 * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A 200 * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A
169 * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0 201 * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0
170 * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1 202 * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1
171 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 203 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
172 *============================================================================= 204 *=============================================================================
173 */ 205 */
174static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { 206static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
175 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, 207 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
176 {IWL_TI_1, 105, CT_KILL_THRESHOLD}, 208 {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1},
177 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} 209 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
178}; 210};
179static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { 211static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
180 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, 212 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
181 {IWL_TI_2, 110, CT_KILL_THRESHOLD}, 213 {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1},
182 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} 214 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
183}; 215};
184static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { 216static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
185 {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, 217 {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
186 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, 218 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX},
187 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} 219 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
188}; 220};
189static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { 221static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
190 {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, 222 {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
@@ -272,13 +304,12 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
272 sizeof(struct iwl_powertable_cmd), cmd); 304 sizeof(struct iwl_powertable_cmd), cmd);
273} 305}
274 306
275 307/* priv->mutex must be held */
276int iwl_power_update_mode(struct iwl_priv *priv, bool force) 308int iwl_power_update_mode(struct iwl_priv *priv, bool force)
277{ 309{
278 int ret = 0; 310 int ret = 0;
279 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 311 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
280 bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) && 312 bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
281 (priv->hw->conf.flags & IEEE80211_CONF_PS);
282 bool update_chains; 313 bool update_chains;
283 struct iwl_powertable_cmd cmd; 314 struct iwl_powertable_cmd cmd;
284 int dtimper; 315 int dtimper;
@@ -288,12 +319,15 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
288 priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; 319 priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
289 320
290 if (priv->vif) 321 if (priv->vif)
291 dtimper = priv->vif->bss_conf.dtim_period; 322 dtimper = priv->hw->conf.ps_dtim_period;
292 else 323 else
293 dtimper = 1; 324 dtimper = 1;
294 325
295 if (priv->cfg->broken_powersave) 326 if (priv->cfg->broken_powersave)
296 iwl_power_sleep_cam_cmd(priv, &cmd); 327 iwl_power_sleep_cam_cmd(priv, &cmd);
328 else if (priv->cfg->supports_idle &&
329 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
330 iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20);
297 else if (tt->state >= IWL_TI_1) 331 else if (tt->state >= IWL_TI_1)
298 iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); 332 iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper);
299 else if (!enabled) 333 else if (!enabled)
@@ -348,6 +382,23 @@ bool iwl_ht_enabled(struct iwl_priv *priv)
348} 382}
349EXPORT_SYMBOL(iwl_ht_enabled); 383EXPORT_SYMBOL(iwl_ht_enabled);
350 384
385bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
386{
387 s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */
388 bool within_margin = false;
389
390 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
391 temp = KELVIN_TO_CELSIUS(priv->temperature);
392
393 if (!priv->thermal_throttle.advanced_tt)
394 within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
395 CT_KILL_THRESHOLD_LEGACY) ? true : false;
396 else
397 within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
398 CT_KILL_THRESHOLD) ? true : false;
399 return within_margin;
400}
401
351enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) 402enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
352{ 403{
353 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 404 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
@@ -372,6 +423,7 @@ enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
372} 423}
373 424
374#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ 425#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */
426#define CT_KILL_WAITING_DURATION (300) /* 300ms duration */
375 427
376/* 428/*
377 * toggle the bit to wake up uCode and check the temperature 429 * toggle the bit to wake up uCode and check the temperature
@@ -409,6 +461,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
409 /* Reschedule the ct_kill timer to occur in 461 /* Reschedule the ct_kill timer to occur in
410 * CT_KILL_EXIT_DURATION seconds to ensure we get a 462 * CT_KILL_EXIT_DURATION seconds to ensure we get a
411 * thermal update */ 463 * thermal update */
464 IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
412 mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + 465 mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
413 CT_KILL_EXIT_DURATION * HZ); 466 CT_KILL_EXIT_DURATION * HZ);
414 } 467 }
@@ -432,6 +485,33 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
432 } 485 }
433} 486}
434 487
488static void iwl_tt_ready_for_ct_kill(unsigned long data)
489{
490 struct iwl_priv *priv = (struct iwl_priv *)data;
491 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
492
493 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
494 return;
495
496 /* temperature timer expired, ready to go into CT_KILL state */
497 if (tt->state != IWL_TI_CT_KILL) {
498 IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n");
499 tt->state = IWL_TI_CT_KILL;
500 set_bit(STATUS_CT_KILL, &priv->status);
501 iwl_perform_ct_kill_task(priv, true);
502 }
503}
504
505static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
506{
507 IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
508 /* make request to retrieve statistics information */
509 iwl_send_statistics_request(priv, CMD_SYNC, false);
510 /* Reschedule the ct_kill wait timer */
511 mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
512 jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));
513}
514
435#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) 515#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY)
436#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) 516#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100)
437#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) 517#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90)
@@ -445,7 +525,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
445 * Throttle early enough to lower the power consumption before 525 * Throttle early enough to lower the power consumption before
446 * drastic steps are needed 526 * drastic steps are needed
447 */ 527 */
448static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) 528static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
449{ 529{
450 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 530 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
451 enum iwl_tt_state old_state; 531 enum iwl_tt_state old_state;
@@ -474,6 +554,8 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
474#ifdef CONFIG_IWLWIFI_DEBUG 554#ifdef CONFIG_IWLWIFI_DEBUG
475 tt->tt_previous_temp = temp; 555 tt->tt_previous_temp = temp;
476#endif 556#endif
557 /* stop ct_kill_waiting_tm timer */
558 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
477 if (tt->state != old_state) { 559 if (tt->state != old_state) {
478 switch (tt->state) { 560 switch (tt->state) {
479 case IWL_TI_0: 561 case IWL_TI_0:
@@ -494,17 +576,28 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
494 break; 576 break;
495 } 577 }
496 mutex_lock(&priv->mutex); 578 mutex_lock(&priv->mutex);
497 if (iwl_power_update_mode(priv, true)) { 579 if (old_state == IWL_TI_CT_KILL)
580 clear_bit(STATUS_CT_KILL, &priv->status);
581 if (tt->state != IWL_TI_CT_KILL &&
582 iwl_power_update_mode(priv, true)) {
498 /* TT state not updated 583 /* TT state not updated
499 * try again during next temperature read 584 * try again during next temperature read
500 */ 585 */
586 if (old_state == IWL_TI_CT_KILL)
587 set_bit(STATUS_CT_KILL, &priv->status);
501 tt->state = old_state; 588 tt->state = old_state;
502 IWL_ERR(priv, "Cannot update power mode, " 589 IWL_ERR(priv, "Cannot update power mode, "
503 "TT state not updated\n"); 590 "TT state not updated\n");
504 } else { 591 } else {
505 if (tt->state == IWL_TI_CT_KILL) 592 if (tt->state == IWL_TI_CT_KILL) {
506 iwl_perform_ct_kill_task(priv, true); 593 if (force) {
507 else if (old_state == IWL_TI_CT_KILL && 594 set_bit(STATUS_CT_KILL, &priv->status);
595 iwl_perform_ct_kill_task(priv, true);
596 } else {
597 iwl_prepare_ct_kill_task(priv);
598 tt->state = old_state;
599 }
600 } else if (old_state == IWL_TI_CT_KILL &&
508 tt->state != IWL_TI_CT_KILL) 601 tt->state != IWL_TI_CT_KILL)
509 iwl_perform_ct_kill_task(priv, false); 602 iwl_perform_ct_kill_task(priv, false);
510 IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", 603 IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
@@ -531,13 +624,13 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
531 *============================================================================= 624 *=============================================================================
532 * Condition Nxt State Condition Nxt State Condition Nxt State 625 * Condition Nxt State Condition Nxt State Condition Nxt State
533 *----------------------------------------------------------------------------- 626 *-----------------------------------------------------------------------------
534 * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A 627 * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A
535 * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0 628 * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0
536 * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1 629 * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1
537 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 630 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
538 *============================================================================= 631 *=============================================================================
539 */ 632 */
540static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) 633static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
541{ 634{
542 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 635 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
543 int i; 636 int i;
@@ -582,6 +675,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
582 break; 675 break;
583 } 676 }
584 } 677 }
678 /* stop ct_kill_waiting_tm timer */
679 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
585 if (changed) { 680 if (changed) {
586 struct iwl_rxon_cmd *rxon = &priv->staging_rxon; 681 struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
587 682
@@ -613,12 +708,17 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
613 iwl_set_rxon_ht(priv, &priv->current_ht_config); 708 iwl_set_rxon_ht(priv, &priv->current_ht_config);
614 } 709 }
615 mutex_lock(&priv->mutex); 710 mutex_lock(&priv->mutex);
616 if (iwl_power_update_mode(priv, true)) { 711 if (old_state == IWL_TI_CT_KILL)
712 clear_bit(STATUS_CT_KILL, &priv->status);
713 if (tt->state != IWL_TI_CT_KILL &&
714 iwl_power_update_mode(priv, true)) {
617 /* TT state not updated 715 /* TT state not updated
618 * try again during next temperature read 716 * try again during next temperature read
619 */ 717 */
620 IWL_ERR(priv, "Cannot update power mode, " 718 IWL_ERR(priv, "Cannot update power mode, "
621 "TT state not updated\n"); 719 "TT state not updated\n");
720 if (old_state == IWL_TI_CT_KILL)
721 set_bit(STATUS_CT_KILL, &priv->status);
622 tt->state = old_state; 722 tt->state = old_state;
623 } else { 723 } else {
624 IWL_DEBUG_POWER(priv, 724 IWL_DEBUG_POWER(priv,
@@ -626,9 +726,15 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
626 tt->state); 726 tt->state);
627 if (old_state != IWL_TI_CT_KILL && 727 if (old_state != IWL_TI_CT_KILL &&
628 tt->state == IWL_TI_CT_KILL) { 728 tt->state == IWL_TI_CT_KILL) {
629 IWL_DEBUG_POWER(priv, "Enter IWL_TI_CT_KILL\n"); 729 if (force) {
630 iwl_perform_ct_kill_task(priv, true); 730 IWL_DEBUG_POWER(priv,
631 731 "Enter IWL_TI_CT_KILL\n");
732 set_bit(STATUS_CT_KILL, &priv->status);
733 iwl_perform_ct_kill_task(priv, true);
734 } else {
735 iwl_prepare_ct_kill_task(priv);
736 tt->state = old_state;
737 }
632 } else if (old_state == IWL_TI_CT_KILL && 738 } else if (old_state == IWL_TI_CT_KILL &&
633 tt->state != IWL_TI_CT_KILL) { 739 tt->state != IWL_TI_CT_KILL) {
634 IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); 740 IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
@@ -665,10 +771,11 @@ static void iwl_bg_ct_enter(struct work_struct *work)
665 "- ucode going to sleep!\n"); 771 "- ucode going to sleep!\n");
666 if (!priv->thermal_throttle.advanced_tt) 772 if (!priv->thermal_throttle.advanced_tt)
667 iwl_legacy_tt_handler(priv, 773 iwl_legacy_tt_handler(priv,
668 IWL_MINIMAL_POWER_THRESHOLD); 774 IWL_MINIMAL_POWER_THRESHOLD,
775 true);
669 else 776 else
670 iwl_advance_tt_handler(priv, 777 iwl_advance_tt_handler(priv,
671 CT_KILL_THRESHOLD + 1); 778 CT_KILL_THRESHOLD + 1, true);
672 } 779 }
673} 780}
674 781
@@ -695,11 +802,18 @@ static void iwl_bg_ct_exit(struct work_struct *work)
695 IWL_ERR(priv, 802 IWL_ERR(priv,
696 "Device temperature below critical" 803 "Device temperature below critical"
697 "- ucode awake!\n"); 804 "- ucode awake!\n");
805 /*
806 * exit from CT_KILL state
807 * reset the current temperature reading
808 */
809 priv->temperature = 0;
698 if (!priv->thermal_throttle.advanced_tt) 810 if (!priv->thermal_throttle.advanced_tt)
699 iwl_legacy_tt_handler(priv, 811 iwl_legacy_tt_handler(priv,
700 IWL_REDUCED_PERFORMANCE_THRESHOLD_2); 812 IWL_REDUCED_PERFORMANCE_THRESHOLD_2,
813 true);
701 else 814 else
702 iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD); 815 iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD,
816 true);
703 } 817 }
704} 818}
705 819
@@ -735,9 +849,9 @@ static void iwl_bg_tt_work(struct work_struct *work)
735 temp = KELVIN_TO_CELSIUS(priv->temperature); 849 temp = KELVIN_TO_CELSIUS(priv->temperature);
736 850
737 if (!priv->thermal_throttle.advanced_tt) 851 if (!priv->thermal_throttle.advanced_tt)
738 iwl_legacy_tt_handler(priv, temp); 852 iwl_legacy_tt_handler(priv, temp, false);
739 else 853 else
740 iwl_advance_tt_handler(priv, temp); 854 iwl_advance_tt_handler(priv, temp, false);
741} 855}
742 856
743void iwl_tt_handler(struct iwl_priv *priv) 857void iwl_tt_handler(struct iwl_priv *priv)
@@ -768,16 +882,18 @@ void iwl_tt_initialize(struct iwl_priv *priv)
768 tt->state = IWL_TI_0; 882 tt->state = IWL_TI_0;
769 init_timer(&priv->thermal_throttle.ct_kill_exit_tm); 883 init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
770 priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; 884 priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
771 priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill; 885 priv->thermal_throttle.ct_kill_exit_tm.function =
772 886 iwl_tt_check_exit_ct_kill;
887 init_timer(&priv->thermal_throttle.ct_kill_waiting_tm);
888 priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv;
889 priv->thermal_throttle.ct_kill_waiting_tm.function =
890 iwl_tt_ready_for_ct_kill;
773 /* setup deferred ct kill work */ 891 /* setup deferred ct kill work */
774 INIT_WORK(&priv->tt_work, iwl_bg_tt_work); 892 INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
775 INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); 893 INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
776 INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); 894 INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
777 895
778 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { 896 if (priv->cfg->adv_thermal_throttle) {
779 case CSR_HW_REV_TYPE_6x00:
780 case CSR_HW_REV_TYPE_6x50:
781 IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); 897 IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
782 tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * 898 tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
783 IWL_TI_STATE_MAX, GFP_KERNEL); 899 IWL_TI_STATE_MAX, GFP_KERNEL);
@@ -810,11 +926,9 @@ void iwl_tt_initialize(struct iwl_priv *priv)
810 &restriction_range[0], size); 926 &restriction_range[0], size);
811 priv->thermal_throttle.advanced_tt = true; 927 priv->thermal_throttle.advanced_tt = true;
812 } 928 }
813 break; 929 } else {
814 default:
815 IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); 930 IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
816 priv->thermal_throttle.advanced_tt = false; 931 priv->thermal_throttle.advanced_tt = false;
817 break;
818 } 932 }
819} 933}
820EXPORT_SYMBOL(iwl_tt_initialize); 934EXPORT_SYMBOL(iwl_tt_initialize);
@@ -826,6 +940,8 @@ void iwl_tt_exit(struct iwl_priv *priv)
826 940
827 /* stop ct_kill_exit_tm timer if activated */ 941 /* stop ct_kill_exit_tm timer if activated */
828 del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); 942 del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
943 /* stop ct_kill_waiting_tm timer if activated */
944 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
829 cancel_work_sync(&priv->tt_work); 945 cancel_work_sync(&priv->tt_work);
830 cancel_work_sync(&priv->ct_enter); 946 cancel_work_sync(&priv->ct_enter);
831 cancel_work_sync(&priv->ct_exit); 947 cancel_work_sync(&priv->ct_exit);