aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-power.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-08-07 18:41:51 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:13:50 -0400
commite312c24cf8229f9b6e76dbfd5d99eefe21f4ac0a (patch)
tree79e3b967f3905716baef4bc73b4510543b38ceb5 /drivers/net/wireless/iwlwifi/iwl-power.c
parentd91b1ba37744bc7fb7524516be855c9fa81142e2 (diff)
iwlwifi: automatically adjust sleep level
Depending on required latency requested by pm_qos (via mac80211) we can automatically adjust the sleep state. Also, mac80211 has a user-visible dynamic sleep feature where we are supposed to stay awake after sending/receiving frames to better receive response frames to our packets, this can be integrated into the sleep command. Currently, and this patch doesn't change that yet, we default to using sleep level 1 if PS is enabled. With a module parameter to iwlcore, automatic adjustment to changing network latency requirements can be enabled -- this isn't yet the default due to requiring more testing. The goal is to enable automatic adjustment and then go into the deepest possible sleep state possible depending on the networking latency requirements. This patch does, however, enable IEEE80211_HW_SUPPORTS_DYNAMIC_PS to avoid the double-timer (one in software and one in the device) when transmitting -- the exact timeout may be ignored but that is not of big concern. Note also that we keep the hard-coded power indices around for thermal throttling -- the specification of that calls for using the specified power levels. Those can also be selected in debugfs to allow easier testing of such parameters. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-power.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c317
1 files changed, 147 insertions, 170 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 27ad59d8643e..0b16841f45f4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -42,20 +42,35 @@
42#include "iwl-power.h" 42#include "iwl-power.h"
43 43
44/* 44/*
45 * Setting power level allow the card to go to sleep when not busy. 45 * Setting power level allows the card to go to sleep when not busy.
46 * 46 *
47 * The power level is set to INDEX_1 (the least deep state) by 47 * We calculate a sleep command based on the required latency, which
48 * default, and will, in the future, be the deepest state unless 48 * we get from mac80211. In order to handle thermal throttling, we can
49 * otherwise required by pm_qos network latency requirements. 49 * also use pre-defined power levels.
50 *
51 * Using INDEX_1 without pm_qos is ok because mac80211 will disable
52 * PS when even checking every beacon for the TIM bit would exceed
53 * the required latency.
54 */ 50 */
55 51
56#define IWL_POWER_RANGE_0_MAX (2) 52/*
57#define IWL_POWER_RANGE_1_MAX (10) 53 * For now, keep using power level 1 instead of automatically
54 * adjusting ...
55 */
56bool no_sleep_autoadjust = true;
57module_param(no_sleep_autoadjust, bool, S_IRUGO);
58MODULE_PARM_DESC(no_sleep_autoadjust,
59 "don't automatically adjust sleep level "
60 "according to maximum network latency");
58 61
62/*
63 * This defines the old power levels. They are still used by default
64 * (level 1) and for thermal throttle (levels 3 through 5)
65 */
66
67struct iwl_power_vec_entry {
68 struct iwl_powertable_cmd cmd;
69 u8 no_dtim;
70};
71
72#define IWL_DTIM_RANGE_0_MAX 2
73#define IWL_DTIM_RANGE_1_MAX 10
59 74
60#define NOSLP cpu_to_le16(0), 0, 0 75#define NOSLP cpu_to_le16(0), 0, 0
61#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 76#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
@@ -67,9 +82,8 @@
67 cpu_to_le32(X3), \ 82 cpu_to_le32(X3), \
68 cpu_to_le32(X4)} 83 cpu_to_le32(X4)}
69/* default power management (not Tx power) table values */ 84/* default power management (not Tx power) table values */
70/* for DTIM period 0 through IWL_POWER_RANGE_0_MAX */ 85/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */
71static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { 86static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
72 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
73 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 87 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
74 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 88 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
75 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0}, 89 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0},
@@ -78,9 +92,8 @@ static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
78}; 92};
79 93
80 94
81/* for DTIM period IWL_POWER_RANGE_0_MAX + 1 through IWL_POWER_RANGE_1_MAX */ 95/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
82static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = { 96static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
83 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
84 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, 97 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
85 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, 98 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
86 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0}, 99 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0},
@@ -88,9 +101,8 @@ static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
88 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} 101 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2}
89}; 102};
90 103
91/* for DTIM period > IWL_POWER_RANGE_1_MAX */ 104/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
92static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { 105static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
93 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
94 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, 106 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
95 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, 107 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
96 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, 108 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
@@ -98,6 +110,56 @@ static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
98 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} 110 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
99}; 111};
100 112
113static void iwl_static_sleep_cmd(struct iwl_priv *priv,
114 struct iwl_powertable_cmd *cmd,
115 enum iwl_power_level lvl, int period)
116{
117 const struct iwl_power_vec_entry *table;
118 int max_sleep, i;
119 bool skip;
120
121 table = range_2;
122 if (period < IWL_DTIM_RANGE_1_MAX)
123 table = range_1;
124 if (period < IWL_DTIM_RANGE_0_MAX)
125 table = range_0;
126
127 BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM);
128
129 *cmd = table[lvl].cmd;
130
131 if (period == 0) {
132 skip = false;
133 period = 1;
134 } else {
135 skip = !!table[lvl].no_dtim;
136 }
137
138 if (skip) {
139 __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
140 max_sleep = le32_to_cpu(slp_itrvl);
141 if (max_sleep == 0xFF)
142 max_sleep = period * (skip + 1);
143 else if (max_sleep > period)
144 max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
145 cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
146 } else {
147 max_sleep = period;
148 cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
149 }
150
151 for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
152 if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
153 cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
154
155 if (priv->power_data.pci_pm)
156 cmd->flags |= IWL_POWER_PCI_PM_MSK;
157 else
158 cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
159
160 IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
161}
162
101/* default Thermal Throttling transaction table 163/* default Thermal Throttling transaction table
102 * Current state | Throttling Down | Throttling Up 164 * Current state | Throttling Down | Throttling Up
103 *============================================================================= 165 *=============================================================================
@@ -138,98 +200,44 @@ static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
138 {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false } 200 {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
139}; 201};
140 202
141/* set card power command */
142static int iwl_set_power(struct iwl_priv *priv, void *cmd)
143{
144 return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
145 sizeof(struct iwl_powertable_cmd), cmd);
146}
147 203
148/* initialize to default */ 204static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
149static void iwl_power_init_handle(struct iwl_priv *priv) 205 struct iwl_powertable_cmd *cmd)
150{ 206{
151 struct iwl_power_mgr *pow_data; 207 memset(cmd, 0, sizeof(*cmd));
152 int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_NUM;
153 struct iwl_powertable_cmd *cmd;
154 int i;
155 u16 lctl;
156
157 IWL_DEBUG_POWER(priv, "Initialize power \n");
158
159 pow_data = &priv->power_data;
160
161 memset(pow_data, 0, sizeof(*pow_data));
162
163 memcpy(&pow_data->pwr_range_0[0], &range_0[0], size);
164 memcpy(&pow_data->pwr_range_1[0], &range_1[0], size);
165 memcpy(&pow_data->pwr_range_2[0], &range_2[0], size);
166
167 lctl = iwl_pcie_link_ctl(priv);
168 208
169 IWL_DEBUG_POWER(priv, "adjust power command flags\n"); 209 if (priv->power_data.pci_pm)
210 cmd->flags |= IWL_POWER_PCI_PM_MSK;
170 211
171 for (i = 0; i < IWL_POWER_NUM; i++) { 212 IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
172 cmd = &pow_data->pwr_range_0[i].cmd;
173
174 if (lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN)
175 cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
176 else
177 cmd->flags |= IWL_POWER_PCI_PM_MSK;
178 }
179} 213}
180 214
181/* adjust power command according to DTIM period and power level*/ 215static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
182static int iwl_update_power_cmd(struct iwl_priv *priv, 216 struct iwl_powertable_cmd *cmd,
183 struct iwl_powertable_cmd *cmd, u16 mode) 217 int dynps_ms, int wakeup_period)
184{ 218{
185 struct iwl_power_vec_entry *range;
186 struct iwl_power_mgr *pow_data;
187 int i; 219 int i;
188 u32 max_sleep = 0;
189 u8 period;
190 bool skip;
191 220
192 if (mode > IWL_POWER_INDEX_5) { 221 memset(cmd, 0, sizeof(*cmd));
193 IWL_DEBUG_POWER(priv, "Error invalid power mode \n");
194 return -EINVAL;
195 }
196 222
197 pow_data = &priv->power_data; 223 cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |
224 IWL_POWER_FAST_PD; /* no use seeing frames for others */
198 225
199 if (pow_data->dtim_period <= IWL_POWER_RANGE_0_MAX) 226 if (priv->power_data.pci_pm)
200 range = &pow_data->pwr_range_0[0]; 227 cmd->flags |= IWL_POWER_PCI_PM_MSK;
201 else if (pow_data->dtim_period <= IWL_POWER_RANGE_1_MAX)
202 range = &pow_data->pwr_range_1[0];
203 else
204 range = &pow_data->pwr_range_2[0];
205 228
206 period = pow_data->dtim_period; 229 cmd->rx_data_timeout = cpu_to_le32(1000 * dynps_ms);
207 memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd)); 230 cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms);
208
209 if (period == 0) {
210 period = 1;
211 skip = false;
212 } else {
213 skip = !!range[mode].no_dtim;
214 }
215
216 if (skip) {
217 __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
218 max_sleep = le32_to_cpu(slp_itrvl);
219 if (max_sleep == 0xFF)
220 max_sleep = period * (skip + 1);
221 else if (max_sleep > period)
222 max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
223 cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
224 } else {
225 max_sleep = period;
226 cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
227 }
228 231
229 for (i = 0; i < IWL_POWER_VEC_SIZE; i++) 232 for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
230 if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) 233 cmd->sleep_interval[i] = cpu_to_le32(wakeup_period);
231 cmd->sleep_interval[i] = cpu_to_le32(max_sleep); 234
235 IWL_DEBUG_POWER(priv, "Automatic sleep command\n");
236}
232 237
238static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
239{
240 IWL_DEBUG_POWER(priv, "Sending power/sleep command\n");
233 IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags); 241 IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags);
234 IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); 242 IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
235 IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); 243 IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout));
@@ -240,50 +248,54 @@ static int iwl_update_power_cmd(struct iwl_priv *priv,
240 le32_to_cpu(cmd->sleep_interval[3]), 248 le32_to_cpu(cmd->sleep_interval[3]),
241 le32_to_cpu(cmd->sleep_interval[4])); 249 le32_to_cpu(cmd->sleep_interval[4]));
242 250
243 return 0; 251 return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
252 sizeof(struct iwl_powertable_cmd), cmd);
244} 253}
245 254
246 255
247/*
248 * compute the final power mode index
249 */
250int iwl_power_update_mode(struct iwl_priv *priv, bool force) 256int iwl_power_update_mode(struct iwl_priv *priv, bool force)
251{ 257{
252 struct iwl_power_mgr *setting = &(priv->power_data);
253 int ret = 0; 258 int ret = 0;
254 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 259 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
255 u16 uninitialized_var(final_mode); 260 bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) &&
261 (priv->hw->conf.flags & IEEE80211_CONF_PS);
256 bool update_chains; 262 bool update_chains;
263 struct iwl_powertable_cmd cmd;
264 int dtimper;
257 265
258 /* Don't update the RX chain when chain noise calibration is running */ 266 /* Don't update the RX chain when chain noise calibration is running */
259 update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || 267 update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
260 priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; 268 priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
261 269
262 final_mode = priv->power_data.user_power_setting; 270 if (priv->vif)
263 271 dtimper = priv->vif->bss_conf.dtim_period;
264 if (setting->power_disabled) 272 else
265 final_mode = IWL_POWER_MODE_CAM; 273 dtimper = 1;
274
275 /* TT power setting overwrites everything */
276 if (tt->state >= IWL_TI_1)
277 iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper);
278 else if (!enabled)
279 iwl_power_sleep_cam_cmd(priv, &cmd);
280 else if (priv->power_data.debug_sleep_level_override >= 0)
281 iwl_static_sleep_cmd(priv, &cmd,
282 priv->power_data.debug_sleep_level_override,
283 dtimper);
284 else if (no_sleep_autoadjust)
285 iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper);
286 else
287 iwl_power_fill_sleep_cmd(priv, &cmd,
288 priv->hw->conf.dynamic_ps_timeout,
289 priv->hw->conf.max_sleep_period);
266 290
267 if (tt->state >= IWL_TI_1) {
268 /* TT power setting overwrite user & system power setting */
269 final_mode = tt->tt_power_mode;
270 }
271 if (iwl_is_ready_rf(priv) && 291 if (iwl_is_ready_rf(priv) &&
272 ((setting->power_mode != final_mode) || force)) { 292 (memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) {
273 struct iwl_powertable_cmd cmd; 293 if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
274
275 if (final_mode != IWL_POWER_MODE_CAM)
276 set_bit(STATUS_POWER_PMI, &priv->status); 294 set_bit(STATUS_POWER_PMI, &priv->status);
277 295
278 iwl_update_power_cmd(priv, &cmd, final_mode);
279 cmd.keep_alive_beacons = 0;
280
281 if (final_mode == IWL_POWER_INDEX_5)
282 cmd.flags |= IWL_POWER_FAST_PD;
283
284 ret = iwl_set_power(priv, &cmd); 296 ret = iwl_set_power(priv, &cmd);
285 if (!ret) { 297 if (!ret) {
286 if (final_mode == IWL_POWER_MODE_CAM) 298 if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
287 clear_bit(STATUS_POWER_PMI, &priv->status); 299 clear_bit(STATUS_POWER_PMI, &priv->status);
288 300
289 if (priv->cfg->ops->lib->update_chain_flags && 301 if (priv->cfg->ops->lib->update_chain_flags &&
@@ -294,7 +306,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
294 "Cannot update the power, chain noise " 306 "Cannot update the power, chain noise "
295 "calibration running: %d\n", 307 "calibration running: %d\n",
296 priv->chain_noise_data.state); 308 priv->chain_noise_data.state);
297 setting->power_mode = final_mode; 309 memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd));
298 } else 310 } else
299 IWL_ERR(priv, "set power fail, ret = %d", ret); 311 IWL_ERR(priv, "set power fail, ret = %d", ret);
300 } 312 }
@@ -303,18 +315,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
303} 315}
304EXPORT_SYMBOL(iwl_power_update_mode); 316EXPORT_SYMBOL(iwl_power_update_mode);
305 317
306/* set user_power_setting */
307int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
308{
309 if (mode >= IWL_POWER_NUM)
310 return -EINVAL;
311
312 priv->power_data.user_power_setting = mode;
313
314 return iwl_power_update_mode(priv, 0);
315}
316EXPORT_SYMBOL(iwl_power_set_user_mode);
317
318bool iwl_ht_enabled(struct iwl_priv *priv) 318bool iwl_ht_enabled(struct iwl_priv *priv)
319{ 319{
320 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 320 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
@@ -349,7 +349,6 @@ enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
349 restriction = tt->restriction + tt->state; 349 restriction = tt->restriction + tt->state;
350 return restriction->rx_stream; 350 return restriction->rx_stream;
351} 351}
352EXPORT_SYMBOL(iwl_rx_ant_restriction);
353 352
354#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ 353#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */
355 354
@@ -429,7 +428,6 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
429{ 428{
430 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 429 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
431 enum iwl_tt_state old_state; 430 enum iwl_tt_state old_state;
432 struct iwl_power_mgr *setting = &priv->power_data;
433 431
434#ifdef CONFIG_IWLWIFI_DEBUG 432#ifdef CONFIG_IWLWIFI_DEBUG
435 if ((tt->tt_previous_temp) && 433 if ((tt->tt_previous_temp) &&
@@ -456,24 +454,13 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
456 tt->tt_previous_temp = temp; 454 tt->tt_previous_temp = temp;
457#endif 455#endif
458 if (tt->state != old_state) { 456 if (tt->state != old_state) {
459 if (old_state == IWL_TI_0) {
460 tt->sys_power_mode = setting->power_mode;
461 IWL_DEBUG_POWER(priv, "current power mode: %u\n",
462 setting->power_mode);
463 }
464 switch (tt->state) { 457 switch (tt->state) {
465 case IWL_TI_0: 458 case IWL_TI_0:
466 /* when system ready to go back to IWL_TI_0 state 459 /*
467 * using system power mode instead of TT power mode 460 * When the system is ready to go back to IWL_TI_0
468 * revert back to the orginal power mode which was saved 461 * we only have to call iwl_power_update_mode() to
469 * before enter Thermal Throttling state 462 * do so.
470 * update priv->power_data.user_power_setting to the
471 * required power mode to make sure
472 * iwl_power_update_mode() will update power correctly.
473 */ 463 */
474 priv->power_data.user_power_setting =
475 tt->sys_power_mode;
476 tt->tt_power_mode = tt->sys_power_mode;
477 break; 464 break;
478 case IWL_TI_1: 465 case IWL_TI_1:
479 tt->tt_power_mode = IWL_POWER_INDEX_3; 466 tt->tt_power_mode = IWL_POWER_INDEX_3;
@@ -576,13 +563,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
576 } 563 }
577 if (changed) { 564 if (changed) {
578 struct iwl_rxon_cmd *rxon = &priv->staging_rxon; 565 struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
579 struct iwl_power_mgr *setting = &priv->power_data;
580 566
581 if (tt->state >= IWL_TI_1) { 567 if (tt->state >= IWL_TI_1) {
582 /* if switching from IWL_TI_0 to other TT state
583 * save previous power setting in tt->sys_power_mode */
584 if (old_state == IWL_TI_0)
585 tt->sys_power_mode = setting->power_mode;
586 /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ 568 /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
587 tt->tt_power_mode = IWL_POWER_INDEX_5; 569 tt->tt_power_mode = IWL_POWER_INDEX_5;
588 if (!iwl_ht_enabled(priv)) 570 if (!iwl_ht_enabled(priv))
@@ -599,17 +581,11 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
599 } 581 }
600 582
601 } else { 583 } else {
602 /* restore system power setting */ 584 /*
603 /* the previous power mode was saved in 585 * restore system power setting -- it will be
604 * tt->sys_power_mode when system move into 586 * recalculated automatically.
605 * Thermal Throttling state
606 * set power_data.user_power_setting to the previous
607 * system power mode to make sure power will get
608 * updated correctly
609 */ 587 */
610 priv->power_data.user_power_setting = 588
611 tt->sys_power_mode;
612 tt->tt_power_mode = tt->sys_power_mode;
613 /* check HT capability and set 589 /* check HT capability and set
614 * according to the system HT capability 590 * according to the system HT capability
615 * in case get disabled before */ 591 * in case get disabled before */
@@ -761,7 +737,6 @@ EXPORT_SYMBOL(iwl_tt_handler);
761void iwl_tt_initialize(struct iwl_priv *priv) 737void iwl_tt_initialize(struct iwl_priv *priv)
762{ 738{
763 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 739 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
764 struct iwl_power_mgr *setting = &priv->power_data;
765 int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); 740 int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
766 struct iwl_tt_trans *transaction; 741 struct iwl_tt_trans *transaction;
767 742
@@ -770,8 +745,6 @@ void iwl_tt_initialize(struct iwl_priv *priv)
770 memset(tt, 0, sizeof(struct iwl_tt_mgmt)); 745 memset(tt, 0, sizeof(struct iwl_tt_mgmt));
771 746
772 tt->state = IWL_TI_0; 747 tt->state = IWL_TI_0;
773 tt->sys_power_mode = setting->power_mode;
774 tt->tt_power_mode = tt->sys_power_mode;
775 init_timer(&priv->thermal_throttle.ct_kill_exit_tm); 748 init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
776 priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; 749 priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
777 priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill; 750 priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill;
@@ -849,9 +822,13 @@ EXPORT_SYMBOL(iwl_tt_exit);
849/* initialize to default */ 822/* initialize to default */
850void iwl_power_initialize(struct iwl_priv *priv) 823void iwl_power_initialize(struct iwl_priv *priv)
851{ 824{
852 iwl_power_init_handle(priv); 825 u16 lctl = iwl_pcie_link_ctl(priv);
853 priv->power_data.user_power_setting = IWL_POWER_INDEX_1; 826
854 /* default to disabled until mac80211 says otherwise */ 827 priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
855 priv->power_data.power_disabled = 1; 828
829 priv->power_data.debug_sleep_level_override = -1;
830
831 memset(&priv->power_data.sleep_cmd, 0,
832 sizeof(priv->power_data.sleep_cmd));
856} 833}
857EXPORT_SYMBOL(iwl_power_initialize); 834EXPORT_SYMBOL(iwl_power_initialize);