Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iwlwifi: separate thermal throttling function

"Thermal Throttling" is an advance feature which only available for
newer _agn devices. Move from iwl-core to iwl-agn for better code
organization.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Wey-Yi Guy and committed by
John W. Linville
0975cc8f 36d34413

+917 -776
+1
drivers/net/wireless/iwlwifi/Makefile
··· 12 12 iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o 13 13 iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o 14 14 iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o 15 + iwlagn-objs += iwl-agn-tt.o 15 16 iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o 16 17 17 18 iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
+5
drivers/net/wireless/iwlwifi/iwl-1000.c
··· 229 229 .check_ack_health = iwl_good_ack_health, 230 230 .txfifo_flush = iwlagn_txfifo_flush, 231 231 .dev_txfifo_flush = iwlagn_dev_txfifo_flush, 232 + .tt_ops = { 233 + .lower_power_detection = iwl_tt_is_low_power_state, 234 + .tt_power_mode = iwl_tt_current_power_mode, 235 + .ct_kill_check = iwl_check_for_ct_kill, 236 + } 232 237 }; 233 238 234 239 static const struct iwl_ops iwl1000_ops = {
+10
drivers/net/wireless/iwlwifi/iwl-5000.c
··· 405 405 .check_ack_health = iwl_good_ack_health, 406 406 .txfifo_flush = iwlagn_txfifo_flush, 407 407 .dev_txfifo_flush = iwlagn_dev_txfifo_flush, 408 + .tt_ops = { 409 + .lower_power_detection = iwl_tt_is_low_power_state, 410 + .tt_power_mode = iwl_tt_current_power_mode, 411 + .ct_kill_check = iwl_check_for_ct_kill, 412 + } 408 413 }; 409 414 410 415 static struct iwl_lib_ops iwl5150_lib = { ··· 475 470 .check_ack_health = iwl_good_ack_health, 476 471 .txfifo_flush = iwlagn_txfifo_flush, 477 472 .dev_txfifo_flush = iwlagn_dev_txfifo_flush, 473 + .tt_ops = { 474 + .lower_power_detection = iwl_tt_is_low_power_state, 475 + .tt_power_mode = iwl_tt_current_power_mode, 476 + .ct_kill_check = iwl_check_for_ct_kill, 477 + } 478 478 }; 479 479 480 480 static const struct iwl_ops iwl5000_ops = {
+5
drivers/net/wireless/iwlwifi/iwl-6000.c
··· 330 330 .check_ack_health = iwl_good_ack_health, 331 331 .txfifo_flush = iwlagn_txfifo_flush, 332 332 .dev_txfifo_flush = iwlagn_dev_txfifo_flush, 333 + .tt_ops = { 334 + .lower_power_detection = iwl_tt_is_low_power_state, 335 + .tt_power_mode = iwl_tt_current_power_mode, 336 + .ct_kill_check = iwl_check_for_ct_kill, 337 + } 333 338 }; 334 339 335 340 static const struct iwl_ops iwl6000_ops = {
+696
drivers/net/wireless/iwlwifi/iwl-agn-tt.c
··· 1 + /****************************************************************************** 2 + * 3 + * Copyright(c) 2007 - 2010 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 <linux/init.h> 34 + 35 + #include <net/mac80211.h> 36 + 37 + #include "iwl-eeprom.h" 38 + #include "iwl-dev.h" 39 + #include "iwl-core.h" 40 + #include "iwl-io.h" 41 + #include "iwl-commands.h" 42 + #include "iwl-debug.h" 43 + #include "iwl-agn-tt.h" 44 + 45 + /* default Thermal Throttling transaction table 46 + * Current state | Throttling Down | Throttling Up 47 + *============================================================================= 48 + * Condition Nxt State Condition Nxt State Condition Nxt State 49 + *----------------------------------------------------------------------------- 50 + * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A 51 + * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 52 + * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 53 + * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 54 + *============================================================================= 55 + */ 56 + static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { 57 + {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, 58 + {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1}, 59 + {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} 60 + }; 61 + static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { 62 + {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, 63 + {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1}, 64 + {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} 65 + }; 66 + static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { 67 + {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, 68 + {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}, 69 + {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} 70 + }; 71 + static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { 72 + {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, 73 + {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, 74 + {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX} 75 + }; 76 + 77 + /* Advance Thermal Throttling default restriction table */ 78 + static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = { 79 + {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true }, 80 + {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true }, 81 + {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false }, 82 + {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false } 83 + }; 84 + 85 + bool iwl_tt_is_low_power_state(struct iwl_priv *priv) 86 + { 87 + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 88 + 89 + if (tt->state >= IWL_TI_1) 90 + return true; 91 + return false; 92 + } 93 + 94 + u8 iwl_tt_current_power_mode(struct iwl_priv *priv) 95 + { 96 + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 97 + 98 + return tt->tt_power_mode; 99 + } 100 + 101 + bool iwl_ht_enabled(struct iwl_priv *priv) 102 + { 103 + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 104 + struct iwl_tt_restriction *restriction; 105 + 106 + if (!priv->thermal_throttle.advanced_tt) 107 + return true; 108 + restriction = tt->restriction + tt->state; 109 + return restriction->is_ht; 110 + } 111 + 112 + static bool iwl_within_ct_kill_margin(struct iwl_priv *priv) 113 + { 114 + s32 temp = priv->temperature; /* degrees CELSIUS except specified */ 115 + bool within_margin = false; 116 + 117 + if (priv->cfg->temperature_kelvin) 118 + temp = KELVIN_TO_CELSIUS(priv->temperature); 119 + 120 + if (!priv->thermal_throttle.advanced_tt) 121 + within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= 122 + CT_KILL_THRESHOLD_LEGACY) ? true : false; 123 + else 124 + within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= 125 + CT_KILL_THRESHOLD) ? true : false; 126 + return within_margin; 127 + } 128 + 129 + bool iwl_check_for_ct_kill(struct iwl_priv *priv) 130 + { 131 + bool is_ct_kill = false; 132 + 133 + if (iwl_within_ct_kill_margin(priv)) { 134 + iwl_tt_enter_ct_kill(priv); 135 + is_ct_kill = true; 136 + } 137 + return is_ct_kill; 138 + } 139 + 140 + enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) 141 + { 142 + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 143 + struct iwl_tt_restriction *restriction; 144 + 145 + if (!priv->thermal_throttle.advanced_tt) 146 + return IWL_ANT_OK_MULTI; 147 + restriction = tt->restriction + tt->state; 148 + return restriction->tx_stream; 149 + } 150 + 151 + enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv) 152 + { 153 + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 154 + struct iwl_tt_restriction *restriction; 155 + 156 + if (!priv->thermal_throttle.advanced_tt) 157 + return IWL_ANT_OK_MULTI; 158 + restriction = tt->restriction + tt->state; 159 + return restriction->rx_stream; 160 + } 161 + 162 + #define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ 163 + #define CT_KILL_WAITING_DURATION (300) /* 300ms duration */ 164 + 165 + /* 166 + * toggle the bit to wake up uCode and check the temperature 167 + * if the temperature is below CT, uCode will stay awake and send card 168 + * state notification with CT_KILL bit clear to inform Thermal Throttling 169 + * Management to change state. Otherwise, uCode will go back to sleep 170 + * without doing anything, driver should continue the 5 seconds timer 171 + * to wake up uCode for temperature check until temperature drop below CT 172 + */ 173 + static void iwl_tt_check_exit_ct_kill(unsigned long data) 174 + { 175 + struct iwl_priv *priv = (struct iwl_priv *)data; 176 + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 177 + unsigned long flags; 178 + 179 + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 180 + return; 181 + 182 + if (tt->state == IWL_TI_CT_KILL) { 183 + if (priv->thermal_throttle.ct_kill_toggle) { 184 + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, 185 + CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); 186 + priv->thermal_throttle.ct_kill_toggle = false; 187 + } else { 188 + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, 189 + CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); 190 + priv->thermal_throttle.ct_kill_toggle = true; 191 + } 192 + iwl_read32(priv, CSR_UCODE_DRV_GP1); 193 + spin_lock_irqsave(&priv->reg_lock, flags); 194 + if (!iwl_grab_nic_access(priv)) 195 + iwl_release_nic_access(priv); 196 + spin_unlock_irqrestore(&priv->reg_lock, flags); 197 + 198 + /* Reschedule the ct_kill timer to occur in 199 + * CT_KILL_EXIT_DURATION seconds to ensure we get a 200 + * thermal update */ 201 + IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n"); 202 + mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, 203 + jiffies + CT_KILL_EXIT_DURATION * HZ); 204 + } 205 + } 206 + 207 + static void iwl_perform_ct_kill_task(struct iwl_priv *priv, 208 + bool stop) 209 + { 210 + if (stop) { 211 + IWL_DEBUG_POWER(priv, "Stop all queues\n"); 212 + if (priv->mac80211_registered) 213 + ieee80211_stop_queues(priv->hw); 214 + IWL_DEBUG_POWER(priv, 215 + "Schedule 5 seconds CT_KILL Timer\n"); 216 + mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, 217 + jiffies + CT_KILL_EXIT_DURATION * HZ); 218 + } else { 219 + IWL_DEBUG_POWER(priv, "Wake all queues\n"); 220 + if (priv->mac80211_registered) 221 + ieee80211_wake_queues(priv->hw); 222 + } 223 + } 224 + 225 + static void iwl_tt_ready_for_ct_kill(unsigned long data) 226 + { 227 + struct iwl_priv *priv = (struct iwl_priv *)data; 228 + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 229 + 230 + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 231 + return; 232 + 233 + /* temperature timer expired, ready to go into CT_KILL state */ 234 + if (tt->state != IWL_TI_CT_KILL) { 235 + IWL_DEBUG_POWER(priv, "entering CT_KILL state when " 236 + "temperature timer expired\n"); 237 + tt->state = IWL_TI_CT_KILL; 238 + set_bit(STATUS_CT_KILL, &priv->status); 239 + iwl_perform_ct_kill_task(priv, true); 240 + } 241 + } 242 + 243 + static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) 244 + { 245 + IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); 246 + /* make request to retrieve statistics information */ 247 + iwl_send_statistics_request(priv, CMD_SYNC, false); 248 + /* Reschedule the ct_kill wait timer */ 249 + mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, 250 + jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); 251 + } 252 + 253 + #define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) 254 + #define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) 255 + #define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) 256 + 257 + /* 258 + * Legacy thermal throttling 259 + * 1) Avoid NIC destruction due to high temperatures 260 + * Chip will identify dangerously high temperatures that can 261 + * harm the device and will power down 262 + * 2) Avoid the NIC power down due to high temperature 263 + * Throttle early enough to lower the power consumption before 264 + * drastic steps are needed 265 + */ 266 + static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) 267 + { 268 + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 269 + enum iwl_tt_state old_state; 270 + 271 + #ifdef CONFIG_IWLWIFI_DEBUG 272 + if ((tt->tt_previous_temp) && 273 + (temp > tt->tt_previous_temp) && 274 + ((temp - tt->tt_previous_temp) > 275 + IWL_TT_INCREASE_MARGIN)) { 276 + IWL_DEBUG_POWER(priv, 277 + "Temperature increase %d degree Celsius\n", 278 + (temp - tt->tt_previous_temp)); 279 + } 280 + #endif 281 + old_state = tt->state; 282 + /* in Celsius */ 283 + if (temp >= IWL_MINIMAL_POWER_THRESHOLD) 284 + tt->state = IWL_TI_CT_KILL; 285 + else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2) 286 + tt->state = IWL_TI_2; 287 + else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1) 288 + tt->state = IWL_TI_1; 289 + else 290 + tt->state = IWL_TI_0; 291 + 292 + #ifdef CONFIG_IWLWIFI_DEBUG 293 + tt->tt_previous_temp = temp; 294 + #endif 295 + /* stop ct_kill_waiting_tm timer */ 296 + del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); 297 + if (tt->state != old_state) { 298 + switch (tt->state) { 299 + case IWL_TI_0: 300 + /* 301 + * When the system is ready to go back to IWL_TI_0 302 + * we only have to call iwl_power_update_mode() to 303 + * do so. 304 + */ 305 + break; 306 + case IWL_TI_1: 307 + tt->tt_power_mode = IWL_POWER_INDEX_3; 308 + break; 309 + case IWL_TI_2: 310 + tt->tt_power_mode = IWL_POWER_INDEX_4; 311 + break; 312 + default: 313 + tt->tt_power_mode = IWL_POWER_INDEX_5; 314 + break; 315 + } 316 + mutex_lock(&priv->mutex); 317 + if (old_state == IWL_TI_CT_KILL) 318 + clear_bit(STATUS_CT_KILL, &priv->status); 319 + if (tt->state != IWL_TI_CT_KILL && 320 + iwl_power_update_mode(priv, true)) { 321 + /* TT state not updated 322 + * try again during next temperature read 323 + */ 324 + if (old_state == IWL_TI_CT_KILL) 325 + set_bit(STATUS_CT_KILL, &priv->status); 326 + tt->state = old_state; 327 + IWL_ERR(priv, "Cannot update power mode, " 328 + "TT state not updated\n"); 329 + } else { 330 + if (tt->state == IWL_TI_CT_KILL) { 331 + if (force) { 332 + set_bit(STATUS_CT_KILL, &priv->status); 333 + iwl_perform_ct_kill_task(priv, true); 334 + } else { 335 + iwl_prepare_ct_kill_task(priv); 336 + tt->state = old_state; 337 + } 338 + } else if (old_state == IWL_TI_CT_KILL && 339 + tt->state != IWL_TI_CT_KILL) 340 + iwl_perform_ct_kill_task(priv, false); 341 + IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", 342 + tt->state); 343 + IWL_DEBUG_POWER(priv, "Power Index change to %u\n", 344 + tt->tt_power_mode); 345 + } 346 + mutex_unlock(&priv->mutex); 347 + } 348 + } 349 + 350 + /* 351 + * Advance thermal throttling 352 + * 1) Avoid NIC destruction due to high temperatures 353 + * Chip will identify dangerously high temperatures that can 354 + * harm the device and will power down 355 + * 2) Avoid the NIC power down due to high temperature 356 + * Throttle early enough to lower the power consumption before 357 + * drastic steps are needed 358 + * Actions include relaxing the power down sleep thresholds and 359 + * decreasing the number of TX streams 360 + * 3) Avoid throughput performance impact as much as possible 361 + * 362 + *============================================================================= 363 + * Condition Nxt State Condition Nxt State Condition Nxt State 364 + *----------------------------------------------------------------------------- 365 + * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A 366 + * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 367 + * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 368 + * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 369 + *============================================================================= 370 + */ 371 + static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) 372 + { 373 + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 374 + int i; 375 + bool changed = false; 376 + enum iwl_tt_state old_state; 377 + struct iwl_tt_trans *transaction; 378 + 379 + old_state = tt->state; 380 + for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) { 381 + /* based on the current TT state, 382 + * find the curresponding transaction table 383 + * each table has (IWL_TI_STATE_MAX - 1) entries 384 + * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1)) 385 + * will advance to the correct table. 386 + * then based on the current temperature 387 + * find the next state need to transaction to 388 + * go through all the possible (IWL_TI_STATE_MAX - 1) entries 389 + * in the current table to see if transaction is needed 390 + */ 391 + transaction = tt->transaction + 392 + ((old_state * (IWL_TI_STATE_MAX - 1)) + i); 393 + if (temp >= transaction->tt_low && 394 + temp <= transaction->tt_high) { 395 + #ifdef CONFIG_IWLWIFI_DEBUG 396 + if ((tt->tt_previous_temp) && 397 + (temp > tt->tt_previous_temp) && 398 + ((temp - tt->tt_previous_temp) > 399 + IWL_TT_INCREASE_MARGIN)) { 400 + IWL_DEBUG_POWER(priv, 401 + "Temperature increase %d " 402 + "degree Celsius\n", 403 + (temp - tt->tt_previous_temp)); 404 + } 405 + tt->tt_previous_temp = temp; 406 + #endif 407 + if (old_state != 408 + transaction->next_state) { 409 + changed = true; 410 + tt->state = 411 + transaction->next_state; 412 + } 413 + break; 414 + } 415 + } 416 + /* stop ct_kill_waiting_tm timer */ 417 + del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); 418 + if (changed) { 419 + struct iwl_rxon_cmd *rxon = &priv->staging_rxon; 420 + 421 + if (tt->state >= IWL_TI_1) { 422 + /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ 423 + tt->tt_power_mode = IWL_POWER_INDEX_5; 424 + if (!iwl_ht_enabled(priv)) 425 + /* disable HT */ 426 + rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | 427 + RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | 428 + RXON_FLG_HT40_PROT_MSK | 429 + RXON_FLG_HT_PROT_MSK); 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_POWER(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_POWER(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 + iwl_prepare_ct_kill_task(priv); 474 + tt->state = old_state; 475 + } 476 + } else if (old_state == IWL_TI_CT_KILL && 477 + tt->state != IWL_TI_CT_KILL) { 478 + IWL_DEBUG_POWER(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_POWER(priv, "Queueing critical temperature enter.\n"); 564 + queue_work(priv->workqueue, &priv->ct_enter); 565 + } 566 + EXPORT_SYMBOL(iwl_tt_enter_ct_kill); 567 + 568 + void iwl_tt_exit_ct_kill(struct iwl_priv *priv) 569 + { 570 + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 571 + return; 572 + 573 + IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n"); 574 + queue_work(priv->workqueue, &priv->ct_exit); 575 + } 576 + EXPORT_SYMBOL(iwl_tt_exit_ct_kill); 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->cfg->temperature_kelvin) 587 + temp = KELVIN_TO_CELSIUS(priv->temperature); 588 + 589 + if (!priv->thermal_throttle.advanced_tt) 590 + iwl_legacy_tt_handler(priv, temp, false); 591 + else 592 + iwl_advance_tt_handler(priv, temp, false); 593 + } 594 + 595 + void iwl_tt_handler(struct iwl_priv *priv) 596 + { 597 + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 598 + return; 599 + 600 + IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n"); 601 + queue_work(priv->workqueue, &priv->tt_work); 602 + } 603 + EXPORT_SYMBOL(iwl_tt_handler); 604 + 605 + /* Thermal throttling initialization 606 + * For advance thermal throttling: 607 + * Initialize Thermal Index and temperature threshold table 608 + * Initialize thermal throttling restriction table 609 + */ 610 + void iwl_tt_initialize(struct iwl_priv *priv) 611 + { 612 + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 613 + int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); 614 + struct iwl_tt_trans *transaction; 615 + 616 + IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); 617 + 618 + memset(tt, 0, sizeof(struct iwl_tt_mgmt)); 619 + 620 + tt->state = IWL_TI_0; 621 + init_timer(&priv->thermal_throttle.ct_kill_exit_tm); 622 + priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; 623 + priv->thermal_throttle.ct_kill_exit_tm.function = 624 + iwl_tt_check_exit_ct_kill; 625 + init_timer(&priv->thermal_throttle.ct_kill_waiting_tm); 626 + priv->thermal_throttle.ct_kill_waiting_tm.data = 627 + (unsigned long)priv; 628 + priv->thermal_throttle.ct_kill_waiting_tm.function = 629 + iwl_tt_ready_for_ct_kill; 630 + /* setup deferred ct kill work */ 631 + INIT_WORK(&priv->tt_work, iwl_bg_tt_work); 632 + INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); 633 + INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); 634 + 635 + if (priv->cfg->adv_thermal_throttle) { 636 + IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); 637 + tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * 638 + IWL_TI_STATE_MAX, GFP_KERNEL); 639 + tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * 640 + IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1), 641 + GFP_KERNEL); 642 + if (!tt->restriction || !tt->transaction) { 643 + IWL_ERR(priv, "Fallback to Legacy Throttling\n"); 644 + priv->thermal_throttle.advanced_tt = false; 645 + kfree(tt->restriction); 646 + tt->restriction = NULL; 647 + kfree(tt->transaction); 648 + tt->transaction = NULL; 649 + } else { 650 + transaction = tt->transaction + 651 + (IWL_TI_0 * (IWL_TI_STATE_MAX - 1)); 652 + memcpy(transaction, &tt_range_0[0], size); 653 + transaction = tt->transaction + 654 + (IWL_TI_1 * (IWL_TI_STATE_MAX - 1)); 655 + memcpy(transaction, &tt_range_1[0], size); 656 + transaction = tt->transaction + 657 + (IWL_TI_2 * (IWL_TI_STATE_MAX - 1)); 658 + memcpy(transaction, &tt_range_2[0], size); 659 + transaction = tt->transaction + 660 + (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1)); 661 + memcpy(transaction, &tt_range_3[0], size); 662 + size = sizeof(struct iwl_tt_restriction) * 663 + IWL_TI_STATE_MAX; 664 + memcpy(tt->restriction, 665 + &restriction_range[0], size); 666 + priv->thermal_throttle.advanced_tt = true; 667 + } 668 + } else { 669 + IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); 670 + priv->thermal_throttle.advanced_tt = false; 671 + } 672 + } 673 + EXPORT_SYMBOL(iwl_tt_initialize); 674 + 675 + /* cleanup thermal throttling management related memory and timer */ 676 + void iwl_tt_exit(struct iwl_priv *priv) 677 + { 678 + struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 679 + 680 + /* stop ct_kill_exit_tm timer if activated */ 681 + del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); 682 + /* stop ct_kill_waiting_tm timer if activated */ 683 + del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); 684 + cancel_work_sync(&priv->tt_work); 685 + cancel_work_sync(&priv->ct_enter); 686 + cancel_work_sync(&priv->ct_exit); 687 + 688 + if (priv->thermal_throttle.advanced_tt) { 689 + /* free advance thermal throttling memory */ 690 + kfree(tt->restriction); 691 + tt->restriction = NULL; 692 + kfree(tt->transaction); 693 + tt->transaction = NULL; 694 + } 695 + } 696 + EXPORT_SYMBOL(iwl_tt_exit);
+129
drivers/net/wireless/iwlwifi/iwl-agn-tt.h
··· 1 + /****************************************************************************** 2 + * 3 + * Copyright(c) 2007 - 2010 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 + #ifndef __iwl_tt_setting_h__ 29 + #define __iwl_tt_setting_h__ 30 + 31 + #include "iwl-commands.h" 32 + 33 + #define IWL_ABSOLUTE_ZERO 0 34 + #define IWL_ABSOLUTE_MAX 0xFFFFFFFF 35 + #define IWL_TT_INCREASE_MARGIN 5 36 + #define IWL_TT_CT_KILL_MARGIN 3 37 + 38 + enum iwl_antenna_ok { 39 + IWL_ANT_OK_NONE, 40 + IWL_ANT_OK_SINGLE, 41 + IWL_ANT_OK_MULTI, 42 + }; 43 + 44 + /* Thermal Throttling State Machine states */ 45 + enum iwl_tt_state { 46 + IWL_TI_0, /* normal temperature, system power state */ 47 + IWL_TI_1, /* high temperature detect, low power state */ 48 + IWL_TI_2, /* higher temperature detected, lower power state */ 49 + IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */ 50 + IWL_TI_STATE_MAX 51 + }; 52 + 53 + /** 54 + * struct iwl_tt_restriction - Thermal Throttling restriction table 55 + * @tx_stream: number of tx stream allowed 56 + * @is_ht: ht enable/disable 57 + * @rx_stream: number of rx stream allowed 58 + * 59 + * This table is used by advance thermal throttling management 60 + * based on the current thermal throttling state, and determines 61 + * the number of tx/rx streams and the status of HT operation. 62 + */ 63 + struct iwl_tt_restriction { 64 + enum iwl_antenna_ok tx_stream; 65 + enum iwl_antenna_ok rx_stream; 66 + bool is_ht; 67 + }; 68 + 69 + /** 70 + * struct iwl_tt_trans - Thermal Throttling transaction table 71 + * @next_state: next thermal throttling mode 72 + * @tt_low: low temperature threshold to change state 73 + * @tt_high: high temperature threshold to change state 74 + * 75 + * This is used by the advanced thermal throttling algorithm 76 + * to determine the next thermal state to go based on the 77 + * current temperature. 78 + */ 79 + struct iwl_tt_trans { 80 + enum iwl_tt_state next_state; 81 + u32 tt_low; 82 + u32 tt_high; 83 + }; 84 + 85 + /** 86 + * struct iwl_tt_mgnt - Thermal Throttling Management structure 87 + * @advanced_tt: advanced thermal throttle required 88 + * @state: current Thermal Throttling state 89 + * @tt_power_mode: Thermal Throttling power mode index 90 + * being used to set power level when 91 + * when thermal throttling state != IWL_TI_0 92 + * the tt_power_mode should set to different 93 + * power mode based on the current tt state 94 + * @tt_previous_temperature: last measured temperature 95 + * @iwl_tt_restriction: ptr to restriction tbl, used by advance 96 + * thermal throttling to determine how many tx/rx streams 97 + * should be used in tt state; and can HT be enabled or not 98 + * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling 99 + * state transaction 100 + * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature 101 + * @ct_kill_exit_tm: timer to exit thermal kill 102 + */ 103 + struct iwl_tt_mgmt { 104 + enum iwl_tt_state state; 105 + bool advanced_tt; 106 + u8 tt_power_mode; 107 + bool ct_kill_toggle; 108 + #ifdef CONFIG_IWLWIFI_DEBUG 109 + s32 tt_previous_temp; 110 + #endif 111 + struct iwl_tt_restriction *restriction; 112 + struct iwl_tt_trans *transaction; 113 + struct timer_list ct_kill_exit_tm; 114 + struct timer_list ct_kill_waiting_tm; 115 + }; 116 + 117 + u8 iwl_tt_current_power_mode(struct iwl_priv *priv); 118 + bool iwl_tt_is_low_power_state(struct iwl_priv *priv); 119 + bool iwl_ht_enabled(struct iwl_priv *priv); 120 + bool iwl_check_for_ct_kill(struct iwl_priv *priv); 121 + enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); 122 + enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); 123 + void iwl_tt_enter_ct_kill(struct iwl_priv *priv); 124 + void iwl_tt_exit_ct_kill(struct iwl_priv *priv); 125 + void iwl_tt_handler(struct iwl_priv *priv); 126 + void iwl_tt_initialize(struct iwl_priv *priv); 127 + void iwl_tt_exit(struct iwl_priv *priv); 128 + 129 + #endif /* __iwl_tt_setting_h__ */
+46
drivers/net/wireless/iwlwifi/iwl-agn.c
··· 2592 2592 return pos; 2593 2593 } 2594 2594 2595 + static void iwl_rf_kill_ct_config(struct iwl_priv *priv) 2596 + { 2597 + struct iwl_ct_kill_config cmd; 2598 + struct iwl_ct_kill_throttling_config adv_cmd; 2599 + unsigned long flags; 2600 + int ret = 0; 2601 + 2602 + spin_lock_irqsave(&priv->lock, flags); 2603 + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, 2604 + CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); 2605 + spin_unlock_irqrestore(&priv->lock, flags); 2606 + priv->thermal_throttle.ct_kill_toggle = false; 2607 + 2608 + if (priv->cfg->support_ct_kill_exit) { 2609 + adv_cmd.critical_temperature_enter = 2610 + cpu_to_le32(priv->hw_params.ct_kill_threshold); 2611 + adv_cmd.critical_temperature_exit = 2612 + cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); 2613 + 2614 + ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, 2615 + sizeof(adv_cmd), &adv_cmd); 2616 + if (ret) 2617 + IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); 2618 + else 2619 + IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " 2620 + "succeeded, " 2621 + "critical temperature enter is %d," 2622 + "exit is %d\n", 2623 + priv->hw_params.ct_kill_threshold, 2624 + priv->hw_params.ct_kill_exit_threshold); 2625 + } else { 2626 + cmd.critical_temperature_R = 2627 + cpu_to_le32(priv->hw_params.ct_kill_threshold); 2628 + 2629 + ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, 2630 + sizeof(cmd), &cmd); 2631 + if (ret) 2632 + IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); 2633 + else 2634 + IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " 2635 + "succeeded, " 2636 + "critical temperature is %d\n", 2637 + priv->hw_params.ct_kill_threshold); 2638 + } 2639 + } 2640 + 2595 2641 /** 2596 2642 * iwl_alive_start - called after REPLY_ALIVE notification received 2597 2643 * from protocol/runtime uCode (initialization uCode's
-48
drivers/net/wireless/iwlwifi/iwl-core.c
··· 1514 1514 } 1515 1515 EXPORT_SYMBOL(iwl_send_statistics_request); 1516 1516 1517 - void iwl_rf_kill_ct_config(struct iwl_priv *priv) 1518 - { 1519 - struct iwl_ct_kill_config cmd; 1520 - struct iwl_ct_kill_throttling_config adv_cmd; 1521 - unsigned long flags; 1522 - int ret = 0; 1523 - 1524 - spin_lock_irqsave(&priv->lock, flags); 1525 - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, 1526 - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); 1527 - spin_unlock_irqrestore(&priv->lock, flags); 1528 - priv->thermal_throttle.ct_kill_toggle = false; 1529 - 1530 - if (priv->cfg->support_ct_kill_exit) { 1531 - adv_cmd.critical_temperature_enter = 1532 - cpu_to_le32(priv->hw_params.ct_kill_threshold); 1533 - adv_cmd.critical_temperature_exit = 1534 - cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); 1535 - 1536 - ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, 1537 - sizeof(adv_cmd), &adv_cmd); 1538 - if (ret) 1539 - IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); 1540 - else 1541 - IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " 1542 - "succeeded, " 1543 - "critical temperature enter is %d," 1544 - "exit is %d\n", 1545 - priv->hw_params.ct_kill_threshold, 1546 - priv->hw_params.ct_kill_exit_threshold); 1547 - } else { 1548 - cmd.critical_temperature_R = 1549 - cpu_to_le32(priv->hw_params.ct_kill_threshold); 1550 - 1551 - ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, 1552 - sizeof(cmd), &cmd); 1553 - if (ret) 1554 - IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); 1555 - else 1556 - IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " 1557 - "succeeded, " 1558 - "critical temperature is %d\n", 1559 - priv->hw_params.ct_kill_threshold); 1560 - } 1561 - } 1562 - EXPORT_SYMBOL(iwl_rf_kill_ct_config); 1563 - 1564 - 1565 1517 /* 1566 1518 * CARD_STATE_CMD 1567 1519 *
+9 -1
drivers/net/wireless/iwlwifi/iwl-core.h
··· 136 136 void (*set_calib_version)(struct iwl_priv *priv); 137 137 }; 138 138 139 + struct iwl_tt_ops { 140 + bool (*lower_power_detection)(struct iwl_priv *priv); 141 + u8 (*tt_power_mode)(struct iwl_priv *priv); 142 + bool (*ct_kill_check)(struct iwl_priv *priv); 143 + }; 144 + 139 145 struct iwl_lib_ops { 140 146 /* set hw dependent parameters */ 141 147 int (*set_hw_params)(struct iwl_priv *priv); ··· 218 212 void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control); 219 213 220 214 struct iwl_debugfs_ops debugfs_ops; 215 + 216 + /* thermal throttling */ 217 + struct iwl_tt_ops tt_ops; 221 218 }; 222 219 223 220 struct iwl_led_ops { ··· 702 693 return iwl_is_ready(priv); 703 694 } 704 695 705 - extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); 706 696 extern void iwl_send_bt_config(struct iwl_priv *priv); 707 697 extern int iwl_send_statistics_request(struct iwl_priv *priv, 708 698 u8 flags, bool clear);
+1
drivers/net/wireless/iwlwifi/iwl-dev.h
··· 47 47 #include "iwl-led.h" 48 48 #include "iwl-power.h" 49 49 #include "iwl-agn-rs.h" 50 + #include "iwl-agn-tt.h" 50 51 51 52 struct iwl_tx_queue; 52 53
+9 -631
drivers/net/wireless/iwlwifi/iwl-power.c
··· 192 192 IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); 193 193 } 194 194 195 - /* default Thermal Throttling transaction table 196 - * Current state | Throttling Down | Throttling Up 197 - *============================================================================= 198 - * Condition Nxt State Condition Nxt State Condition Nxt State 199 - *----------------------------------------------------------------------------- 200 - * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A 201 - * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 202 - * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 203 - * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 204 - *============================================================================= 205 - */ 206 - static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { 207 - {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, 208 - {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1}, 209 - {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} 210 - }; 211 - static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { 212 - {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, 213 - {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1}, 214 - {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} 215 - }; 216 - static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { 217 - {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, 218 - {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}, 219 - {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} 220 - }; 221 - static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { 222 - {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, 223 - {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, 224 - {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX} 225 - }; 226 - 227 - /* Advance Thermal Throttling default restriction table */ 228 - static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = { 229 - {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true }, 230 - {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true }, 231 - {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false }, 232 - {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false } 233 - }; 234 - 235 - 236 195 static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv, 237 196 struct iwl_powertable_cmd *cmd) 238 197 { ··· 267 308 int iwl_power_update_mode(struct iwl_priv *priv, bool force) 268 309 { 269 310 int ret = 0; 270 - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 271 311 bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS; 272 312 bool update_chains; 273 313 struct iwl_powertable_cmd cmd; ··· 283 325 else if (priv->cfg->supports_idle && 284 326 priv->hw->conf.flags & IEEE80211_CONF_IDLE) 285 327 iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); 286 - else if (tt->state >= IWL_TI_1) 287 - iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); 288 - else if (!enabled) 328 + else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && 329 + priv->cfg->ops->lib->tt_ops.tt_power_mode) { 330 + if (priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) { 331 + /* in thermal throttling low power state */ 332 + iwl_static_sleep_cmd(priv, &cmd, 333 + priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), 334 + dtimper); 335 + } 336 + } else if (!enabled) 289 337 iwl_power_sleep_cam_cmd(priv, &cmd); 290 338 else if (priv->power_data.debug_sleep_level_override >= 0) 291 339 iwl_static_sleep_cmd(priv, &cmd, ··· 330 366 return ret; 331 367 } 332 368 EXPORT_SYMBOL(iwl_power_update_mode); 333 - 334 - bool iwl_ht_enabled(struct iwl_priv *priv) 335 - { 336 - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 337 - struct iwl_tt_restriction *restriction; 338 - 339 - if (!priv->thermal_throttle.advanced_tt) 340 - return true; 341 - restriction = tt->restriction + tt->state; 342 - return restriction->is_ht; 343 - } 344 - EXPORT_SYMBOL(iwl_ht_enabled); 345 - 346 - bool iwl_within_ct_kill_margin(struct iwl_priv *priv) 347 - { 348 - s32 temp = priv->temperature; /* degrees CELSIUS except specified */ 349 - bool within_margin = false; 350 - 351 - if (priv->cfg->temperature_kelvin) 352 - temp = KELVIN_TO_CELSIUS(priv->temperature); 353 - 354 - if (!priv->thermal_throttle.advanced_tt) 355 - within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= 356 - CT_KILL_THRESHOLD_LEGACY) ? true : false; 357 - else 358 - within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= 359 - CT_KILL_THRESHOLD) ? true : false; 360 - return within_margin; 361 - } 362 - 363 - enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) 364 - { 365 - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 366 - struct iwl_tt_restriction *restriction; 367 - 368 - if (!priv->thermal_throttle.advanced_tt) 369 - return IWL_ANT_OK_MULTI; 370 - restriction = tt->restriction + tt->state; 371 - return restriction->tx_stream; 372 - } 373 - EXPORT_SYMBOL(iwl_tx_ant_restriction); 374 - 375 - enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv) 376 - { 377 - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 378 - struct iwl_tt_restriction *restriction; 379 - 380 - if (!priv->thermal_throttle.advanced_tt) 381 - return IWL_ANT_OK_MULTI; 382 - restriction = tt->restriction + tt->state; 383 - return restriction->rx_stream; 384 - } 385 - 386 - #define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ 387 - #define CT_KILL_WAITING_DURATION (300) /* 300ms duration */ 388 - 389 - /* 390 - * toggle the bit to wake up uCode and check the temperature 391 - * if the temperature is below CT, uCode will stay awake and send card 392 - * state notification with CT_KILL bit clear to inform Thermal Throttling 393 - * Management to change state. Otherwise, uCode will go back to sleep 394 - * without doing anything, driver should continue the 5 seconds timer 395 - * to wake up uCode for temperature check until temperature drop below CT 396 - */ 397 - static void iwl_tt_check_exit_ct_kill(unsigned long data) 398 - { 399 - struct iwl_priv *priv = (struct iwl_priv *)data; 400 - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 401 - unsigned long flags; 402 - 403 - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 404 - return; 405 - 406 - if (tt->state == IWL_TI_CT_KILL) { 407 - if (priv->thermal_throttle.ct_kill_toggle) { 408 - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, 409 - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); 410 - priv->thermal_throttle.ct_kill_toggle = false; 411 - } else { 412 - iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, 413 - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); 414 - priv->thermal_throttle.ct_kill_toggle = true; 415 - } 416 - iwl_read32(priv, CSR_UCODE_DRV_GP1); 417 - spin_lock_irqsave(&priv->reg_lock, flags); 418 - if (!iwl_grab_nic_access(priv)) 419 - iwl_release_nic_access(priv); 420 - spin_unlock_irqrestore(&priv->reg_lock, flags); 421 - 422 - /* Reschedule the ct_kill timer to occur in 423 - * CT_KILL_EXIT_DURATION seconds to ensure we get a 424 - * thermal update */ 425 - IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n"); 426 - mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + 427 - CT_KILL_EXIT_DURATION * HZ); 428 - } 429 - } 430 - 431 - static void iwl_perform_ct_kill_task(struct iwl_priv *priv, 432 - bool stop) 433 - { 434 - if (stop) { 435 - IWL_DEBUG_POWER(priv, "Stop all queues\n"); 436 - if (priv->mac80211_registered) 437 - ieee80211_stop_queues(priv->hw); 438 - IWL_DEBUG_POWER(priv, 439 - "Schedule 5 seconds CT_KILL Timer\n"); 440 - mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + 441 - CT_KILL_EXIT_DURATION * HZ); 442 - } else { 443 - IWL_DEBUG_POWER(priv, "Wake all queues\n"); 444 - if (priv->mac80211_registered) 445 - ieee80211_wake_queues(priv->hw); 446 - } 447 - } 448 - 449 - static void iwl_tt_ready_for_ct_kill(unsigned long data) 450 - { 451 - struct iwl_priv *priv = (struct iwl_priv *)data; 452 - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 453 - 454 - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 455 - return; 456 - 457 - /* temperature timer expired, ready to go into CT_KILL state */ 458 - if (tt->state != IWL_TI_CT_KILL) { 459 - IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n"); 460 - tt->state = IWL_TI_CT_KILL; 461 - set_bit(STATUS_CT_KILL, &priv->status); 462 - iwl_perform_ct_kill_task(priv, true); 463 - } 464 - } 465 - 466 - static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) 467 - { 468 - IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); 469 - /* make request to retrieve statistics information */ 470 - iwl_send_statistics_request(priv, CMD_SYNC, false); 471 - /* Reschedule the ct_kill wait timer */ 472 - mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, 473 - jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); 474 - } 475 - 476 - #define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) 477 - #define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) 478 - #define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) 479 - 480 - /* 481 - * Legacy thermal throttling 482 - * 1) Avoid NIC destruction due to high temperatures 483 - * Chip will identify dangerously high temperatures that can 484 - * harm the device and will power down 485 - * 2) Avoid the NIC power down due to high temperature 486 - * Throttle early enough to lower the power consumption before 487 - * drastic steps are needed 488 - */ 489 - static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) 490 - { 491 - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 492 - enum iwl_tt_state old_state; 493 - 494 - #ifdef CONFIG_IWLWIFI_DEBUG 495 - if ((tt->tt_previous_temp) && 496 - (temp > tt->tt_previous_temp) && 497 - ((temp - tt->tt_previous_temp) > 498 - IWL_TT_INCREASE_MARGIN)) { 499 - IWL_DEBUG_POWER(priv, 500 - "Temperature increase %d degree Celsius\n", 501 - (temp - tt->tt_previous_temp)); 502 - } 503 - #endif 504 - old_state = tt->state; 505 - /* in Celsius */ 506 - if (temp >= IWL_MINIMAL_POWER_THRESHOLD) 507 - tt->state = IWL_TI_CT_KILL; 508 - else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2) 509 - tt->state = IWL_TI_2; 510 - else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1) 511 - tt->state = IWL_TI_1; 512 - else 513 - tt->state = IWL_TI_0; 514 - 515 - #ifdef CONFIG_IWLWIFI_DEBUG 516 - tt->tt_previous_temp = temp; 517 - #endif 518 - /* stop ct_kill_waiting_tm timer */ 519 - del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); 520 - if (tt->state != old_state) { 521 - switch (tt->state) { 522 - case IWL_TI_0: 523 - /* 524 - * When the system is ready to go back to IWL_TI_0 525 - * we only have to call iwl_power_update_mode() to 526 - * do so. 527 - */ 528 - break; 529 - case IWL_TI_1: 530 - tt->tt_power_mode = IWL_POWER_INDEX_3; 531 - break; 532 - case IWL_TI_2: 533 - tt->tt_power_mode = IWL_POWER_INDEX_4; 534 - break; 535 - default: 536 - tt->tt_power_mode = IWL_POWER_INDEX_5; 537 - break; 538 - } 539 - mutex_lock(&priv->mutex); 540 - if (old_state == IWL_TI_CT_KILL) 541 - clear_bit(STATUS_CT_KILL, &priv->status); 542 - if (tt->state != IWL_TI_CT_KILL && 543 - iwl_power_update_mode(priv, true)) { 544 - /* TT state not updated 545 - * try again during next temperature read 546 - */ 547 - if (old_state == IWL_TI_CT_KILL) 548 - set_bit(STATUS_CT_KILL, &priv->status); 549 - tt->state = old_state; 550 - IWL_ERR(priv, "Cannot update power mode, " 551 - "TT state not updated\n"); 552 - } else { 553 - if (tt->state == IWL_TI_CT_KILL) { 554 - if (force) { 555 - set_bit(STATUS_CT_KILL, &priv->status); 556 - iwl_perform_ct_kill_task(priv, true); 557 - } else { 558 - iwl_prepare_ct_kill_task(priv); 559 - tt->state = old_state; 560 - } 561 - } else if (old_state == IWL_TI_CT_KILL && 562 - tt->state != IWL_TI_CT_KILL) 563 - iwl_perform_ct_kill_task(priv, false); 564 - IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", 565 - tt->state); 566 - IWL_DEBUG_POWER(priv, "Power Index change to %u\n", 567 - tt->tt_power_mode); 568 - } 569 - mutex_unlock(&priv->mutex); 570 - } 571 - } 572 - 573 - /* 574 - * Advance thermal throttling 575 - * 1) Avoid NIC destruction due to high temperatures 576 - * Chip will identify dangerously high temperatures that can 577 - * harm the device and will power down 578 - * 2) Avoid the NIC power down due to high temperature 579 - * Throttle early enough to lower the power consumption before 580 - * drastic steps are needed 581 - * Actions include relaxing the power down sleep thresholds and 582 - * decreasing the number of TX streams 583 - * 3) Avoid throughput performance impact as much as possible 584 - * 585 - *============================================================================= 586 - * Condition Nxt State Condition Nxt State Condition Nxt State 587 - *----------------------------------------------------------------------------- 588 - * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A 589 - * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 590 - * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 591 - * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 592 - *============================================================================= 593 - */ 594 - static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) 595 - { 596 - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 597 - int i; 598 - bool changed = false; 599 - enum iwl_tt_state old_state; 600 - struct iwl_tt_trans *transaction; 601 - 602 - old_state = tt->state; 603 - for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) { 604 - /* based on the current TT state, 605 - * find the curresponding transaction table 606 - * each table has (IWL_TI_STATE_MAX - 1) entries 607 - * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1)) 608 - * will advance to the correct table. 609 - * then based on the current temperature 610 - * find the next state need to transaction to 611 - * go through all the possible (IWL_TI_STATE_MAX - 1) entries 612 - * in the current table to see if transaction is needed 613 - */ 614 - transaction = tt->transaction + 615 - ((old_state * (IWL_TI_STATE_MAX - 1)) + i); 616 - if (temp >= transaction->tt_low && 617 - temp <= transaction->tt_high) { 618 - #ifdef CONFIG_IWLWIFI_DEBUG 619 - if ((tt->tt_previous_temp) && 620 - (temp > tt->tt_previous_temp) && 621 - ((temp - tt->tt_previous_temp) > 622 - IWL_TT_INCREASE_MARGIN)) { 623 - IWL_DEBUG_POWER(priv, 624 - "Temperature increase %d " 625 - "degree Celsius\n", 626 - (temp - tt->tt_previous_temp)); 627 - } 628 - tt->tt_previous_temp = temp; 629 - #endif 630 - if (old_state != 631 - transaction->next_state) { 632 - changed = true; 633 - tt->state = 634 - transaction->next_state; 635 - } 636 - break; 637 - } 638 - } 639 - /* stop ct_kill_waiting_tm timer */ 640 - del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); 641 - if (changed) { 642 - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; 643 - 644 - if (tt->state >= IWL_TI_1) { 645 - /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ 646 - tt->tt_power_mode = IWL_POWER_INDEX_5; 647 - if (!iwl_ht_enabled(priv)) 648 - /* disable HT */ 649 - rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | 650 - RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | 651 - RXON_FLG_HT40_PROT_MSK | 652 - RXON_FLG_HT_PROT_MSK); 653 - else { 654 - /* check HT capability and set 655 - * according to the system HT capability 656 - * in case get disabled before */ 657 - iwl_set_rxon_ht(priv, &priv->current_ht_config); 658 - } 659 - 660 - } else { 661 - /* 662 - * restore system power setting -- it will be 663 - * recalculated automatically. 664 - */ 665 - 666 - /* check HT capability and set 667 - * according to the system HT capability 668 - * in case get disabled before */ 669 - iwl_set_rxon_ht(priv, &priv->current_ht_config); 670 - } 671 - mutex_lock(&priv->mutex); 672 - if (old_state == IWL_TI_CT_KILL) 673 - clear_bit(STATUS_CT_KILL, &priv->status); 674 - if (tt->state != IWL_TI_CT_KILL && 675 - iwl_power_update_mode(priv, true)) { 676 - /* TT state not updated 677 - * try again during next temperature read 678 - */ 679 - IWL_ERR(priv, "Cannot update power mode, " 680 - "TT state not updated\n"); 681 - if (old_state == IWL_TI_CT_KILL) 682 - set_bit(STATUS_CT_KILL, &priv->status); 683 - tt->state = old_state; 684 - } else { 685 - IWL_DEBUG_POWER(priv, 686 - "Thermal Throttling to new state: %u\n", 687 - tt->state); 688 - if (old_state != IWL_TI_CT_KILL && 689 - tt->state == IWL_TI_CT_KILL) { 690 - if (force) { 691 - IWL_DEBUG_POWER(priv, 692 - "Enter IWL_TI_CT_KILL\n"); 693 - set_bit(STATUS_CT_KILL, &priv->status); 694 - iwl_perform_ct_kill_task(priv, true); 695 - } else { 696 - iwl_prepare_ct_kill_task(priv); 697 - tt->state = old_state; 698 - } 699 - } else if (old_state == IWL_TI_CT_KILL && 700 - tt->state != IWL_TI_CT_KILL) { 701 - IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); 702 - iwl_perform_ct_kill_task(priv, false); 703 - } 704 - } 705 - mutex_unlock(&priv->mutex); 706 - } 707 - } 708 - 709 - /* Card State Notification indicated reach critical temperature 710 - * if PSP not enable, no Thermal Throttling function will be performed 711 - * just set the GP1 bit to acknowledge the event 712 - * otherwise, go into IWL_TI_CT_KILL state 713 - * since Card State Notification will not provide any temperature reading 714 - * for Legacy mode 715 - * so just pass the CT_KILL temperature to iwl_legacy_tt_handler() 716 - * for advance mode 717 - * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state 718 - */ 719 - static void iwl_bg_ct_enter(struct work_struct *work) 720 - { 721 - struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); 722 - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 723 - 724 - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 725 - return; 726 - 727 - if (!iwl_is_ready(priv)) 728 - return; 729 - 730 - if (tt->state != IWL_TI_CT_KILL) { 731 - IWL_ERR(priv, "Device reached critical temperature " 732 - "- ucode going to sleep!\n"); 733 - if (!priv->thermal_throttle.advanced_tt) 734 - iwl_legacy_tt_handler(priv, 735 - IWL_MINIMAL_POWER_THRESHOLD, 736 - true); 737 - else 738 - iwl_advance_tt_handler(priv, 739 - CT_KILL_THRESHOLD + 1, true); 740 - } 741 - } 742 - 743 - /* Card State Notification indicated out of critical temperature 744 - * since Card State Notification will not provide any temperature reading 745 - * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature 746 - * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state 747 - */ 748 - static void iwl_bg_ct_exit(struct work_struct *work) 749 - { 750 - struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); 751 - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 752 - 753 - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 754 - return; 755 - 756 - if (!iwl_is_ready(priv)) 757 - return; 758 - 759 - /* stop ct_kill_exit_tm timer */ 760 - del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); 761 - 762 - if (tt->state == IWL_TI_CT_KILL) { 763 - IWL_ERR(priv, 764 - "Device temperature below critical" 765 - "- ucode awake!\n"); 766 - /* 767 - * exit from CT_KILL state 768 - * reset the current temperature reading 769 - */ 770 - priv->temperature = 0; 771 - if (!priv->thermal_throttle.advanced_tt) 772 - iwl_legacy_tt_handler(priv, 773 - IWL_REDUCED_PERFORMANCE_THRESHOLD_2, 774 - true); 775 - else 776 - iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD, 777 - true); 778 - } 779 - } 780 - 781 - void iwl_tt_enter_ct_kill(struct iwl_priv *priv) 782 - { 783 - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 784 - return; 785 - 786 - IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n"); 787 - queue_work(priv->workqueue, &priv->ct_enter); 788 - } 789 - EXPORT_SYMBOL(iwl_tt_enter_ct_kill); 790 - 791 - void iwl_tt_exit_ct_kill(struct iwl_priv *priv) 792 - { 793 - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 794 - return; 795 - 796 - IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n"); 797 - queue_work(priv->workqueue, &priv->ct_exit); 798 - } 799 - EXPORT_SYMBOL(iwl_tt_exit_ct_kill); 800 - 801 - static void iwl_bg_tt_work(struct work_struct *work) 802 - { 803 - struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); 804 - s32 temp = priv->temperature; /* degrees CELSIUS except specified */ 805 - 806 - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 807 - return; 808 - 809 - if (priv->cfg->temperature_kelvin) 810 - temp = KELVIN_TO_CELSIUS(priv->temperature); 811 - 812 - if (!priv->thermal_throttle.advanced_tt) 813 - iwl_legacy_tt_handler(priv, temp, false); 814 - else 815 - iwl_advance_tt_handler(priv, temp, false); 816 - } 817 - 818 - void iwl_tt_handler(struct iwl_priv *priv) 819 - { 820 - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 821 - return; 822 - 823 - IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n"); 824 - queue_work(priv->workqueue, &priv->tt_work); 825 - } 826 - EXPORT_SYMBOL(iwl_tt_handler); 827 - 828 - /* Thermal throttling initialization 829 - * For advance thermal throttling: 830 - * Initialize Thermal Index and temperature threshold table 831 - * Initialize thermal throttling restriction table 832 - */ 833 - void iwl_tt_initialize(struct iwl_priv *priv) 834 - { 835 - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 836 - int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); 837 - struct iwl_tt_trans *transaction; 838 - 839 - IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); 840 - 841 - memset(tt, 0, sizeof(struct iwl_tt_mgmt)); 842 - 843 - tt->state = IWL_TI_0; 844 - init_timer(&priv->thermal_throttle.ct_kill_exit_tm); 845 - priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; 846 - priv->thermal_throttle.ct_kill_exit_tm.function = 847 - iwl_tt_check_exit_ct_kill; 848 - init_timer(&priv->thermal_throttle.ct_kill_waiting_tm); 849 - priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv; 850 - priv->thermal_throttle.ct_kill_waiting_tm.function = 851 - iwl_tt_ready_for_ct_kill; 852 - /* setup deferred ct kill work */ 853 - INIT_WORK(&priv->tt_work, iwl_bg_tt_work); 854 - INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); 855 - INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); 856 - 857 - if (priv->cfg->adv_thermal_throttle) { 858 - IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); 859 - tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * 860 - IWL_TI_STATE_MAX, GFP_KERNEL); 861 - tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * 862 - IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1), 863 - GFP_KERNEL); 864 - if (!tt->restriction || !tt->transaction) { 865 - IWL_ERR(priv, "Fallback to Legacy Throttling\n"); 866 - priv->thermal_throttle.advanced_tt = false; 867 - kfree(tt->restriction); 868 - tt->restriction = NULL; 869 - kfree(tt->transaction); 870 - tt->transaction = NULL; 871 - } else { 872 - transaction = tt->transaction + 873 - (IWL_TI_0 * (IWL_TI_STATE_MAX - 1)); 874 - memcpy(transaction, &tt_range_0[0], size); 875 - transaction = tt->transaction + 876 - (IWL_TI_1 * (IWL_TI_STATE_MAX - 1)); 877 - memcpy(transaction, &tt_range_1[0], size); 878 - transaction = tt->transaction + 879 - (IWL_TI_2 * (IWL_TI_STATE_MAX - 1)); 880 - memcpy(transaction, &tt_range_2[0], size); 881 - transaction = tt->transaction + 882 - (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1)); 883 - memcpy(transaction, &tt_range_3[0], size); 884 - size = sizeof(struct iwl_tt_restriction) * 885 - IWL_TI_STATE_MAX; 886 - memcpy(tt->restriction, 887 - &restriction_range[0], size); 888 - priv->thermal_throttle.advanced_tt = true; 889 - } 890 - } else { 891 - IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); 892 - priv->thermal_throttle.advanced_tt = false; 893 - } 894 - } 895 - EXPORT_SYMBOL(iwl_tt_initialize); 896 - 897 - /* cleanup thermal throttling management related memory and timer */ 898 - void iwl_tt_exit(struct iwl_priv *priv) 899 - { 900 - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 901 - 902 - /* stop ct_kill_exit_tm timer if activated */ 903 - del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); 904 - /* stop ct_kill_waiting_tm timer if activated */ 905 - del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); 906 - cancel_work_sync(&priv->tt_work); 907 - cancel_work_sync(&priv->ct_enter); 908 - cancel_work_sync(&priv->ct_exit); 909 - 910 - if (priv->thermal_throttle.advanced_tt) { 911 - /* free advance thermal throttling memory */ 912 - kfree(tt->restriction); 913 - tt->restriction = NULL; 914 - kfree(tt->transaction); 915 - tt->transaction = NULL; 916 - } 917 - } 918 - EXPORT_SYMBOL(iwl_tt_exit); 919 369 920 370 /* initialize to default */ 921 371 void iwl_power_initialize(struct iwl_priv *priv)
-93
drivers/net/wireless/iwlwifi/iwl-power.h
··· 30 30 31 31 #include "iwl-commands.h" 32 32 33 - #define IWL_ABSOLUTE_ZERO 0 34 - #define IWL_ABSOLUTE_MAX 0xFFFFFFFF 35 - #define IWL_TT_INCREASE_MARGIN 5 36 - #define IWL_TT_CT_KILL_MARGIN 3 37 - 38 - enum iwl_antenna_ok { 39 - IWL_ANT_OK_NONE, 40 - IWL_ANT_OK_SINGLE, 41 - IWL_ANT_OK_MULTI, 42 - }; 43 - 44 - /* Thermal Throttling State Machine states */ 45 - enum iwl_tt_state { 46 - IWL_TI_0, /* normal temperature, system power state */ 47 - IWL_TI_1, /* high temperature detect, low power state */ 48 - IWL_TI_2, /* higher temperature detected, lower power state */ 49 - IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */ 50 - IWL_TI_STATE_MAX 51 - }; 52 - 53 - /** 54 - * struct iwl_tt_restriction - Thermal Throttling restriction table 55 - * @tx_stream: number of tx stream allowed 56 - * @is_ht: ht enable/disable 57 - * @rx_stream: number of rx stream allowed 58 - * 59 - * This table is used by advance thermal throttling management 60 - * based on the current thermal throttling state, and determines 61 - * the number of tx/rx streams and the status of HT operation. 62 - */ 63 - struct iwl_tt_restriction { 64 - enum iwl_antenna_ok tx_stream; 65 - enum iwl_antenna_ok rx_stream; 66 - bool is_ht; 67 - }; 68 - 69 - /** 70 - * struct iwl_tt_trans - Thermal Throttling transaction table 71 - * @next_state: next thermal throttling mode 72 - * @tt_low: low temperature threshold to change state 73 - * @tt_high: high temperature threshold to change state 74 - * 75 - * This is used by the advanced thermal throttling algorithm 76 - * to determine the next thermal state to go based on the 77 - * current temperature. 78 - */ 79 - struct iwl_tt_trans { 80 - enum iwl_tt_state next_state; 81 - u32 tt_low; 82 - u32 tt_high; 83 - }; 84 - 85 - /** 86 - * struct iwl_tt_mgnt - Thermal Throttling Management structure 87 - * @advanced_tt: advanced thermal throttle required 88 - * @state: current Thermal Throttling state 89 - * @tt_power_mode: Thermal Throttling power mode index 90 - * being used to set power level when 91 - * when thermal throttling state != IWL_TI_0 92 - * the tt_power_mode should set to different 93 - * power mode based on the current tt state 94 - * @tt_previous_temperature: last measured temperature 95 - * @iwl_tt_restriction: ptr to restriction tbl, used by advance 96 - * thermal throttling to determine how many tx/rx streams 97 - * should be used in tt state; and can HT be enabled or not 98 - * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling 99 - * state transaction 100 - * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature 101 - * @ct_kill_exit_tm: timer to exit thermal kill 102 - */ 103 - struct iwl_tt_mgmt { 104 - enum iwl_tt_state state; 105 - bool advanced_tt; 106 - u8 tt_power_mode; 107 - bool ct_kill_toggle; 108 - #ifdef CONFIG_IWLWIFI_DEBUG 109 - s32 tt_previous_temp; 110 - #endif 111 - struct iwl_tt_restriction *restriction; 112 - struct iwl_tt_trans *transaction; 113 - struct timer_list ct_kill_exit_tm; 114 - struct timer_list ct_kill_waiting_tm; 115 - }; 116 - 117 33 enum iwl_power_level { 118 34 IWL_POWER_INDEX_1, 119 35 IWL_POWER_INDEX_2, ··· 46 130 }; 47 131 48 132 int iwl_power_update_mode(struct iwl_priv *priv, bool force); 49 - bool iwl_ht_enabled(struct iwl_priv *priv); 50 - bool iwl_within_ct_kill_margin(struct iwl_priv *priv); 51 - enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); 52 - enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); 53 - void iwl_tt_enter_ct_kill(struct iwl_priv *priv); 54 - void iwl_tt_exit_ct_kill(struct iwl_priv *priv); 55 - void iwl_tt_handler(struct iwl_priv *priv); 56 - void iwl_tt_initialize(struct iwl_priv *priv); 57 - void iwl_tt_exit(struct iwl_priv *priv); 58 133 void iwl_power_initialize(struct iwl_priv *priv); 59 134 60 135 extern bool no_sleep_autoadjust;
+6 -3
drivers/net/wireless/iwlwifi/iwl-tx.c
··· 422 422 int len; 423 423 u32 idx; 424 424 u16 fix_size; 425 + bool is_ct_kill = false; 425 426 426 427 cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); 427 428 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); ··· 444 443 445 444 if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { 446 445 IWL_ERR(priv, "No space in command queue\n"); 447 - if (iwl_within_ct_kill_margin(priv)) 448 - iwl_tt_enter_ct_kill(priv); 449 - else { 446 + if (priv->cfg->ops->lib->tt_ops.ct_kill_check) { 447 + is_ct_kill = 448 + priv->cfg->ops->lib->tt_ops.ct_kill_check(priv); 449 + } 450 + if (!is_ct_kill) { 450 451 IWL_ERR(priv, "Restarting adapter due to queue full\n"); 451 452 queue_work(priv->workqueue, &priv->restart); 452 453 }