From patchwork Sat Feb 15 00:54:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Limonciello X-Patchwork-Id: 13975840 X-Patchwork-Delegate: mario.limonciello@amd.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E5BA91624F5; Sat, 15 Feb 2025 00:54:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739580900; cv=none; b=IO6F3SYGbPjZi9qEoR7JUC5oT0eevp95ADScilPSO/19HGfK6UkR/OyDJT6WfbTEuA6EZW1VpUGxP3Ump98xSoO7ItOOZ1jdSFytxEvqjk2jlcOFmH3q4PmruFVE3JCjeiYOXH7+P5aQhjG8eA2Dhr8FRbPSXRI24lhYWWiQY9s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739580900; c=relaxed/simple; bh=Kh9i76QZnvXcrFOKWbznwnDUq8Z1/V5J/dxcpgTR5UI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TeSZ0LGLM6YxBZEES5wM/LpkFSg+DeqiOIise1nZrqTKzIfG27hzDz6rVZhHNArs9WUFo+Eq4kHVmnPgCVw0KO+vdwX0LXn7CVG8MiihEtSYWzDtfiPnx19RAXbKUZbSK+cNi7SEJkqbSTogMQagtjcJvTzWOqgn66fhIdERIQ0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Rj//G1uW; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Rj//G1uW" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C241AC4CEE2; Sat, 15 Feb 2025 00:54:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739580899; bh=Kh9i76QZnvXcrFOKWbznwnDUq8Z1/V5J/dxcpgTR5UI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Rj//G1uWkEex65qU8d9mJxS02SYCiiSmBgtLyuE8A1g3CPA3nPG427e/ybOmzseJ2 j8nbyu2WoLDApPOIehZ+/AuO2as9AOiUfpeEVkdJ9FvQP/7EfacGZbpE1QXvNNpP/G NZfDU/0cncGyMByRfQjNhN0ufyV+44qJ2fLqQGKr1K7v73iAM0Lh1Jx9eIYXQXNulb Y648qmjboXKkJPMVmxt5mgiBkEs/QwiqSBUsizNOtndwqAw5ROOQN9F4JecCcdaL8F jkSsaPzVuGPwtNTpo/i4RdvgxbfBs/YK05IODiZBjJDFDzlTAN6p21p4ckcA1BqWjM OlBvSfzJ5cShw== From: Mario Limonciello To: "Gautham R . Shenoy" , Perry Yuan Cc: Dhananjay Ugwekar , linux-kernel@vger.kernel.org (open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)), linux-pm@vger.kernel.org (open list:CPU FREQUENCY SCALING FRAMEWORK), Mario Limonciello Subject: [PATCH 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference Date: Fri, 14 Feb 2025 18:54:44 -0600 Message-ID: <20250215005448.1216646-2-superm1@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250215005448.1216646-1-superm1@kernel.org> References: <20250215005448.1216646-1-superm1@kernel.org> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Mario Limonciello Dynamic energy performance preference will change the EPP profile based on whether the machine is running on AC or DC power. A notification chain from the power supply core is used to adjust EPP values on plug in or plug out events. For non-server systems: * the default EPP for AC mode is `balance_performance`. * the default EPP for DC mode is `balance_power`. Signed-off-by: Mario Limonciello --- Documentation/admin-guide/pm/amd-pstate.rst | 18 ++- drivers/cpufreq/Kconfig.x86 | 12 ++ drivers/cpufreq/amd-pstate.c | 129 ++++++++++++++++++-- drivers/cpufreq/amd-pstate.h | 5 +- 4 files changed, 155 insertions(+), 9 deletions(-) diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst index 412423c54f258..2e076650dc77c 100644 --- a/Documentation/admin-guide/pm/amd-pstate.rst +++ b/Documentation/admin-guide/pm/amd-pstate.rst @@ -289,7 +289,7 @@ and user can change current preference according to energy or performance needs Please get all support profiles list from ``energy_performance_available_preferences`` attribute, all the profiles are integer values defined between 0 to 255 when EPP feature is enabled by platform -firmware, if EPP feature is disabled, driver will ignore the written value +firmware, but if the dynamic EPP feature is enabled, driver will block writes. This attribute is read-write. ``boost`` @@ -311,6 +311,22 @@ boost or `1` to enable it, for the respective CPU using the sysfs path Other performance and frequency values can be read back from ``/sys/devices/system/cpu/cpuX/acpi_cppc/``, see :ref:`cppc_sysfs`. +Dynamic energy performance profile +================================== +The amd-pstate driver supports dynamically selecting the energy performance +profile based on whether the machine is running on AC or DC power. + +Whether this behavior is enabled by default with the kernel config option +`CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`. This behavior can also be overridden +at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``. + +When set to enabled, the driver will select a different energy performance +profile when the machine is running on battery or AC power. +When set to disabled, the driver will not change the energy performance profile +based on the power source and will not react to user desired power state. + +Attempting to manually write to the ``energy_performance_preference`` sysfs +file will fail when ``dynamic_epp`` is enabled. ``amd-pstate`` vs ``acpi-cpufreq`` ====================================== diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index 97c2d4f15d76e..bfe957b653b05 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 @@ -68,6 +68,18 @@ config X86_AMD_PSTATE_DEFAULT_MODE For details, take a look at: . +config X86_AMD_PSTATE_DYNAMIC_EPP + bool "AMD Processor P-State dynamic EPP support" + depends on X86_AMD_PSTATE + default y if X86_AMD_PSTATE + help + Allow the kenrel to dynamically change the energy performance + value from events like ACPI platform profile and AC adapter plug + events. + + This feature can also be changed at runtime, this configuration + option only sets the kernel default value behavior. + config X86_AMD_PSTATE_UT tristate "selftest for AMD Processor P-State driver" depends on X86 && ACPI_PROCESSOR diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c index aafd765c43f30..95cf8ac29b08c 100644 --- a/drivers/cpufreq/amd-pstate.c +++ b/drivers/cpufreq/amd-pstate.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -86,6 +87,7 @@ static struct cpufreq_driver amd_pstate_driver; static struct cpufreq_driver amd_pstate_epp_driver; static int cppc_state = AMD_PSTATE_UNDEFINED; static bool amd_pstate_prefcore = true; +static bool dynamic_epp = CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP; static struct quirk_entry *quirks; /* @@ -1066,6 +1068,73 @@ static int amd_pstate_cpu_resume(struct cpufreq_policy *policy) return amd_pstate_cppc_enable(policy); } +static int amd_pstate_get_balanced_epp(struct cpufreq_policy *policy) +{ + struct amd_cpudata *cpudata = policy->driver_data; + + if (power_supply_is_system_supplied()) + return cpudata->epp_default_ac; + else + return cpudata->epp_default_dc; +} + +static int amd_pstate_power_supply_notifier(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct amd_cpudata *cpudata = container_of(nb, struct amd_cpudata, power_nb); + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu); + u8 epp; + int ret; + + if (event != PSY_EVENT_PROP_CHANGED) + return NOTIFY_OK; + + epp = amd_pstate_get_balanced_epp(policy); + + ret = amd_pstate_set_epp(policy, epp); + if (ret) + pr_warn("Failed to set CPU %d EPP %u: %d\n", cpudata->cpu, epp, ret); + + return NOTIFY_OK; +} +static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy) +{ + struct amd_cpudata *cpudata = policy->driver_data; + + if (cpudata->power_nb.notifier_call) + power_supply_unreg_notifier(&cpudata->power_nb); + cpudata->dynamic_epp = false; +} + +static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy) +{ + struct amd_cpudata *cpudata = policy->driver_data; + int ret; + u8 epp; + + epp = amd_pstate_get_balanced_epp(policy); + ret = amd_pstate_set_epp(policy, epp); + if (ret) + return ret; + + /* only enable notifier if things will actually change */ + if (cpudata->epp_default_ac != cpudata->epp_default_dc) { + ret = power_supply_reg_notifier(&cpudata->power_nb); + if (ret) + goto cleanup; + cpudata->power_nb.notifier_call = amd_pstate_power_supply_notifier; + } + + cpudata->dynamic_epp = true; + + return 0; + +cleanup: + amd_pstate_clear_dynamic_epp(policy); + + return ret; +} + /* Sysfs attributes */ /* @@ -1162,6 +1231,11 @@ static ssize_t store_energy_performance_preference( ssize_t ret; u8 epp; + if (cpudata->dynamic_epp) { + pr_debug("EPP cannot be set when dynamic EPP is enabled\n"); + return -EBUSY; + } + ret = sscanf(buf, "%20s", str_preference); if (ret != 1) return -EINVAL; @@ -1170,10 +1244,10 @@ static ssize_t store_energy_performance_preference( if (ret < 0) return -EINVAL; - if (!ret) - epp = cpudata->epp_default; - else + if (ret) epp = epp_values[ret]; + else + epp = amd_pstate_get_balanced_epp(policy); if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) { pr_debug("EPP cannot be set under performance policy\n"); @@ -1193,6 +1267,8 @@ static ssize_t store_energy_performance_preference( } ret = amd_pstate_set_epp(policy, epp); + if (ret) + return ret; return ret ? ret : count; } @@ -1392,6 +1468,32 @@ static ssize_t prefcore_show(struct device *dev, return sysfs_emit(buf, "%s\n", str_enabled_disabled(amd_pstate_prefcore)); } +static ssize_t dynamic_epp_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "%s\n", str_enabled_disabled(dynamic_epp)); +} + +static ssize_t dynamic_epp_store(struct device *a, struct device_attribute *b, + const char *buf, size_t count) +{ + bool enabled; + int ret; + + ret = kstrtobool(buf, &enabled); + if (ret) + return ret; + + if (dynamic_epp == enabled) + return -EINVAL; + + /* reinitialize with desired dynamic EPP value */ + dynamic_epp = enabled; + ret = amd_pstate_change_driver_mode(cppc_state); + + return ret ? ret : count; +} + cpufreq_freq_attr_ro(amd_pstate_max_freq); cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq); @@ -1402,6 +1504,7 @@ cpufreq_freq_attr_rw(energy_performance_preference); cpufreq_freq_attr_ro(energy_performance_available_preferences); static DEVICE_ATTR_RW(status); static DEVICE_ATTR_RO(prefcore); +static DEVICE_ATTR_RW(dynamic_epp); static struct freq_attr *amd_pstate_attr[] = { &amd_pstate_max_freq, @@ -1426,6 +1529,7 @@ static struct freq_attr *amd_pstate_epp_attr[] = { static struct attribute *pstate_global_attributes[] = { &dev_attr_status.attr, &dev_attr_prefcore.attr, + &dev_attr_dynamic_epp.attr, NULL }; @@ -1518,10 +1622,11 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) if (amd_pstate_acpi_pm_profile_server() || amd_pstate_acpi_pm_profile_undefined()) { policy->policy = CPUFREQ_POLICY_PERFORMANCE; - cpudata->epp_default = amd_pstate_get_epp(cpudata); + cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata); } else { policy->policy = CPUFREQ_POLICY_POWERSAVE; - cpudata->epp_default = AMD_CPPC_EPP_BALANCE_PERFORMANCE; + cpudata->epp_default_ac = AMD_CPPC_EPP_PERFORMANCE; + cpudata->epp_default_dc = AMD_CPPC_EPP_BALANCE_PERFORMANCE; } if (cpu_feature_enabled(X86_FEATURE_CPPC)) { @@ -1530,9 +1635,13 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) return ret; WRITE_ONCE(cpudata->cppc_req_cached, value); } - ret = amd_pstate_set_epp(policy, cpudata->epp_default); + + if (dynamic_epp) + ret = amd_pstate_set_dynamic_epp(policy); + else + ret = amd_pstate_set_epp(policy, amd_pstate_get_balanced_epp(policy)); if (ret) - return ret; + goto free_cpudata1; current_pstate_driver->adjust_perf = NULL; @@ -1549,6 +1658,8 @@ static void amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy) struct amd_cpudata *cpudata = policy->driver_data; if (cpudata) { + if (cpudata->dynamic_epp) + amd_pstate_clear_dynamic_epp(policy); kfree(cpudata); policy->driver_data = NULL; } @@ -1584,6 +1695,10 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy) if (!policy->cpuinfo.max_freq) return -ENODEV; + /* policy can't be changed to performance policy while dynamic epp is enabled */ + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && cpudata->dynamic_epp) + return -EBUSY; + cpudata->policy = policy->policy; ret = amd_pstate_epp_update_limit(policy); diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h index 13918853f0a82..a3b70c635a7d7 100644 --- a/drivers/cpufreq/amd-pstate.h +++ b/drivers/cpufreq/amd-pstate.h @@ -102,7 +102,10 @@ struct amd_cpudata { /* EPP feature related attributes*/ u32 policy; bool suspended; - u8 epp_default; + u8 epp_default_ac; + u8 epp_default_dc; + bool dynamic_epp; + struct notifier_block power_nb; }; /* From patchwork Sat Feb 15 00:54:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Limonciello X-Patchwork-Id: 13975841 X-Patchwork-Delegate: mario.limonciello@amd.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CFCD717799F; Sat, 15 Feb 2025 00:55:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739580900; cv=none; b=cPylU+dxqP+ghSX3tl+uoKIEpDPqafPFgCW6NnnU/2JYH+ijClEe7KGviaByb4PyqlpYoHeuByyd+zELS176OY8IhG53b8cnPjmiCBHHVAHx+slyedOQK/JjD4wr+FZ289Lg/ERznfXfwsUCHvioyemKkbYsPhPSJCLRMLtxCAk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739580900; c=relaxed/simple; bh=1fpLNpbPgcGKVyKFjXfajuXkpkQU1RnDwuoelu2h1hA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cyHLweeoWehOqDkpDUGSHSGw83I6tON/3v0KKongbmvMCDiIfpa72vBb4TNNtbfn1h7cD61R26nnNmPRJgPJ1R1IjQUr0ONsMwG94dV7eQMqbetP0MZwFPfhEUC82QjtYLlnMjeGhDnZ7uw7l52OzKX0xyp6wI4qqVQnwmcmnfs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YddGIKYE; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YddGIKYE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A8E75C4CEE6; Sat, 15 Feb 2025 00:54:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739580900; bh=1fpLNpbPgcGKVyKFjXfajuXkpkQU1RnDwuoelu2h1hA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YddGIKYErMpOWrvP7ibByOQSoPHmSapgD5CnvVBt9qSJmTN8L3xR1HxWfR0EhAak3 7WhzzEbPx404wYLtmD4Diwb3HXJm7k7qSx8/QF9a7A/MdQ7/sRBSrvDowdGdlMcp4H zcVOoWoxIwQH1WbM37idOMrZiVSHFPd4vvn7aKrW7a+cq4hkRuQO5MzlPZg3LXXfzh c3Ic3HwVObsCpDI9vNBz+71dRo0JUVKI9L0P19dYSFTCPXuU3bvA4B12R+miVZ/zCk greQQs61lfTpKD547J3q5IwEZ/PXGwWrLfdCpRyFxW9BSMgerZ6QwmIQ5Xy0SDcwrG wSIULkBI9LKqw== From: Mario Limonciello To: "Gautham R . Shenoy" , Perry Yuan Cc: Dhananjay Ugwekar , linux-kernel@vger.kernel.org (open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)), linux-pm@vger.kernel.org (open list:CPU FREQUENCY SCALING FRAMEWORK), Mario Limonciello Subject: [PATCH 2/5] cpufreq/amd-pstate: add kernel command line to override dynamic epp Date: Fri, 14 Feb 2025 18:54:45 -0600 Message-ID: <20250215005448.1216646-3-superm1@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250215005448.1216646-1-superm1@kernel.org> References: <20250215005448.1216646-1-superm1@kernel.org> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Mario Limonciello Add `amd_dynamic_epp=enable` and `amd_dynamic_epp=disable` to override the kernel configuration option `CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP` locally. Signed-off-by: Mario Limonciello --- Documentation/admin-guide/kernel-parameters.txt | 7 +++++++ Documentation/admin-guide/pm/amd-pstate.rst | 7 +++++++ drivers/cpufreq/amd-pstate.c | 11 +++++++++++ 3 files changed, 25 insertions(+) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index fb8752b42ec85..1afe6d8ab09bb 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -392,6 +392,13 @@ disable Disable amd-pstate preferred core. + amd_dynamic_epp= + [X86] + disable + Disable amd-pstate dynamic EPP. + enable + Enable amd-pstate dynamic EPP. + amijoy.map= [HW,JOY] Amiga joystick support Map of devices attached to JOY0DAT and JOY1DAT Format: , diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst index 2e076650dc77c..8424e7119dd7e 100644 --- a/Documentation/admin-guide/pm/amd-pstate.rst +++ b/Documentation/admin-guide/pm/amd-pstate.rst @@ -438,6 +438,13 @@ For systems that support ``amd-pstate`` preferred core, the core rankings will always be advertised by the platform. But OS can choose to ignore that via the kernel parameter ``amd_prefcore=disable``. +``amd_dynamic_epp`` + +When AMD pstate is in auto mode, dynamic EPP will control whether the kernel +autonomously changes the EPP mode. The default is configured by +``CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`` but can be explicitly enabled with +``amd_pstate_epp=enable`` or disabled with ``amd_pstate_epp=disable``. + User Space Interface in ``sysfs`` - General =========================================== diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c index 95cf8ac29b08c..f72f385f9f92e 100644 --- a/drivers/cpufreq/amd-pstate.c +++ b/drivers/cpufreq/amd-pstate.c @@ -1969,8 +1969,19 @@ static int __init amd_prefcore_param(char *str) return 0; } +static int __init amd_dynamic_epp_param(char *str) +{ + if (!strcmp(str, "disable")) + dynamic_epp = false; + if (!strcmp(str, "enable")) + dynamic_epp = true; + + return 0; +} + early_param("amd_pstate", amd_pstate_param); early_param("amd_prefcore", amd_prefcore_param); +early_param("amd_dynamic_epp", amd_dynamic_epp_param); MODULE_AUTHOR("Huang Rui "); MODULE_DESCRIPTION("AMD Processor P-state Frequency Driver"); From patchwork Sat Feb 15 00:54:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Limonciello X-Patchwork-Id: 13975842 X-Patchwork-Delegate: mario.limonciello@amd.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2A8918C004; Sat, 15 Feb 2025 00:55:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739580901; cv=none; b=bVoaFL+xhbxM7N9X0l/2F9PuuFDzFg/tWw8SAIkL6TGIjvEYTSDWLL3nFuBJyFTp2bOWvfD2VtgO0qkco7gwW14ZtZvUBpPjllLQGByPhaFDRlisxxuYCX8KsKrgwy+zZ5u0RM+Spc+6M8UG2BVsOTQrnVW8+ipdZ38SaFf6QnU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739580901; c=relaxed/simple; bh=DhZ3YXZcPMLtIFRNwbPKyIRSQL0TNWs0xy4ILudBErs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YbknMy0NfqMrdiisa95QFo1sEMXUZIgZ4qHnbBPwLOHVCdmzFth4nqgwUa+mJH4b28MtyFinxfJdXZCymyIPMO5djrWWLoAMCjk6ZIyMqwa9pXafaLRw/lGapEZ86frtJ1N01yizwnusXUDBA2yEu/w634lNCe37+gugebbGy9Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IYWvBYNH; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IYWvBYNH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8DA40C4CEE2; Sat, 15 Feb 2025 00:55:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739580901; bh=DhZ3YXZcPMLtIFRNwbPKyIRSQL0TNWs0xy4ILudBErs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IYWvBYNHXY+CCocH5n9O5kBaKN1KW8bnjdMzjZU6K4+u3mHABpupLN/3SHhmW1E2g 6kxbUEk1glssvGXV4A1MzRpSrKbe93MwaaZJlHsnvzirk6yZXjqhOGzZKQQRyJoB/1 wjPS37Jsm9WREBjbbYCEkKYemxJCu69JSfMlRmsqqhNjOQP0N6t+eEUOkz40rZi7oJ E80LSzm2IIQGS6qdEF0tx2LDlmXmrZWNeqGSf93O9l7BUo1UVZwixRnEkSrQzPtKMq pK0XC6fUI/PWJOaxNvdepRk0zWKdRYPOE7oxrRmKlGCn0soDrgCmWIiSnLj3falztn Rqr/vIW3N9LmA== From: Mario Limonciello To: "Gautham R . Shenoy" , Perry Yuan Cc: Dhananjay Ugwekar , linux-kernel@vger.kernel.org (open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)), linux-pm@vger.kernel.org (open list:CPU FREQUENCY SCALING FRAMEWORK), Mario Limonciello Subject: [PATCH 3/5] cpufreq/amd-pstate: Add support for platform profile class Date: Fri, 14 Feb 2025 18:54:46 -0600 Message-ID: <20250215005448.1216646-4-superm1@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250215005448.1216646-1-superm1@kernel.org> References: <20250215005448.1216646-1-superm1@kernel.org> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Mario Limonciello The platform profile core allows multiple drivers and devices to register platform profile support. When the legacy platform profile interface is used all drivers will adjust the platform profile as well. Add support for registering every CPU with the platform profile handler when dynamic EPP is enabled. The end result will be that changing the platform profile will modify EPP accordingly. Signed-off-by: Mario Limonciello --- Documentation/admin-guide/pm/amd-pstate.rst | 4 +- drivers/cpufreq/Kconfig.x86 | 1 + drivers/cpufreq/amd-pstate.c | 154 ++++++++++++++++---- drivers/cpufreq/amd-pstate.h | 10 ++ 4 files changed, 140 insertions(+), 29 deletions(-) diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst index 8424e7119dd7e..36950fb6568c0 100644 --- a/Documentation/admin-guide/pm/amd-pstate.rst +++ b/Documentation/admin-guide/pm/amd-pstate.rst @@ -321,7 +321,9 @@ Whether this behavior is enabled by default with the kernel config option at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``. When set to enabled, the driver will select a different energy performance -profile when the machine is running on battery or AC power. +profile when the machine is running on battery or AC power. The driver will +also register with the platform profile handler to receive notifications of +user desired power state and react to those. When set to disabled, the driver will not change the energy performance profile based on the power source and will not react to user desired power state. diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index bfe957b653b05..f9906b4943e40 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 @@ -40,6 +40,7 @@ config X86_AMD_PSTATE select ACPI_PROCESSOR select ACPI_CPPC_LIB if X86_64 select CPU_FREQ_GOV_SCHEDUTIL if SMP + select ACPI_PLATFORM_PROFILE help This driver adds a CPUFreq driver which utilizes a fine grain processor performance frequency control range instead of legacy diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c index f72f385f9f92e..5d5f602ef1407 100644 --- a/drivers/cpufreq/amd-pstate.c +++ b/drivers/cpufreq/amd-pstate.c @@ -105,6 +105,7 @@ static struct quirk_entry *quirks; * 2 balance_performance * 3 balance_power * 4 power + * 5 custom (for raw EPP values) */ enum energy_perf_value_index { EPP_INDEX_DEFAULT = 0, @@ -112,6 +113,7 @@ enum energy_perf_value_index { EPP_INDEX_BALANCE_PERFORMANCE, EPP_INDEX_BALANCE_POWERSAVE, EPP_INDEX_POWERSAVE, + EPP_INDEX_CUSTOM, }; static const char * const energy_perf_strings[] = { @@ -120,6 +122,7 @@ static const char * const energy_perf_strings[] = { [EPP_INDEX_BALANCE_PERFORMANCE] = "balance_performance", [EPP_INDEX_BALANCE_POWERSAVE] = "balance_power", [EPP_INDEX_POWERSAVE] = "power", + [EPP_INDEX_CUSTOM] = "custom", NULL }; @@ -1089,6 +1092,10 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb, if (event != PSY_EVENT_PROP_CHANGED) return NOTIFY_OK; + /* dynamic actions are only applied while platform profile is in balanced */ + if (cpudata->current_profile != PLATFORM_PROFILE_BALANCED) + return 0; + epp = amd_pstate_get_balanced_epp(policy); ret = amd_pstate_set_epp(policy, epp); @@ -1097,14 +1104,84 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb, return NOTIFY_OK; } -static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy) + +static int amd_pstate_profile_probe(void *drvdata, unsigned long *choices) +{ + set_bit(PLATFORM_PROFILE_LOW_POWER, choices); + set_bit(PLATFORM_PROFILE_BALANCED, choices); + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); + + return 0; +} + +static int amd_pstate_profile_get(struct device *dev, + enum platform_profile_option *profile) +{ + struct amd_cpudata *cpudata = dev_get_drvdata(dev); + + *profile = cpudata->current_profile; + + return 0; +} + +static int amd_pstate_profile_set(struct device *dev, + enum platform_profile_option profile) +{ + struct amd_cpudata *cpudata = dev_get_drvdata(dev); + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu); + int ret; + + switch (profile) { + case PLATFORM_PROFILE_LOW_POWER: + if (cpudata->policy != CPUFREQ_POLICY_POWERSAVE) + cpudata->policy = CPUFREQ_POLICY_POWERSAVE; + ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_POWERSAVE); + if (ret) + return ret; + break; + case PLATFORM_PROFILE_BALANCED: + if (cpudata->policy != CPUFREQ_POLICY_POWERSAVE) + cpudata->policy = CPUFREQ_POLICY_POWERSAVE; + ret = amd_pstate_set_epp(policy, + amd_pstate_get_balanced_epp(policy)); + if (ret) + return ret; + break; + case PLATFORM_PROFILE_PERFORMANCE: + ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_PERFORMANCE); + if (ret) + return ret; + break; + default: + pr_err("Unknown Platform Profile %d\n", profile); + return -EOPNOTSUPP; + } + + cpudata->current_profile = profile; + + return 0; +} + +static const struct platform_profile_ops amd_pstate_profile_ops = { + .probe = amd_pstate_profile_probe, + .profile_set = amd_pstate_profile_set, + .profile_get = amd_pstate_profile_get, +}; + +void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy) { struct amd_cpudata *cpudata = policy->driver_data; if (cpudata->power_nb.notifier_call) power_supply_unreg_notifier(&cpudata->power_nb); + if (cpudata->ppdev) { + platform_profile_remove(cpudata->ppdev); + cpudata->ppdev = NULL; + } + kfree(cpudata->profile_name); cpudata->dynamic_epp = false; } +EXPORT_SYMBOL_GPL(amd_pstate_clear_dynamic_epp); static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy) { @@ -1112,11 +1189,35 @@ static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy) int ret; u8 epp; - epp = amd_pstate_get_balanced_epp(policy); + switch (cpudata->current_profile) { + case PLATFORM_PROFILE_PERFORMANCE: + epp = AMD_CPPC_EPP_PERFORMANCE; + break; + case PLATFORM_PROFILE_LOW_POWER: + epp = AMD_CPPC_EPP_POWERSAVE; + break; + case PLATFORM_PROFILE_BALANCED: + epp = amd_pstate_get_balanced_epp(policy); + break; + default: + pr_err("Unknown Platform Profile %d\n", cpudata->current_profile); + return -EOPNOTSUPP; + } ret = amd_pstate_set_epp(policy, epp); if (ret) return ret; + cpudata->profile_name = kasprintf(GFP_KERNEL, "amd-pstate-epp-cpu%d", cpudata->cpu); + + cpudata->ppdev = platform_profile_register(get_cpu_device(policy->cpu), + cpudata->profile_name, + policy->driver_data, + &amd_pstate_profile_ops); + if (IS_ERR(cpudata->ppdev)) { + ret = PTR_ERR(cpudata->ppdev); + goto cleanup; + } + /* only enable notifier if things will actually change */ if (cpudata->epp_default_ac != cpudata->epp_default_dc) { ret = power_supply_reg_notifier(&cpudata->power_nb); @@ -1223,8 +1324,8 @@ static ssize_t show_energy_performance_available_preferences( return offset; } -static ssize_t store_energy_performance_preference( - struct cpufreq_policy *policy, const char *buf, size_t count) +ssize_t store_energy_performance_preference(struct cpufreq_policy *policy, + const char *buf, size_t count) { struct amd_cpudata *cpudata = policy->driver_data; char str_preference[21]; @@ -1240,41 +1341,35 @@ static ssize_t store_energy_performance_preference( if (ret != 1) return -EINVAL; - ret = match_string(energy_perf_strings, -1, str_preference); - if (ret < 0) - return -EINVAL; - - if (ret) - epp = epp_values[ret]; - else - epp = amd_pstate_get_balanced_epp(policy); + /* + * if the value matches a number, use that, otherwise see if + * matches an index in the energy_perf_strings array + */ + ret = kstrtou8(str_preference, 0, &epp); + if (ret) { + ret = match_string(energy_perf_strings, -1, str_preference); + if (ret < 0 || ret == EPP_INDEX_CUSTOM) + return -EINVAL; + if (ret) + epp = epp_values[ret]; + else + epp = amd_pstate_get_balanced_epp(policy); + } - if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) { + if (epp > 0 && cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) { pr_debug("EPP cannot be set under performance policy\n"); return -EBUSY; } - if (trace_amd_pstate_epp_perf_enabled()) { - union perf_cached perf = cpudata->perf; - - trace_amd_pstate_epp_perf(cpudata->cpu, perf.highest_perf, - epp, - FIELD_GET(AMD_CPPC_MIN_PERF_MASK, cpudata->cppc_req_cached), - FIELD_GET(AMD_CPPC_MAX_PERF_MASK, cpudata->cppc_req_cached), - policy->boost_enabled, - FIELD_GET(AMD_CPPC_EPP_PERF_MASK, - cpudata->cppc_req_cached) != epp); - } - ret = amd_pstate_set_epp(policy, epp); if (ret) return ret; return ret ? ret : count; } +EXPORT_SYMBOL_GPL(store_energy_performance_preference); -static ssize_t show_energy_performance_preference( - struct cpufreq_policy *policy, char *buf) +ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf) { struct amd_cpudata *cpudata = policy->driver_data; u8 preference, epp; @@ -1295,11 +1390,12 @@ static ssize_t show_energy_performance_preference( preference = EPP_INDEX_POWERSAVE; break; default: - return -EINVAL; + return sysfs_emit(buf, "%u\n", epp); } return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]); } +EXPORT_SYMBOL_GPL(show_energy_performance_preference); static void amd_pstate_driver_cleanup(void) { @@ -1623,10 +1719,12 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) amd_pstate_acpi_pm_profile_undefined()) { policy->policy = CPUFREQ_POLICY_PERFORMANCE; cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata); + cpudata->current_profile = PLATFORM_PROFILE_PERFORMANCE; } else { policy->policy = CPUFREQ_POLICY_POWERSAVE; cpudata->epp_default_ac = AMD_CPPC_EPP_PERFORMANCE; cpudata->epp_default_dc = AMD_CPPC_EPP_BALANCE_PERFORMANCE; + cpudata->current_profile = PLATFORM_PROFILE_BALANCED; } if (cpu_feature_enabled(X86_FEATURE_CPPC)) { diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h index a3b70c635a7d7..f1bbac4faf83d 100644 --- a/drivers/cpufreq/amd-pstate.h +++ b/drivers/cpufreq/amd-pstate.h @@ -9,6 +9,7 @@ #define _LINUX_AMD_PSTATE_H #include +#include /********************************************************************* * AMD P-state INTERFACE * @@ -106,6 +107,11 @@ struct amd_cpudata { u8 epp_default_dc; bool dynamic_epp; struct notifier_block power_nb; + + /* platform profile */ + enum platform_profile_option current_profile; + struct device *ppdev; + char *profile_name; }; /* @@ -121,5 +127,9 @@ enum amd_pstate_mode { }; const char *amd_pstate_get_mode_string(enum amd_pstate_mode mode); int amd_pstate_update_status(const char *buf, size_t size); +ssize_t store_energy_performance_preference(struct cpufreq_policy *policy, + const char *buf, size_t count); +ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf); +void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy); #endif /* _LINUX_AMD_PSTATE_H */ From patchwork Sat Feb 15 00:54:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Limonciello X-Patchwork-Id: 13975843 X-Patchwork-Delegate: mario.limonciello@amd.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 933231925AC; Sat, 15 Feb 2025 00:55:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739580902; cv=none; b=FJaDtX41B8BcTzMcPRs5jJ9PQEOWXVeU/tQPG612Ft9kopXko3IxWeY3QcQwS3J7KuRu4PBVsd7R0SvguoibdKzaO9D0tUyHZe/uRxBNLpSc9EA6bwilebhemCFA7nsQpN4fjfnrY5Zlxru8ZpJSfESopOXxI+SxmtuB46uurnA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739580902; c=relaxed/simple; bh=xNVlLenkvG2vhuYPE5tLdxeYbge7k4Nuv4kwBtl5rD8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Y25DIHz8xBETGJHWffZbEXAr8N3p5rHBitQbkI3GPQzneBSeOmO9CTeVD7oGunZARLIppoxHZH+U7SkyuqRvMQ/Vu/VR8st3dajnck0NIa3Zi4bOVygjJmwfu4VKU+URlMelCVhqUMLDS3WoKr378GdFmFmesnFVYDBVQuZvsYA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=l9CnHvia; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="l9CnHvia" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 70A47C4CEE6; Sat, 15 Feb 2025 00:55:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739580902; bh=xNVlLenkvG2vhuYPE5tLdxeYbge7k4Nuv4kwBtl5rD8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=l9CnHviagF8D3AVJL73gegi7YXunng4wPOq5gGmz5Y/jWNpgQwJtclG/yBT9NqPAv OUXW/BUGv8KLqs4Xmv5pK8AfELt2PQAcMaCKBgU5vmoP7xJB1kMpE/RjVwCMv3cN6X W5lH+Fi8d1VrSPKQRFlgJgHK9EHJhoteAImf92pv4P+Ia/ed2g6bdbkPe7PEcvRw0f M5sfebFXoCQstgyNHFViwHOW5tfAWPbjRwHZXs7f6Ec8aXVfHN9FfMkO2lUPjbtd6o gWYodg8iYrjCrWtu0Bbx0eIVnx83cWz/s0TMcWqZiqXj3qTE1Uxo8AMGNd/z1x06bj ijsqm4eXXMk7w== From: Mario Limonciello To: "Gautham R . Shenoy" , Perry Yuan Cc: Dhananjay Ugwekar , linux-kernel@vger.kernel.org (open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)), linux-pm@vger.kernel.org (open list:CPU FREQUENCY SCALING FRAMEWORK), Mario Limonciello Subject: [PATCH 4/5] cpufreq/amd-pstate: Add support for raw EPP writes Date: Fri, 14 Feb 2025 18:54:47 -0600 Message-ID: <20250215005448.1216646-5-superm1@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250215005448.1216646-1-superm1@kernel.org> References: <20250215005448.1216646-1-superm1@kernel.org> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Mario Limonciello The energy performance preference field of the CPPC request MSR supports values from 0 to 255, but the strings only offer 4 values. The other values are useful for tuning the performance of some workloads. Add support for writing the raw energy performance preference value to the sysfs file. If the last value written was an integer then an integer will be returned. If the last value written was a string then a string will be returned. Signed-off-by: Mario Limonciello --- Documentation/admin-guide/pm/amd-pstate.rst | 16 +++++++++++----- drivers/cpufreq/amd-pstate.c | 11 +++++++++-- drivers/cpufreq/amd-pstate.h | 1 + 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst index 36950fb6568c0..0e4d2e0aaeff7 100644 --- a/Documentation/admin-guide/pm/amd-pstate.rst +++ b/Documentation/admin-guide/pm/amd-pstate.rst @@ -280,16 +280,22 @@ A list of all the supported EPP preferences that could be used for These profiles represent different hints that are provided to the low-level firmware about the user's desired energy vs efficiency tradeoff. ``default`` represents the epp value is set by platform -firmware. This attribute is read-only. +firmware. ``custom`` designates that integer values 0-255 may be written +as well. This attribute is read-only. ``energy_performance_preference`` The current energy performance preference can be read from this attribute. and user can change current preference according to energy or performance needs -Please get all support profiles list from -``energy_performance_available_preferences`` attribute, all the profiles are -integer values defined between 0 to 255 when EPP feature is enabled by platform -firmware, but if the dynamic EPP feature is enabled, driver will block writes. +Coarse named profiles are available in the attribute +``energy_performance_available_preferences``. +Users can also write individual integer values between 0 to 255. +When EPP feature is enabled by platform firmware but if the dynamic EPP feature is +enabled, driver will ignore the written value. Lower epp values shift the bias +towards improved performance while a higher epp value shifts the bias towards +power-savings. The exact impact can change from one platform to the other. +If a valid integer was last written, then a number will be returned on future reads. +If a valid string was last written then a string will be returned on future reads. This attribute is read-write. ``boost`` diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c index 5d5f602ef1407..0d71eaf7366f2 100644 --- a/drivers/cpufreq/amd-pstate.c +++ b/drivers/cpufreq/amd-pstate.c @@ -1330,6 +1330,7 @@ ssize_t store_energy_performance_preference(struct cpufreq_policy *policy, struct amd_cpudata *cpudata = policy->driver_data; char str_preference[21]; ssize_t ret; + bool raw_epp = FALSE; u8 epp; if (cpudata->dynamic_epp) { @@ -1346,6 +1347,7 @@ ssize_t store_energy_performance_preference(struct cpufreq_policy *policy, * matches an index in the energy_perf_strings array */ ret = kstrtou8(str_preference, 0, &epp); + raw_epp = !ret; if (ret) { ret = match_string(energy_perf_strings, -1, str_preference); if (ret < 0 || ret == EPP_INDEX_CUSTOM) @@ -1365,7 +1367,9 @@ ssize_t store_energy_performance_preference(struct cpufreq_policy *policy, if (ret) return ret; - return ret ? ret : count; + cpudata->raw_epp = raw_epp; + + return count; } EXPORT_SYMBOL_GPL(store_energy_performance_preference); @@ -1376,6 +1380,9 @@ ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char * epp = FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached); + if (cpudata->raw_epp) + return sysfs_emit(buf, "%u\n", epp); + switch (epp) { case AMD_CPPC_EPP_PERFORMANCE: preference = EPP_INDEX_PERFORMANCE; @@ -1390,7 +1397,7 @@ ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char * preference = EPP_INDEX_POWERSAVE; break; default: - return sysfs_emit(buf, "%u\n", epp); + return -EINVAL; } return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]); diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h index f1bbac4faf83d..490fb46f05602 100644 --- a/drivers/cpufreq/amd-pstate.h +++ b/drivers/cpufreq/amd-pstate.h @@ -106,6 +106,7 @@ struct amd_cpudata { u8 epp_default_ac; u8 epp_default_dc; bool dynamic_epp; + bool raw_epp; struct notifier_block power_nb; /* platform profile */ From patchwork Sat Feb 15 00:54:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Limonciello X-Patchwork-Id: 13975844 X-Patchwork-Delegate: mario.limonciello@amd.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7EA1319ABDE; Sat, 15 Feb 2025 00:55:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739580903; cv=none; b=HS1hvDBlyxpyczwa379VYo4qm5OKMHNQsfRI6sWmDIF977P3HDJXIKGXz2+DCtC1+NB7V/YyzqhbdUMbKIzIl2mh8Ujx0/ZozYgH5po8JIHPzCBmGKa0t2JeEmRUypsaAUA2vlghqsZNP3X+z+0U0fPhfkXvySHMwMAh3fSTvfQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739580903; c=relaxed/simple; bh=gJBb3JyO4xb+ZhP18SRMcjTy36ZQoLUIZdnq9lF0008=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BZQbQpaRthvDsjN3XnVTES+JNak4miwWdoNFbdhWdhrXM+bvo7aWep66RLB3lFuU74Hem7Bc9KTm47wz15lmaxbzez4feck3o0DU7XTVuBqOZOCLbv2ckGRm6Gt2bd2A27sedRYCBN/JZbKm9XlOLMDYrYTNCq8tk6uDBCXt9Ak= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GhoKX1i7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GhoKX1i7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 57B8AC4CEE9; Sat, 15 Feb 2025 00:55:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739580903; bh=gJBb3JyO4xb+ZhP18SRMcjTy36ZQoLUIZdnq9lF0008=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GhoKX1i7AugFrX1chA1NAottTknWKSNboE3e9MCu0TV4jrk+qzbGEzRLr00R3hb60 hM++KpZpvO207VlYIKDnVp+VHwbsu9NZhJD+FOwZVRqQ29Xw50ywSjoqehTvecQp9c eutnSu+vfHvHnmaQN+pc0bWHuPbe+rrhoG6BoE3V5NlkKaV8fsLK+6eqVH6HrHyf0k NTr4JfNm5aT0EzYLQ/s7pJ6DypYmkAw+h9CAbR/sb8onvQNJfn3B1wm8vyuByM205u LqzAOXfjm07S1bbYA734/B/taeGu2BPDzxKuNVgs8rUWIpqFzdQGaJBUT6Sslvlflo TGaVCCM0hdcMA== From: Mario Limonciello To: "Gautham R . Shenoy" , Perry Yuan Cc: Dhananjay Ugwekar , linux-kernel@vger.kernel.org (open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)), linux-pm@vger.kernel.org (open list:CPU FREQUENCY SCALING FRAMEWORK), Mario Limonciello Subject: [PATCH 5/5] cpufreq/amd-pstate-ut: Add a unit test for raw EPP Date: Fri, 14 Feb 2025 18:54:48 -0600 Message-ID: <20250215005448.1216646-6-superm1@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250215005448.1216646-1-superm1@kernel.org> References: <20250215005448.1216646-1-superm1@kernel.org> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Mario Limonciello Ensure that all supported raw EPP values work properly. Signed-off-by: Mario Limonciello --- drivers/cpufreq/amd-pstate-ut.c | 58 +++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/drivers/cpufreq/amd-pstate-ut.c b/drivers/cpufreq/amd-pstate-ut.c index 067e9e325102e..b5bf0c37d8037 100644 --- a/drivers/cpufreq/amd-pstate-ut.c +++ b/drivers/cpufreq/amd-pstate-ut.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,7 @@ #include "amd-pstate.h" +DEFINE_FREE(free_page, void *, if (_T) free_page((unsigned long)_T)) struct amd_pstate_ut_struct { const char *name; @@ -45,6 +47,7 @@ static int amd_pstate_ut_acpi_cpc_valid(u32 index); static int amd_pstate_ut_check_enabled(u32 index); static int amd_pstate_ut_check_perf(u32 index); static int amd_pstate_ut_check_freq(u32 index); +static int amd_pstate_ut_epp(u32 index); static int amd_pstate_ut_check_driver(u32 index); static struct amd_pstate_ut_struct amd_pstate_ut_cases[] = { @@ -52,6 +55,7 @@ static struct amd_pstate_ut_struct amd_pstate_ut_cases[] = { {"amd_pstate_ut_check_enabled", amd_pstate_ut_check_enabled }, {"amd_pstate_ut_check_perf", amd_pstate_ut_check_perf }, {"amd_pstate_ut_check_freq", amd_pstate_ut_check_freq }, + {"amd_pstate_ut_epp", amd_pstate_ut_epp }, {"amd_pstate_ut_check_driver", amd_pstate_ut_check_driver } }; @@ -238,6 +242,60 @@ static int amd_pstate_set_mode(enum amd_pstate_mode mode) return amd_pstate_update_status(mode_str, strlen(mode_str)); } +static int amd_pstate_ut_epp(u32 index) +{ + struct cpufreq_policy *policy __free(put_cpufreq_policy) = NULL; + void *buf __free(free_page) = NULL; + struct amd_cpudata *cpudata; + int ret, cpu = 0; + u16 epp; + + policy = cpufreq_cpu_get(cpu); + if (!policy) + return -ENODEV; + + cpudata = policy->driver_data; + + /* disable dynamic EPP before running test */ + if (cpudata->dynamic_epp) { + pr_debug("Dynamic EPP is enabled, disabling it\n"); + amd_pstate_clear_dynamic_epp(policy); + } + + buf = (void *)__get_free_page(GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = amd_pstate_set_mode(AMD_PSTATE_ACTIVE); + if (ret) + return ret; + + for (epp = 0; epp <= U8_MAX; epp++) { + u8 val; + + /* write all EPP values */ + memset(buf, 0, sizeof(buf)); + snprintf(buf, PAGE_SIZE, "%d", epp); + ret = store_energy_performance_preference(policy, buf, sizeof(buf)); + if (ret < 0) + return ret; + + /* check if the EPP value reads back correctly for raw numbers */ + memset(buf, 0, sizeof(buf)); + ret = show_energy_performance_preference(policy, buf); + if (ret < 0) + return ret; + strreplace(buf, '\n', '\0'); + ret = kstrtou8(buf, 0, &val); + if (!ret && epp != val) { + pr_err("Raw EPP value mismatch: %d != %d\n", epp, val); + return -EINVAL; + } + } + + return 0; +} + static int amd_pstate_ut_check_driver(u32 index) { enum amd_pstate_mode mode1, mode2 = AMD_PSTATE_DISABLE;