Commit 0c0e2c71 authored by Ido Yariv's avatar Ido Yariv Committed by Emmanuel Grumbach

iwlwifi: mvm: handle platform PCIe power limitation

The tx backoff settings used by the thermal throttling mechanism can
also be used for enforcing a limit on the power consumption of the module.

Handle the platform PCIe power limitation by translating the limit
(measured in mw) to its respective tx backoff value. The translation is
module specific.

The resulting tx backoff value is sent to the ucode, and also serves as the
minimal backoff value that can be set by the thermal throttling mechanism.
Signed-off-by: default avatarIdo Yariv <idox.yariv@intel.com>
Reviewed-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent bcb079a1
...@@ -193,6 +193,15 @@ struct iwl_eeprom_params { ...@@ -193,6 +193,15 @@ struct iwl_eeprom_params {
bool enhanced_txpower; bool enhanced_txpower;
}; };
/* Tx-backoff power threshold
* @pwr: The power limit in mw
* @backoff: The tx-backoff in uSec
*/
struct iwl_pwr_tx_backoff {
u32 pwr;
u32 backoff;
};
/** /**
* struct iwl_cfg * struct iwl_cfg
* @name: Offical name of the device * @name: Offical name of the device
...@@ -219,6 +228,7 @@ struct iwl_eeprom_params { ...@@ -219,6 +228,7 @@ struct iwl_eeprom_params {
* @host_interrupt_operation_mode: device needs host interrupt operation * @host_interrupt_operation_mode: device needs host interrupt operation
* mode set * mode set
* @nvm_hw_section_num: the ID of the HW NVM section * @nvm_hw_section_num: the ID of the HW NVM section
* @pwr_tx_backoffs: translation table between power limits and backoffs
* *
* We enable the driver to be backward compatible wrt. hardware features. * We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs * API differences in uCode shouldn't be handled here but through TLVs
...@@ -250,6 +260,7 @@ struct iwl_cfg { ...@@ -250,6 +260,7 @@ struct iwl_cfg {
const bool host_interrupt_operation_mode; const bool host_interrupt_operation_mode;
bool high_temp; bool high_temp;
u8 nvm_hw_section_num; u8 nvm_hw_section_num;
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
}; };
/* /*
......
...@@ -439,6 +439,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm) ...@@ -439,6 +439,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error; goto error;
} }
/* Initialize tx backoffs to the minimal possible */
iwl_mvm_tt_tx_backoff(mvm, 0);
ret = iwl_mvm_power_update_device_mode(mvm); ret = iwl_mvm_power_update_device_mode(mvm);
if (ret) if (ret)
goto error; goto error;
......
...@@ -418,6 +418,7 @@ struct iwl_tt_params { ...@@ -418,6 +418,7 @@ struct iwl_tt_params {
* @ct_kill_exit: worker to exit thermal kill * @ct_kill_exit: worker to exit thermal kill
* @dynamic_smps: Is thermal throttling enabled dynamic_smps? * @dynamic_smps: Is thermal throttling enabled dynamic_smps?
* @tx_backoff: The current thremal throttling tx backoff in uSec. * @tx_backoff: The current thremal throttling tx backoff in uSec.
* @min_backoff: The minimal tx backoff due to power restrictions
* @params: Parameters to configure the thermal throttling algorithm. * @params: Parameters to configure the thermal throttling algorithm.
* @throttle: Is thermal throttling is active? * @throttle: Is thermal throttling is active?
*/ */
...@@ -425,6 +426,7 @@ struct iwl_mvm_tt_mgmt { ...@@ -425,6 +426,7 @@ struct iwl_mvm_tt_mgmt {
struct delayed_work ct_kill_exit; struct delayed_work ct_kill_exit;
bool dynamic_smps; bool dynamic_smps;
u32 tx_backoff; u32 tx_backoff;
u32 min_backoff;
const struct iwl_tt_params *params; const struct iwl_tt_params *params;
bool throttle; bool throttle;
}; };
...@@ -947,8 +949,9 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) ...@@ -947,8 +949,9 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif)
} }
/* Thermal management and CT-kill */ /* Thermal management and CT-kill */
void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff);
void iwl_mvm_tt_handler(struct iwl_mvm *mvm); void iwl_mvm_tt_handler(struct iwl_mvm *mvm);
void iwl_mvm_tt_initialize(struct iwl_mvm *mvm); void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff);
void iwl_mvm_tt_exit(struct iwl_mvm *mvm); void iwl_mvm_tt_exit(struct iwl_mvm *mvm);
void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state);
......
...@@ -326,6 +326,23 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { ...@@ -326,6 +326,23 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
/* this forward declaration can avoid to export the function */ /* this forward declaration can avoid to export the function */
static void iwl_mvm_async_handlers_wk(struct work_struct *wk); static void iwl_mvm_async_handlers_wk(struct work_struct *wk);
static u32 calc_min_backoff(struct iwl_trans *trans, const struct iwl_cfg *cfg)
{
const struct iwl_pwr_tx_backoff *pwr_tx_backoff = cfg->pwr_tx_backoffs;
if (!pwr_tx_backoff)
return 0;
while (pwr_tx_backoff->pwr) {
if (trans->dflt_pwr_limit >= pwr_tx_backoff->pwr)
return pwr_tx_backoff->backoff;
pwr_tx_backoff++;
}
return 0;
}
static struct iwl_op_mode * static struct iwl_op_mode *
iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
const struct iwl_fw *fw, struct dentry *dbgfs_dir) const struct iwl_fw *fw, struct dentry *dbgfs_dir)
...@@ -338,6 +355,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -338,6 +355,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
TX_CMD, TX_CMD,
}; };
int err, scan_size; int err, scan_size;
u32 min_backoff;
/* /*
* We use IWL_MVM_STATION_COUNT to check the validity of the station * We use IWL_MVM_STATION_COUNT to check the validity of the station
...@@ -433,7 +451,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -433,7 +451,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
IWL_INFO(mvm, "Detected %s, REV=0x%X\n", IWL_INFO(mvm, "Detected %s, REV=0x%X\n",
mvm->cfg->name, mvm->trans->hw_rev); mvm->cfg->name, mvm->trans->hw_rev);
iwl_mvm_tt_initialize(mvm); min_backoff = calc_min_backoff(trans, cfg);
iwl_mvm_tt_initialize(mvm, min_backoff);
/* /*
* If the NVM exists in an external file, * If the NVM exists in an external file,
......
...@@ -403,7 +403,7 @@ static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable) ...@@ -403,7 +403,7 @@ static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable)
} }
} }
static void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff) void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff)
{ {
struct iwl_host_cmd cmd = { struct iwl_host_cmd cmd = {
.id = REPLY_THERMAL_MNG_BACKOFF, .id = REPLY_THERMAL_MNG_BACKOFF,
...@@ -412,6 +412,8 @@ static void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff) ...@@ -412,6 +412,8 @@ static void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff)
.flags = CMD_SYNC, .flags = CMD_SYNC,
}; };
backoff = max(backoff, mvm->thermal_throttle.min_backoff);
if (iwl_mvm_send_cmd(mvm, &cmd) == 0) { if (iwl_mvm_send_cmd(mvm, &cmd) == 0) {
IWL_DEBUG_TEMP(mvm, "Set Thermal Tx backoff to: %u\n", IWL_DEBUG_TEMP(mvm, "Set Thermal Tx backoff to: %u\n",
backoff); backoff);
...@@ -534,7 +536,7 @@ static const struct iwl_tt_params iwl7000_high_temp_tt_params = { ...@@ -534,7 +536,7 @@ static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
.support_tx_backoff = true, .support_tx_backoff = true,
}; };
void iwl_mvm_tt_initialize(struct iwl_mvm *mvm) void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff)
{ {
struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
...@@ -546,6 +548,7 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm) ...@@ -546,6 +548,7 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm)
tt->params = &iwl7000_tt_params; tt->params = &iwl7000_tt_params;
tt->throttle = false; tt->throttle = false;
tt->min_backoff = min_backoff;
INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment