diff options
author | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2009-07-24 14:13:03 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-27 15:24:21 -0400 |
commit | 46f9381aa3fb62f6a141bfd41dcbeda1ec5fa26e (patch) | |
tree | 1023c715eac2b99b4443afbfefddb52719923593 /drivers/net/wireless/iwlwifi/iwl-power.c | |
parent | 39b73fb15e4704fd4d1e33688135810637f5f3fb (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.c | 285 |
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 | */ | ||
112 | static 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 | }; | ||
117 | static 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 | }; | ||
122 | static 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 | }; | ||
127 | static 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 */ | ||
134 | static 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 */ |
103 | static int iwl_set_power(struct iwl_priv *priv, void *cmd) | 142 | static 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 | } |
274 | EXPORT_SYMBOL(iwl_power_set_user_mode); | 313 | EXPORT_SYMBOL(iwl_power_set_user_mode); |
275 | 314 | ||
315 | bool 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 | } | ||
325 | EXPORT_SYMBOL(iwl_ht_enabled); | ||
326 | |||
327 | u8 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 | } | ||
337 | EXPORT_SYMBOL(iwl_tx_ant_restriction); | ||
338 | |||
339 | u8 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 | } | ||
349 | EXPORT_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 | */ | ||
526 | static 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 | */ |
437 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv) | 647 | void 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 | } |
450 | EXPORT_SYMBOL(iwl_tt_enter_ct_kill); | 665 | EXPORT_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 | } |
475 | EXPORT_SYMBOL(iwl_tt_exit_ct_kill); | 693 | EXPORT_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 | } |
489 | EXPORT_SYMBOL(iwl_tt_handler); | 710 | EXPORT_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 | */ |
493 | void iwl_tt_initialize(struct iwl_priv *priv) | 717 | void 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 | } |
509 | EXPORT_SYMBOL(iwl_tt_initialize); | 776 | EXPORT_SYMBOL(iwl_tt_initialize); |
510 | 777 | ||
511 | /* cleanup thermal throttling management related memory and timer */ | 778 | /* cleanup thermal throttling management related memory and timer */ |
512 | void iwl_tt_exit(struct iwl_priv *priv) | 779 | void 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 | } |
517 | EXPORT_SYMBOL(iwl_tt_exit); | 794 | EXPORT_SYMBOL(iwl_tt_exit); |
518 | 795 | ||