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