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