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.c66
1 files changed, 49 insertions, 17 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index a099c9e30e55..16f834d0c486 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -152,9 +152,10 @@ static u16 iwl_get_auto_power_mode(struct iwl_priv *priv)
152/* initialize to default */ 152/* initialize to default */
153static int iwl_power_init_handle(struct iwl_priv *priv) 153static int iwl_power_init_handle(struct iwl_priv *priv)
154{ 154{
155 int ret = 0, i;
156 struct iwl_power_mgr *pow_data; 155 struct iwl_power_mgr *pow_data;
157 int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX; 156 int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX;
157 struct iwl_powertable_cmd *cmd;
158 int i;
158 u16 pci_pm; 159 u16 pci_pm;
159 160
160 IWL_DEBUG_POWER("Initialize power \n"); 161 IWL_DEBUG_POWER("Initialize power \n");
@@ -167,25 +168,19 @@ static int iwl_power_init_handle(struct iwl_priv *priv)
167 memcpy(&pow_data->pwr_range_1[0], &range_1[0], size); 168 memcpy(&pow_data->pwr_range_1[0], &range_1[0], size);
168 memcpy(&pow_data->pwr_range_2[0], &range_2[0], size); 169 memcpy(&pow_data->pwr_range_2[0], &range_2[0], size);
169 170
170 ret = pci_read_config_word(priv->pci_dev, 171 pci_read_config_word(priv->pci_dev, PCI_CFG_LINK_CTRL, &pci_pm);
171 PCI_LINK_CTRL, &pci_pm);
172 if (ret != 0)
173 return 0;
174 else {
175 struct iwl_powertable_cmd *cmd;
176 172
177 IWL_DEBUG_POWER("adjust power command flags\n"); 173 IWL_DEBUG_POWER("adjust power command flags\n");
178 174
179 for (i = 0; i < IWL_POWER_MAX; i++) { 175 for (i = 0; i < IWL_POWER_MAX; i++) {
180 cmd = &pow_data->pwr_range_0[i].cmd; 176 cmd = &pow_data->pwr_range_0[i].cmd;
181 177
182 if (pci_pm & 0x1) 178 if (pci_pm & PCI_CFG_LINK_CTRL_VAL_L0S_EN)
183 cmd->flags &= ~IWL_POWER_PCI_PM_MSK; 179 cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
184 else 180 else
185 cmd->flags |= IWL_POWER_PCI_PM_MSK; 181 cmd->flags |= IWL_POWER_PCI_PM_MSK;
186 }
187 } 182 }
188 return ret; 183 return 0;
189} 184}
190 185
191/* adjust power command according to dtim period and power level*/ 186/* adjust power command according to dtim period and power level*/
@@ -324,7 +319,7 @@ EXPORT_SYMBOL(iwl_power_update_mode);
324 * this will be usefull for rate scale to disable PM during heavy 319 * this will be usefull for rate scale to disable PM during heavy
325 * Tx/Rx activities 320 * Tx/Rx activities
326 */ 321 */
327int iwl_power_disable_management(struct iwl_priv *priv) 322int iwl_power_disable_management(struct iwl_priv *priv, u32 ms)
328{ 323{
329 u16 prev_mode; 324 u16 prev_mode;
330 int ret = 0; 325 int ret = 0;
@@ -337,6 +332,11 @@ int iwl_power_disable_management(struct iwl_priv *priv)
337 ret = iwl_power_update_mode(priv, 0); 332 ret = iwl_power_update_mode(priv, 0);
338 priv->power_data.power_disabled = 1; 333 priv->power_data.power_disabled = 1;
339 priv->power_data.user_power_setting = prev_mode; 334 priv->power_data.user_power_setting = prev_mode;
335 cancel_delayed_work(&priv->set_power_save);
336 if (ms)
337 queue_delayed_work(priv->workqueue, &priv->set_power_save,
338 msecs_to_jiffies(ms));
339
340 340
341 return ret; 341 return ret;
342} 342}
@@ -431,3 +431,35 @@ int iwl_power_temperature_change(struct iwl_priv *priv)
431 return ret; 431 return ret;
432} 432}
433EXPORT_SYMBOL(iwl_power_temperature_change); 433EXPORT_SYMBOL(iwl_power_temperature_change);
434
435static void iwl_bg_set_power_save(struct work_struct *work)
436{
437 struct iwl_priv *priv = container_of(work,
438 struct iwl_priv, set_power_save.work);
439 IWL_DEBUG(IWL_DL_STATE, "update power\n");
440
441 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
442 return;
443
444 mutex_lock(&priv->mutex);
445
446 /* on starting association we disable power managment
447 * until association, if association failed then this
448 * timer will expire and enable PM again.
449 */
450 if (!iwl_is_associated(priv))
451 iwl_power_enable_management(priv);
452
453 mutex_unlock(&priv->mutex);
454}
455void iwl_setup_power_deferred_work(struct iwl_priv *priv)
456{
457 INIT_DELAYED_WORK(&priv->set_power_save, iwl_bg_set_power_save);
458}
459EXPORT_SYMBOL(iwl_setup_power_deferred_work);
460
461void iwl_power_cancel_timeout(struct iwl_priv *priv)
462{
463 cancel_delayed_work(&priv->set_power_save);
464}
465EXPORT_SYMBOL(iwl_power_cancel_timeout);