From a4640eddcec46391e93bf8fcb930094c476e61e1 Mon Sep 17 00:00:00 2001 From: vasilito Date: Wed, 8 Jul 2026 15:19:42 +0300 Subject: [PATCH] =?UTF-8?q?iwlwifi:=20thermal=20management=20=E2=80=94=20C?= =?UTF-8?q?T-KILL=20+=20TX=20backoff=20from=20Linux=207.1=20tt.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .../redbear-iwlwifi/source/src/linux_mvm.c | 76 +++++++++++++++++++ .../redbear-iwlwifi/source/src/linux_mvm.h | 40 ++++++++++ .../redbear-iwlwifi/source/src/linux_port.c | 1 + 3 files changed, 117 insertions(+) diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.c b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.c index 128e9b4a62..bc778ac732 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.c +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.c @@ -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; +} diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.h b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.h index 4fcbee0e79..9eb0677257 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.h +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.h @@ -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 */ diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c index 46817be649..4735051cea 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c @@ -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];