root/drivers/net/wireless/intel/iwlwifi/dvm/tt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. iwl_tt_is_low_power_state
  2. iwl_tt_current_power_mode
  3. iwl_ht_enabled
  4. iwl_within_ct_kill_margin
  5. iwl_check_for_ct_kill
  6. iwl_tx_ant_restriction
  7. iwl_rx_ant_restriction
  8. iwl_tt_check_exit_ct_kill
  9. iwl_perform_ct_kill_task
  10. iwl_tt_ready_for_ct_kill
  11. iwl_prepare_ct_kill_task
  12. iwl_legacy_tt_handler
  13. iwl_advance_tt_handler
  14. iwl_bg_ct_enter
  15. iwl_bg_ct_exit
  16. iwl_tt_enter_ct_kill
  17. iwl_tt_exit_ct_kill
  18. iwl_bg_tt_work
  19. iwl_tt_handler
  20. iwl_tt_initialize
  21. iwl_tt_exit

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

/* [<][>][^][v][top][bottom][index][help] */