aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c146
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c10
5 files changed, 135 insertions, 32 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 744f0cac6859..3bd0e59bb5a4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -580,6 +580,7 @@ void iwlcore_free_geos(struct iwl_priv *priv);
580#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ 580#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
581#define STATUS_INT_ENABLED 2 581#define STATUS_INT_ENABLED 2
582#define STATUS_RF_KILL_HW 3 582#define STATUS_RF_KILL_HW 3
583#define STATUS_CT_KILL 4
583#define STATUS_INIT 5 584#define STATUS_INIT 5
584#define STATUS_ALIVE 6 585#define STATUS_ALIVE 6
585#define STATUS_READY 7 586#define STATUS_READY 7
@@ -624,6 +625,11 @@ static inline int iwl_is_rfkill(struct iwl_priv *priv)
624 return iwl_is_rfkill_hw(priv); 625 return iwl_is_rfkill_hw(priv);
625} 626}
626 627
628static inline int iwl_is_ctkill(struct iwl_priv *priv)
629{
630 return test_bit(STATUS_CT_KILL, &priv->status);
631}
632
627static inline int iwl_is_ready_rf(struct iwl_priv *priv) 633static inline int iwl_is_ready_rf(struct iwl_priv *priv)
628{ 634{
629 635
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 037b75ca77f1..fa6371d171c5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -535,6 +535,8 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
535 test_bit(STATUS_INT_ENABLED, &priv->status)); 535 test_bit(STATUS_INT_ENABLED, &priv->status));
536 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", 536 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
537 test_bit(STATUS_RF_KILL_HW, &priv->status)); 537 test_bit(STATUS_RF_KILL_HW, &priv->status));
538 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
539 test_bit(STATUS_CT_KILL, &priv->status));
538 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", 540 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
539 test_bit(STATUS_INIT, &priv->status)); 541 test_bit(STATUS_INIT, &priv->status));
540 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", 542 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
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);
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index df6f6a49712b..310c32e8f698 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -33,6 +33,7 @@
33#define IWL_ABSOLUTE_ZERO 0 33#define IWL_ABSOLUTE_ZERO 0
34#define IWL_ABSOLUTE_MAX 0xFFFFFFFF 34#define IWL_ABSOLUTE_MAX 0xFFFFFFFF
35#define IWL_TT_INCREASE_MARGIN 5 35#define IWL_TT_INCREASE_MARGIN 5
36#define IWL_TT_CT_KILL_MARGIN 3
36 37
37enum iwl_antenna_ok { 38enum iwl_antenna_ok {
38 IWL_ANT_OK_NONE, 39 IWL_ANT_OK_NONE,
@@ -110,6 +111,7 @@ struct iwl_tt_mgmt {
110 struct iwl_tt_restriction *restriction; 111 struct iwl_tt_restriction *restriction;
111 struct iwl_tt_trans *transaction; 112 struct iwl_tt_trans *transaction;
112 struct timer_list ct_kill_exit_tm; 113 struct timer_list ct_kill_exit_tm;
114 struct timer_list ct_kill_waiting_tm;
113}; 115};
114 116
115enum iwl_power_level { 117enum iwl_power_level {
@@ -129,6 +131,7 @@ struct iwl_power_mgr {
129 131
130int iwl_power_update_mode(struct iwl_priv *priv, bool force); 132int iwl_power_update_mode(struct iwl_priv *priv, bool force);
131bool iwl_ht_enabled(struct iwl_priv *priv); 133bool iwl_ht_enabled(struct iwl_priv *priv);
134bool iwl_within_ct_kill_margin(struct iwl_priv *priv);
132enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); 135enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
133enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); 136enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
134void iwl_tt_enter_ct_kill(struct iwl_priv *priv); 137void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index ad69479376a6..2ba9725beff9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -969,13 +969,19 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
969 BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && 969 BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
970 !(cmd->flags & CMD_SIZE_HUGE)); 970 !(cmd->flags & CMD_SIZE_HUGE));
971 971
972 if (iwl_is_rfkill(priv)) { 972 if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
973 IWL_DEBUG_INFO(priv, "Not sending command - RF KILL\n"); 973 IWL_DEBUG_INFO(priv, "Not sending command - RF/CT KILL\n");
974 return -EIO; 974 return -EIO;
975 } 975 }
976 976
977 if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { 977 if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
978 IWL_ERR(priv, "No space for Tx\n"); 978 IWL_ERR(priv, "No space for Tx\n");
979 if (iwl_within_ct_kill_margin(priv))
980 iwl_tt_enter_ct_kill(priv);
981 else {
982 IWL_ERR(priv, "Restarting adapter due to queue full\n");
983 queue_work(priv->workqueue, &priv->restart);
984 }
979 return -ENOSPC; 985 return -ENOSPC;
980 } 986 }
981 987