diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-power.c | 146 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-power.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 10 |
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 | ||
628 | static inline int iwl_is_ctkill(struct iwl_priv *priv) | ||
629 | { | ||
630 | return test_bit(STATUS_CT_KILL, &priv->status); | ||
631 | } | ||
632 | |||
627 | static inline int iwl_is_ready_rf(struct iwl_priv *priv) | 633 | static 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 | */ |
174 | static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { | 174 | static 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 | }; |
179 | static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { | 179 | static 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 | }; |
184 | static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { | 184 | static 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 | }; |
189 | static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { | 189 | static 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 | } |
352 | EXPORT_SYMBOL(iwl_ht_enabled); | 352 | EXPORT_SYMBOL(iwl_ht_enabled); |
353 | 353 | ||
354 | bool 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 | |||
354 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) | 371 | enum 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 | ||
457 | static 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 | |||
474 | static 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 | */ |
451 | static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) | 497 | static 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 | */ |
543 | static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) | 602 | static 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 | ||
746 | void iwl_tt_handler(struct iwl_priv *priv) | 826 | void 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 | ||
37 | enum iwl_antenna_ok { | 38 | enum 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 | ||
115 | enum iwl_power_level { | 117 | enum iwl_power_level { |
@@ -129,6 +131,7 @@ struct iwl_power_mgr { | |||
129 | 131 | ||
130 | int iwl_power_update_mode(struct iwl_priv *priv, bool force); | 132 | int iwl_power_update_mode(struct iwl_priv *priv, bool force); |
131 | bool iwl_ht_enabled(struct iwl_priv *priv); | 133 | bool iwl_ht_enabled(struct iwl_priv *priv); |
134 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv); | ||
132 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); | 135 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); |
133 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); | 136 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); |
134 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv); | 137 | void 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 | ||