Merge tag 'pm-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management updates from Rafael Wysocki:
 "Once again, cpufreq is the most active development area, mostly
  because of the new feature additions and documentation updates in the
  amd-pstate driver, but there are also changes in the cpufreq core
  related to boost support and other assorted updates elsewhere.

  Next up are power capping changes due to the major cleanup of the
  Intel RAPL driver.

  On the cpuidle front, a new C-states table for Intel Panther Lake is
  added to the intel_idle driver, the stopped tick handling in the menu
  and teo governors is updated, and there are a couple of cleanups.

  Apart from the above, support for Tegra114 is added to devfreq and
  there are assorted cleanups of that code, there are also two updates
  of the operating performance points (OPP) library, two minor updates
  related to hibernation, and cpupower utility man pages updates and
  cleanups.

  Specifics:

   - Update qcom-hw DT bindings to include Eliza hardware (Abel Vesa)

   - Update cpufreq-dt-platdev blocklist (Faruque Ansari)

   - Minor updates to driver and dt-bindings for Tegra (Thierry Reding,
     Rosen Penev)

   - Add MAINTAINERS entry for CPPC driver (Viresh Kumar)

   - Add support for new features: CPPC performance priority, Dynamic
     EPP, Raw EPP, and new unit tests for them to amd-pstate (Gautham
     Shenoy, Mario Limonciello)

   - Fix sysfs files being present when HW missing and broken/outdated
     documentation in the amd-pstate driver (Ninad Naik, Gautham Shenoy)

   - Pass the policy to cpufreq_driver->adjust_perf() to avoid using
     cpufreq_cpu_get() in the .adjust_perf() callback in amd-pstate
     which leads to a scheduling-while-atomic bug (K Prateek Nayak)

   - Clean up dead code in Kconfig for cpufreq (Julian Braha)

   - Remove max_freq_req update for pre-existing cpufreq policy and add
     a boost_freq_req QoS request to save the boost constraint instead
     of overwriting the last scaling_max_freq constraint (Pierre
     Gondois)

   - Embed cpufreq QoS freq_req objects in cpufreq policy so they all
     are allocated in one go along with the policy to simplify lifetime
     rules and avoid error handling issues (Viresh Kumar)

   - Use DMI max speed when CPPC is unavailable in the acpi-cpufreq
     scaling driver (Henry Tseng)

   - Switch policy_is_shared() in cpufreq to using cpumask_nth() instead
     of cpumask_weight() because the former is more efficient (Yury
     Norov)

   - Use sysfs_emit() in sysfs show functions for cpufreq governor
     attributes (Thorsten Blum)

   - Update intel_pstate to stop returning an error when "off" is
     written to its status sysfs attribute while the driver is already
     off (Fabio De Francesco)

   - Include current frequency in the debug message printed by
     __cpufreq_driver_target() (Pengjie Zhang)

   - Refine stopped tick handling in the menu cpuidle governor and
     rearrange stopped tick handling in the teo cpuidle governor (Rafael
     Wysocki)

   - Add Panther Lake C-states table to the intel_idle driver (Artem
     Bityutskiy)

   - Clean up dead dependencies on CPU_IDLE in Kconfig (Julian Braha)

   - Simplify cpuidle_register_device() with guard() (Huisong Li)

   - Use performance level if available to distinguish between rates in
     OPP debugfs (Manivannan Sadhasivam)

   - Fix scoped_guard in dev_pm_opp_xlate_required_opp() (Viresh Kumar)

   - Return -ENODATA if the snapshot image is not loaded (Alberto
     Garcia)

   - Remove inclusion of crypto/hash.h from hibernate_64.c on x86 (Eric
     Biggers)

   - Clean up and rearrange the intel_rapl power capping driver to make
     the respective interface drivers (TPMI, MSR, and MMOI) hold their
     own settings and primitives and consolidate PL4 and PMU support
     flags into rapl_defaults (Kuppuswamy Sathyanarayanan)

   - Correct kernel-doc function parameter names in the power capping
     core code (Randy Dunlap)

   - Remove unneeded casting for HZ_PER_KHZ in devfreq (Andy Shevchenko)

   - Use _visible attribute to replace create/remove_sysfs_files() in
     devfreq (Pengjie Zhang)

   - Add Tegra114 support to activity monitor device in tegra30-devfreq
     as a preparation to upcoming EMC controller support (Svyatoslav
     Ryhel)

   - Fix mistakes in cpupower man pages, add the boost and epp options
     to the cpupower-frequency-info man page, and add the perf-bias
     option to the cpupower-info man page (Roberto Ricci)

   - Remove unnecessary extern declarations from getopt.h in arguments
     parsing functions in cpufreq-set, cpuidle-info, cpuidle-set,
     cpupower-info, and cpupower-set utilities (Kaushlendra Kumar)"

