tt.c (21278B)
1// SPDX-License-Identifier: GPL-2.0-only 2/****************************************************************************** 3 * 4 * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. 5 * Copyright (C) 2018, 2020 Intel Corporation 6 * 7 * Portions of this file are derived from the ipw3945 project, as well 8 * 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 table 25 * Current state | Throttling Down | Throttling Up 26 *============================================================================= 27 * Condition Nxt State Condition Nxt State Condition Nxt State 28 *----------------------------------------------------------------------------- 29 * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A 30 * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 31 * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 32 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 33 *============================================================================= 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 else 100 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 temperature 143 * if the temperature is below CT, uCode will stay awake and send card 144 * state notification with CT_KILL bit clear to inform Thermal Throttling 145 * Management to change state. Otherwise, uCode will go back to sleep 146 * without doing anything, driver should continue the 5 seconds timer 147 * to wake up uCode for temperature check until temperature drop below CT 148 */ 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 in 173 * CT_KILL_EXIT_DURATION seconds to ensure we get a 174 * 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 throttling 234 * 1) Avoid NIC destruction due to high temperatures 235 * Chip will identify dangerously high temperatures that can 236 * harm the device and will power down 237 * 2) Avoid the NIC power down due to high temperature 238 * Throttle early enough to lower the power consumption before 239 * drastic steps are needed 240 */ 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_DEBUG 247 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#endif 256 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 else 265 tt->state = IWL_TI_0; 266 267#ifdef CONFIG_IWLWIFI_DEBUG 268 tt->tt_previous_temp = temp; 269#endif 270 /* 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_0 277 * we only have to call iwl_power_update_mode() to 278 * 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 updated 297 * try again during next temperature read 298 */ 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 throttling 327 * 1) Avoid NIC destruction due to high temperatures 328 * Chip will identify dangerously high temperatures that can 329 * harm the device and will power down 330 * 2) Avoid the NIC power down due to high temperature 331 * Throttle early enough to lower the power consumption before 332 * drastic steps are needed 333 * Actions include relaxing the power down sleep thresholds and 334 * decreasing the number of TX streams 335 * 3) Avoid throughput performance impact as much as possible 336 * 337 *============================================================================= 338 * Condition Nxt State Condition Nxt State Condition Nxt State 339 *----------------------------------------------------------------------------- 340 * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A 341 * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 342 * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 343 * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 344 *============================================================================= 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 table 358 * each table has (IWL_TI_STATE_MAX - 1) entries 359 * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1)) 360 * will advance to the correct table. 361 * then based on the current temperature 362 * find the next state need to transaction to 363 * go through all the possible (IWL_TI_STATE_MAX - 1) entries 364 * in the current table to see if transaction is needed 365 */ 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_DEBUG 371 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#endif 382 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 set 415 * according to the system HT capability 416 * 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 be 423 * recalculated automatically. 424 */ 425 426 /* check HT capability and set 427 * according to the system HT capability 428 * 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 updated 437 * try again during next temperature read 438 */ 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 temperature 470 * if PSP not enable, no Thermal Throttling function will be performed 471 * just set the GP1 bit to acknowledge the event 472 * otherwise, go into IWL_TI_CT_KILL state 473 * since Card State Notification will not provide any temperature reading 474 * for Legacy mode 475 * so just pass the CT_KILL temperature to iwl_legacy_tt_handler() 476 * for advance mode 477 * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state 478 */ 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 else 498 iwl_advance_tt_handler(priv, 499 CT_KILL_THRESHOLD + 1, true); 500 } 501} 502 503/* Card State Notification indicated out of critical temperature 504 * since Card State Notification will not provide any temperature reading 505 * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature 506 * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state 507 */ 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 state 528 * reset the current temperature reading 529 */ 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 else 536 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 else 570 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 initialization 583 * For advance thermal throttling: 584 * Initialize Thermal Index and temperature threshold table 585 * Initialize thermal throttling restriction table 586 */ 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}