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