* tag 'pm-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (74 commits)
  cpufreq/amd-pstate: Add POWER_SUPPLY select for dynamic EPP
  cpupower: remove extern declarations in cmd functions
  cpuidle: Simplify cpuidle_register_device() with guard()
  PM / devfreq: tegra30-devfreq: add support for Tegra114
  PM / devfreq: use _visible attribute to replace create/remove_sysfs_files()
  PM / devfreq: Remove unneeded casting for HZ_PER_KHZ
  MAINTAINERS: amd-pstate: Step down as maintainer, add Prateek as reviewer
  cpufreq: Pass the policy to cpufreq_driver->adjust_perf()
  cpufreq/amd-pstate: Pass the policy to amd_pstate_update()
  cpufreq/amd-pstate-ut: Add a unit test for raw EPP
  cpufreq/amd-pstate: Add support for raw EPP writes
  cpufreq/amd-pstate: Add support for platform profile class
  cpufreq/amd-pstate: add kernel command line to override dynamic epp
  cpufreq/amd-pstate: Add dynamic energy performance preference
  Documentation: amd-pstate: fix dead links in the reference section
  cpufreq/amd-pstate: Cache the max frequency in cpudata
  Documentation/amd-pstate: Add documentation for amd_pstate_floor_{freq,count}
  Documentation/amd-pstate: List amd_pstate_prefcore_ranking sysfs file
  Documentation/amd-pstate: List amd_pstate_hw_prefcore sysfs file
  amd-pstate-ut: Add a testcase to validate the visibility of driver attributes
  ...
