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