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