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.c149
1 files changed, 119 insertions, 30 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 60be976afff..9c6b1495206 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -165,26 +165,26 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
165 *============================================================================= 165 *=============================================================================
166 * Condition Nxt State Condition Nxt State Condition Nxt State 166 * Condition Nxt State Condition Nxt State Condition Nxt State
167 *----------------------------------------------------------------------------- 167 *-----------------------------------------------------------------------------
168 * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A 168 * 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 169 * 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 170 * 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 171 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
172 *============================================================================= 172 *=============================================================================
173 */ 173 */
174static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { 174static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
175 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, 175 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
176 {IWL_TI_1, 105, CT_KILL_THRESHOLD}, 176 {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1},
177 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} 177 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
178}; 178};
179static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { 179static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
180 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, 180 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
181 {IWL_TI_2, 110, CT_KILL_THRESHOLD}, 181 {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1},
182 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} 182 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
183}; 183};
184static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { 184static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
185 {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, 185 {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
186 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, 186 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX},
187 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} 187 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
188}; 188};
189static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { 189static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
190 {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, 190 {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
@@ -294,6 +294,9 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
294 294
295 if (priv->cfg->broken_powersave) 295 if (priv->cfg->broken_powersave)
296 iwl_power_sleep_cam_cmd(priv, &cmd); 296 iwl_power_sleep_cam_cmd(priv, &cmd);
297 else if (priv->cfg->supports_idle &&
298 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
299 iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20);
297 else if (tt->state >= IWL_TI_1) 300 else if (tt->state >= IWL_TI_1)
298 iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); 301 iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper);
299 else if (!enabled) 302 else if (!enabled)
@@ -348,6 +351,23 @@ bool iwl_ht_enabled(struct iwl_priv *priv)
348} 351}
349EXPORT_SYMBOL(iwl_ht_enabled); 352EXPORT_SYMBOL(iwl_ht_enabled);
350 353
354bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
355{
356 s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */
357 bool within_margin = false;
358
359 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
360 temp = KELVIN_TO_CELSIUS(priv->temperature);
361
362 if (!priv->thermal_throttle.advanced_tt)
363 within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
364 CT_KILL_THRESHOLD_LEGACY) ? true : false;
365 else
366 within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
367 CT_KILL_THRESHOLD) ? true : false;
368 return within_margin;
369}
370
351enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) 371enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
352{ 372{
353 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 373 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
@@ -372,6 +392,7 @@ enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
372} 392}
373 393
374#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ 394#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */
395#define CT_KILL_WAITING_DURATION (300) /* 300ms duration */
375 396
376/* 397/*
377 * toggle the bit to wake up uCode and check the temperature 398 * toggle the bit to wake up uCode and check the temperature
@@ -409,6 +430,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
409 /* Reschedule the ct_kill timer to occur in 430 /* Reschedule the ct_kill timer to occur in
410 * CT_KILL_EXIT_DURATION seconds to ensure we get a 431 * CT_KILL_EXIT_DURATION seconds to ensure we get a
411 * thermal update */ 432 * thermal update */
433 IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
412 mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + 434 mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
413 CT_KILL_EXIT_DURATION * HZ); 435 CT_KILL_EXIT_DURATION * HZ);
414 } 436 }
@@ -432,6 +454,33 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
432 } 454 }
433} 455}
434 456
457static void iwl_tt_ready_for_ct_kill(unsigned long data)
458{
459 struct iwl_priv *priv = (struct iwl_priv *)data;
460 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
461
462 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
463 return;
464
465 /* temperature timer expired, ready to go into CT_KILL state */
466 if (tt->state != IWL_TI_CT_KILL) {
467 IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n");
468 tt->state = IWL_TI_CT_KILL;
469 set_bit(STATUS_CT_KILL, &priv->status);
470 iwl_perform_ct_kill_task(priv, true);
471 }
472}
473
474static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
475{
476 IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
477 /* make request to retrieve statistics information */
478 iwl_send_statistics_request(priv, 0);
479 /* Reschedule the ct_kill wait timer */
480 mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
481 jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));
482}
483
435#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) 484#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY)
436#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) 485#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100)
437#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) 486#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90)
@@ -445,7 +494,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
445 * Throttle early enough to lower the power consumption before 494 * Throttle early enough to lower the power consumption before
446 * drastic steps are needed 495 * drastic steps are needed
447 */ 496 */
448static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) 497static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
449{ 498{
450 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 499 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
451 enum iwl_tt_state old_state; 500 enum iwl_tt_state old_state;
@@ -474,6 +523,8 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
474#ifdef CONFIG_IWLWIFI_DEBUG 523#ifdef CONFIG_IWLWIFI_DEBUG
475 tt->tt_previous_temp = temp; 524 tt->tt_previous_temp = temp;
476#endif 525#endif
526 /* stop ct_kill_waiting_tm timer */
527 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
477 if (tt->state != old_state) { 528 if (tt->state != old_state) {
478 switch (tt->state) { 529 switch (tt->state) {
479 case IWL_TI_0: 530 case IWL_TI_0:
@@ -494,17 +545,28 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
494 break; 545 break;
495 } 546 }
496 mutex_lock(&priv->mutex); 547 mutex_lock(&priv->mutex);
497 if (iwl_power_update_mode(priv, true)) { 548 if (old_state == IWL_TI_CT_KILL)
549 clear_bit(STATUS_CT_KILL, &priv->status);
550 if (tt->state != IWL_TI_CT_KILL &&
551 iwl_power_update_mode(priv, true)) {
498 /* TT state not updated 552 /* TT state not updated
499 * try again during next temperature read 553 * try again during next temperature read
500 */ 554 */
555 if (old_state == IWL_TI_CT_KILL)
556 set_bit(STATUS_CT_KILL, &priv->status);
501 tt->state = old_state; 557 tt->state = old_state;
502 IWL_ERR(priv, "Cannot update power mode, " 558 IWL_ERR(priv, "Cannot update power mode, "
503 "TT state not updated\n"); 559 "TT state not updated\n");
504 } else { 560 } else {
505 if (tt->state == IWL_TI_CT_KILL) 561 if (tt->state == IWL_TI_CT_KILL) {
506 iwl_perform_ct_kill_task(priv, true); 562 if (force) {
507 else if (old_state == IWL_TI_CT_KILL && 563 set_bit(STATUS_CT_KILL, &priv->status);
564 iwl_perform_ct_kill_task(priv, true);
565 } else {
566 iwl_prepare_ct_kill_task(priv);
567 tt->state = old_state;
568 }
569 } else if (old_state == IWL_TI_CT_KILL &&
508 tt->state != IWL_TI_CT_KILL) 570 tt->state != IWL_TI_CT_KILL)
509 iwl_perform_ct_kill_task(priv, false); 571 iwl_perform_ct_kill_task(priv, false);
510 IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", 572 IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
@@ -531,13 +593,13 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
531 *============================================================================= 593 *=============================================================================
532 * Condition Nxt State Condition Nxt State Condition Nxt State 594 * Condition Nxt State Condition Nxt State Condition Nxt State
533 *----------------------------------------------------------------------------- 595 *-----------------------------------------------------------------------------
534 * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A 596 * 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 597 * 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 598 * 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 599 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
538 *============================================================================= 600 *=============================================================================
539 */ 601 */
540static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) 602static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
541{ 603{
542 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 604 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
543 int i; 605 int i;
@@ -582,6 +644,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
582 break; 644 break;
583 } 645 }
584 } 646 }
647 /* stop ct_kill_waiting_tm timer */
648 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
585 if (changed) { 649 if (changed) {
586 struct iwl_rxon_cmd *rxon = &priv->staging_rxon; 650 struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
587 651
@@ -613,12 +677,17 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
613 iwl_set_rxon_ht(priv, &priv->current_ht_config); 677 iwl_set_rxon_ht(priv, &priv->current_ht_config);
614 } 678 }
615 mutex_lock(&priv->mutex); 679 mutex_lock(&priv->mutex);
616 if (iwl_power_update_mode(priv, true)) { 680 if (old_state == IWL_TI_CT_KILL)
681 clear_bit(STATUS_CT_KILL, &priv->status);
682 if (tt->state != IWL_TI_CT_KILL &&
683 iwl_power_update_mode(priv, true)) {
617 /* TT state not updated 684 /* TT state not updated
618 * try again during next temperature read 685 * try again during next temperature read
619 */ 686 */
620 IWL_ERR(priv, "Cannot update power mode, " 687 IWL_ERR(priv, "Cannot update power mode, "
621 "TT state not updated\n"); 688 "TT state not updated\n");
689 if (old_state == IWL_TI_CT_KILL)
690 set_bit(STATUS_CT_KILL, &priv->status);
622 tt->state = old_state; 691 tt->state = old_state;
623 } else { 692 } else {
624 IWL_DEBUG_POWER(priv, 693 IWL_DEBUG_POWER(priv,
@@ -626,9 +695,15 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
626 tt->state); 695 tt->state);
627 if (old_state != IWL_TI_CT_KILL && 696 if (old_state != IWL_TI_CT_KILL &&
628 tt->state == IWL_TI_CT_KILL) { 697 tt->state == IWL_TI_CT_KILL) {
629 IWL_DEBUG_POWER(priv, "Enter IWL_TI_CT_KILL\n"); 698 if (force) {
630 iwl_perform_ct_kill_task(priv, true); 699 IWL_DEBUG_POWER(priv,
631 700 "Enter IWL_TI_CT_KILL\n");
701 set_bit(STATUS_CT_KILL, &priv->status);
702 iwl_perform_ct_kill_task(priv, true);
703 } else {
704 iwl_prepare_ct_kill_task(priv);
705 tt->state = old_state;
706 }
632 } else if (old_state == IWL_TI_CT_KILL && 707 } else if (old_state == IWL_TI_CT_KILL &&
633 tt->state != IWL_TI_CT_KILL) { 708 tt->state != IWL_TI_CT_KILL) {
634 IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); 709 IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
@@ -665,10 +740,11 @@ static void iwl_bg_ct_enter(struct work_struct *work)
665 "- ucode going to sleep!\n"); 740 "- ucode going to sleep!\n");
666 if (!priv->thermal_throttle.advanced_tt) 741 if (!priv->thermal_throttle.advanced_tt)
667 iwl_legacy_tt_handler(priv, 742 iwl_legacy_tt_handler(priv,
668 IWL_MINIMAL_POWER_THRESHOLD); 743 IWL_MINIMAL_POWER_THRESHOLD,
744 true);
669 else 745 else
670 iwl_advance_tt_handler(priv, 746 iwl_advance_tt_handler(priv,
671 CT_KILL_THRESHOLD + 1); 747 CT_KILL_THRESHOLD + 1, true);
672 } 748 }
673} 749}
674 750
@@ -695,11 +771,18 @@ static void iwl_bg_ct_exit(struct work_struct *work)
695 IWL_ERR(priv, 771 IWL_ERR(priv,
696 "Device temperature below critical" 772 "Device temperature below critical"
697 "- ucode awake!\n"); 773 "- ucode awake!\n");
774 /*
775 * exit from CT_KILL state
776 * reset the current temperature reading
777 */
778 priv->temperature = 0;
698 if (!priv->thermal_throttle.advanced_tt) 779 if (!priv->thermal_throttle.advanced_tt)
699 iwl_legacy_tt_handler(priv, 780 iwl_legacy_tt_handler(priv,
700 IWL_REDUCED_PERFORMANCE_THRESHOLD_2); 781 IWL_REDUCED_PERFORMANCE_THRESHOLD_2,
782 true);
701 else 783 else
702 iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD); 784 iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD,
785 true);
703 } 786 }
704} 787}
705 788
@@ -735,9 +818,9 @@ static void iwl_bg_tt_work(struct work_struct *work)
735 temp = KELVIN_TO_CELSIUS(priv->temperature); 818 temp = KELVIN_TO_CELSIUS(priv->temperature);
736 819
737 if (!priv->thermal_throttle.advanced_tt) 820 if (!priv->thermal_throttle.advanced_tt)
738 iwl_legacy_tt_handler(priv, temp); 821 iwl_legacy_tt_handler(priv, temp, false);
739 else 822 else
740 iwl_advance_tt_handler(priv, temp); 823 iwl_advance_tt_handler(priv, temp, false);
741} 824}
742 825
743void iwl_tt_handler(struct iwl_priv *priv) 826void iwl_tt_handler(struct iwl_priv *priv)
@@ -768,8 +851,12 @@ void iwl_tt_initialize(struct iwl_priv *priv)
768 tt->state = IWL_TI_0; 851 tt->state = IWL_TI_0;
769 init_timer(&priv->thermal_throttle.ct_kill_exit_tm); 852 init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
770 priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; 853 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; 854 priv->thermal_throttle.ct_kill_exit_tm.function =
772 855 iwl_tt_check_exit_ct_kill;
856 init_timer(&priv->thermal_throttle.ct_kill_waiting_tm);
857 priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv;
858 priv->thermal_throttle.ct_kill_waiting_tm.function =
859 iwl_tt_ready_for_ct_kill;
773 /* setup deferred ct kill work */ 860 /* setup deferred ct kill work */
774 INIT_WORK(&priv->tt_work, iwl_bg_tt_work); 861 INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
775 INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); 862 INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
@@ -826,6 +913,8 @@ void iwl_tt_exit(struct iwl_priv *priv)
826 913
827 /* stop ct_kill_exit_tm timer if activated */ 914 /* stop ct_kill_exit_tm timer if activated */
828 del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); 915 del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
916 /* stop ct_kill_waiting_tm timer if activated */
917 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
829 cancel_work_sync(&priv->tt_work); 918 cancel_work_sync(&priv->tt_work);
830 cancel_work_sync(&priv->ct_enter); 919 cancel_work_sync(&priv->ct_enter);
831 cancel_work_sync(&priv->ct_exit); 920 cancel_work_sync(&priv->ct_exit);