669 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/******************************************************************************3 *4 * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.5 * Copyright (C) 2018, 2020 Intel Corporation6 *7 * Portions of this file are derived from the ipw3945 project, as well8 * as portions of the ieee80211 subsystem header files.9 *****************************************************************************/10 11 12#include <linux/kernel.h>13#include <linux/module.h>14#include <linux/slab.h>15#include <net/mac80211.h>16#include "iwl-io.h"17#include "iwl-modparams.h"18#include "iwl-debug.h"19#include "agn.h"20#include "dev.h"21#include "commands.h"22#include "tt.h"23 24/* default Thermal Throttling transaction table25 * Current state | Throttling Down | Throttling Up26 *=============================================================================27 * Condition Nxt State Condition Nxt State Condition Nxt State28 *-----------------------------------------------------------------------------29 * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A30 * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_031 * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_132 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_033 *=============================================================================34 */35static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {36 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},37 {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1},38 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}39};40static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {41 {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},42 {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1},43 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}44};45static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {46 {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},47 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX},48 {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}49};50static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {51 {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},52 {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX},53 {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}54};55 56/* Advance Thermal Throttling default restriction table */57static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {58 {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true },59 {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true },60 {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false },61 {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }62};63 64bool iwl_tt_is_low_power_state(struct iwl_priv *priv)65{66 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;67 68 if (tt->state >= IWL_TI_1)69 return true;70 return false;71}72 73u8 iwl_tt_current_power_mode(struct iwl_priv *priv)74{75 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;76 77 return tt->tt_power_mode;78}79 80bool iwl_ht_enabled(struct iwl_priv *priv)81{82 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;83 struct iwl_tt_restriction *restriction;84 85 if (!priv->thermal_throttle.advanced_tt)86 return true;87 restriction = tt->restriction + tt->state;88 return restriction->is_ht;89}90 91static bool iwl_within_ct_kill_margin(struct iwl_priv *priv)92{93 s32 temp = priv->temperature; /* degrees CELSIUS except specified */94 bool within_margin = false;95 96 if (!priv->thermal_throttle.advanced_tt)97 within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=98 CT_KILL_THRESHOLD_LEGACY) ? true : false;99 else100 within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=101 CT_KILL_THRESHOLD) ? true : false;102 return within_margin;103}104 105bool iwl_check_for_ct_kill(struct iwl_priv *priv)106{107 bool is_ct_kill = false;108 109 if (iwl_within_ct_kill_margin(priv)) {110 iwl_tt_enter_ct_kill(priv);111 is_ct_kill = true;112 }113 return is_ct_kill;114}115 116enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)117{118 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;119 struct iwl_tt_restriction *restriction;120 121 if (!priv->thermal_throttle.advanced_tt)122 return IWL_ANT_OK_MULTI;123 restriction = tt->restriction + tt->state;124 return restriction->tx_stream;125}126 127enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)128{129 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;130 struct iwl_tt_restriction *restriction;131 132 if (!priv->thermal_throttle.advanced_tt)133 return IWL_ANT_OK_MULTI;134 restriction = tt->restriction + tt->state;135 return restriction->rx_stream;136}137 138#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */139#define CT_KILL_WAITING_DURATION (300) /* 300ms duration */140 141/*142 * toggle the bit to wake up uCode and check the temperature143 * if the temperature is below CT, uCode will stay awake and send card144 * state notification with CT_KILL bit clear to inform Thermal Throttling145 * Management to change state. Otherwise, uCode will go back to sleep146 * without doing anything, driver should continue the 5 seconds timer147 * to wake up uCode for temperature check until temperature drop below CT148 */149static void iwl_tt_check_exit_ct_kill(struct timer_list *t)150{151 struct iwl_priv *priv = from_timer(priv, t,152 thermal_throttle.ct_kill_exit_tm);153 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;154 155 if (test_bit(STATUS_EXIT_PENDING, &priv->status))156 return;157 158 if (tt->state == IWL_TI_CT_KILL) {159 if (priv->thermal_throttle.ct_kill_toggle) {160 iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,161 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);162 priv->thermal_throttle.ct_kill_toggle = false;163 } else {164 iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET,165 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);166 priv->thermal_throttle.ct_kill_toggle = true;167 }168 iwl_read32(priv->trans, CSR_UCODE_DRV_GP1);169 if (iwl_trans_grab_nic_access(priv->trans))170 iwl_trans_release_nic_access(priv->trans);171 172 /* Reschedule the ct_kill timer to occur in173 * CT_KILL_EXIT_DURATION seconds to ensure we get a174 * thermal update */175 IWL_DEBUG_TEMP(priv, "schedule ct_kill exit timer\n");176 mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,177 jiffies + CT_KILL_EXIT_DURATION * HZ);178 }179}180 181static void iwl_perform_ct_kill_task(struct iwl_priv *priv,182 bool stop)183{184 if (stop) {185 IWL_DEBUG_TEMP(priv, "Stop all queues\n");186 if (priv->mac80211_registered)187 ieee80211_stop_queues(priv->hw);188 IWL_DEBUG_TEMP(priv,189 "Schedule 5 seconds CT_KILL Timer\n");190 mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,191 jiffies + CT_KILL_EXIT_DURATION * HZ);192 } else {193 IWL_DEBUG_TEMP(priv, "Wake all queues\n");194 if (priv->mac80211_registered)195 ieee80211_wake_queues(priv->hw);196 }197}198 199static void iwl_tt_ready_for_ct_kill(struct timer_list *t)200{201 struct iwl_priv *priv = from_timer(priv, t,202 thermal_throttle.ct_kill_waiting_tm);203 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;204 205 if (test_bit(STATUS_EXIT_PENDING, &priv->status))206 return;207 208 /* temperature timer expired, ready to go into CT_KILL state */209 if (tt->state != IWL_TI_CT_KILL) {210 IWL_DEBUG_TEMP(priv, "entering CT_KILL state when "211 "temperature timer expired\n");212 tt->state = IWL_TI_CT_KILL;213 set_bit(STATUS_CT_KILL, &priv->status);214 iwl_perform_ct_kill_task(priv, true);215 }216}217 218static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)219{220 IWL_DEBUG_TEMP(priv, "Prepare to enter IWL_TI_CT_KILL\n");221 /* make request to retrieve statistics information */222 iwl_send_statistics_request(priv, 0, false);223 /* Reschedule the ct_kill wait timer */224 mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,225 jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));226}227 228#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY)229#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100)230#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90)231 232/*233 * Legacy thermal throttling234 * 1) Avoid NIC destruction due to high temperatures235 * Chip will identify dangerously high temperatures that can236 * harm the device and will power down237 * 2) Avoid the NIC power down due to high temperature238 * Throttle early enough to lower the power consumption before239 * drastic steps are needed240 */241static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)242{243 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;244 enum iwl_tt_state old_state;245 246#ifdef CONFIG_IWLWIFI_DEBUG247 if ((tt->tt_previous_temp) &&248 (temp > tt->tt_previous_temp) &&249 ((temp - tt->tt_previous_temp) >250 IWL_TT_INCREASE_MARGIN)) {251 IWL_DEBUG_TEMP(priv,252 "Temperature increase %d degree Celsius\n",253 (temp - tt->tt_previous_temp));254 }255#endif256 old_state = tt->state;257 /* in Celsius */258 if (temp >= IWL_MINIMAL_POWER_THRESHOLD)259 tt->state = IWL_TI_CT_KILL;260 else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2)261 tt->state = IWL_TI_2;262 else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1)263 tt->state = IWL_TI_1;264 else265 tt->state = IWL_TI_0;266 267#ifdef CONFIG_IWLWIFI_DEBUG268 tt->tt_previous_temp = temp;269#endif270 /* stop ct_kill_waiting_tm timer */271 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);272 if (tt->state != old_state) {273 switch (tt->state) {274 case IWL_TI_0:275 /*276 * When the system is ready to go back to IWL_TI_0277 * we only have to call iwl_power_update_mode() to278 * do so.279 */280 break;281 case IWL_TI_1:282 tt->tt_power_mode = IWL_POWER_INDEX_3;283 break;284 case IWL_TI_2:285 tt->tt_power_mode = IWL_POWER_INDEX_4;286 break;287 default:288 tt->tt_power_mode = IWL_POWER_INDEX_5;289 break;290 }291 mutex_lock(&priv->mutex);292 if (old_state == IWL_TI_CT_KILL)293 clear_bit(STATUS_CT_KILL, &priv->status);294 if (tt->state != IWL_TI_CT_KILL &&295 iwl_power_update_mode(priv, true)) {296 /* TT state not updated297 * try again during next temperature read298 */299 if (old_state == IWL_TI_CT_KILL)300 set_bit(STATUS_CT_KILL, &priv->status);301 tt->state = old_state;302 IWL_ERR(priv, "Cannot update power mode, "303 "TT state not updated\n");304 } else {305 if (tt->state == IWL_TI_CT_KILL) {306 if (force) {307 set_bit(STATUS_CT_KILL, &priv->status);308 iwl_perform_ct_kill_task(priv, true);309 } else {310 iwl_prepare_ct_kill_task(priv);311 tt->state = old_state;312 }313 } else if (old_state == IWL_TI_CT_KILL) {314 iwl_perform_ct_kill_task(priv, false);315 }316 IWL_DEBUG_TEMP(priv, "Temperature state changed %u\n",317 tt->state);318 IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",319 tt->tt_power_mode);320 }321 mutex_unlock(&priv->mutex);322 }323}324 325/*326 * Advance thermal throttling327 * 1) Avoid NIC destruction due to high temperatures328 * Chip will identify dangerously high temperatures that can329 * harm the device and will power down330 * 2) Avoid the NIC power down due to high temperature331 * Throttle early enough to lower the power consumption before332 * drastic steps are needed333 * Actions include relaxing the power down sleep thresholds and334 * decreasing the number of TX streams335 * 3) Avoid throughput performance impact as much as possible336 *337 *=============================================================================338 * Condition Nxt State Condition Nxt State Condition Nxt State339 *-----------------------------------------------------------------------------340 * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A341 * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0342 * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1343 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0344 *=============================================================================345 */346static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)347{348 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;349 int i;350 bool changed = false;351 enum iwl_tt_state old_state;352 struct iwl_tt_trans *transaction;353 354 old_state = tt->state;355 for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) {356 /* based on the current TT state,357 * find the curresponding transaction table358 * each table has (IWL_TI_STATE_MAX - 1) entries359 * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1))360 * will advance to the correct table.361 * then based on the current temperature362 * find the next state need to transaction to363 * go through all the possible (IWL_TI_STATE_MAX - 1) entries364 * in the current table to see if transaction is needed365 */366 transaction = tt->transaction +367 ((old_state * (IWL_TI_STATE_MAX - 1)) + i);368 if (temp >= transaction->tt_low &&369 temp <= transaction->tt_high) {370#ifdef CONFIG_IWLWIFI_DEBUG371 if ((tt->tt_previous_temp) &&372 (temp > tt->tt_previous_temp) &&373 ((temp - tt->tt_previous_temp) >374 IWL_TT_INCREASE_MARGIN)) {375 IWL_DEBUG_TEMP(priv,376 "Temperature increase %d "377 "degree Celsius\n",378 (temp - tt->tt_previous_temp));379 }380 tt->tt_previous_temp = temp;381#endif382 if (old_state !=383 transaction->next_state) {384 changed = true;385 tt->state =386 transaction->next_state;387 }388 break;389 }390 }391 /* stop ct_kill_waiting_tm timer */392 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);393 if (changed) {394 if (tt->state >= IWL_TI_1) {395 /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */396 tt->tt_power_mode = IWL_POWER_INDEX_5;397 398 if (!iwl_ht_enabled(priv)) {399 struct iwl_rxon_context *ctx;400 401 for_each_context(priv, ctx) {402 struct iwl_rxon_cmd *rxon;403 404 rxon = &ctx->staging;405 406 /* disable HT */407 rxon->flags &= ~(408 RXON_FLG_CHANNEL_MODE_MSK |409 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |410 RXON_FLG_HT40_PROT_MSK |411 RXON_FLG_HT_PROT_MSK);412 }413 } else {414 /* check HT capability and set415 * according to the system HT capability416 * in case get disabled before */417 iwl_set_rxon_ht(priv, &priv->current_ht_config);418 }419 420 } else {421 /*422 * restore system power setting -- it will be423 * recalculated automatically.424 */425 426 /* check HT capability and set427 * according to the system HT capability428 * in case get disabled before */429 iwl_set_rxon_ht(priv, &priv->current_ht_config);430 }431 mutex_lock(&priv->mutex);432 if (old_state == IWL_TI_CT_KILL)433 clear_bit(STATUS_CT_KILL, &priv->status);434 if (tt->state != IWL_TI_CT_KILL &&435 iwl_power_update_mode(priv, true)) {436 /* TT state not updated437 * try again during next temperature read438 */439 IWL_ERR(priv, "Cannot update power mode, "440 "TT state not updated\n");441 if (old_state == IWL_TI_CT_KILL)442 set_bit(STATUS_CT_KILL, &priv->status);443 tt->state = old_state;444 } else {445 IWL_DEBUG_TEMP(priv,446 "Thermal Throttling to new state: %u\n",447 tt->state);448 if (old_state != IWL_TI_CT_KILL &&449 tt->state == IWL_TI_CT_KILL) {450 if (force) {451 IWL_DEBUG_TEMP(priv,452 "Enter IWL_TI_CT_KILL\n");453 set_bit(STATUS_CT_KILL, &priv->status);454 iwl_perform_ct_kill_task(priv, true);455 } else {456 tt->state = old_state;457 iwl_prepare_ct_kill_task(priv);458 }459 } else if (old_state == IWL_TI_CT_KILL &&460 tt->state != IWL_TI_CT_KILL) {461 IWL_DEBUG_TEMP(priv, "Exit IWL_TI_CT_KILL\n");462 iwl_perform_ct_kill_task(priv, false);463 }464 }465 mutex_unlock(&priv->mutex);466 }467}468 469/* Card State Notification indicated reach critical temperature470 * if PSP not enable, no Thermal Throttling function will be performed471 * just set the GP1 bit to acknowledge the event472 * otherwise, go into IWL_TI_CT_KILL state473 * since Card State Notification will not provide any temperature reading474 * for Legacy mode475 * so just pass the CT_KILL temperature to iwl_legacy_tt_handler()476 * for advance mode477 * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state478 */479static void iwl_bg_ct_enter(struct work_struct *work)480{481 struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);482 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;483 484 if (test_bit(STATUS_EXIT_PENDING, &priv->status))485 return;486 487 if (!iwl_is_ready(priv))488 return;489 490 if (tt->state != IWL_TI_CT_KILL) {491 IWL_ERR(priv, "Device reached critical temperature "492 "- ucode going to sleep!\n");493 if (!priv->thermal_throttle.advanced_tt)494 iwl_legacy_tt_handler(priv,495 IWL_MINIMAL_POWER_THRESHOLD,496 true);497 else498 iwl_advance_tt_handler(priv,499 CT_KILL_THRESHOLD + 1, true);500 }501}502 503/* Card State Notification indicated out of critical temperature504 * since Card State Notification will not provide any temperature reading505 * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature506 * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state507 */508static void iwl_bg_ct_exit(struct work_struct *work)509{510 struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);511 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;512 513 if (test_bit(STATUS_EXIT_PENDING, &priv->status))514 return;515 516 if (!iwl_is_ready(priv))517 return;518 519 /* stop ct_kill_exit_tm timer */520 del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);521 522 if (tt->state == IWL_TI_CT_KILL) {523 IWL_ERR(priv,524 "Device temperature below critical"525 "- ucode awake!\n");526 /*527 * exit from CT_KILL state528 * reset the current temperature reading529 */530 priv->temperature = 0;531 if (!priv->thermal_throttle.advanced_tt)532 iwl_legacy_tt_handler(priv,533 IWL_REDUCED_PERFORMANCE_THRESHOLD_2,534 true);535 else536 iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD,537 true);538 }539}540 541void iwl_tt_enter_ct_kill(struct iwl_priv *priv)542{543 if (test_bit(STATUS_EXIT_PENDING, &priv->status))544 return;545 546 IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");547 queue_work(priv->workqueue, &priv->ct_enter);548}549 550void iwl_tt_exit_ct_kill(struct iwl_priv *priv)551{552 if (test_bit(STATUS_EXIT_PENDING, &priv->status))553 return;554 555 IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");556 queue_work(priv->workqueue, &priv->ct_exit);557}558 559static void iwl_bg_tt_work(struct work_struct *work)560{561 struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);562 s32 temp = priv->temperature; /* degrees CELSIUS except specified */563 564 if (test_bit(STATUS_EXIT_PENDING, &priv->status))565 return;566 567 if (!priv->thermal_throttle.advanced_tt)568 iwl_legacy_tt_handler(priv, temp, false);569 else570 iwl_advance_tt_handler(priv, temp, false);571}572 573void iwl_tt_handler(struct iwl_priv *priv)574{575 if (test_bit(STATUS_EXIT_PENDING, &priv->status))576 return;577 578 IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");579 queue_work(priv->workqueue, &priv->tt_work);580}581 582/* Thermal throttling initialization583 * For advance thermal throttling:584 * Initialize Thermal Index and temperature threshold table585 * Initialize thermal throttling restriction table586 */587void iwl_tt_initialize(struct iwl_priv *priv)588{589 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;590 int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);591 struct iwl_tt_trans *transaction;592 593 IWL_DEBUG_TEMP(priv, "Initialize Thermal Throttling\n");594 595 memset(tt, 0, sizeof(struct iwl_tt_mgmt));596 597 tt->state = IWL_TI_0;598 timer_setup(&priv->thermal_throttle.ct_kill_exit_tm,599 iwl_tt_check_exit_ct_kill, 0);600 timer_setup(&priv->thermal_throttle.ct_kill_waiting_tm,601 iwl_tt_ready_for_ct_kill, 0);602 /* setup deferred ct kill work */603 INIT_WORK(&priv->tt_work, iwl_bg_tt_work);604 INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);605 INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);606 607 if (priv->lib->adv_thermal_throttle) {608 IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n");609 tt->restriction = kcalloc(IWL_TI_STATE_MAX,610 sizeof(struct iwl_tt_restriction),611 GFP_KERNEL);612 tt->transaction = kcalloc(IWL_TI_STATE_MAX *613 (IWL_TI_STATE_MAX - 1),614 sizeof(struct iwl_tt_trans),615 GFP_KERNEL);616 if (!tt->restriction || !tt->transaction) {617 IWL_ERR(priv, "Fallback to Legacy Throttling\n");618 priv->thermal_throttle.advanced_tt = false;619 kfree(tt->restriction);620 tt->restriction = NULL;621 kfree(tt->transaction);622 tt->transaction = NULL;623 } else {624 transaction = tt->transaction +625 (IWL_TI_0 * (IWL_TI_STATE_MAX - 1));626 memcpy(transaction, &tt_range_0[0], size);627 transaction = tt->transaction +628 (IWL_TI_1 * (IWL_TI_STATE_MAX - 1));629 memcpy(transaction, &tt_range_1[0], size);630 transaction = tt->transaction +631 (IWL_TI_2 * (IWL_TI_STATE_MAX - 1));632 memcpy(transaction, &tt_range_2[0], size);633 transaction = tt->transaction +634 (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1));635 memcpy(transaction, &tt_range_3[0], size);636 size = sizeof(struct iwl_tt_restriction) *637 IWL_TI_STATE_MAX;638 memcpy(tt->restriction,639 &restriction_range[0], size);640 priv->thermal_throttle.advanced_tt = true;641 }642 } else {643 IWL_DEBUG_TEMP(priv, "Legacy Thermal Throttling\n");644 priv->thermal_throttle.advanced_tt = false;645 }646}647 648/* cleanup thermal throttling management related memory and timer */649void iwl_tt_exit(struct iwl_priv *priv)650{651 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;652 653 /* stop ct_kill_exit_tm timer if activated */654 del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);655 /* stop ct_kill_waiting_tm timer if activated */656 del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);657 cancel_work_sync(&priv->tt_work);658 cancel_work_sync(&priv->ct_enter);659 cancel_work_sync(&priv->ct_exit);660 661 if (priv->thermal_throttle.advanced_tt) {662 /* free advance thermal throttling memory */663 kfree(tt->restriction);664 tt->restriction = NULL;665 kfree(tt->transaction);666 tt->transaction = NULL;667 }668}669