kernel-ark/drivers/net/wireless/iwlwifi/iwl-power.h
Wey-Yi Guy 7812b16730 iwlwifi: reliable entering of critical temperature state
When uCode detects critical temperature it should send "card state
notification" interrupt to driver and then shut itself down to prevent
overheating. There is a race condition where uCode shuts down before it
can deliver the interrupt to driver.
Additional method provided here for driver to enter CT_KILL state based
on temperature reading.

How it works:
Method 1:
If driver receive "card state notification" interrupt from uCode; it
enters "CT_KILL" state immediately

Method 2:
If the last temperature report by Card reach Critical temperature,
driver will send "statistic notification" request to uCode to verify the
temperature reading, if driver can not get reply from uCode within
300ms, driver will enter CT_KILL state automatically.

Method 3:
If the last temperature report by Card did not reach Critical
temperature, but uCode already shut down due to critical temperature.
All the host commands send to uCode will not get process by uCode;
when command queue reach the limit, driver will check the last reported
temperature reading, if it is within pre-defined margin, enter "CT_KILL"
state immediately. In this case, when uCode ready to exit from "CT_KILL" state,
driver need to restart the adapter in order to reset all the queues and
resume normal operation.

One additional issue being address here, when system is in CT_KILL
state, both tx and rx already stopped, but driver still can send host
command to uCode, it will flood the command queue since card was not
responding; adding STATUS_CT_KILL flag to reject enqueue host commands
to uCode if it is in CT_KILL state, when uCode is ready to come out of
CT_KILL, driver will clear  the STATUS_CT_KILL bit and allow enqueue the host
commands to uCode to recover from CT_KILL state.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-10-07 16:39:44 -04:00

147 lines
4.9 KiB
C

/******************************************************************************
*
* Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#ifndef __iwl_power_setting_h__
#define __iwl_power_setting_h__
#include "iwl-commands.h"
#define IWL_ABSOLUTE_ZERO 0
#define IWL_ABSOLUTE_MAX 0xFFFFFFFF
#define IWL_TT_INCREASE_MARGIN 5
#define IWL_TT_CT_KILL_MARGIN 3
enum iwl_antenna_ok {
IWL_ANT_OK_NONE,
IWL_ANT_OK_SINGLE,
IWL_ANT_OK_MULTI,
};
/* Thermal Throttling State Machine states */
enum iwl_tt_state {
IWL_TI_0, /* normal temperature, system power state */
IWL_TI_1, /* high temperature detect, low power state */
IWL_TI_2, /* higher temperature detected, lower power state */
IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */
IWL_TI_STATE_MAX
};
/**
* struct iwl_tt_restriction - Thermal Throttling restriction table
* @tx_stream: number of tx stream allowed
* @is_ht: ht enable/disable
* @rx_stream: number of rx stream allowed
*
* This table is used by advance thermal throttling management
* based on the current thermal throttling state, and determines
* the number of tx/rx streams and the status of HT operation.
*/
struct iwl_tt_restriction {
enum iwl_antenna_ok tx_stream;
enum iwl_antenna_ok rx_stream;
bool is_ht;
};
/**
* struct iwl_tt_trans - Thermal Throttling transaction table
* @next_state: next thermal throttling mode
* @tt_low: low temperature threshold to change state
* @tt_high: high temperature threshold to change state
*
* This is used by the advanced thermal throttling algorithm
* to determine the next thermal state to go based on the
* current temperature.
*/
struct iwl_tt_trans {
enum iwl_tt_state next_state;
u32 tt_low;
u32 tt_high;
};
/**
* struct iwl_tt_mgnt - Thermal Throttling Management structure
* @advanced_tt: advanced thermal throttle required
* @state: current Thermal Throttling state
* @tt_power_mode: Thermal Throttling power mode index
* being used to set power level when
* when thermal throttling state != IWL_TI_0
* the tt_power_mode should set to different
* power mode based on the current tt state
* @tt_previous_temperature: last measured temperature
* @iwl_tt_restriction: ptr to restriction tbl, used by advance
* thermal throttling to determine how many tx/rx streams
* should be used in tt state; and can HT be enabled or not
* @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling
* state transaction
* @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature
* @ct_kill_exit_tm: timer to exit thermal kill
*/
struct iwl_tt_mgmt {
enum iwl_tt_state state;
bool advanced_tt;
u8 tt_power_mode;
bool ct_kill_toggle;
#ifdef CONFIG_IWLWIFI_DEBUG
s32 tt_previous_temp;
#endif
struct iwl_tt_restriction *restriction;
struct iwl_tt_trans *transaction;
struct timer_list ct_kill_exit_tm;
struct timer_list ct_kill_waiting_tm;
};
enum iwl_power_level {
IWL_POWER_INDEX_1,
IWL_POWER_INDEX_2,
IWL_POWER_INDEX_3,
IWL_POWER_INDEX_4,
IWL_POWER_INDEX_5,
IWL_POWER_NUM
};
struct iwl_power_mgr {
struct iwl_powertable_cmd sleep_cmd;
int debug_sleep_level_override;
bool pci_pm;
};
int iwl_power_update_mode(struct iwl_priv *priv, bool force);
bool iwl_ht_enabled(struct iwl_priv *priv);
bool iwl_within_ct_kill_margin(struct iwl_priv *priv);
enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
void iwl_tt_exit_ct_kill(struct iwl_priv *priv);
void iwl_tt_handler(struct iwl_priv *priv);
void iwl_tt_initialize(struct iwl_priv *priv);
void iwl_tt_exit(struct iwl_priv *priv);
void iwl_power_initialize(struct iwl_priv *priv);
extern bool no_sleep_autoadjust;
#endif /* __iwl_power_setting_h__ */