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