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