@@ -664,6 +664,8 @@ enum iwl_mvm_sched_scan_pass_all_states {
* @min_backoff: The minimal tx backoff due to power restrictions
* @params: Parameters to configure the thermal throttling algorithm.
* @throttle: Is thermal throttling is active?
+ * @power_budget_mw: maximum cTDP power budget as defined for this system and
+ * device
*/
struct iwl_mvm_tt_mgmt {
struct delayed_work ct_kill_exit;
@@ -672,6 +674,8 @@ struct iwl_mvm_tt_mgmt {
u32 min_backoff;
struct iwl_tt_params params;
bool throttle;
+
+ u32 power_budget_mw;
};
#ifdef CONFIG_THERMAL
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2019-2022, 2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2019-2022, 2024-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2016 Intel Deutschland GmbH
*/
@@ -8,6 +8,9 @@
#include "mvm.h"
+#define IWL_MVM_NUM_CTDP_STEPS 20
+#define IWL_MVM_MIN_CTDP_BUDGET_MW 150
+
#define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT HZ
void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm)
@@ -479,43 +482,28 @@ static const struct iwl_tt_params iwl_mvm_default_tt_params = {
.support_tx_backoff = true,
};
-/* budget in mWatt */
-static const u32 iwl_mvm_cdev_budgets[] = {
- 2400, /* cooling state 0 */
- 2000, /* cooling state 1 */
- 1800, /* cooling state 2 */
- 1600, /* cooling state 3 */
- 1400, /* cooling state 4 */
- 1200, /* cooling state 5 */
- 1000, /* cooling state 6 */
- 900, /* cooling state 7 */
- 800, /* cooling state 8 */
- 700, /* cooling state 9 */
- 650, /* cooling state 10 */
- 600, /* cooling state 11 */
- 550, /* cooling state 12 */
- 500, /* cooling state 13 */
- 450, /* cooling state 14 */
- 400, /* cooling state 15 */
- 350, /* cooling state 16 */
- 300, /* cooling state 17 */
- 250, /* cooling state 18 */
- 200, /* cooling state 19 */
- 150, /* cooling state 20 */
-};
-
int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 state)
{
struct iwl_ctdp_cmd cmd = {
.operation = cpu_to_le32(op),
- .budget = cpu_to_le32(iwl_mvm_cdev_budgets[state]),
.window_size = 0,
};
+ u32 budget;
int ret;
u32 status;
lockdep_assert_held(&mvm->mutex);
+ /* Do a linear scale from IWL_MVM_MIN_CTDP_BUDGET_MW to the configured
+ * maximum in the predefined number of steps.
+ */
+ budget = ((mvm->thermal_throttle.power_budget_mw -
+ IWL_MVM_MIN_CTDP_BUDGET_MW) *
+ (IWL_MVM_NUM_CTDP_STEPS - 1 - state)) /
+ (IWL_MVM_NUM_CTDP_STEPS - 1) +
+ IWL_MVM_MIN_CTDP_BUDGET_MW;
+ cmd.budget = cpu_to_le32(budget);
+
status = 0;
ret = iwl_mvm_send_cmd_pdu_status(mvm, WIDE_ID(PHY_OPS_GROUP,
CTDP_CONFIG_CMD),
@@ -707,7 +695,7 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
static int iwl_mvm_tcool_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
- *state = ARRAY_SIZE(iwl_mvm_cdev_budgets) - 1;
+ *state = IWL_MVM_NUM_CTDP_STEPS - 1;
return 0;
}
@@ -733,7 +721,7 @@ static int iwl_mvm_tcool_set_cur_state(struct thermal_cooling_device *cdev,
mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
return -EIO;
- if (new_state >= ARRAY_SIZE(iwl_mvm_cdev_budgets))
+ if (new_state >= IWL_MVM_NUM_CTDP_STEPS)
return -EINVAL;
return iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_START,
@@ -794,6 +782,47 @@ static void iwl_mvm_cooling_device_unregister(struct iwl_mvm *mvm)
}
#endif /* CONFIG_THERMAL */
+static u32 iwl_mvm_ctdp_get_max_budget(struct iwl_mvm *mvm)
+{
+ u64 bios_power_budget = 0;
+ u32 default_power_budget;
+
+ switch (CSR_HW_RFID_TYPE(mvm->trans->info.hw_rf_id)) {
+ case IWL_CFG_RF_TYPE_JF2:
+ case IWL_CFG_RF_TYPE_JF1:
+ default_power_budget = 2000;
+ break;
+ case IWL_CFG_RF_TYPE_HR2:
+ case IWL_CFG_RF_TYPE_HR1:
+ default_power_budget = 2400;
+ break;
+ case IWL_CFG_RF_TYPE_GF:
+ /* dual-radio devices have a higher budget */
+ if (CSR_HW_RFID_IS_CDB(mvm->trans->info.hw_rf_id))
+ default_power_budget = 5200;
+ else
+ default_power_budget = 2880;
+ break;
+ case IWL_CFG_RF_TYPE_FM:
+ default_power_budget = 3450;
+ break;
+ default:
+ default_power_budget = 5550;
+ break;
+ }
+
+ iwl_bios_get_pwr_limit(&mvm->fwrt, &bios_power_budget);
+
+ /* 32bit in UEFI, 16bit in ACPI; use BIOS value if it is in range */
+ if (bios_power_budget &&
+ bios_power_budget != 0xffff && bios_power_budget != 0xffffffff &&
+ bios_power_budget >= IWL_MVM_MIN_CTDP_BUDGET_MW &&
+ bios_power_budget <= default_power_budget)
+ return (u32)bios_power_budget;
+
+ return default_power_budget;
+}
+
void iwl_mvm_thermal_initialize(struct iwl_mvm *mvm, u32 min_backoff)
{
struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
@@ -805,6 +834,8 @@ void iwl_mvm_thermal_initialize(struct iwl_mvm *mvm, u32 min_backoff)
else
tt->params = iwl_mvm_default_tt_params;
+ tt->power_budget_mw = iwl_mvm_ctdp_get_max_budget(mvm);
+ IWL_DEBUG_TEMP(mvm, "cTDP power budget: %d mW\n", tt->power_budget_mw);
tt->throttle = false;
tt->dynamic_smps = false;
tt->min_backoff = min_backoff;