linux/drivers/net/wireless/intel/iwlwifi/dvm/tt.c
<<
>>
Prefs
   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 */
  39static 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};
  44static 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};
  49static 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};
  54static 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 */
  61static 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
  68bool 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
  77u8 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
  84bool 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
  95static 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
 109bool 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
 120enum 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
 131enum 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 */
 153static 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
 186static 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
 204static 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
 223static 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 */
 246static 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 */
 351static 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 */
 484static 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 */
 513static 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
 546void 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
 555void 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
 564static 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
 578void 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 */
 592void 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 */
 654void 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}
 674