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.c146
1 files changed, 116 insertions, 30 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index e50d77bd7aad..9c6b14952061 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},
@@ -351,6 +351,23 @@ bool iwl_ht_enabled(struct iwl_priv *priv)
351} 351}
352EXPORT_SYMBOL(iwl_ht_enabled); 352EXPORT_SYMBOL(iwl_ht_enabled);
353 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
354enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) 371enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
355{ 372{
356 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 373 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
@@ -375,6 +392,7 @@ enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
375} 392}
376 393
377#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 */
378 396
379/* 397/*
380 * toggle the bit to wake up uCode and check the temperature 398 * toggle the bit to wake up uCode and check the temperature
@@ -412,6 +430,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
412 /* Reschedule the ct_kill timer to occur in 430 /* Reschedule the ct_kill timer to occur in
413 * CT_KILL_EXIT_DURATION seconds to ensure we get a 431 * CT_KILL_EXIT_DURATION seconds to ensure we get a
414 * thermal update */ 432 * thermal update */
433 IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
415 mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + 434 mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
416 CT_KILL_EXIT_DURATION * HZ); 435 CT_KILL_EXIT_DURATION * HZ);
417 } 436 }
@@ -435,6 +454,33 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
435 } 454 }
436} 455}
437 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
438#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) 484#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY)
439#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) 485#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100)
440#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) 486#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90)
@@ -448,7 +494,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
448 * Throttle early enough to lower the power consumption before 494 * Throttle early enough to lower the power consumption before
449 * drastic steps are needed 495 * drastic steps are needed
450 */ 496 */
451static 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)
452{ 498{
453 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 499 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
454 enum iwl_tt_state old_state; 500 enum iwl_tt_state old_state;
@@ -477,6 +523,8 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
477#ifdef CONFIG_IWLWIFI_DEBUG 523#ifdef CONFIG_IWLWIFI_DEBUG
478 tt->tt_previous_temp = temp; 524 tt->tt_previous_temp = temp;
479#endif 525#endif
526 /* stop ct_kill_waiting_tm timer */
527 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
480 if (tt->state != old_state) { 528 if (tt->state != old_state) {
481 switch (tt->state) { 529 switch (tt->state) {
482 case IWL_TI_0: 530 case IWL_TI_0:
@@ -497,17 +545,28 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
497 break; 545 break;
498 } 546 }
499 mutex_lock(&priv->mutex); 547 mutex_lock(&priv->mutex);
500 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)) {
501 /* TT state not updated 552 /* TT state not updated
502 * try again during next temperature read 553 * try again during next temperature read
503 */ 554 */
555 if (old_state == IWL_TI_CT_KILL)
556 set_bit(STATUS_CT_KILL, &priv->status);
504 tt->state = old_state; 557 tt->state = old_state;
505 IWL_ERR(priv, "Cannot update power mode, " 558 IWL_ERR(priv, "Cannot update power mode, "
506 "TT state not updated\n"); 559 "TT state not updated\n");
507 } else { 560 } else {
508 if (tt->state == IWL_TI_CT_KILL) 561 if (tt->state == IWL_TI_CT_KILL) {
509 iwl_perform_ct_kill_task(priv, true); 562 if (force) {
510 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 &&
511 tt->state != IWL_TI_CT_KILL) 570 tt->state != IWL_TI_CT_KILL)
512 iwl_perform_ct_kill_task(priv, false); 571 iwl_perform_ct_kill_task(priv, false);
513 IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", 572 IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
@@ -534,13 +593,13 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
534 *============================================================================= 593 *=============================================================================
535 * Condition Nxt State Condition Nxt State Condition Nxt State 594 * Condition Nxt State Condition Nxt State Condition Nxt State
536 *----------------------------------------------------------------------------- 595 *-----------------------------------------------------------------------------
537 * 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
538 * 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
539 * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1 598 * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1
540 * 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
541 *============================================================================= 600 *=============================================================================
542 */ 601 */
543static 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)
544{ 603{
545 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 604 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
546 int i; 605 int i;
@@ -585,6 +644,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
585 break; 644 break;
586 } 645 }
587 } 646 }
647 /* stop ct_kill_waiting_tm timer */
648 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
588 if (changed) { 649 if (changed) {
589 struct iwl_rxon_cmd *rxon = &priv->staging_rxon; 650 struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
590 651
@@ -616,12 +677,17 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
616 iwl_set_rxon_ht(priv, &priv->current_ht_config); 677 iwl_set_rxon_ht(priv, &priv->current_ht_config);
617 } 678 }
618 mutex_lock(&priv->mutex); 679 mutex_lock(&priv->mutex);
619 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)) {
620 /* TT state not updated 684 /* TT state not updated
621 * try again during next temperature read 685 * try again during next temperature read
622 */ 686 */
623 IWL_ERR(priv, "Cannot update power mode, " 687 IWL_ERR(priv, "Cannot update power mode, "
624 "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);
625 tt->state = old_state; 691 tt->state = old_state;
626 } else { 692 } else {
627 IWL_DEBUG_POWER(priv, 693 IWL_DEBUG_POWER(priv,
@@ -629,9 +695,15 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
629 tt->state); 695 tt->state);
630 if (old_state != IWL_TI_CT_KILL && 696 if (old_state != IWL_TI_CT_KILL &&
631 tt->state == IWL_TI_CT_KILL) { 697 tt->state == IWL_TI_CT_KILL) {
632 IWL_DEBUG_POWER(priv, "Enter IWL_TI_CT_KILL\n"); 698 if (force) {
633 iwl_perform_ct_kill_task(priv, true); 699 IWL_DEBUG_POWER(priv,
634 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 }
635 } else if (old_state == IWL_TI_CT_KILL && 707 } else if (old_state == IWL_TI_CT_KILL &&
636 tt->state != IWL_TI_CT_KILL) { 708 tt->state != IWL_TI_CT_KILL) {
637 IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); 709 IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
@@ -668,10 +740,11 @@ static void iwl_bg_ct_enter(struct work_struct *work)
668 "- ucode going to sleep!\n"); 740 "- ucode going to sleep!\n");
669 if (!priv->thermal_throttle.advanced_tt) 741 if (!priv->thermal_throttle.advanced_tt)
670 iwl_legacy_tt_handler(priv, 742 iwl_legacy_tt_handler(priv,
671 IWL_MINIMAL_POWER_THRESHOLD); 743 IWL_MINIMAL_POWER_THRESHOLD,
744 true);
672 else 745 else
673 iwl_advance_tt_handler(priv, 746 iwl_advance_tt_handler(priv,
674 CT_KILL_THRESHOLD + 1); 747 CT_KILL_THRESHOLD + 1, true);
675 } 748 }
676} 749}
677 750
@@ -698,11 +771,18 @@ static void iwl_bg_ct_exit(struct work_struct *work)
698 IWL_ERR(priv, 771 IWL_ERR(priv,
699 "Device temperature below critical" 772 "Device temperature below critical"
700 "- 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;
701 if (!priv->thermal_throttle.advanced_tt) 779 if (!priv->thermal_throttle.advanced_tt)
702 iwl_legacy_tt_handler(priv, 780 iwl_legacy_tt_handler(priv,
703 IWL_REDUCED_PERFORMANCE_THRESHOLD_2); 781 IWL_REDUCED_PERFORMANCE_THRESHOLD_2,
782 true);
704 else 783 else
705 iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD); 784 iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD,
785 true);
706 } 786 }
707} 787}
708 788
@@ -738,9 +818,9 @@ static void iwl_bg_tt_work(struct work_struct *work)
738 temp = KELVIN_TO_CELSIUS(priv->temperature); 818 temp = KELVIN_TO_CELSIUS(priv->temperature);
739 819
740 if (!priv->thermal_throttle.advanced_tt) 820 if (!priv->thermal_throttle.advanced_tt)
741 iwl_legacy_tt_handler(priv, temp); 821 iwl_legacy_tt_handler(priv, temp, false);
742 else 822 else
743 iwl_advance_tt_handler(priv, temp); 823 iwl_advance_tt_handler(priv, temp, false);
744} 824}
745 825
746void iwl_tt_handler(struct iwl_priv *priv) 826void iwl_tt_handler(struct iwl_priv *priv)
@@ -771,8 +851,12 @@ void iwl_tt_initialize(struct iwl_priv *priv)
771 tt->state = IWL_TI_0; 851 tt->state = IWL_TI_0;
772 init_timer(&priv->thermal_throttle.ct_kill_exit_tm); 852 init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
773 priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; 853 priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
774 priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill; 854 priv->thermal_throttle.ct_kill_exit_tm.function =
775 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;
776 /* setup deferred ct kill work */ 860 /* setup deferred ct kill work */
777 INIT_WORK(&priv->tt_work, iwl_bg_tt_work); 861 INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
778 INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); 862 INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
@@ -829,6 +913,8 @@ void iwl_tt_exit(struct iwl_priv *priv)
829 913
830 /* stop ct_kill_exit_tm timer if activated */ 914 /* stop ct_kill_exit_tm timer if activated */
831 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);
832 cancel_work_sync(&priv->tt_work); 918 cancel_work_sync(&priv->tt_work);
833 cancel_work_sync(&priv->ct_enter); 919 cancel_work_sync(&priv->ct_enter);
834 cancel_work_sync(&priv->ct_exit); 920 cancel_work_sync(&priv->ct_exit);