iwlwifi: thermal management — CT-KILL + TX backoff from Linux 7.1 tt.c

Ported thermal throttling algorithm from Linux 7.1 mvm/tt.c.
Default parameters from iwl_mvm_default_tt_params:
  CT-KILL entry 118degC, exit 96degC, duration 5s
  TX backoff: 200us@112degC → 10000us@117degC (6 steps)
  SMPS entry 114degC, TX protection entry 114degC

Functions: rb_iwl_mvm_tt_init, rb_iwl_mvm_tt_temp_notif (DTS notification),
rb_iwl_mvm_tt_ct_kill_notif (firmware CT-KILL notification).
Wired into transport as tt_mgmt. When temperature exceeds CT-KILL entry,
driver stops TX. TX backoff reduces duty cycle proportionally.

Live BE201 reference: 50degC idle — well below throttling thresholds.
This commit is contained in:
2026-07-08 15:19:42 +03:00
parent f19c9c93f2
commit a4640eddce
3 changed files with 117 additions and 0 deletions
@@ -308,3 +308,79 @@ int rb_iwl_mvm_rs_select(struct rb_iwl_mvm_rs_state *rs, int signal)
rs->best_rate = best;
return best > 0 ? best : base_rate;
}
/* ------------------------------------------------------------------ */
/* Thermal management — ported from Linux 7.1 mvm/tt.c. */
/* */
/* CT-KILL (Critical Temperature Kill): */
/* Firmware reports temperature via DTS_MEASUREMENT_NOTIFICATION. */
/* If temp >= ct_kill_entry → stop TX, schedule exit timer. */
/* If temp <= ct_kill_exit → resume TX. */
/* */
/* TX backoff: */
/* For temperatures between normal and ct_kill_entry, reduce TX */
/* duty cycle using the tx_backoff table (temp → backoff_us). */
/* Backoff = max_backoff where temp >= threshold. */
/* ------------------------------------------------------------------ */
static const struct rb_iwl_mvm_tt_params rb_iwl_mvm_default_tt_params = {
.ct_kill_entry = 118,
.ct_kill_exit = 96,
.ct_kill_duration = 5,
.dynamic_smps_entry = 114,
.dynamic_smps_exit = 110,
.tx_protection_entry = 114,
.tx_protection_exit = 108,
.tx_backoff_temp = { 112, 113, 114, 115, 116, 117 },
.tx_backoff_us = { 200, 600, 1200, 2000, 4000, 10000 },
.support_ct_kill = 1,
.support_dynamic_smps = 1,
.support_tx_protection = 1,
.support_tx_backoff = 1,
};
void rb_iwl_mvm_tt_init(struct rb_iwl_mvm_tt_mgmt *tt)
{
if (!tt) return;
memset(tt, 0, sizeof(*tt));
memcpy(&tt->params, &rb_iwl_mvm_default_tt_params, sizeof(tt->params));
}
void rb_iwl_mvm_tt_temp_notif(struct rb_iwl_mvm_tt_mgmt *tt, int32_t temp)
{
int i;
uint32_t tx_backoff;
if (!tt) return;
if (tt->ct_kill_active)
return;
tt->temperature = temp;
if (tt->params.support_ct_kill && temp >= (int32_t)tt->params.ct_kill_entry) {
tt->ct_kill_active = 1;
tt->throttle_active = 0;
tt->tx_backoff = 0;
tt->tt_timestamp = 0;
return;
}
if (tt->params.support_tx_backoff) {
tx_backoff = 0;
for (i = 0; i < 6; ++i) {
if (temp < (int32_t)tt->params.tx_backoff_temp[i])
break;
tx_backoff = tt->params.tx_backoff_us[i];
}
tt->tx_backoff = tx_backoff;
tt->throttle_active = (tx_backoff > 0);
}
}
void rb_iwl_mvm_tt_ct_kill_notif(struct rb_iwl_mvm_tt_mgmt *tt)
{
if (!tt) return;
tt->ct_kill_active = 1;
tt->tx_backoff = 0;
tt->tt_timestamp = 0;
}
@@ -256,4 +256,44 @@ void rb_iwl_mvm_rs_update(struct rb_iwl_mvm_rs_state *rs,
int rate_idx, int status, int retries);
int rb_iwl_mvm_rs_select(struct rb_iwl_mvm_rs_state *rs, int signal);
/* ------------------------------------------------------------------ */
/* Thermal management — Linux 7.1 mvm/tt.c + iwl-config.h:284. */
/* CT-KILL: firmware enters critical thermal state → stop TX. */
/* TX backoff: reduce TX duty cycle proportional to temperature. */
/* Live BE201 reference: 50degC idle, CT-KILL entry 118degC. */
/* ------------------------------------------------------------------ */
#define RB_IWL_MVM_CT_KILL_ENTRY_DEF 118
#define RB_IWL_MVM_CT_KILL_EXIT_DEF 96
#define RB_IWL_MVM_CT_KILL_DURATION_DEF 5
struct rb_iwl_mvm_tt_params {
uint32_t ct_kill_entry;
uint32_t ct_kill_exit;
uint32_t ct_kill_duration;
uint32_t dynamic_smps_entry;
uint32_t dynamic_smps_exit;
uint32_t tx_protection_entry;
uint32_t tx_protection_exit;
uint32_t tx_backoff_temp[6];
uint32_t tx_backoff_us[6];
uint8_t support_ct_kill;
uint8_t support_dynamic_smps;
uint8_t support_tx_protection;
uint8_t support_tx_backoff;
};
struct rb_iwl_mvm_tt_mgmt {
struct rb_iwl_mvm_tt_params params;
uint32_t tx_backoff;
int32_t temperature;
uint32_t ct_kill_active;
uint32_t throttle_active;
uint32_t tt_timestamp;
};
void rb_iwl_mvm_tt_init(struct rb_iwl_mvm_tt_mgmt *tt);
void rb_iwl_mvm_tt_temp_notif(struct rb_iwl_mvm_tt_mgmt *tt, int32_t temp);
void rb_iwl_mvm_tt_ct_kill_notif(struct rb_iwl_mvm_tt_mgmt *tt);
#endif /* RB_IWLWIFI_MVM_H */
@@ -278,6 +278,7 @@ struct iwl_trans_pcie {
struct rb_iwl_fw_blob_info pnvm_info;
struct rb_iwl_fw_metadata fw_meta;
struct rb_iwl_mvm_rs_state rs_state;
struct rb_iwl_mvm_tt_mgmt tt_mgmt;
struct rb_iwl_key keys[4];
char fw_name_storage[RB_IWL_MAX_FW_NAME];
char pnvm_name_storage[RB_IWL_MAX_FW_NAME];