diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-power.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-power.c | 66 |
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 */ |
153 | static int iwl_power_init_handle(struct iwl_priv *priv) | 153 | static 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 | */ |
327 | int iwl_power_disable_management(struct iwl_priv *priv) | 322 | int 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 | } |
433 | EXPORT_SYMBOL(iwl_power_temperature_change); | 433 | EXPORT_SYMBOL(iwl_power_temperature_change); |
434 | |||
435 | static 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 | } | ||
455 | void iwl_setup_power_deferred_work(struct iwl_priv *priv) | ||
456 | { | ||
457 | INIT_DELAYED_WORK(&priv->set_power_save, iwl_bg_set_power_save); | ||
458 | } | ||
459 | EXPORT_SYMBOL(iwl_setup_power_deferred_work); | ||
460 | |||
461 | void iwl_power_cancel_timeout(struct iwl_priv *priv) | ||
462 | { | ||
463 | cancel_delayed_work(&priv->set_power_save); | ||
464 | } | ||
465 | EXPORT_SYMBOL(iwl_power_cancel_timeout); | ||