aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c26
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c228
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h39
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c20
7 files changed, 48 insertions, 292 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 43bc8a66864e..13a35dc710a4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1838,7 +1838,6 @@ void iwl_post_associate(struct iwl_priv *priv)
1838 if (!priv->vif || !priv->is_open) 1838 if (!priv->vif || !priv->is_open)
1839 return; 1839 return;
1840 1840
1841 iwl_power_cancel_timeout(priv);
1842 iwl_scan_cancel_timeout(priv, 200); 1841 iwl_scan_cancel_timeout(priv, 200);
1843 1842
1844 conf = ieee80211_get_hw_conf(priv->hw); 1843 conf = ieee80211_get_hw_conf(priv->hw);
@@ -1914,7 +1913,7 @@ void iwl_post_associate(struct iwl_priv *priv)
1914 * If chain noise has already been run, then we need to enable 1913 * If chain noise has already been run, then we need to enable
1915 * power management here */ 1914 * power management here */
1916 if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) 1915 if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
1917 iwl_power_enable_management(priv); 1916 iwl_power_update_mode(priv, 0);
1918 1917
1919 /* Enable Rx differential gain and sensitivity calibrations */ 1918 /* Enable Rx differential gain and sensitivity calibrations */
1920 iwl_chain_noise_reset(priv); 1919 iwl_chain_noise_reset(priv);
@@ -2465,26 +2464,11 @@ static ssize_t show_power_level(struct device *d,
2465{ 2464{
2466 struct iwl_priv *priv = dev_get_drvdata(d); 2465 struct iwl_priv *priv = dev_get_drvdata(d);
2467 int mode = priv->power_data.user_power_setting; 2466 int mode = priv->power_data.user_power_setting;
2468 int system = priv->power_data.system_power_setting;
2469 int level = priv->power_data.power_mode; 2467 int level = priv->power_data.power_mode;
2470 char *p = buf; 2468 char *p = buf;
2471 2469
2472 switch (system) { 2470 p += sprintf(p, "INDEX:%d\t", level);
2473 case IWL_POWER_SYS_AUTO: 2471 p += sprintf(p, "USER:%d\n", mode);
2474 p += sprintf(p, "SYSTEM:auto");
2475 break;
2476 case IWL_POWER_SYS_AC:
2477 p += sprintf(p, "SYSTEM:ac");
2478 break;
2479 case IWL_POWER_SYS_BATTERY:
2480 p += sprintf(p, "SYSTEM:battery");
2481 break;
2482 }
2483
2484 p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ?
2485 "fixed" : "auto");
2486 p += sprintf(p, "\tINDEX:%d", level);
2487 p += sprintf(p, "\n");
2488 return p - buf + 1; 2472 return p - buf + 1;
2489} 2473}
2490 2474
@@ -2553,7 +2537,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
2553 INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); 2537 INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
2554 2538
2555 iwl_setup_scan_deferred_work(priv); 2539 iwl_setup_scan_deferred_work(priv);
2556 iwl_setup_power_deferred_work(priv);
2557 2540
2558 if (priv->cfg->ops->lib->setup_deferred_work) 2541 if (priv->cfg->ops->lib->setup_deferred_work)
2559 priv->cfg->ops->lib->setup_deferred_work(priv); 2542 priv->cfg->ops->lib->setup_deferred_work(priv);
@@ -2573,7 +2556,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
2573 2556
2574 cancel_delayed_work_sync(&priv->init_alive_start); 2557 cancel_delayed_work_sync(&priv->init_alive_start);
2575 cancel_delayed_work(&priv->scan_check); 2558 cancel_delayed_work(&priv->scan_check);
2576 cancel_delayed_work_sync(&priv->set_power_save);
2577 cancel_delayed_work(&priv->alive_start); 2559 cancel_delayed_work(&priv->alive_start);
2578 cancel_work_sync(&priv->beacon_update); 2560 cancel_work_sync(&priv->beacon_update);
2579 del_timer_sync(&priv->statistics_periodic); 2561 del_timer_sync(&priv->statistics_periodic);
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index 735f3f19928c..a5d63672ad39 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -857,7 +857,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
857 priv->cfg->ops->lib->update_chain_flags(priv); 857 priv->cfg->ops->lib->update_chain_flags(priv);
858 858
859 data->state = IWL_CHAIN_NOISE_DONE; 859 data->state = IWL_CHAIN_NOISE_DONE;
860 iwl_power_enable_management(priv); 860 iwl_power_update_mode(priv, 0);
861} 861}
862EXPORT_SYMBOL(iwl_chain_noise_calibration); 862EXPORT_SYMBOL(iwl_chain_noise_calibration);
863 863
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index aa1e1dc95ef6..112bfa50b8fa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1352,7 +1352,6 @@ int iwl_init_drv(struct iwl_priv *priv)
1352 priv->ibss_beacon = NULL; 1352 priv->ibss_beacon = NULL;
1353 1353
1354 spin_lock_init(&priv->lock); 1354 spin_lock_init(&priv->lock);
1355 spin_lock_init(&priv->power_data.lock);
1356 spin_lock_init(&priv->sta_lock); 1355 spin_lock_init(&priv->sta_lock);
1357 spin_lock_init(&priv->hcmd_lock); 1356 spin_lock_init(&priv->hcmd_lock);
1358 1357
@@ -2576,14 +2575,13 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
2576 iwl_set_rate(priv); 2575 iwl_set_rate(priv);
2577 } 2576 }
2578 2577
2579 if (changed & IEEE80211_CONF_CHANGE_PS) { 2578 if (changed & IEEE80211_CONF_CHANGE_PS &&
2580 if (conf->flags & IEEE80211_CONF_PS) 2579 priv->iw_mode == NL80211_IFTYPE_STATION) {
2581 ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3); 2580 priv->power_data.power_disabled =
2582 else 2581 !(conf->flags & IEEE80211_CONF_PS);
2583 ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM); 2582 ret = iwl_power_update_mode(priv, 0);
2584 if (ret) 2583 if (ret)
2585 IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); 2584 IWL_DEBUG_MAC80211(priv, "Error setting power level\n");
2586
2587 } 2585 }
2588 2586
2589 if (changed & IEEE80211_CONF_CHANGE_POWER) { 2587 if (changed & IEEE80211_CONF_CHANGE_POWER) {
@@ -2719,21 +2717,7 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
2719 iwlcore_commit_rxon(priv); 2717 iwlcore_commit_rxon(priv);
2720 } 2718 }
2721 2719
2722 iwl_power_update_mode(priv, 0);
2723
2724 /* Per mac80211.h: This is only used in IBSS mode... */
2725 if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { 2720 if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
2726
2727 /* switch to CAM during association period.
2728 * the ucode will block any association/authentication
2729 * frome during assiciation period if it can not hear
2730 * the AP because of PM. the timer enable PM back is
2731 * association do not complete
2732 */
2733 if (priv->hw->conf.channel->flags &
2734 (IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_RADAR))
2735 iwl_power_disable_management(priv, 3000);
2736
2737 IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); 2721 IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n");
2738 mutex_unlock(&priv->mutex); 2722 mutex_unlock(&priv->mutex);
2739 return; 2723 return;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 0f2c1b217515..3049ba25c3fc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1075,7 +1075,6 @@ struct iwl_priv {
1075 1075
1076 struct tasklet_struct irq_tasklet; 1076 struct tasklet_struct irq_tasklet;
1077 1077
1078 struct delayed_work set_power_save;
1079 struct delayed_work init_alive_start; 1078 struct delayed_work init_alive_start;
1080 struct delayed_work alive_start; 1079 struct delayed_work alive_start;
1081 struct delayed_work scan_check; 1080 struct delayed_work scan_check;
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index c913069a2496..f2ea3f05f6e1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -41,38 +41,33 @@
41#include "iwl-power.h" 41#include "iwl-power.h"
42 42
43/* 43/*
44 * Setting power level allow the card to go to sleep when not busy 44 * Setting power level allow the card to go to sleep when not busy.
45 * there are three factor that decide the power level to go to, they
46 * are list here with its priority
47 * 1- critical_power_setting this will be set according to card temperature.
48 * 2- system_power_setting this will be set by system PM manager.
49 * 3- user_power_setting this will be set by user either by writing to sys or
50 * mac80211
51 * 45 *
52 * if system_power_setting and user_power_setting is set to auto 46 * The power level is set to INDEX_1 (the least deep state) by
53 * the power level will be decided according to association status and battery 47 * default, and will, in the future, be the deepest state unless
54 * status. 48 * otherwise required by pm_qos network latency requirements.
55 * 49 *
50 * Using INDEX_1 without pm_qos is ok because mac80211 will disable
51 * PS when even checking every beacon for the TIM bit would exceed
52 * the required latency.
56 */ 53 */
57 54
58#define MSEC_TO_USEC 1024
59#define IWL_POWER_RANGE_0_MAX (2) 55#define IWL_POWER_RANGE_0_MAX (2)
60#define IWL_POWER_RANGE_1_MAX (10) 56#define IWL_POWER_RANGE_1_MAX (10)
61 57
62 58
63 59#define NOSLP cpu_to_le16(0), 0, 0
64#define IWL_POWER_ON_BATTERY IWL_POWER_INDEX_5 60#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
65#define IWL_POWER_ON_AC_DISASSOC IWL_POWER_MODE_CAM 61#define TU_TO_USEC 1024
66#define IWL_POWER_ON_AC_ASSOC IWL_POWER_MODE_CAM 62#define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC)
67 63#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \
68 64 cpu_to_le32(X1), \
69#define IWL_CT_KILL_TEMPERATURE 110 65 cpu_to_le32(X2), \
70#define IWL_MIN_POWER_TEMPERATURE 100 66 cpu_to_le32(X3), \
71#define IWL_REDUCED_POWER_TEMPERATURE 95 67 cpu_to_le32(X4)}
72
73/* default power management (not Tx power) table values */ 68/* default power management (not Tx power) table values */
74/* for TIM 0-10 */ 69/* for DTIM period 0 through IWL_POWER_RANGE_0_MAX */
75static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = { 70static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
76 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, 71 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
77 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 72 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
78 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 73 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
@@ -82,8 +77,8 @@ static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = {
82}; 77};
83 78
84 79
85/* for TIM = 3-10 */ 80/* for DTIM period IWL_POWER_RANGE_0_MAX + 1 through IWL_POWER_RANGE_1_MAX */
86static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = { 81static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
87 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, 82 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
88 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, 83 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
89 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, 84 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
@@ -92,8 +87,8 @@ static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = {
92 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} 87 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2}
93}; 88};
94 89
95/* for TIM > 11 */ 90/* for DTIM period > IWL_POWER_RANGE_1_MAX */
96static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = { 91static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
97 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, 92 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
98 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, 93 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
99 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, 94 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
@@ -109,35 +104,12 @@ static int iwl_set_power(struct iwl_priv *priv, void *cmd)
109 return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, 104 return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
110 sizeof(struct iwl_powertable_cmd), cmd); 105 sizeof(struct iwl_powertable_cmd), cmd);
111} 106}
112/* decide the right power level according to association status
113 * and battery status
114 */
115static u16 iwl_get_auto_power_mode(struct iwl_priv *priv)
116{
117 u16 mode;
118
119 switch (priv->power_data.user_power_setting) {
120 case IWL_POWER_AUTO:
121 /* if running on battery */
122 if (priv->power_data.is_battery_active)
123 mode = IWL_POWER_ON_BATTERY;
124 else if (iwl_is_associated(priv))
125 mode = IWL_POWER_ON_AC_ASSOC;
126 else
127 mode = IWL_POWER_ON_AC_DISASSOC;
128 break;
129 default:
130 mode = priv->power_data.user_power_setting;
131 break;
132 }
133 return mode;
134}
135 107
136/* initialize to default */ 108/* initialize to default */
137static void iwl_power_init_handle(struct iwl_priv *priv) 109static void iwl_power_init_handle(struct iwl_priv *priv)
138{ 110{
139 struct iwl_power_mgr *pow_data; 111 struct iwl_power_mgr *pow_data;
140 int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX; 112 int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_NUM;
141 struct iwl_powertable_cmd *cmd; 113 struct iwl_powertable_cmd *cmd;
142 int i; 114 int i;
143 u16 lctl; 115 u16 lctl;
@@ -156,7 +128,7 @@ static void iwl_power_init_handle(struct iwl_priv *priv)
156 128
157 IWL_DEBUG_POWER(priv, "adjust power command flags\n"); 129 IWL_DEBUG_POWER(priv, "adjust power command flags\n");
158 130
159 for (i = 0; i < IWL_POWER_MAX; i++) { 131 for (i = 0; i < IWL_POWER_NUM; i++) {
160 cmd = &pow_data->pwr_range_0[i].cmd; 132 cmd = &pow_data->pwr_range_0[i].cmd;
161 133
162 if (lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN) 134 if (lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN)
@@ -246,33 +218,12 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
246 update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || 218 update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
247 priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; 219 priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
248 220
249 /* If on battery, set to 3, 221 final_mode = priv->power_data.user_power_setting;
250 * if plugged into AC power, set to CAM ("continuously aware mode"),
251 * else user level */
252
253 switch (setting->system_power_setting) {
254 case IWL_POWER_SYS_AUTO:
255 final_mode = iwl_get_auto_power_mode(priv);
256 break;
257 case IWL_POWER_SYS_BATTERY:
258 final_mode = IWL_POWER_INDEX_3;
259 break;
260 case IWL_POWER_SYS_AC:
261 final_mode = IWL_POWER_MODE_CAM;
262 break;
263 default:
264 final_mode = IWL_POWER_INDEX_3;
265 WARN_ON(1);
266 }
267
268 if (setting->critical_power_setting > final_mode)
269 final_mode = setting->critical_power_setting;
270 222
271 /* driver only support CAM for non STA network */ 223 if (setting->power_disabled)
272 if (priv->iw_mode != NL80211_IFTYPE_STATION)
273 final_mode = IWL_POWER_MODE_CAM; 224 final_mode = IWL_POWER_MODE_CAM;
274 225
275 if (iwl_is_ready_rf(priv) && !setting->power_disabled && 226 if (iwl_is_ready_rf(priv) &&
276 ((setting->power_mode != final_mode) || force)) { 227 ((setting->power_mode != final_mode) || force)) {
277 struct iwl_powertable_cmd cmd; 228 struct iwl_powertable_cmd cmd;
278 229
@@ -289,8 +240,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
289 240
290 if (final_mode == IWL_POWER_MODE_CAM) 241 if (final_mode == IWL_POWER_MODE_CAM)
291 clear_bit(STATUS_POWER_PMI, &priv->status); 242 clear_bit(STATUS_POWER_PMI, &priv->status);
292 else
293 set_bit(STATUS_POWER_PMI, &priv->status);
294 243
295 if (priv->cfg->ops->lib->update_chain_flags && update_chains) 244 if (priv->cfg->ops->lib->update_chain_flags && update_chains)
296 priv->cfg->ops->lib->update_chain_flags(priv); 245 priv->cfg->ops->lib->update_chain_flags(priv);
@@ -306,51 +255,10 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
306} 255}
307EXPORT_SYMBOL(iwl_power_update_mode); 256EXPORT_SYMBOL(iwl_power_update_mode);
308 257
309/* Allow other iwl code to disable/enable power management active
310 * this will be useful for rate scale to disable PM during heavy
311 * Tx/Rx activities
312 */
313int iwl_power_disable_management(struct iwl_priv *priv, u32 ms)
314{
315 u16 prev_mode;
316 int ret = 0;
317
318 if (priv->power_data.power_disabled)
319 return -EBUSY;
320
321 prev_mode = priv->power_data.user_power_setting;
322 priv->power_data.user_power_setting = IWL_POWER_MODE_CAM;
323 ret = iwl_power_update_mode(priv, 0);
324 priv->power_data.power_disabled = 1;
325 priv->power_data.user_power_setting = prev_mode;
326 cancel_delayed_work(&priv->set_power_save);
327 if (ms)
328 queue_delayed_work(priv->workqueue, &priv->set_power_save,
329 msecs_to_jiffies(ms));
330
331
332 return ret;
333}
334EXPORT_SYMBOL(iwl_power_disable_management);
335
336/* Allow other iwl code to disable/enable power management active
337 * this will be useful for rate scale to disable PM during high
338 * volume activities
339 */
340int iwl_power_enable_management(struct iwl_priv *priv)
341{
342 int ret = 0;
343
344 priv->power_data.power_disabled = 0;
345 ret = iwl_power_update_mode(priv, 0);
346 return ret;
347}
348EXPORT_SYMBOL(iwl_power_enable_management);
349
350/* set user_power_setting */ 258/* set user_power_setting */
351int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode) 259int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
352{ 260{
353 if (mode > IWL_POWER_MAX) 261 if (mode >= IWL_POWER_NUM)
354 return -EINVAL; 262 return -EINVAL;
355 263
356 priv->power_data.user_power_setting = mode; 264 priv->power_data.user_power_setting = mode;
@@ -359,86 +267,12 @@ int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
359} 267}
360EXPORT_SYMBOL(iwl_power_set_user_mode); 268EXPORT_SYMBOL(iwl_power_set_user_mode);
361 269
362/* set system_power_setting. This should be set by over all
363 * PM application.
364 */
365int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode)
366{
367 if (mode < IWL_POWER_SYS_MAX)
368 priv->power_data.system_power_setting = mode;
369 else
370 return -EINVAL;
371 return iwl_power_update_mode(priv, 0);
372}
373EXPORT_SYMBOL(iwl_power_set_system_mode);
374
375/* initialize to default */ 270/* initialize to default */
376void iwl_power_initialize(struct iwl_priv *priv) 271void iwl_power_initialize(struct iwl_priv *priv)
377{ 272{
378 iwl_power_init_handle(priv); 273 iwl_power_init_handle(priv);
379 priv->power_data.user_power_setting = IWL_POWER_AUTO; 274 priv->power_data.user_power_setting = IWL_POWER_INDEX_1;
380 priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO; 275 /* default to disabled until mac80211 says otherwise */
381 priv->power_data.power_disabled = 0; 276 priv->power_data.power_disabled = 1;
382 priv->power_data.is_battery_active = 0;
383 priv->power_data.critical_power_setting = 0;
384} 277}
385EXPORT_SYMBOL(iwl_power_initialize); 278EXPORT_SYMBOL(iwl_power_initialize);
386
387/* set critical_power_setting according to temperature value */
388int iwl_power_temperature_change(struct iwl_priv *priv)
389{
390 int ret = 0;
391 s32 temperature = KELVIN_TO_CELSIUS(priv->last_temperature);
392 u16 new_critical = priv->power_data.critical_power_setting;
393
394 if (temperature > IWL_CT_KILL_TEMPERATURE)
395 return 0;
396 else if (temperature > IWL_MIN_POWER_TEMPERATURE)
397 new_critical = IWL_POWER_INDEX_5;
398 else if (temperature > IWL_REDUCED_POWER_TEMPERATURE)
399 new_critical = IWL_POWER_INDEX_3;
400 else
401 new_critical = IWL_POWER_MODE_CAM;
402
403 if (new_critical != priv->power_data.critical_power_setting)
404 priv->power_data.critical_power_setting = new_critical;
405
406 if (priv->power_data.critical_power_setting >
407 priv->power_data.power_mode)
408 ret = iwl_power_update_mode(priv, 0);
409
410 return ret;
411}
412EXPORT_SYMBOL(iwl_power_temperature_change);
413
414static void iwl_bg_set_power_save(struct work_struct *work)
415{
416 struct iwl_priv *priv = container_of(work,
417 struct iwl_priv, set_power_save.work);
418 IWL_DEBUG_POWER(priv, "update power\n");
419
420 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
421 return;
422
423 mutex_lock(&priv->mutex);
424
425 /* on starting association we disable power management
426 * until association, if association failed then this
427 * timer will expire and enable PM again.
428 */
429 if (!iwl_is_associated(priv))
430 iwl_power_enable_management(priv);
431
432 mutex_unlock(&priv->mutex);
433}
434void iwl_setup_power_deferred_work(struct iwl_priv *priv)
435{
436 INIT_DELAYED_WORK(&priv->set_power_save, iwl_bg_set_power_save);
437}
438EXPORT_SYMBOL(iwl_setup_power_deferred_work);
439
440void iwl_power_cancel_timeout(struct iwl_priv *priv)
441{
442 cancel_delayed_work(&priv->set_power_save);
443}
444EXPORT_SYMBOL(iwl_power_cancel_timeout);
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 18963392121e..37ba3bb7a25a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -40,56 +40,29 @@ enum {
40 IWL_POWER_INDEX_3, 40 IWL_POWER_INDEX_3,
41 IWL_POWER_INDEX_4, 41 IWL_POWER_INDEX_4,
42 IWL_POWER_INDEX_5, 42 IWL_POWER_INDEX_5,
43 IWL_POWER_AUTO, 43 IWL_POWER_NUM
44 IWL_POWER_MAX = IWL_POWER_AUTO,
45}; 44};
46 45
47enum {
48 IWL_POWER_SYS_AUTO,
49 IWL_POWER_SYS_AC,
50 IWL_POWER_SYS_BATTERY,
51 IWL_POWER_SYS_MAX,
52};
53
54
55/* Power management (not Tx power) structures */ 46/* Power management (not Tx power) structures */
56 47
57#define NOSLP cpu_to_le16(0), 0, 0
58#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
59#define SLP_TOUT(T) cpu_to_le32((T) * MSEC_TO_USEC)
60#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \
61 cpu_to_le32(X1), \
62 cpu_to_le32(X2), \
63 cpu_to_le32(X3), \
64 cpu_to_le32(X4)}
65struct iwl_power_vec_entry { 48struct iwl_power_vec_entry {
66 struct iwl_powertable_cmd cmd; 49 struct iwl_powertable_cmd cmd;
67 u8 no_dtim; 50 u8 no_dtim;
68}; 51};
69 52
70struct iwl_power_mgr { 53struct iwl_power_mgr {
71 spinlock_t lock; 54 struct iwl_power_vec_entry pwr_range_0[IWL_POWER_NUM];
72 struct iwl_power_vec_entry pwr_range_0[IWL_POWER_MAX]; 55 struct iwl_power_vec_entry pwr_range_1[IWL_POWER_NUM];
73 struct iwl_power_vec_entry pwr_range_1[IWL_POWER_MAX]; 56 struct iwl_power_vec_entry pwr_range_2[IWL_POWER_NUM];
74 struct iwl_power_vec_entry pwr_range_2[IWL_POWER_MAX];
75 u32 dtim_period; 57 u32 dtim_period;
76 /* final power level that used to calculate final power command */ 58 /* final power level that used to calculate final power command */
77 u8 power_mode; 59 u8 power_mode;
78 u8 user_power_setting; /* set by user through mac80211 or sysfs */ 60 u8 user_power_setting; /* set by user through sysfs */
79 u8 system_power_setting; /* set by kernel system tools */ 61 u8 power_disabled; /* set by mac80211's CONF_PS */
80 u8 critical_power_setting; /* set if driver over heated */
81 u8 is_battery_active; /* DC/AC power */
82 u8 power_disabled; /* flag to disable using power saving level */
83}; 62};
84 63
85void iwl_setup_power_deferred_work(struct iwl_priv *priv);
86void iwl_power_cancel_timeout(struct iwl_priv *priv);
87int iwl_power_update_mode(struct iwl_priv *priv, bool force); 64int iwl_power_update_mode(struct iwl_priv *priv, bool force);
88int iwl_power_disable_management(struct iwl_priv *priv, u32 ms);
89int iwl_power_enable_management(struct iwl_priv *priv);
90int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode); 65int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode);
91int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode);
92void iwl_power_initialize(struct iwl_priv *priv); 66void iwl_power_initialize(struct iwl_priv *priv);
93int iwl_power_temperature_change(struct iwl_priv *priv);
94 67
95#endif /* __iwl_power_setting_h__ */ 68#endif /* __iwl_power_setting_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 271e5d1f8425..c32ec809053f 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -3845,26 +3845,11 @@ static ssize_t show_power_level(struct device *d,
3845{ 3845{
3846 struct iwl_priv *priv = dev_get_drvdata(d); 3846 struct iwl_priv *priv = dev_get_drvdata(d);
3847 int mode = priv->power_data.user_power_setting; 3847 int mode = priv->power_data.user_power_setting;
3848 int system = priv->power_data.system_power_setting;
3849 int level = priv->power_data.power_mode; 3848 int level = priv->power_data.power_mode;
3850 char *p = buf; 3849 char *p = buf;
3851 3850
3852 switch (system) { 3851 p += sprintf(p, "INDEX:%d\t", level);
3853 case IWL_POWER_SYS_AUTO: 3852 p += sprintf(p, "USER:%d\n", mode);
3854 p += sprintf(p, "SYSTEM:auto");
3855 break;
3856 case IWL_POWER_SYS_AC:
3857 p += sprintf(p, "SYSTEM:ac");
3858 break;
3859 case IWL_POWER_SYS_BATTERY:
3860 p += sprintf(p, "SYSTEM:battery");
3861 break;
3862 }
3863
3864 p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ?
3865 "fixed" : "auto");
3866 p += sprintf(p, "\tINDEX:%d", level);
3867 p += sprintf(p, "\n");
3868 return p - buf + 1; 3853 return p - buf + 1;
3869} 3854}
3870 3855
@@ -4108,7 +4093,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
4108 priv->ibss_beacon = NULL; 4093 priv->ibss_beacon = NULL;
4109 4094
4110 spin_lock_init(&priv->lock); 4095 spin_lock_init(&priv->lock);
4111 spin_lock_init(&priv->power_data.lock);
4112 spin_lock_init(&priv->sta_lock); 4096 spin_lock_init(&priv->sta_lock);
4113 spin_lock_init(&priv->hcmd_lock); 4097 spin_lock_init(&priv->hcmd_lock);
4114 4098