aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-power.c
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2009-07-24 14:13:03 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-27 15:24:21 -0400
commit46f9381aa3fb62f6a141bfd41dcbeda1ec5fa26e (patch)
tree1023c715eac2b99b4443afbfefddb52719923593 /drivers/net/wireless/iwlwifi/iwl-power.c
parent39b73fb15e4704fd4d1e33688135810637f5f3fb (diff)
iwlwifi: Thermal Throttling Management - part 2
Part 2 of Thermal Throttling Management - Thermal Throttling feature is used to put NIC into low power state when driver detect the Radio temperature reach pre-defined threshold Two Thermal Throttling Management Methods; this patch introduce the Advance Thermal Throttling: TI-0: system power index, no tx/rx restriction, HT enabled TI-1: power index 5, 1 spatial stream Tx, multiple spatial stream Rx, HT enabled TI-2: power index 5: 1 spatial stream Tx, 1 spatial stream Rx, HT disabled TI-CT-KILL: power index 5, no Tx, no Rx, HT disabled For advance Thermal Throttling, CT_KILL_ENTER threshold and CT_KILL_EXIT threshold are different; uCode will not stay awake until reach CT_KILL_EXIT threshold. Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-power.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c285
1 files changed, 281 insertions, 4 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index d7fdb5825450..00937b3ee8ec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -98,6 +98,45 @@ static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
98 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} 98 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
99}; 99};
100 100
101/* default Thermal Throttling transaction table
102 * Current state | Throttling Down | Throttling Up
103 *=============================================================================
104 * Condition Nxt State Condition Nxt State Condition Nxt State
105 *-----------------------------------------------------------------------------
106 * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A
107 * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0
108 * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1
109 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
110 *=============================================================================
111 */
112static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
113 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
114 {IWL_TI_1, 105, CT_KILL_THRESHOLD},
115 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
116};
117static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
118 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
119 {IWL_TI_2, 110, CT_KILL_THRESHOLD},
120 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
121};
122static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
123 {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
124 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
125 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
126};
127static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
128 {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
129 {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
130 {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
131};
132
133/* Advance Thermal Throttling default restriction table */
134static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
135 {IWL_TX_MULTI, true, IWL_RX_MULTI},
136 {IWL_TX_SINGLE, true, IWL_RX_MULTI},
137 {IWL_TX_SINGLE, false, IWL_RX_SINGLE},
138 {IWL_TX_NONE, false, IWL_RX_NONE}
139};
101 140
102/* set card power command */ 141/* set card power command */
103static int iwl_set_power(struct iwl_priv *priv, void *cmd) 142static int iwl_set_power(struct iwl_priv *priv, void *cmd)
@@ -273,6 +312,42 @@ int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
273} 312}
274EXPORT_SYMBOL(iwl_power_set_user_mode); 313EXPORT_SYMBOL(iwl_power_set_user_mode);
275 314
315bool iwl_ht_enabled(struct iwl_priv *priv)
316{
317 struct iwl_tt_mgmt *tt = &priv->power_data.tt;
318 struct iwl_tt_restriction *restriction;
319
320 if (!priv->power_data.adv_tt)
321 return true;
322 restriction = tt->restriction + tt->state;
323 return restriction->is_ht;
324}
325EXPORT_SYMBOL(iwl_ht_enabled);
326
327u8 iwl_tx_ant_restriction(struct iwl_priv *priv)
328{
329 struct iwl_tt_mgmt *tt = &priv->power_data.tt;
330 struct iwl_tt_restriction *restriction;
331
332 if (!priv->power_data.adv_tt)
333 return IWL_TX_MULTI;
334 restriction = tt->restriction + tt->state;
335 return restriction->tx_stream;
336}
337EXPORT_SYMBOL(iwl_tx_ant_restriction);
338
339u8 iwl_rx_ant_restriction(struct iwl_priv *priv)
340{
341 struct iwl_tt_mgmt *tt = &priv->power_data.tt;
342 struct iwl_tt_restriction *restriction;
343
344 if (!priv->power_data.adv_tt)
345 return IWL_RX_MULTI;
346 restriction = tt->restriction + tt->state;
347 return restriction->rx_stream;
348}
349EXPORT_SYMBOL(iwl_rx_ant_restriction);
350
276#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ 351#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */
277 352
278/* 353/*
@@ -427,12 +502,147 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
427 } 502 }
428} 503}
429 504
505/*
506 * Advance thermal throttling
507 * 1) Avoid NIC destruction due to high temperatures
508 * Chip will identify dangerously high temperatures that can
509 * harm the device and will power down
510 * 2) Avoid the NIC power down due to high temperature
511 * Throttle early enough to lower the power consumption before
512 * drastic steps are needed
513 * Actions include relaxing the power down sleep thresholds and
514 * decreasing the number of TX streams
515 * 3) Avoid throughput performance impact as much as possible
516 *
517 *=============================================================================
518 * Condition Nxt State Condition Nxt State Condition Nxt State
519 *-----------------------------------------------------------------------------
520 * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A
521 * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0
522 * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1
523 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
524 *=============================================================================
525 */
526static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
527{
528 struct iwl_tt_mgmt *tt = &priv->power_data.tt;
529 int i;
530 bool changed = false;
531 enum iwl_tt_state old_state;
532 struct iwl_tt_trans *transaction;
533
534 old_state = tt->state;
535 for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) {
536 /* based on the current TT state,
537 * find the curresponding transaction table
538 * each table has (IWL_TI_STATE_MAX - 1) entries
539 * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1))
540 * will advance to the correct table.
541 * then based on the current temperature
542 * find the next state need to transaction to
543 * go through all the possible (IWL_TI_STATE_MAX - 1) entries
544 * in the current table to see if transaction is needed
545 */
546 transaction = tt->transaction +
547 ((old_state * (IWL_TI_STATE_MAX - 1)) + i);
548 if (temp >= transaction->tt_low &&
549 temp <= transaction->tt_high) {
550#ifdef CONFIG_IWLWIFI_DEBUG
551 if ((tt->tt_previous_temp) &&
552 (temp > tt->tt_previous_temp) &&
553 ((temp - tt->tt_previous_temp) >
554 IWL_TT_INCREASE_MARGIN)) {
555 IWL_DEBUG_POWER(priv,
556 "Temperature increase %d "
557 "degree Celsius\n",
558 (temp - tt->tt_previous_temp));
559 }
560 tt->tt_previous_temp = temp;
561#endif
562 if (old_state !=
563 transaction->next_state) {
564 changed = true;
565 tt->state =
566 transaction->next_state;
567 }
568 break;
569 }
570 }
571 if (changed) {
572 struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
573 struct iwl_power_mgr *setting = &priv->power_data;
574
575 if (tt->state >= IWL_TI_1) {
576 /* if switching from IWL_TI_0 to other TT state
577 * save previous power setting in tt->sys_power_mode */
578 if (old_state == IWL_TI_0)
579 tt->sys_power_mode = setting->power_mode;
580 /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
581 tt->tt_power_mode = IWL_POWER_INDEX_5;
582 if (!iwl_ht_enabled(priv))
583 /* disable HT */
584 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
585 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
586 RXON_FLG_FAT_PROT_MSK |
587 RXON_FLG_HT_PROT_MSK);
588 else {
589 /* check HT capability and set
590 * according to the system HT capability
591 * in case get disabled before */
592 iwl_set_rxon_ht(priv, &priv->current_ht_config);
593 }
594
595 } else {
596 /* restore system power setting */
597 /* the previous power mode was saved in
598 * tt->sys_power_mode when system move into
599 * Thermal Throttling state
600 * set power_data.user_power_setting to the previous
601 * system power mode to make sure power will get
602 * updated correctly
603 */
604 priv->power_data.user_power_setting =
605 tt->sys_power_mode;
606 tt->tt_power_mode = tt->sys_power_mode;
607 /* check HT capability and set
608 * according to the system HT capability
609 * in case get disabled before */
610 iwl_set_rxon_ht(priv, &priv->current_ht_config);
611 }
612 if (iwl_power_update_mode(priv, true)) {
613 /* TT state not updated
614 * try again during next temperature read
615 */
616 IWL_ERR(priv, "Cannot update power mode, "
617 "TT state not updated\n");
618 tt->state = old_state;
619 } else {
620 IWL_DEBUG_POWER(priv,
621 "Thermal Throttling to new state: %u\n",
622 tt->state);
623 if (old_state != IWL_TI_CT_KILL &&
624 tt->state == IWL_TI_CT_KILL) {
625 IWL_DEBUG_POWER(priv, "Enter IWL_TI_CT_KILL\n");
626 iwl_perform_ct_kill_task(priv, true);
627
628 } else if (old_state == IWL_TI_CT_KILL &&
629 tt->state != IWL_TI_CT_KILL) {
630 IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
631 iwl_perform_ct_kill_task(priv, false);
632 }
633 }
634 }
635}
636
430/* Card State Notification indicated reach critical temperature 637/* Card State Notification indicated reach critical temperature
431 * if PSP not enable, no Thermal Throttling function will be performed 638 * if PSP not enable, no Thermal Throttling function will be performed
432 * just set the GP1 bit to acknowledge the event 639 * just set the GP1 bit to acknowledge the event
433 * otherwise, go into IWL_TI_CT_KILL state 640 * otherwise, go into IWL_TI_CT_KILL state
434 * since Card State Notification will not provide any temperature reading 641 * since Card State Notification will not provide any temperature reading
642 * for Legacy mode
435 * so just pass the CT_KILL temperature to iwl_legacy_tt_handler() 643 * so just pass the CT_KILL temperature to iwl_legacy_tt_handler()
644 * for advance mode
645 * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state
436 */ 646 */
437void iwl_tt_enter_ct_kill(struct iwl_priv *priv) 647void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
438{ 648{
@@ -444,7 +654,12 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
444 if (tt->state != IWL_TI_CT_KILL) { 654 if (tt->state != IWL_TI_CT_KILL) {
445 IWL_ERR(priv, "Device reached critical temperature " 655 IWL_ERR(priv, "Device reached critical temperature "
446 "- ucode going to sleep!\n"); 656 "- ucode going to sleep!\n");
447 iwl_legacy_tt_handler(priv, IWL_MINIMAL_POWER_THRESHOLD); 657 if (!priv->power_data.adv_tt)
658 iwl_legacy_tt_handler(priv,
659 IWL_MINIMAL_POWER_THRESHOLD);
660 else
661 iwl_advance_tt_handler(priv,
662 CT_KILL_THRESHOLD + 1);
448 } 663 }
449} 664}
450EXPORT_SYMBOL(iwl_tt_enter_ct_kill); 665EXPORT_SYMBOL(iwl_tt_enter_ct_kill);
@@ -468,8 +683,11 @@ void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
468 IWL_ERR(priv, 683 IWL_ERR(priv,
469 "Device temperature below critical" 684 "Device temperature below critical"
470 "- ucode awake!\n"); 685 "- ucode awake!\n");
471 iwl_legacy_tt_handler(priv, 686 if (!priv->power_data.adv_tt)
472 IWL_REDUCED_PERFORMANCE_THRESHOLD_2); 687 iwl_legacy_tt_handler(priv,
688 IWL_REDUCED_PERFORMANCE_THRESHOLD_2);
689 else
690 iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD);
473 } 691 }
474} 692}
475EXPORT_SYMBOL(iwl_tt_exit_ct_kill); 693EXPORT_SYMBOL(iwl_tt_exit_ct_kill);
@@ -484,16 +702,24 @@ void iwl_tt_handler(struct iwl_priv *priv)
484 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) 702 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
485 temp = KELVIN_TO_CELSIUS(priv->temperature); 703 temp = KELVIN_TO_CELSIUS(priv->temperature);
486 704
487 iwl_legacy_tt_handler(priv, temp); 705 if (!priv->power_data.adv_tt)
706 iwl_legacy_tt_handler(priv, temp);
707 else
708 iwl_advance_tt_handler(priv, temp);
488} 709}
489EXPORT_SYMBOL(iwl_tt_handler); 710EXPORT_SYMBOL(iwl_tt_handler);
490 711
491/* Thermal throttling initialization 712/* Thermal throttling initialization
713 * For advance thermal throttling:
714 * Initialize Thermal Index and temperature threshold table
715 * Initialize thermal throttling restriction table
492 */ 716 */
493void iwl_tt_initialize(struct iwl_priv *priv) 717void iwl_tt_initialize(struct iwl_priv *priv)
494{ 718{
495 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 719 struct iwl_tt_mgmt *tt = &priv->power_data.tt;
496 struct iwl_power_mgr *setting = &priv->power_data; 720 struct iwl_power_mgr *setting = &priv->power_data;
721 int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
722 struct iwl_tt_trans *transaction;
497 723
498 IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling \n"); 724 IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling \n");
499 725
@@ -505,14 +731,65 @@ void iwl_tt_initialize(struct iwl_priv *priv)
505 init_timer(&priv->power_data.ct_kill_exit_tm); 731 init_timer(&priv->power_data.ct_kill_exit_tm);
506 priv->power_data.ct_kill_exit_tm.data = (unsigned long)priv; 732 priv->power_data.ct_kill_exit_tm.data = (unsigned long)priv;
507 priv->power_data.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill; 733 priv->power_data.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill;
734 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
735 case CSR_HW_REV_TYPE_6x00:
736 case CSR_HW_REV_TYPE_6x50:
737 IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
738 tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
739 IWL_TI_STATE_MAX, GFP_KERNEL);
740 tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
741 IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1),
742 GFP_KERNEL);
743 if (!tt->restriction || !tt->transaction) {
744 IWL_ERR(priv, "Fallback to Legacy Throttling\n");
745 priv->power_data.adv_tt = false;
746 kfree(tt->restriction);
747 tt->restriction = NULL;
748 kfree(tt->transaction);
749 tt->transaction = NULL;
750 } else {
751 transaction = tt->transaction +
752 (IWL_TI_0 * (IWL_TI_STATE_MAX - 1));
753 memcpy(transaction, &tt_range_0[0], size);
754 transaction = tt->transaction +
755 (IWL_TI_1 * (IWL_TI_STATE_MAX - 1));
756 memcpy(transaction, &tt_range_1[0], size);
757 transaction = tt->transaction +
758 (IWL_TI_2 * (IWL_TI_STATE_MAX - 1));
759 memcpy(transaction, &tt_range_2[0], size);
760 transaction = tt->transaction +
761 (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1));
762 memcpy(transaction, &tt_range_3[0], size);
763 size = sizeof(struct iwl_tt_restriction) *
764 IWL_TI_STATE_MAX;
765 memcpy(tt->restriction,
766 &restriction_range[0], size);
767 priv->power_data.adv_tt = true;
768 }
769 break;
770 default:
771 IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
772 priv->power_data.adv_tt = false;
773 break;
774 }
508} 775}
509EXPORT_SYMBOL(iwl_tt_initialize); 776EXPORT_SYMBOL(iwl_tt_initialize);
510 777
511/* cleanup thermal throttling management related memory and timer */ 778/* cleanup thermal throttling management related memory and timer */
512void iwl_tt_exit(struct iwl_priv *priv) 779void iwl_tt_exit(struct iwl_priv *priv)
513{ 780{
781 struct iwl_tt_mgmt *tt = &priv->power_data.tt;
782
514 /* stop ct_kill_exit_tm timer if activated */ 783 /* stop ct_kill_exit_tm timer if activated */
515 del_timer_sync(&priv->power_data.ct_kill_exit_tm); 784 del_timer_sync(&priv->power_data.ct_kill_exit_tm);
785
786 if (priv->power_data.adv_tt) {
787 /* free advance thermal throttling memory */
788 kfree(tt->restriction);
789 tt->restriction = NULL;
790 kfree(tt->transaction);
791 tt->transaction = NULL;
792 }
516} 793}
517EXPORT_SYMBOL(iwl_tt_exit); 794EXPORT_SYMBOL(iwl_tt_exit);
518 795