This commit is contained in:
Linus Torvalds
2026-04-13 19:47:52 -07:00
58 changed files with 1950 additions and 902 deletions
@@ -501,6 +501,13 @@ Kernel parameters
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: <a>,<b>
+77 -10
View File
@@ -239,8 +239,12 @@ control its functionality at the system level. They are located in the
root@hr-test1:/home/ray# ls /sys/devices/system/cpu/cpufreq/policy0/*amd*
/sys/devices/system/cpu/cpufreq/policy0/amd_pstate_highest_perf
/sys/devices/system/cpu/cpufreq/policy0/amd_pstate_hw_prefcore
/sys/devices/system/cpu/cpufreq/policy0/amd_pstate_lowest_nonlinear_freq
/sys/devices/system/cpu/cpufreq/policy0/amd_pstate_max_freq
/sys/devices/system/cpu/cpufreq/policy0/amd_pstate_floor_freq
/sys/devices/system/cpu/cpufreq/policy0/amd_pstate_floor_count
/sys/devices/system/cpu/cpufreq/policy0/amd_pstate_prefcore_ranking
``amd_pstate_highest_perf / amd_pstate_max_freq``
@@ -264,14 +268,46 @@ This attribute is read-only.
``amd_pstate_hw_prefcore``
Whether the platform supports the preferred core feature and it has been
enabled. This attribute is read-only.
Whether the platform supports the preferred core feature and it has
been enabled. This attribute is read-only. This file is only visible
on platforms which support the preferred core feature.
``amd_pstate_prefcore_ranking``
The performance ranking of the core. This number doesn't have any unit, but
larger numbers are preferred at the time of reading. This can change at
runtime based on platform conditions. This attribute is read-only.
runtime based on platform conditions. This attribute is read-only. This file
is only visible on platforms which support the preferred core feature.
``amd_pstate_floor_freq``
The floor frequency associated with each CPU. Userspace can write any
value between ``cpuinfo_min_freq`` and ``scaling_max_freq`` into this
file. When the system is under power or thermal constraints, the
platform firmware will attempt to throttle the CPU frequency to the
value specified in ``amd_pstate_floor_freq`` before throttling it
further. This allows userspace to specify different floor frequencies
to different CPUs. For optimal results, threads of the same core
should have the same floor frequency value. This file is only visible
on platforms that support the CPPC Performance Priority feature.
``amd_pstate_floor_count``
The number of distinct Floor Performance levels supported by the
platform. For example, if this value is 2, then the number of unique
values obtained from the command ``cat
/sys/devices/system/cpu/cpufreq/policy*/amd_pstate_floor_freq |
sort -n | uniq`` should be at most this number for the behavior
described in ``amd_pstate_floor_freq`` to take effect. A zero value
implies that the platform supports unlimited floor performance levels.
This file is only visible on platforms that support the CPPC
Performance Priority feature.
**Note**: When ``amd_pstate_floor_count`` is non-zero, the frequency to
which the CPU is throttled under power or thermal constraints is
undefined when the number of unique values of ``amd_pstate_floor_freq``
across all CPUs in the system exceeds ``amd_pstate_floor_count``.
``energy_performance_available_preferences``
@@ -280,16 +316,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, if EPP feature is disabled, driver will ignore the written value
Coarse named profiles are available in the attribute
``energy_performance_available_preferences``.
Users can also write individual integer values between 0 to 255.
When dynamic EPP is enabled, writes to energy_performance_preference are blocked
even when EPP feature is enabled by platform firmware. 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``
@@ -311,6 +353,24 @@ 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 depends on 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. 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.
Attempting to manually write to the ``energy_performance_preference`` sysfs
file will fail when ``dynamic_epp`` is enabled.
``amd-pstate`` vs ``acpi-cpufreq``
======================================
@@ -422,6 +482,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_dynamic_epp=enable`` or disabled with ``amd_dynamic_epp=disable``.
User Space Interface in ``sysfs`` - General
===========================================
@@ -790,13 +857,13 @@ Reference
===========
.. [1] AMD64 Architecture Programmer's Manual Volume 2: System Programming,
https://www.amd.com/system/files/TechDocs/24593.pdf
https://docs.amd.com/v/u/en-US/24593_3.44_APM_Vol2
.. [2] Advanced Configuration and Power Interface Specification,
https://uefi.org/sites/default/files/resources/ACPI_Spec_6_4_Jan22.pdf
.. [3] Processor Programming Reference (PPR) for AMD Family 19h Model 51h, Revision A1 Processors
https://www.amd.com/system/files/TechDocs/56569-A1-PUB.zip
https://docs.amd.com/v/u/en-US/56569-A1-PUB_3.03
.. [4] Linux Kernel Selftests,
https://www.kernel.org/doc/html/latest/dev-tools/kselftest.html
@@ -24,6 +24,7 @@ properties:
enum:
- nvidia,tegra186-ccplex-cluster
- nvidia,tegra234-ccplex-cluster
- nvidia,tegra238-ccplex-cluster
reg:
maxItems: 1
@@ -35,6 +35,7 @@ properties:
- description: v2 of CPUFREQ HW (EPSS)
items:
- enum:
- qcom,eliza-cpufreq-epss
- qcom,milos-cpufreq-epss
- qcom,qcs8300-cpufreq-epss
- qcom,qdu1000-cpufreq-epss
+18 -7
View File
@@ -1234,9 +1234,9 @@ F: drivers/gpu/drm/amd/pm/
AMD PSTATE DRIVER
M: Huang Rui <ray.huang@amd.com>
M: Gautham R. Shenoy <gautham.shenoy@amd.com>
M: Mario Limonciello <mario.limonciello@amd.com>
R: Perry Yuan <perry.yuan@amd.com>
R: K Prateek Nayak <kprateek.nayak@amd.com>
L: linux-pm@vger.kernel.org
S: Supported
F: Documentation/admin-guide/pm/amd-pstate.rst
@@ -6618,6 +6618,17 @@ M: Bence Csókás <bence98@sch.bme.hu>
S: Maintained
F: drivers/i2c/busses/i2c-cp2615.c
CPU FREQUENCY DRIVERS - CPPC CPUFREQ
M: "Rafael J. Wysocki" <rafael@kernel.org>
M: Viresh Kumar <viresh.kumar@linaro.org>
R: Jie Zhan <zhanjie9@hisilicon.com>
R: Lifeng Zheng <zhenglifeng1@huawei.com>
R: Pierre Gondois <pierre.gondois@arm.com>
R: Sumit Gupta <sumitg@nvidia.com>
L: linux-pm@vger.kernel.org
S: Maintained
F: drivers/cpufreq/cppc_cpufreq.c
CPU FREQUENCY DRIVERS - VEXPRESS SPC ARM BIG LITTLE
M: Viresh Kumar <viresh.kumar@linaro.org>
M: Sudeep Holla <sudeep.holla@kernel.org>
@@ -6626,6 +6637,12 @@ S: Maintained
W: http://www.arm.com/products/processors/technologies/biglittleprocessing.php
F: drivers/cpufreq/vexpress-spc-cpufreq.c
CPU FREQUENCY DRIVERS - VIRTUAL MACHINE CPUFREQ
M: Saravana Kannan <saravanak@kernel.org>
L: linux-pm@vger.kernel.org
S: Maintained
F: drivers/cpufreq/virtual-cpufreq.c
CPU FREQUENCY SCALING FRAMEWORK
M: "Rafael J. Wysocki" <rafael@kernel.org>
M: Viresh Kumar <viresh.kumar@linaro.org>
@@ -6645,12 +6662,6 @@ F: kernel/sched/cpufreq*.c
F: rust/kernel/cpufreq.rs
F: tools/testing/selftests/cpufreq/
CPU FREQUENCY DRIVERS - VIRTUAL MACHINE CPUFREQ
M: Saravana Kannan <saravanak@kernel.org>
L: linux-pm@vger.kernel.org
S: Maintained
F: drivers/cpufreq/virtual-cpufreq.c
CPU HOTPLUG
M: Thomas Gleixner <tglx@kernel.org>
M: Peter Zijlstra <peterz@infradead.org>
+1 -1
View File
@@ -415,7 +415,7 @@
*/
#define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* "overflow_recov" MCA overflow recovery support */
#define X86_FEATURE_SUCCOR (17*32+ 1) /* "succor" Uncorrectable error containment and recovery */
#define X86_FEATURE_CPPC_PERF_PRIO (17*32+ 2) /* CPPC Floor Perf support */
#define X86_FEATURE_SMCA (17*32+ 3) /* "smca" Scalable MCA */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
+5
View File
@@ -765,12 +765,14 @@
#define MSR_AMD_CPPC_CAP2 0xc00102b2
#define MSR_AMD_CPPC_REQ 0xc00102b3
#define MSR_AMD_CPPC_STATUS 0xc00102b4
#define MSR_AMD_CPPC_REQ2 0xc00102b5
/* Masks for use with MSR_AMD_CPPC_CAP1 */
#define AMD_CPPC_LOWEST_PERF_MASK GENMASK(7, 0)
#define AMD_CPPC_LOWNONLIN_PERF_MASK GENMASK(15, 8)
#define AMD_CPPC_NOMINAL_PERF_MASK GENMASK(23, 16)
#define AMD_CPPC_HIGHEST_PERF_MASK GENMASK(31, 24)
#define AMD_CPPC_FLOOR_PERF_CNT_MASK GENMASK_ULL(39, 32)
/* Masks for use with MSR_AMD_CPPC_REQ */
#define AMD_CPPC_MAX_PERF_MASK GENMASK(7, 0)
@@ -778,6 +780,9 @@
#define AMD_CPPC_DES_PERF_MASK GENMASK(23, 16)
#define AMD_CPPC_EPP_PERF_MASK GENMASK(31, 24)
/* Masks for use with MSR_AMD_CPPC_REQ2 */
#define AMD_CPPC_FLOOR_PERF_MASK GENMASK(7, 0)
/* AMD Performance Counter Global Status and Control MSRs */
#define MSR_AMD64_PERF_CNTR_GLOBAL_STATUS 0xc0000300
#define MSR_AMD64_PERF_CNTR_GLOBAL_CTL 0xc0000301
+1
View File
@@ -52,6 +52,7 @@ static const struct cpuid_bit cpuid_bits[] = {
{ X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 },
{ X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 },
{ X86_FEATURE_AMD_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 },
{ X86_FEATURE_CPPC_PERF_PRIO, CPUID_EDX, 16, 0x80000007, 0 },
{ X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 },
{ X86_FEATURE_X2AVIC_EXT, CPUID_ECX, 6, 0x8000000a, 0 },
{ X86_FEATURE_COHERENCY_SFW_NO, CPUID_EBX, 31, 0x8000001f, 0 },
-2
View File
@@ -14,8 +14,6 @@
#include <linux/kdebug.h>
#include <linux/pgtable.h>
#include <crypto/hash.h>
#include <asm/e820/api.h>
#include <asm/init.h>
#include <asm/proto.h>
+2 -1
View File
@@ -2145,7 +2145,7 @@ static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private)
}
/* Look up the max frequency in DMI */
static u64 cppc_get_dmi_max_khz(void)
u64 cppc_get_dmi_max_khz(void)
{
u16 mhz = 0;
@@ -2159,6 +2159,7 @@ static u64 cppc_get_dmi_max_khz(void)
return KHZ_PER_MHZ * mhz;
}
EXPORT_SYMBOL_GPL(cppc_get_dmi_max_khz);
/*
* If CPPC lowest_freq and nominal_freq registers are exposed then we can
+2 -3
View File
@@ -163,7 +163,6 @@ config CPU_FREQ_GOV_ONDEMAND
config CPU_FREQ_GOV_CONSERVATIVE
tristate "'conservative' cpufreq governor"
depends on CPU_FREQ
select CPU_FREQ_GOV_COMMON
help
'conservative' - this driver is rather similar to the 'ondemand'
@@ -188,7 +187,7 @@ config CPU_FREQ_GOV_CONSERVATIVE
config CPU_FREQ_GOV_SCHEDUTIL
bool "'schedutil' cpufreq policy governor"
depends on CPU_FREQ && SMP
depends on SMP
select CPU_FREQ_GOV_ATTR_SET
select IRQ_WORK
help
@@ -365,6 +364,6 @@ config ACPI_CPPC_CPUFREQ_FIE
If in doubt, say N.
endif
endif # CPU_FREQ
endmenu
+1 -1
View File
@@ -248,7 +248,7 @@ config ARM_TEGRA186_CPUFREQ
config ARM_TEGRA194_CPUFREQ
tristate "Tegra194 CPUFreq support"
depends on ARCH_TEGRA_194_SOC || ARCH_TEGRA_234_SOC || (64BIT && COMPILE_TEST)
depends on ARCH_TEGRA_194_SOC || ARCH_TEGRA_234_SOC
depends on TEGRA_BPMP
default ARCH_TEGRA_194_SOC || ARCH_TEGRA_234_SOC
help
+14
View File
@@ -40,6 +40,8 @@ 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
select POWER_SUPPLY
help
This driver adds a CPUFreq driver which utilizes a fine grain
processor performance frequency control range instead of legacy
@@ -68,6 +70,18 @@ config X86_AMD_PSTATE_DEFAULT_MODE
For details, take a look at:
<file:Documentation/admin-guide/pm/amd-pstate.rst>.
config X86_AMD_PSTATE_DYNAMIC_EPP
bool "AMD Processor P-State dynamic EPP support"
depends on X86_AMD_PSTATE
default n
help
Allow the kernel 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
+24 -7
View File
@@ -675,6 +675,29 @@ static inline u64 get_max_boost_ratio(unsigned int cpu, u64 *nominal_freq)
}
#endif
static void acpi_cpufreq_resolve_max_freq(struct cpufreq_policy *policy,
unsigned int pss_max_freq)
{
#ifdef CONFIG_ACPI_CPPC_LIB
u64 max_speed = cppc_get_dmi_max_khz();
/*
* Use DMI "Max Speed" if it looks plausible: must be
* above _PSS P0 frequency and within 2x of it.
*/
if (max_speed > pss_max_freq && max_speed < pss_max_freq * 2) {
policy->cpuinfo.max_freq = max_speed;
return;
}
#endif
/*
* If the maximum "boost" frequency is unknown, ask the arch
* scale-invariance code to use the "nominal" performance for
* CPU utilization scaling so as to prevent the schedutil
* governor from selecting inadequate CPU frequencies.
*/
arch_set_max_freq_ratio(true);
}
static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
struct cpufreq_frequency_table *freq_table;
@@ -849,13 +872,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.max_freq = freq * max_boost_ratio >> SCHED_CAPACITY_SHIFT;
} else {
/*
* If the maximum "boost" frequency is unknown, ask the arch
* scale-invariance code to use the "nominal" performance for
* CPU utilization scaling so as to prevent the schedutil
* governor from selecting inadequate CPU frequencies.
*/
arch_set_max_freq_ratio(true);
acpi_cpufreq_resolve_max_freq(policy, freq_table[0].frequency);
}
policy->freq_table = freq_table;
+35
View File
@@ -133,6 +133,41 @@ TRACE_EVENT(amd_pstate_epp_perf,
)
);
TRACE_EVENT(amd_pstate_cppc_req2,
TP_PROTO(unsigned int cpu_id,
u8 floor_perf,
bool changed,
int err_code
),
TP_ARGS(cpu_id,
floor_perf,
changed,
err_code),
TP_STRUCT__entry(
__field(unsigned int, cpu_id)
__field(u8, floor_perf)
__field(bool, changed)
__field(int, err_code)
),
TP_fast_assign(
__entry->cpu_id = cpu_id;
__entry->floor_perf = floor_perf;
__entry->changed = changed;
__entry->err_code = err_code;
),
TP_printk("cpu%u: floor_perf=%u, changed=%u (error = %d)",
__entry->cpu_id,
__entry->floor_perf,
__entry->changed,
__entry->err_code
)
);
#endif /* _AMD_PSTATE_TRACE_H */
/* This part must be outside protection */
+273 -6
View File
@@ -23,9 +23,12 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bitfield.h>
#include <linux/cpufeature.h>
#include <linux/cpufreq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/cleanup.h>
@@ -35,6 +38,11 @@
#include "amd-pstate.h"
static char *test_list;
module_param(test_list, charp, 0444);
MODULE_PARM_DESC(test_list,
"Comma-delimited list of tests to run (empty means run all tests)");
DEFINE_FREE(cleanup_page, void *, if (_T) free_page((unsigned long)_T))
struct amd_pstate_ut_struct {
const char *name;
@@ -48,16 +56,39 @@ 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 int amd_pstate_ut_check_freq_attrs(u32 index);
static struct amd_pstate_ut_struct amd_pstate_ut_cases[] = {
{"amd_pstate_ut_acpi_cpc_valid", amd_pstate_ut_acpi_cpc_valid },
{"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_check_driver", amd_pstate_ut_check_driver }
{"amd_pstate_ut_acpi_cpc_valid", amd_pstate_ut_acpi_cpc_valid },
{"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 },
{"amd_pstate_ut_check_freq_attrs", amd_pstate_ut_check_freq_attrs },
};
static bool test_in_list(const char *list, const char *name)
{
size_t name_len = strlen(name);
const char *p = list;
while (*p) {
const char *sep = strchr(p, ',');
size_t token_len = sep ? sep - p : strlen(p);
if (token_len == name_len && !strncmp(p, name, token_len))
return true;
if (!sep)
break;
p = sep + 1;
}
return false;
}
static bool get_shared_mem(void)
{
bool result = false;
@@ -241,6 +272,111 @@ 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;
char *buf __free(cleanup_page) = NULL;
static const char * const epp_strings[] = {
"performance",
"balance_performance",
"balance_power",
"power",
};
struct amd_cpudata *cpudata;
enum amd_pstate_mode orig_mode;
bool orig_dynamic_epp;
int ret, cpu = 0;
int i;
u16 epp;
policy = cpufreq_cpu_get(cpu);
if (!policy)
return -ENODEV;
cpudata = policy->driver_data;
orig_mode = amd_pstate_get_status();
orig_dynamic_epp = cpudata->dynamic_epp;
/* 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 = (char *)__get_free_page(GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = amd_pstate_set_mode(AMD_PSTATE_ACTIVE);
if (ret)
goto out;
for (epp = 0; epp <= U8_MAX; epp++) {
u8 val;
/* write all EPP values */
memset(buf, 0, PAGE_SIZE);
snprintf(buf, PAGE_SIZE, "%d", epp);
ret = store_energy_performance_preference(policy, buf, strlen(buf));
if (ret < 0)
goto out;
/* check if the EPP value reads back correctly for raw numbers */
memset(buf, 0, PAGE_SIZE);
ret = show_energy_performance_preference(policy, buf);
if (ret < 0)
goto out;
strreplace(buf, '\n', '\0');
ret = kstrtou8(buf, 0, &val);
if (!ret && epp != val) {
pr_err("Raw EPP value mismatch: %d != %d\n", epp, val);
ret = -EINVAL;
goto out;
}
}
for (i = 0; i < ARRAY_SIZE(epp_strings); i++) {
memset(buf, 0, PAGE_SIZE);
snprintf(buf, PAGE_SIZE, "%s", epp_strings[i]);
ret = store_energy_performance_preference(policy, buf, strlen(buf));
if (ret < 0)
goto out;
memset(buf, 0, PAGE_SIZE);
ret = show_energy_performance_preference(policy, buf);
if (ret < 0)
goto out;
strreplace(buf, '\n', '\0');
if (strcmp(buf, epp_strings[i])) {
pr_err("String EPP value mismatch: %s != %s\n", buf, epp_strings[i]);
ret = -EINVAL;
goto out;
}
}
ret = 0;
out:
if (orig_dynamic_epp) {
int ret2;
ret2 = amd_pstate_set_mode(AMD_PSTATE_DISABLE);
if (!ret && ret2)
ret = ret2;
}
if (orig_mode != amd_pstate_get_status()) {
int ret2;
ret2 = amd_pstate_set_mode(orig_mode);
if (!ret && ret2)
ret = ret2;
}
return ret;
}
static int amd_pstate_ut_check_driver(u32 index)
{
enum amd_pstate_mode mode1, mode2 = AMD_PSTATE_DISABLE;
@@ -270,12 +406,143 @@ out:
return ret;
}
enum attr_category {
ATTR_ALWAYS,
ATTR_PREFCORE,
ATTR_EPP,
ATTR_FLOOR_FREQ,
};
static const struct {
const char *name;
enum attr_category category;
} expected_freq_attrs[] = {
{"amd_pstate_max_freq", ATTR_ALWAYS},
{"amd_pstate_lowest_nonlinear_freq", ATTR_ALWAYS},
{"amd_pstate_highest_perf", ATTR_ALWAYS},
{"amd_pstate_prefcore_ranking", ATTR_PREFCORE},
{"amd_pstate_hw_prefcore", ATTR_PREFCORE},
{"energy_performance_preference", ATTR_EPP},
{"energy_performance_available_preferences", ATTR_EPP},
{"amd_pstate_floor_freq", ATTR_FLOOR_FREQ},
{"amd_pstate_floor_count", ATTR_FLOOR_FREQ},
};
static bool attr_in_driver(struct freq_attr **driver_attrs, const char *name)
{
int j;
for (j = 0; driver_attrs[j]; j++) {
if (!strcmp(driver_attrs[j]->attr.name, name))
return true;
}
return false;
}
/*
* Verify that for each mode the driver's live ->attr array contains exactly
* the attributes that should be visible. Expected visibility is derived
* independently from hw_prefcore, cpu features, and the current mode
* not from the driver's own visibility functions.
*/
static int amd_pstate_ut_check_freq_attrs(u32 index)
{
enum amd_pstate_mode orig_mode = amd_pstate_get_status();
static const enum amd_pstate_mode modes[] = {
AMD_PSTATE_PASSIVE, AMD_PSTATE_ACTIVE, AMD_PSTATE_GUIDED,
};
bool has_prefcore, has_floor_freq;
int m, i, ret;
has_floor_freq = cpu_feature_enabled(X86_FEATURE_CPPC_PERF_PRIO);
/*
* Determine prefcore support from any online CPU's cpudata.
* hw_prefcore reflects the platform-wide decision made at init.
*/
has_prefcore = false;
for_each_online_cpu(i) {
struct cpufreq_policy *policy __free(put_cpufreq_policy) = NULL;
struct amd_cpudata *cpudata;
policy = cpufreq_cpu_get(i);
if (!policy)
continue;
cpudata = policy->driver_data;
has_prefcore = cpudata->hw_prefcore;
break;
}
for (m = 0; m < ARRAY_SIZE(modes); m++) {
struct freq_attr **driver_attrs;
ret = amd_pstate_set_mode(modes[m]);
if (ret)
goto out;
driver_attrs = amd_pstate_get_current_attrs();
if (!driver_attrs) {
pr_err("%s: no driver attrs in mode %s\n",
__func__, amd_pstate_get_mode_string(modes[m]));
ret = -EINVAL;
goto out;
}
for (i = 0; i < ARRAY_SIZE(expected_freq_attrs); i++) {
bool expected, found;
switch (expected_freq_attrs[i].category) {
case ATTR_ALWAYS:
expected = true;
break;
case ATTR_PREFCORE:
expected = has_prefcore;
break;
case ATTR_EPP:
expected = (modes[m] == AMD_PSTATE_ACTIVE);
break;
case ATTR_FLOOR_FREQ:
expected = has_floor_freq;
break;
default:
expected = false;
break;
}
found = attr_in_driver(driver_attrs,
expected_freq_attrs[i].name);
if (expected != found) {
pr_err("%s: mode %s: attr %s expected %s but is %s\n",
__func__,
amd_pstate_get_mode_string(modes[m]),
expected_freq_attrs[i].name,
expected ? "visible" : "hidden",
found ? "visible" : "hidden");
ret = -EINVAL;
goto out;
}
}
}
ret = 0;
out:
amd_pstate_set_mode(orig_mode);
return ret;
}
static int __init amd_pstate_ut_init(void)
{
u32 i = 0, arr_size = ARRAY_SIZE(amd_pstate_ut_cases);
for (i = 0; i < arr_size; i++) {
int ret = amd_pstate_ut_cases[i].func(i);
int ret;
if (test_list && *test_list &&
!test_in_list(test_list, amd_pstate_ut_cases[i].name))
continue;
ret = amd_pstate_ut_cases[i].func(i);
if (ret)
pr_err("%-4d %-20s\t fail: %d!\n", i+1, amd_pstate_ut_cases[i].name, ret);
File diff suppressed because it is too large Load Diff
+36 -1
View File
@@ -9,6 +9,7 @@
#define _LINUX_AMD_PSTATE_H
#include <linux/pm_qos.h>
#include <linux/platform_profile.h>
/*********************************************************************
* AMD P-state INTERFACE *
@@ -62,13 +63,20 @@ struct amd_aperf_mperf {
* @cpu: CPU number
* @req: constraint request to apply
* @cppc_req_cached: cached performance request hints
* @cppc_req2_cached: cached value of MSR_AMD_CPPC_REQ2
* @perf: cached performance-related data
* @prefcore_ranking: the preferred core ranking, the higher value indicates a higher
* priority.
* @floor_perf_cnt: Cached value of the number of distinct floor
* performance levels supported
* @bios_floor_perf: Cached value of the boot-time floor performance level from
* MSR_AMD_CPPC_REQ2
* @min_limit_freq: Cached value of policy->min (in khz)
* @max_limit_freq: Cached value of policy->max (in khz)
* @nominal_freq: the frequency (in khz) that mapped to nominal_perf
* @max_freq: in ideal conditions the maximum frequency (in khz) possible frequency
* @lowest_nonlinear_freq: the frequency (in khz) that mapped to lowest_nonlinear_perf
* @floor_freq: Cached value of the user requested floor_freq
* @cur: Difference of Aperf/Mperf/tsc count between last and current sample
* @prev: Last Aperf/Mperf/tsc count value read from register
* @freq: current cpu frequency value (in khz)
@@ -78,6 +86,11 @@ struct amd_aperf_mperf {
* AMD P-State driver supports preferred core featue.
* @epp_cached: Cached CPPC energy-performance preference value
* @policy: Cpufreq policy value
* @suspended: If CPU core if offlined
* @epp_default_ac: Default EPP value for AC power source
* @epp_default_dc: Default EPP value for DC power source
* @dynamic_epp: Whether dynamic EPP is enabled
* @power_nb: Notifier block for power events
*
* The amd_cpudata is key private data for each CPU thread in AMD P-State, and
* represents all the attributes and goals that AMD P-State requests at runtime.
@@ -87,14 +100,19 @@ struct amd_cpudata {
struct freq_qos_request req[2];
u64 cppc_req_cached;
u64 cppc_req2_cached;
union perf_cached perf;
u8 prefcore_ranking;
u8 floor_perf_cnt;
u8 bios_floor_perf;
u32 min_limit_freq;
u32 max_limit_freq;
u32 nominal_freq;
u32 max_freq;
u32 lowest_nonlinear_freq;
u32 floor_freq;
struct amd_aperf_mperf cur;
struct amd_aperf_mperf prev;
@@ -106,7 +124,16 @@ 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;
bool raw_epp;
struct notifier_block power_nb;
/* platform profile */
enum platform_profile_option current_profile;
struct device *ppdev;
char *profile_name;
};
/*
@@ -123,5 +150,13 @@ enum amd_pstate_mode {
const char *amd_pstate_get_mode_string(enum amd_pstate_mode mode);
int amd_pstate_get_status(void);
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);
struct freq_attr;
struct freq_attr **amd_pstate_get_current_attrs(void);
#endif /* _LINUX_AMD_PSTATE_H */
+2 -8
View File
@@ -834,17 +834,11 @@ static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
{
struct cppc_cpudata *cpu_data = policy->driver_data;
struct cppc_perf_caps *caps = &cpu_data->perf_caps;
int ret;
if (state)
policy->max = cppc_perf_to_khz(caps, caps->highest_perf);
policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, caps->highest_perf);
else
policy->max = cppc_perf_to_khz(caps, caps->nominal_perf);
policy->cpuinfo.max_freq = policy->max;
ret = freq_qos_update_request(policy->max_freq_req, policy->max);
if (ret < 0)
return ret;
policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, caps->nominal_perf);
return 0;
}
+1
View File
@@ -159,6 +159,7 @@ static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "qcom,qcm2290", },
{ .compatible = "qcom,qcm6490", },
{ .compatible = "qcom,qcs404", },
{ .compatible = "qcom,qcs8300", },
{ .compatible = "qcom,qdu1000", },
{ .compatible = "qcom,sa8155p" },
{ .compatible = "qcom,sa8540p" },

Some files were not shown because too many files have changed in this diff Show More