summaryrefslogtreecommitdiff
path: root/SOURCES/AMD_CPPC.patch
diff options
context:
space:
mode:
Diffstat (limited to 'SOURCES/AMD_CPPC.patch')
-rw-r--r--SOURCES/AMD_CPPC.patch2088
1 files changed, 1142 insertions, 946 deletions
diff --git a/SOURCES/AMD_CPPC.patch b/SOURCES/AMD_CPPC.patch
index 97cfa77..fe4c48f 100644
--- a/SOURCES/AMD_CPPC.patch
+++ b/SOURCES/AMD_CPPC.patch
@@ -1,35 +1,32 @@
-From 674082f34ac8bfab164a630a275eac291e1bd7be Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Thu, 28 Jan 2021 10:50:26 +0800
-Subject: x86/cpufreatures: add AMD CPPC extension feature flag
+Add Collaborative Processor Performance Control feature flag for AMD
+processors.
-Add Collaborative Processor Performance Control Extension feature flag
-for AMD processors.
+This feature flag will be used on the following amd-pstate driver. The
+amd-pstate driver has two approaches to implement the frequency control
+behavior. That depends on the CPU hardware implementation. One is "Full
+MSR Support" and another is "Shared Memory Support". The feature flag
+indicates the current processors with "Full MSR Support".
+Acked-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
arch/x86/include/asm/cpufeatures.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
-index d0ce5cfd3ac14..f7aea50e33711 100644
+index d5b5f2ab87a0..18de5f76f198 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
-@@ -313,6 +313,7 @@
+@@ -315,6 +315,7 @@
#define X86_FEATURE_AMD_SSBD (13*32+24) /* "" Speculative Store Bypass Disable */
#define X86_FEATURE_VIRT_SSBD (13*32+25) /* Virtualized Speculative Store Bypass Disable */
#define X86_FEATURE_AMD_SSB_NO (13*32+26) /* "" Speculative Store Bypass is fixed in hardware. */
-+#define X86_FEATURE_AMD_CPPC_EXT (13*32+27) /* Collaborative Processor Performance Control Extension */
-
++#define X86_FEATURE_CPPC (13*32+27) /* Collaborative Processor Performance Control */
+
/* Thermal and Power Management Leaf, CPUID level 0x00000006 (EAX), word 14 */
#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */
---
-cgit 1.2.3-1.el7
-From 8180f01cf18d8ba79dac94a817294e85a8d84dc4 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Mon, 25 Jan 2021 15:50:24 +0800
-Subject: x86/msr: add AMD CPPC MSR definitions
+
AMD CPPC (Collaborative Processor Performance Control) function uses MSR
registers to manage the performance hints. So add the MSR register macro
@@ -41,13 +38,13 @@ Signed-off-by: Huang Rui <ray.huang@amd.com>
1 file changed, 17 insertions(+)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
-index a7c413432b33d..ce42e15cf3034 100644
+index 01e2650b9585..e7945ef6a8df 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -486,6 +486,23 @@
-
+
#define MSR_AMD64_VIRT_SPEC_CTRL 0xc001011f
-
+
+/* AMD Collaborative Processor Performance Control MSRs */
+#define MSR_AMD_CPPC_CAP1 0xc00102b0
+#define MSR_AMD_CPPC_ENABLE 0xc00102b1
@@ -67,50 +64,186 @@ index a7c413432b33d..ce42e15cf3034 100644
+
/* Fam 17h MSRs */
#define MSR_F17H_IRPERF 0xc00000e9
+
+
+
+
+From: Steven Noonan <steven@valvesoftware.com>
+
+According to the ACPI v6.2 (and later) specification, SystemIO can be
+used for _CPC registers. This teaches cppc_acpi how to handle such
+registers.
+
+This patch was tested using the amd_pstate driver on my Zephyrus G15
+(model GA503QS) using the current version 410 BIOS, which uses
+a SystemIO register for the HighestPerformance element in _CPC.
+
+Signed-off-by: Steven Noonan <steven@valvesoftware.com>
+Signed-off-by: Huang Rui <ray.huang@amd.com>
+---
+ drivers/acpi/cppc_acpi.c | 46 +++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 43 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
+index a85c351589be..ca62c3dc9899 100644
+--- a/drivers/acpi/cppc_acpi.c
++++ b/drivers/acpi/cppc_acpi.c
+@@ -746,9 +746,24 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
+ goto out_free;
+ cpc_ptr->cpc_regs[i-2].sys_mem_vaddr = addr;
+ }
++ } else if (gas_t->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
++ if (gas_t->access_width < 1 || gas_t->access_width > 3) {
++ /* 1 = 8-bit, 2 = 16-bit, and 3 = 32-bit. SystemIO doesn't
++ * implement 64-bit registers.
++ */
++ pr_debug("Invalid access width %d for SystemIO register\n",
++ gas_t->access_width);
++ goto out_free;
++ }
++ if (gas_t->address & ~0xFFFFULL) {
++ /* SystemIO registers use 16-bit integer addresses */
++ pr_debug("Invalid IO port %llu for SystemIO register\n",
++ gas_t->address);
++ goto out_free;
++ }
+ } else {
+ if (gas_t->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE || !cpc_ffh_supported()) {
+- /* Support only PCC ,SYS MEM and FFH type regs */
++ /* Support only PCC, SystemMemory, SystemIO, and FFH type regs. */
+ pr_debug("Unsupported register type: %d\n", gas_t->space_id);
+ goto out_free;
+ }
+@@ -923,7 +938,20 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
+ }
+
+ *val = 0;
+- if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
++
++ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
++ u32 width = 8 << (reg->access_width - 1);
++ acpi_status status;
++
++ status = acpi_os_read_port((acpi_io_address)reg->address, (u32 *)val, width);
++
++ if (status != AE_OK) {
++ pr_debug("Error: Failed to read SystemIO port %llx\n", reg->address);
++ return -EFAULT;
++ }
++
++ return 0;
++ } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
+ vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
+ else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ vaddr = reg_res->sys_mem_vaddr;
+@@ -962,7 +990,19 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
+ int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
+ struct cpc_reg *reg = &reg_res->cpc_entry.reg;
+
+- if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
++ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
++ u32 width = 8 << (reg->access_width - 1);
++ acpi_status status;
++
++ status = acpi_os_write_port((acpi_io_address)reg->address, (u32)val, width);
++
++ if (status != AE_OK) {
++ pr_debug("Error: Failed to write SystemIO port %llx\n", reg->address);
++ return -EFAULT;
++ }
++
++ return 0;
++ } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
+ vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
+ else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ vaddr = reg_res->sys_mem_vaddr;
+
+
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+As this is a static check, it should be based upon what is currently
+present on the system. This makes probeing more deterministic.
+
+While local APIC flags field (lapic_flags) of cpu core in MADT table is
+0, then the cpu core won't be enabled. In this case, _CPC won't be found
+in this core, and return back to _CPC invalid with walking through
+possible cpus (include disable cpus). This is not expected, so switch to
+check present CPUs instead.
+
+Reported-by: Jinzhou Su <Jinzhou.Su@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Huang Rui <ray.huang@amd.com>
+---
+ drivers/acpi/cppc_acpi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
+index ca62c3dc9899..a46f227dc254 100644
+--- a/drivers/acpi/cppc_acpi.c
++++ b/drivers/acpi/cppc_acpi.c
+@@ -411,7 +411,7 @@ bool acpi_cpc_valid(void)
+ struct cpc_desc *cpc_ptr;
+ int cpu;
+
+- for_each_possible_cpu(cpu) {
++ for_each_present_cpu(cpu) {
+ cpc_ptr = per_cpu(cpc_desc_ptr, cpu);
+ if (!cpc_ptr)
+ return false;
+
---
-cgit 1.2.3-1.el7
-From 8dc33d1590f80a60f12325e7c646a8551a41adf1 Mon Sep 17 00:00:00 2001
From: Jinzhou Su <Jinzhou.Su@amd.com>
-Date: Mon, 9 Aug 2021 19:04:17 +0800
-Subject: ACPI: CPPC: add cppc enable register function
-Export the cppc enable register function for future use.
+Add a new function to enable CPPC feature. This function
+will write Continuous Performance Control package
+EnableRegister field on the processor.
+
+CPPC EnableRegister register described in section 8.4.7.1 of ACPI 6.4:
+This element is optional. If supported, contains a resource descriptor
+with a single Register() descriptor that describes a register to which
+OSPM writes a One to enable CPPC on this processor. Before this register
+is set, the processor will be controlled by legacy mechanisms (ACPI
+Pstates, firmware, etc.).
+
+This register will be used for AMD processors to enable amd-pstate
+function instead of legacy ACPI P-States.
Signed-off-by: Jinzhou Su <Jinzhou.Su@amd.com>
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- drivers/acpi/cppc_acpi.c | 42 ++++++++++++++++++++++++++++++++++++++++++
+ drivers/acpi/cppc_acpi.c | 45 ++++++++++++++++++++++++++++++++++++++++
include/acpi/cppc_acpi.h | 5 +++++
- 2 files changed, 47 insertions(+)
+ 2 files changed, 50 insertions(+)
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
-index a4d4eebba1da4..de4b30545215f 100644
+index a46f227dc254..003df9fba122 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
-@@ -1220,6 +1220,48 @@ out_err:
+@@ -1262,6 +1262,51 @@ int cppc_get_perf_ctrs(int cpunum, struct cppc_perf_fb_ctrs *perf_fb_ctrs)
}
EXPORT_SYMBOL_GPL(cppc_get_perf_ctrs);
-
+
+/**
-+ * cppc_set_enable - Set to enable CPPC register.
++ * cppc_set_enable - Set to enable CPPC on the processor by writing the
++ * Continuous Performance Control package EnableRegister field.
+ * @cpu: CPU for which to enable CPPC register.
-+ * @enable: enable field to write into share memory.
++ * @enable: 0 - disable, 1 - enable CPPC feature on the processor.
+ *
-+ * Return: 0 for success, -ERRNO otherwise.
++ * Return: 0 for success, -ERRNO or -EIO otherwise.
+ */
-+int cppc_set_enable(int cpu, u32 enable)
++int cppc_set_enable(int cpu, bool enable)
+{
+ int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
+ struct cpc_register_resource *enable_reg;
+ struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
+ struct cppc_pcc_data *pcc_ss_data = NULL;
-+ int ret = -1;
++ int ret = -EINVAL;
+
+ if (!cpc_desc) {
+ pr_debug("No CPC descriptor for CPU:%d\n", cpu);
-+ return -ENODEV;
++ return -EINVAL;
+ }
+
+ enable_reg = &cpc_desc->cpc_regs[ENABLE];
@@ -127,11 +260,13 @@ index a4d4eebba1da4..de4b30545215f 100644
+ pcc_ss_data = pcc_data[pcc_ss_id];
+
+ down_write(&pcc_ss_data->pcc_lock);
-+ send_pcc_cmd(pcc_ss_id, CMD_WRITE);
++ /* after writing CPC, transfer the ownership of PCC to platfrom */
++ ret = send_pcc_cmd(pcc_ss_id, CMD_WRITE);
+ up_write(&pcc_ss_data->pcc_lock);
++ return ret;
+ }
+
-+ return ret;
++ return cpc_write(cpu, enable_reg, enable);
+}
+EXPORT_SYMBOL_GPL(cppc_set_enable);
+
@@ -139,36 +274,30 @@ index a4d4eebba1da4..de4b30545215f 100644
* cppc_set_perf - Set a CPU's performance controls.
* @cpu: CPU for which to set performance controls.
diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h
-index 9f4985b4d64de..3fdae40a75fcd 100644
+index bc159a9b4a73..92b7ea8d8f5e 100644
--- a/include/acpi/cppc_acpi.h
+++ b/include/acpi/cppc_acpi.h
-@@ -137,6 +137,7 @@ struct cppc_cpudata {
- extern int cppc_get_desired_perf(int cpunum, u64 *desired_perf);
+@@ -138,6 +138,7 @@ extern int cppc_get_desired_perf(int cpunum, u64 *desired_perf);
+ extern int cppc_get_nominal_perf(int cpunum, u64 *nominal_perf);
extern int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs);
extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls);
-+extern int cppc_set_enable(int cpu, u32 enable);
++extern int cppc_set_enable(int cpu, bool enable);
extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps);
extern bool acpi_cpc_valid(void);
extern int acpi_get_psd_map(unsigned int cpu, struct cppc_cpudata *cpu_data);
-@@ -157,6 +158,10 @@ static inline int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
+@@ -162,6 +163,10 @@ static inline int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
{
return -ENOTSUPP;
}
-+static inline int cppc_set_enable(int cpu, u32 enable)
++static inline int cppc_set_enable(int cpu, bool enable)
+{
+ return -ENOTSUPP;
+}
static inline int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps)
{
return -ENOTSUPP;
---
-cgit 1.2.3-1.el7
-From df9ad0b99a9f0e3371aa94e49fe92a2c2a9fa95d Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Thu, 10 Jun 2021 18:04:45 +0800
-Subject: cpufreq: amd: introduce a new amd pstate driver to support future
- processors
+
amd-pstate is the AMD CPU performance scaling driver that introduces a
new CPU frequency control mechanism on AMD Zen based CPU series in Linux
@@ -188,17 +317,17 @@ the hardware and SBIOS functionalities.
There are two types of hardware implementations for amd-pstate: one is full
MSR support and another is shared memory support. It can use
-X86_FEATURE_AMD_CPPC_EXT feature flag to distinguish the different types.
+X86_FEATURE_CPPC feature flag to distinguish the different types.
Using the new AMD P-States method + kernel governors (*schedutil*,
*ondemand*, ...) to manage the frequency update is the most appropriate
bridge between AMD Zen based hardware processor and Linux kernel, the
-processor is able to ajust to the most efficiency frequency according to
+processor is able to adjust to the most efficiency frequency according to
the kernel scheduler loading.
-Performance Per Watt (PPW) Caculation:
+Performance Per Watt (PPW) Calculation:
-The PPW caculation is referred by below paper:
+The PPW calculation is referred by below paper:
https://software.intel.com/content/dam/develop/external/us/en/documents/performance-per-what-paper.pdf
Below formula is referred from below spec to measure the PPW:
@@ -206,13 +335,13 @@ Below formula is referred from below spec to measure the PPW:
(F / t) / P = F * t / (t * E) = F / E,
"F" is the number of frames per second.
-"P" is power measurd in watts.
+"P" is power measured in watts.
"E" is energy measured in joules.
We use the RAPL interface with "perf" tool to get the energy data of the
package power.
-The data comparsions between amd-pstate and acpi-freq module are tested on
+The data comparisons between amd-pstate and acpi-freq module are tested on
AMD Cezanne processor:
1) TBench CPU benchmark:
@@ -280,30 +409,34 @@ performance per watt scaling on mobile CPU benchmarks in most of cases.
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- drivers/cpufreq/Kconfig.x86 | 13 ++
+ drivers/cpufreq/Kconfig.x86 | 17 ++
drivers/cpufreq/Makefile | 1 +
- drivers/cpufreq/amd-pstate.c | 478 +++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 492 insertions(+)
+ drivers/cpufreq/amd-pstate.c | 398 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 416 insertions(+)
create mode 100644 drivers/cpufreq/amd-pstate.c
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
-index 92701a18bdd91..9cd7e338bdcdf 100644
+index 92701a18bdd9..21837eb1698b 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
-@@ -34,6 +34,19 @@ config X86_PCC_CPUFREQ
-
+@@ -34,6 +34,23 @@ config X86_PCC_CPUFREQ
+
If in doubt, say N.
-
+
+config X86_AMD_PSTATE
+ tristate "AMD Processor P-State driver"
+ depends on X86
+ select ACPI_PROCESSOR if ACPI
-+ select ACPI_CPPC_LIB if X86_64 && ACPI && SCHED_MC_PRIO
++ select ACPI_CPPC_LIB if X86_64 && ACPI
+ select CPU_FREQ_GOV_SCHEDUTIL if SMP
+ help
+ This driver adds a CPUFreq driver which utilizes a fine grain
-+ processor performance freqency control range instead of legacy
-+ performance levels. This driver also supports newer AMD CPUs.
++ processor performance frequency control range instead of legacy
++ performance levels. This driver supports the AMD processors with
++ _CPC object in the SBIOS.
++
++ For details, take a look at:
++ <file:Documentation/admin-guide/pm/amd-pstate.rst>.
+
+ If in doubt, say N.
+
@@ -311,43 +444,29 @@ index 92701a18bdd91..9cd7e338bdcdf 100644
tristate "ACPI Processor P-States driver"
depends on ACPI_PROCESSOR
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
-index 27d3bd7ea9d4e..3d4bd7141cf85 100644
+index 48ee5859030c..c8d307010922 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
-@@ -24,6 +24,7 @@ obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o
- # powernow-k8 can load then. ACPI is preferred to all other hardware-specific drivers.
+@@ -25,6 +25,7 @@ obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o
# speedstep-* is preferred over p4-clockmod.
-
-+obj-$(CONFIG_X86_AMD_PSTATE) += amd-pstate.o
+
obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
++obj-$(CONFIG_X86_AMD_PSTATE) += amd-pstate.o
obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o
+ obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
new file mode 100644
-index 0000000000000..4c9c9bf1d72bb
+index 000000000000..8b501a72c3dd
--- /dev/null
+++ b/drivers/cpufreq/amd-pstate.c
-@@ -0,0 +1,478 @@
+@@ -0,0 +1,398 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * amd-pstate.c - AMD Processor P-state Frequency Driver
+ *
+ * Copyright (C) 2021 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2
-+ * of the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+ *
+ * Author: Huang Rui <ray.huang@amd.com>
+ */
+
@@ -366,6 +485,7 @@ index 0000000000000..4c9c9bf1d72bb
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
++#include <linux/static_call.h>
+
+#include <acpi/processor.h>
+#include <acpi/cppc_acpi.h>
@@ -384,7 +504,6 @@ index 0000000000000..4c9c9bf1d72bb
+ int cpu;
+
+ struct freq_qos_request req[2];
-+ struct cpufreq_policy *policy;
+
+ u64 cppc_req_cached;
+
@@ -399,26 +518,16 @@ index 0000000000000..4c9c9bf1d72bb
+ u32 lowest_nonlinear_freq;
+};
+
-+struct amd_pstate_perf_funcs {
-+ int (*enable)(bool enable);
-+ int (*init_perf)(struct amd_cpudata *cpudata);
-+ void (*update_perf)(struct amd_cpudata *cpudata,
-+ u32 min_perf, u32 des_perf,
-+ u32 max_perf, bool fast_switch);
-+};
-+
+static inline int pstate_enable(bool enable)
+{
+ return wrmsrl_safe(MSR_AMD_CPPC_ENABLE, enable ? 1 : 0);
+}
+
-+static int
-+amd_pstate_enable(struct amd_pstate_perf_funcs *funcs, bool enable)
-+{
-+ if (!funcs)
-+ return -EINVAL;
++DEFINE_STATIC_CALL(amd_pstate_enable, pstate_enable);
+
-+ return funcs->enable(enable);
++static inline int amd_pstate_enable(bool enable)
++{
++ return static_call(amd_pstate_enable)(enable);
+}
+
+static int pstate_init_perf(struct amd_cpudata *cpudata)
@@ -430,9 +539,10 @@ index 0000000000000..4c9c9bf1d72bb
+ if (ret)
+ return ret;
+
-+ /* Some AMD processors has specific power features that the cppc entry
-+ * doesn't indicate the highest performance. It will introduce the
-+ * feature in following days.
++ /*
++ * TODO: Introduce AMD specific power feature.
++ *
++ * CPPC entry doesn't indicate the highest performance in some ASICs.
+ */
+ WRITE_ONCE(cpudata->highest_perf, amd_get_highest_perf());
+
@@ -443,19 +553,15 @@ index 0000000000000..4c9c9bf1d72bb
+ return 0;
+}
+
-+static int amd_pstate_init_perf(struct amd_cpudata *cpudata)
-+{
-+ struct amd_pstate_perf_funcs *funcs = cpufreq_get_driver_data();
-+
-+ if (!funcs)
-+ return -EINVAL;
++DEFINE_STATIC_CALL(amd_pstate_init_perf, pstate_init_perf);
+
-+ return funcs->init_perf(cpudata);
++static inline int amd_pstate_init_perf(struct amd_cpudata *cpudata)
++{
++ return static_call(amd_pstate_init_perf)(cpudata);
+}
+
-+static void pstate_update_perf(struct amd_cpudata *cpudata,
-+ u32 min_perf, u32 des_perf, u32 max_perf,
-+ bool fast_switch)
++static void pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
++ u32 des_perf, u32 max_perf, bool fast_switch)
+{
+ if (fast_switch)
+ wrmsrl(MSR_AMD_CPPC_REQ, READ_ONCE(cpudata->cppc_req_cached));
@@ -464,24 +570,18 @@ index 0000000000000..4c9c9bf1d72bb
+ READ_ONCE(cpudata->cppc_req_cached));
+}
+
-+static int
-+amd_pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
-+ u32 des_perf, u32 max_perf, bool fast_switch)
-+{
-+ struct amd_pstate_perf_funcs *funcs = cpufreq_get_driver_data();
-+
-+ if (!funcs)
-+ return -EINVAL;
++DEFINE_STATIC_CALL(amd_pstate_update_perf, pstate_update_perf);
+
-+ funcs->update_perf(cpudata, min_perf, des_perf,
-+ max_perf, fast_switch);
-+
-+ return 0;
++static inline void amd_pstate_update_perf(struct amd_cpudata *cpudata,
++ u32 min_perf, u32 des_perf,
++ u32 max_perf, bool fast_switch)
++{
++ static_call(amd_pstate_update_perf)(cpudata, min_perf, des_perf,
++ max_perf, fast_switch);
+}
+
-+static int
-+amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
-+ u32 des_perf, u32 max_perf, bool fast_switch)
++static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
++ u32 des_perf, u32 max_perf, bool fast_switch)
+{
+ u64 prev = READ_ONCE(cpudata->cppc_req_cached);
+ u64 value = prev;
@@ -496,12 +596,12 @@ index 0000000000000..4c9c9bf1d72bb
+ value |= REQ_MAX_PERF(max_perf);
+
+ if (value == prev)
-+ return 0;
++ return;
+
+ WRITE_ONCE(cpudata->cppc_req_cached, value);
+
-+ return amd_pstate_update_perf(cpudata, min_perf, des_perf,
-+ max_perf, fast_switch);
++ amd_pstate_update_perf(cpudata, min_perf, des_perf,
++ max_perf, fast_switch);
+}
+
+static int amd_pstate_verify(struct cpufreq_policy_data *policy)
@@ -515,31 +615,29 @@ index 0000000000000..4c9c9bf1d72bb
+ unsigned int target_freq,
+ unsigned int relation)
+{
-+ int ret;
+ struct cpufreq_freqs freqs;
+ struct amd_cpudata *cpudata = policy->driver_data;
-+ unsigned long amd_max_perf, amd_min_perf, amd_des_perf,
-+ amd_cap_perf;
++ unsigned long max_perf, min_perf, des_perf, cap_perf;
+
+ if (!cpudata->max_freq)
+ return -ENODEV;
+
-+ amd_cap_perf = READ_ONCE(cpudata->highest_perf);
-+ amd_min_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
-+ amd_max_perf = amd_cap_perf;
++ cap_perf = READ_ONCE(cpudata->highest_perf);
++ min_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
++ max_perf = cap_perf;
+
+ freqs.old = policy->cur;
+ freqs.new = target_freq;
+
-+ amd_des_perf = DIV_ROUND_CLOSEST(target_freq * amd_cap_perf,
-+ cpudata->max_freq);
++ des_perf = DIV_ROUND_CLOSEST(target_freq * cap_perf,
++ cpudata->max_freq);
+
+ cpufreq_freq_transition_begin(policy, &freqs);
-+ ret = amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
-+ amd_max_perf, false);
++ amd_pstate_update(cpudata, min_perf, des_perf,
++ max_perf, false);
+ cpufreq_freq_transition_end(policy, &freqs, false);
+
-+ return ret;
++ return 0;
+}
+
+static int amd_get_min_freq(struct amd_cpudata *cpudata)
@@ -580,16 +678,13 @@ index 0000000000000..4c9c9bf1d72bb
+static int amd_get_nominal_freq(struct amd_cpudata *cpudata)
+{
+ struct cppc_perf_caps cppc_perf;
-+ u32 nominal_freq;
+
+ int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
+ if (ret)
+ return ret;
+
-+ nominal_freq = cppc_perf.nominal_freq;
-+
+ /* Switch to khz */
-+ return nominal_freq * 1000;
++ return cppc_perf.nominal_freq * 1000;
+}
+
+static int amd_get_lowest_nonlinear_freq(struct amd_cpudata *cpudata)
@@ -608,8 +703,8 @@ index 0000000000000..4c9c9bf1d72bb
+
+ lowest_nonlinear_perf = cppc_perf.lowest_nonlinear_perf;
+
-+ lowest_nonlinear_ratio = div_u64(lowest_nonlinear_perf <<
-+ SCHED_CAPACITY_SHIFT, nominal_perf);
++ lowest_nonlinear_ratio = div_u64(lowest_nonlinear_perf << SCHED_CAPACITY_SHIFT,
++ nominal_perf);
+
+ lowest_nonlinear_freq = nominal_freq * lowest_nonlinear_ratio >> SCHED_CAPACITY_SHIFT;
+
@@ -617,33 +712,9 @@ index 0000000000000..4c9c9bf1d72bb
+ return lowest_nonlinear_freq * 1000;
+}
+
-+static int amd_pstate_init_freqs_in_cpudata(struct amd_cpudata *cpudata,
-+ u32 max_freq, u32 min_freq,
-+ u32 nominal_freq,
-+ u32 lowest_nonlinear_freq)
-+{
-+ if (!cpudata)
-+ return -EINVAL;
-+
-+ /* Initial processor data capability frequencies */
-+ cpudata->max_freq = max_freq;
-+ cpudata->min_freq = min_freq;
-+ cpudata->nominal_freq = nominal_freq;
-+ cpudata->lowest_nonlinear_freq = lowest_nonlinear_freq;
-+
-+ return 0;
-+}
-+
-+static struct amd_pstate_perf_funcs pstate_funcs = {
-+ .enable = pstate_enable,
-+ .init_perf = pstate_init_perf,
-+ .update_perf = pstate_update_perf,
-+};
-+
+static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
+{
+ int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
-+ unsigned int cpu = policy->cpu;
+ struct device *dev;
+ struct amd_cpudata *cpudata;
+
@@ -655,8 +726,7 @@ index 0000000000000..4c9c9bf1d72bb
+ if (!cpudata)
+ return -ENOMEM;
+
-+ cpudata->cpu = cpu;
-+ cpudata->policy = policy;
++ cpudata->cpu = policy->cpu;
+
+ ret = amd_pstate_init_perf(cpudata);
+ if (ret)
@@ -700,20 +770,16 @@ index 0000000000000..4c9c9bf1d72bb
+ goto free_cpudata2;
+ }
+
-+ ret = amd_pstate_init_freqs_in_cpudata(cpudata, max_freq, min_freq,
-+ nominal_freq,
-+ lowest_nonlinear_freq);
-+ if (ret) {
-+ dev_err(dev, "Failed to init cpudata (%d)\n", ret);
-+ goto free_cpudata3;
-+ }
++ /* Initial processor data capability frequencies */
++ cpudata->max_freq = max_freq;
++ cpudata->min_freq = min_freq;
++ cpudata->nominal_freq = nominal_freq;
++ cpudata->lowest_nonlinear_freq = lowest_nonlinear_freq;
+
+ policy->driver_data = cpudata;
+
+ return 0;
+
-+free_cpudata3:
-+ freq_qos_remove_request(&cpudata->req[1]);
+free_cpudata2:
+ freq_qos_remove_request(&cpudata->req[0]);
+free_cpudata1:
@@ -746,14 +812,12 @@ index 0000000000000..4c9c9bf1d72bb
+static int __init amd_pstate_init(void)
+{
+ int ret;
-+ struct amd_pstate_perf_funcs *funcs;
+
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+ return -ENODEV;
+
+ if (!acpi_cpc_valid()) {
-+ pr_debug("%s, the _CPC object is not present in SBIOS\n",
-+ __func__);
++ pr_debug("the _CPC object is not present in SBIOS\n");
+ return -ENODEV;
+ }
+
@@ -762,42 +826,31 @@ index 0000000000000..4c9c9bf1d72bb
+ return -EEXIST;
+
+ /* capability check */
-+ if (!boot_cpu_has(X86_FEATURE_AMD_CPPC_EXT)) {
-+ pr_debug("%s, AMD CPPC extension functionality is supported\n",
-+ __func__);
++ if (!boot_cpu_has(X86_FEATURE_CPPC)) {
++ pr_debug("AMD CPPC MSR based functionality is not supported\n");
+ return -ENODEV;
+ }
+
-+ funcs = &pstate_funcs;
-+
+ /* enable amd pstate feature */
-+ ret = amd_pstate_enable(funcs, true);
++ ret = amd_pstate_enable(true);
+ if (ret) {
-+ pr_err("%s, failed to enable amd-pstate with return %d\n",
-+ __func__, ret);
++ pr_err("failed to enable amd-pstate with return %d\n", ret);
+ return ret;
+ }
+
-+ amd_pstate_driver.driver_data = funcs;
-+
+ ret = cpufreq_register_driver(&amd_pstate_driver);
-+ if (ret) {
-+ pr_err("%s, return %d\n", __func__, ret);
-+ return ret;
-+ }
++ if (ret)
++ pr_err("failed to register amd_pstate_driver with return %d\n",
++ ret);
+
-+ return 0;
++ return ret;
+}
+
+static void __exit amd_pstate_exit(void)
+{
-+ struct amd_pstate_perf_funcs *funcs;
-+
-+ funcs = cpufreq_get_driver_data();
-+
+ cpufreq_unregister_driver(&amd_pstate_driver);
+
-+ amd_pstate_enable(funcs, false);
++ amd_pstate_enable(false);
+}
+
+module_init(amd_pstate_init);
@@ -806,138 +859,124 @@ index 0000000000000..4c9c9bf1d72bb
+MODULE_AUTHOR("Huang Rui <ray.huang@amd.com>");
+MODULE_DESCRIPTION("AMD Processor P-state Frequency Driver");
+MODULE_LICENSE("GPL");
---
-cgit 1.2.3-1.el7
-From 54beca4738acc38c08710cfcb1c3312755000cf6 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Fri, 13 Aug 2021 18:43:47 +0800
-Subject: cpufreq: amd: add fast switch function for amd-pstate module
-Introduce the fast switch function for amd-pstate module on the AMD
-processors which support the full MSR register control. It's able to
-decrease the lattency on interrupt context.
+
+Introduce the fast switch function for amd-pstate on the AMD processors
+which support the full MSR register control. It's able to decrease the
+latency on interrupt context.
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- drivers/cpufreq/amd-pstate.c | 64 ++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 64 insertions(+)
+ drivers/cpufreq/amd-pstate.c | 35 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 35 insertions(+)
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index 4c9c9bf1d72bb..32b4f6d797830 100644
+index 8b501a72c3dd..4a02a42f4113 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
-@@ -212,6 +212,66 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
- return ret;
+@@ -177,6 +177,38 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
+ return 0;
}
-
+
+static void amd_pstate_adjust_perf(unsigned int cpu,
-+ unsigned long min_perf,
++ unsigned long _min_perf,
+ unsigned long target_perf,
+ unsigned long capacity)
+{
-+ unsigned long amd_max_perf, amd_min_perf, amd_des_perf,
-+ amd_cap_perf, lowest_nonlinear_perf;
++ unsigned long max_perf, min_perf, des_perf,
++ cap_perf, lowest_nonlinear_perf;
+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+ struct amd_cpudata *cpudata = policy->driver_data;
+
-+ amd_cap_perf = READ_ONCE(cpudata->highest_perf);
++ cap_perf = READ_ONCE(cpudata->highest_perf);
+ lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
+
+ if (target_perf < capacity)
-+ amd_des_perf = DIV_ROUND_UP(amd_cap_perf * target_perf,
-+ capacity);
-+
-+ amd_min_perf = READ_ONCE(cpudata->highest_perf);
-+ if (min_perf < capacity)
-+ amd_min_perf = DIV_ROUND_UP(amd_cap_perf * min_perf, capacity);
++ des_perf = DIV_ROUND_UP(cap_perf * target_perf, capacity);
+
-+ if (amd_min_perf < lowest_nonlinear_perf)
-+ amd_min_perf = lowest_nonlinear_perf;
++ min_perf = READ_ONCE(cpudata->highest_perf);
++ if (_min_perf < capacity)
++ min_perf = DIV_ROUND_UP(cap_perf * _min_perf, capacity);
+
-+ amd_max_perf = amd_cap_perf;
-+ if (amd_max_perf < amd_min_perf)
-+ amd_max_perf = amd_min_perf;
++ if (min_perf < lowest_nonlinear_perf)
++ min_perf = lowest_nonlinear_perf;
+
-+ amd_des_perf = clamp_t(unsigned long, amd_des_perf,
-+ amd_min_perf, amd_max_perf);
++ max_perf = cap_perf;
++ if (max_perf < min_perf)
++ max_perf = min_perf;
+
-+ amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
-+ amd_max_perf, true);
-+}
-+
-+static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
-+ unsigned int target_freq)
-+{
-+ u64 ratio;
-+ struct amd_cpudata *cpudata = policy->driver_data;
-+ unsigned long amd_max_perf, amd_min_perf, amd_des_perf, nominal_perf;
-+
-+ if (!cpudata->max_freq)
-+ return -ENODEV;
-+
-+ amd_max_perf = READ_ONCE(cpudata->highest_perf);
-+ amd_min_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
++ des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
+
-+ amd_des_perf = DIV_ROUND_UP(target_freq * amd_max_perf,
-+ cpudata->max_freq);
-+
-+ amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
-+ amd_max_perf, true);
-+
-+ nominal_perf = READ_ONCE(cpudata->nominal_perf);
-+ ratio = div_u64(amd_des_perf << SCHED_CAPACITY_SHIFT, nominal_perf);
-+
-+ return cpudata->nominal_freq * ratio >> SCHED_CAPACITY_SHIFT;
++ amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true);
+}
+
static int amd_get_min_freq(struct amd_cpudata *cpudata)
{
struct cppc_perf_caps cppc_perf;
-@@ -356,6 +416,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
+@@ -293,6 +325,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
/* It will be updated by governor */
policy->cur = policy->cpuinfo.min_freq;
-
+
+ policy->fast_switch_possible = true;
+
ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0],
FREQ_QOS_MIN, policy->cpuinfo.min_freq);
if (ret < 0) {
-@@ -408,6 +470,8 @@ static struct cpufreq_driver amd_pstate_driver = {
+@@ -341,6 +375,7 @@ static struct cpufreq_driver amd_pstate_driver = {
.flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
.verify = amd_pstate_verify,
.target = amd_pstate_target,
-+ .fast_switch = amd_pstate_fast_switch,
+ .adjust_perf = amd_pstate_adjust_perf,
.init = amd_pstate_cpu_init,
.exit = amd_pstate_cpu_exit,
.name = "amd-pstate",
---
-cgit 1.2.3-1.el7
-From ad7cc7a238ee889b9001d95fef83172763b95939 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Mon, 9 Aug 2021 19:06:51 +0800
-Subject: cpufreq: amd: add acpi cppc function as the backend for legacy
- processors
-In some old Zen based processors, they are using the shared memory that
-exposed from ACPI SBIOS.
+
+In some of Zen2 and Zen3 based processors, they are using the shared
+memory that exposed from ACPI SBIOS. In this kind of the processors,
+there is no MSR support, so we add acpi cppc function as the backend for
+them.
+
+It is using a module param (shared_mem) to enable related processors
+manually. We will enable this by default once we address performance
+issue on this solution.
Signed-off-by: Jinzhou Su <Jinzhou.Su@amd.com>
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- drivers/cpufreq/amd-pstate.c | 63 +++++++++++++++++++++++++++++++++++++++-----
- 1 file changed, 57 insertions(+), 6 deletions(-)
+ drivers/cpufreq/amd-pstate.c | 71 ++++++++++++++++++++++++++++++++++--
+ 1 file changed, 67 insertions(+), 4 deletions(-)
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index 32b4f6d797830..a46cd5dd9f7cc 100644
+index 4a02a42f4113..14a29326ceae 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
-@@ -82,6 +82,19 @@ static inline int pstate_enable(bool enable)
+@@ -35,6 +35,19 @@
+ #define AMD_PSTATE_TRANSITION_LATENCY 0x20000
+ #define AMD_PSTATE_TRANSITION_DELAY 500
+
++/* TODO: We need more time to fine tune processors with shared memory solution
++ * with community together.
++ *
++ * There are some performance drops on the CPU benchmarks which reports from
++ * Suse. We are co-working with them to fine tune the shared memory solution. So
++ * we disable it by default to go acpi-cpufreq on these processors and add a
++ * module parameter to be able to enable it manually for debugging.
++ */
++static bool shared_mem = false;
++module_param(shared_mem, bool, 0444);
++MODULE_PARM_DESC(shared_mem,
++ "enable amd-pstate on processors with shared memory solution (false = disabled (default), true = enabled)");
++
+ static struct cpufreq_driver amd_pstate_driver;
+
+ struct amd_cpudata {
+@@ -60,6 +73,19 @@ static inline int pstate_enable(bool enable)
return wrmsrl_safe(MSR_AMD_CPPC_ENABLE, enable ? 1 : 0);
}
-
+
+static int cppc_enable(bool enable)
+{
+ int cpu, ret = 0;
@@ -951,13 +990,13 @@ index 32b4f6d797830..a46cd5dd9f7cc 100644
+ return ret;
+}
+
- static int
- amd_pstate_enable(struct amd_pstate_perf_funcs *funcs, bool enable)
- {
-@@ -113,6 +126,24 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
+ DEFINE_STATIC_CALL(amd_pstate_enable, pstate_enable);
+
+ static inline int amd_pstate_enable(bool enable)
+@@ -90,6 +116,24 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
return 0;
}
-
+
+static int cppc_init_perf(struct amd_cpudata *cpudata)
+{
+ struct cppc_perf_caps cppc_perf;
@@ -976,13 +1015,13 @@ index 32b4f6d797830..a46cd5dd9f7cc 100644
+ return 0;
+}
+
- static int amd_pstate_init_perf(struct amd_cpudata *cpudata)
- {
- struct amd_pstate_perf_funcs *funcs = cpufreq_get_driver_data();
-@@ -134,6 +165,19 @@ static void pstate_update_perf(struct amd_cpudata *cpudata,
+ DEFINE_STATIC_CALL(amd_pstate_init_perf, pstate_init_perf);
+
+ static inline int amd_pstate_init_perf(struct amd_cpudata *cpudata)
+@@ -107,6 +151,19 @@ static void pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
READ_ONCE(cpudata->cppc_req_cached));
}
-
+
+static void cppc_update_perf(struct amd_cpudata *cpudata,
+ u32 min_perf, u32 des_perf,
+ u32 max_perf, bool fast_switch)
@@ -996,67 +1035,46 @@ index 32b4f6d797830..a46cd5dd9f7cc 100644
+ cppc_set_perf(cpudata->cpu, &perf_ctrls);
+}
+
- static int
- amd_pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
- u32 des_perf, u32 max_perf, bool fast_switch)
-@@ -370,6 +414,12 @@ static struct amd_pstate_perf_funcs pstate_funcs = {
- .update_perf = pstate_update_perf,
- };
-
-+static struct amd_pstate_perf_funcs cppc_funcs = {
-+ .enable = cppc_enable,
-+ .init_perf = cppc_init_perf,
-+ .update_perf = cppc_update_perf,
-+};
-+
- static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
- {
- int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
-@@ -416,7 +466,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
+ DEFINE_STATIC_CALL(amd_pstate_update_perf, pstate_update_perf);
+
+ static inline void amd_pstate_update_perf(struct amd_cpudata *cpudata,
+@@ -325,7 +382,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
/* It will be updated by governor */
policy->cur = policy->cpuinfo.min_freq;
-
+
- policy->fast_switch_possible = true;
-+ if (boot_cpu_has(X86_FEATURE_AMD_CPPC_EXT))
++ if (boot_cpu_has(X86_FEATURE_CPPC))
+ policy->fast_switch_possible = true;
-
+
ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0],
FREQ_QOS_MIN, policy->cpuinfo.min_freq);
-@@ -471,7 +522,6 @@ static struct cpufreq_driver amd_pstate_driver = {
+@@ -375,7 +433,6 @@ static struct cpufreq_driver amd_pstate_driver = {
+ .flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
.verify = amd_pstate_verify,
.target = amd_pstate_target,
- .fast_switch = amd_pstate_fast_switch,
- .adjust_perf = amd_pstate_adjust_perf,
.init = amd_pstate_cpu_init,
.exit = amd_pstate_cpu_exit,
.name = "amd-pstate",
-@@ -496,14 +546,15 @@ static int __init amd_pstate_init(void)
+@@ -398,8 +455,14 @@ static int __init amd_pstate_init(void)
return -EEXIST;
-
+
/* capability check */
-- if (!boot_cpu_has(X86_FEATURE_AMD_CPPC_EXT)) {
-+ if (boot_cpu_has(X86_FEATURE_AMD_CPPC_EXT)) {
- pr_debug("%s, AMD CPPC extension functionality is supported\n",
- __func__);
-- return -ENODEV;
-+ funcs = &pstate_funcs;
+- if (!boot_cpu_has(X86_FEATURE_CPPC)) {
+- pr_debug("AMD CPPC MSR based functionality is not supported\n");
++ if (boot_cpu_has(X86_FEATURE_CPPC)) {
++ pr_debug("AMD CPPC MSR based functionality is supported\n");
+ amd_pstate_driver.adjust_perf = amd_pstate_adjust_perf;
++ } else if (shared_mem) {
++ static_call_update(amd_pstate_enable, cppc_enable);
++ static_call_update(amd_pstate_init_perf, cppc_init_perf);
++ static_call_update(amd_pstate_update_perf, cppc_update_perf);
+ } else {
-+ funcs = &cppc_funcs;
+ return -ENODEV;
}
+
-- funcs = &pstate_funcs;
--
- /* enable amd pstate feature */
- ret = amd_pstate_enable(funcs, true);
- if (ret) {
---
-cgit 1.2.3-1.el7
-From e007c18166d11d78757454ebfac967ae460ebf08 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Thu, 10 Jun 2021 20:24:00 +0800
-Subject: cpufreq: amd: add trace for amd-pstate module
Add trace event to monitor the performance value changes which is
controlled by cpu governors.
@@ -1065,20 +1083,20 @@ Signed-off-by: Huang Rui <ray.huang@amd.com>
---
drivers/cpufreq/Makefile | 6 ++-
drivers/cpufreq/amd-pstate-trace.c | 2 +
- drivers/cpufreq/amd-pstate-trace.h | 96 ++++++++++++++++++++++++++++++++++++++
- drivers/cpufreq/amd-pstate.c | 19 ++++++--
- 4 files changed, 118 insertions(+), 5 deletions(-)
+ drivers/cpufreq/amd-pstate-trace.h | 77 ++++++++++++++++++++++++++++++
+ drivers/cpufreq/amd-pstate.c | 4 ++
+ 4 files changed, 88 insertions(+), 1 deletion(-)
create mode 100644 drivers/cpufreq/amd-pstate-trace.c
create mode 100644 drivers/cpufreq/amd-pstate-trace.h
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
-index 3d4bd7141cf85..c1909475eaf9e 100644
+index c8d307010922..285de70af877 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -17,6 +17,10 @@ obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o
obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o
obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o
-
+
+# Traces
+CFLAGS_amd-pstate-trace.o := -I$(src)
+amd_pstate-y := amd-pstate.o amd-pstate-trace.o
@@ -1086,18 +1104,18 @@ index 3d4bd7141cf85..c1909475eaf9e 100644
##################################################################################
# x86 drivers.
# Link order matters. K8 is preferred to ACPI because of firmware bugs in early
-@@ -24,7 +28,7 @@ obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o
- # powernow-k8 can load then. ACPI is preferred to all other hardware-specific drivers.
+@@ -25,7 +29,7 @@ obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o
# speedstep-* is preferred over p4-clockmod.
-
+
+ obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
-obj-$(CONFIG_X86_AMD_PSTATE) += amd-pstate.o
+obj-$(CONFIG_X86_AMD_PSTATE) += amd_pstate.o
- obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o
+ obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o
diff --git a/drivers/cpufreq/amd-pstate-trace.c b/drivers/cpufreq/amd-pstate-trace.c
new file mode 100644
-index 0000000000000..891b696dcd694
+index 000000000000..891b696dcd69
--- /dev/null
+++ b/drivers/cpufreq/amd-pstate-trace.c
@@ -0,0 +1,2 @@
@@ -1105,30 +1123,16 @@ index 0000000000000..891b696dcd694
+#include "amd-pstate-trace.h"
diff --git a/drivers/cpufreq/amd-pstate-trace.h b/drivers/cpufreq/amd-pstate-trace.h
new file mode 100644
-index 0000000000000..50c85e150f303
+index 000000000000..647505957d4f
--- /dev/null
+++ b/drivers/cpufreq/amd-pstate-trace.h
-@@ -0,0 +1,96 @@
+@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * amd-pstate-trace.h - AMD Processor P-state Frequency Driver Tracer
+ *
+ * Copyright (C) 2021 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2
-+ * of the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+ *
+ * Author: Huang Rui <ray.huang@amd.com>
+ */
+
@@ -1153,18 +1157,16 @@ index 0000000000000..50c85e150f303
+ unsigned long target_perf,
+ unsigned long capacity,
+ unsigned int cpu_id,
-+ u64 prev,
-+ u64 value,
-+ int type
++ bool changed,
++ bool fast_switch
+ ),
+
+ TP_ARGS(min_perf,
+ target_perf,
+ capacity,
+ cpu_id,
-+ prev,
-+ value,
-+ type
++ changed,
++ fast_switch
+ ),
+
+ TP_STRUCT__entry(
@@ -1172,9 +1174,8 @@ index 0000000000000..50c85e150f303
+ __field(unsigned long, target_perf)
+ __field(unsigned long, capacity)
+ __field(unsigned int, cpu_id)
-+ __field(u64, prev)
-+ __field(u64, value)
-+ __field(int, type)
++ __field(bool, changed)
++ __field(bool, fast_switch)
+ ),
+
+ TP_fast_assign(
@@ -1182,19 +1183,17 @@ index 0000000000000..50c85e150f303
+ __entry->target_perf = target_perf;
+ __entry->capacity = capacity;
+ __entry->cpu_id = cpu_id;
-+ __entry->prev = prev;
-+ __entry->value = value;
-+ __entry->type = type;
++ __entry->changed = changed;
++ __entry->fast_switch = fast_switch;
+ ),
+
-+ TP_printk("amd_min_perf=%lu amd_des_perf=%lu amd_max_perf=%lu cpu_id=%u prev=0x%llx value=0x%llx type=0x%d",
++ TP_printk("amd_min_perf=%lu amd_des_perf=%lu amd_max_perf=%lu cpu_id=%u changed=%s fast_switch=%s",
+ (unsigned long)__entry->min_perf,
+ (unsigned long)__entry->target_perf,
+ (unsigned long)__entry->capacity,
+ (unsigned int)__entry->cpu_id,
-+ (u64)__entry->prev,
-+ (u64)__entry->value,
-+ (int)__entry->type
++ (__entry->changed) ? "true" : "false",
++ (__entry->fast_switch) ? "true" : "false"
+ )
+);
+
@@ -1206,127 +1205,55 @@ index 0000000000000..50c85e150f303
+
+#include <trace/define_trace.h>
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index a46cd5dd9f7cc..ea965a122431d 100644
+index 14a29326ceae..5e080d0dc45f 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
-@@ -44,10 +44,18 @@
+@@ -31,6 +31,7 @@
#include <asm/processor.h>
#include <asm/cpufeature.h>
#include <asm/cpu_device_id.h>
+#include "amd-pstate-trace.h"
-
+
#define AMD_PSTATE_TRANSITION_LATENCY 0x20000
#define AMD_PSTATE_TRANSITION_DELAY 500
-
-+enum switch_type
-+{
-+ AMD_TARGET = 0,
-+ AMD_ADJUST_PERF,
-+ AMD_FAST_SWITCH,
-+};
-+
- static struct cpufreq_driver amd_pstate_driver;
-
- struct amd_cpudata {
-@@ -195,7 +203,8 @@ amd_pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
-
- static int
- amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
-- u32 des_perf, u32 max_perf, bool fast_switch)
-+ u32 des_perf, u32 max_perf, bool fast_switch,
-+ enum switch_type type)
- {
- u64 prev = READ_ONCE(cpudata->cppc_req_cached);
- u64 value = prev;
-@@ -209,6 +218,8 @@ amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
+@@ -189,6 +190,9 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
value &= ~REQ_MAX_PERF(~0L);
value |= REQ_MAX_PERF(max_perf);
-
+
+ trace_amd_pstate_perf(min_perf, des_perf, max_perf,
-+ cpudata->cpu, prev, value, type);
++ cpudata->cpu, (value != prev), fast_switch);
++
if (value == prev)
- return 0;
-
-@@ -250,7 +261,7 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
-
- cpufreq_freq_transition_begin(policy, &freqs);
- ret = amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
-- amd_max_perf, false);
-+ amd_max_perf, false, AMD_TARGET);
- cpufreq_freq_transition_end(policy, &freqs, false);
-
- return ret;
-@@ -288,7 +299,7 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
- amd_min_perf, amd_max_perf);
-
- amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
-- amd_max_perf, true);
-+ amd_max_perf, true, AMD_ADJUST_PERF);
- }
-
- static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
-@@ -308,7 +319,7 @@ static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
- cpudata->max_freq);
+ return;
+
- amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
-- amd_max_perf, true);
-+ amd_max_perf, true, AMD_FAST_SWITCH);
- nominal_perf = READ_ONCE(cpudata->nominal_perf);
- ratio = div_u64(amd_des_perf << SCHED_CAPACITY_SHIFT, nominal_perf);
---
-cgit 1.2.3-1.el7
-
-From 24ab2966561da669b9879a6167e2cc7e5929735c Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Thu, 10 Jun 2021 23:13:00 +0800
-Subject: cpufreq: amd: add boost mode support for amd-pstate
If the sbios supports the boost mode of amd-pstate, let's switch to
boost enabled by default.
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- drivers/cpufreq/amd-pstate.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 50 insertions(+)
+ drivers/cpufreq/amd-pstate.c | 44 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index ea965a122431d..67a9a117f5243 100644
+index 5e080d0dc45f..0c335a917307 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
-@@ -75,6 +75,8 @@ struct amd_cpudata {
+@@ -67,6 +67,8 @@ struct amd_cpudata {
u32 min_freq;
u32 nominal_freq;
u32 lowest_nonlinear_freq;
+
+ bool boost_supported;
};
-
- struct amd_pstate_perf_funcs {
-@@ -229,6 +231,19 @@ amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
- max_perf, fast_switch);
- }
-
-+static bool amd_pstate_boost_supported(struct amd_cpudata *cpudata)
-+{
-+ u32 highest_perf, nominal_perf;
-+
-+ highest_perf = READ_ONCE(cpudata->highest_perf);
-+ nominal_perf = READ_ONCE(cpudata->nominal_perf);
-+
-+ if (highest_perf > nominal_perf)
-+ return true;
-+
-+ return false;
-+}
-+
- static int amd_pstate_verify(struct cpufreq_policy_data *policy)
- {
- cpufreq_verify_within_cpu_limits(policy);
-@@ -402,6 +417,37 @@ static int amd_get_lowest_nonlinear_freq(struct amd_cpudata *cpudata)
+
+ static inline int pstate_enable(bool enable)
+@@ -342,6 +344,45 @@ static int amd_get_lowest_nonlinear_freq(struct amd_cpudata *cpudata)
return lowest_nonlinear_freq * 1000;
}
-
+
+static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
+{
+ struct amd_cpudata *cpudata = policy->driver_data;
@@ -1354,110 +1281,67 @@ index ea965a122431d..67a9a117f5243 100644
+
+static void amd_pstate_boost_init(struct amd_cpudata *cpudata)
+{
++ u32 highest_perf, nominal_perf;
++
++ highest_perf = READ_ONCE(cpudata->highest_perf);
++ nominal_perf = READ_ONCE(cpudata->nominal_perf);
++
++ if (highest_perf <= nominal_perf)
++ return;
++
+ cpudata->boost_supported = true;
+ amd_pstate_driver.boost_enabled = true;
+}
+
- static int amd_pstate_init_freqs_in_cpudata(struct amd_cpudata *cpudata,
- u32 max_freq, u32 min_freq,
- u32 nominal_freq,
-@@ -504,6 +550,9 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
-
+ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
+ {
+ int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
+@@ -411,6 +452,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
+
policy->driver_data = cpudata;
-
-+ if (amd_pstate_boost_supported(cpudata))
-+ amd_pstate_boost_init(cpudata);
+
++ amd_pstate_boost_init(cpudata);
+
return 0;
-
- free_cpudata3:
-@@ -535,6 +584,7 @@ static struct cpufreq_driver amd_pstate_driver = {
- .fast_switch = amd_pstate_fast_switch,
+
+ free_cpudata2:
+@@ -439,6 +482,7 @@ static struct cpufreq_driver amd_pstate_driver = {
+ .target = amd_pstate_target,
.init = amd_pstate_cpu_init,
.exit = amd_pstate_cpu_exit,
+ .set_boost = amd_pstate_set_boost,
.name = "amd-pstate",
};
+
---
-cgit 1.2.3-1.el7
-
-From fdbec5a44fab1213e459312b542e27dc0181d7e4 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sat, 19 Jun 2021 23:41:30 +0800
-Subject: cpufreq: amd: add amd-pstate checking support check attribute
-The amd-pstate hardware support check will be needed by cpupower to know
-whether amd-pstate is enabled and supported.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- drivers/cpufreq/amd-pstate.c | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
-diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index 67a9a117f5243..48dedd5af1016 100644
---- a/drivers/cpufreq/amd-pstate.c
-+++ b/drivers/cpufreq/amd-pstate.c
-@@ -577,6 +577,19 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
- return 0;
- }
-
-+static ssize_t show_is_amd_pstate_enabled(struct cpufreq_policy *policy,
-+ char *buf)
-+{
-+ return sprintf(&buf[0], "%d\n", acpi_cpc_valid() ? 1 : 0);
-+}
-+
-+cpufreq_freq_attr_ro(is_amd_pstate_enabled);
-+
-+static struct freq_attr *amd_pstate_attr[] = {
-+ &is_amd_pstate_enabled,
-+ NULL,
-+};
-+
- static struct cpufreq_driver amd_pstate_driver = {
- .flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
- .verify = amd_pstate_verify,
-@@ -586,6 +599,7 @@ static struct cpufreq_driver amd_pstate_driver = {
- .exit = amd_pstate_cpu_exit,
- .set_boost = amd_pstate_set_boost,
- .name = "amd-pstate",
-+ .attr = amd_pstate_attr,
- };
-
- static int __init amd_pstate_init(void)
---
-cgit 1.2.3-1.el7
-
-From 4043d05067a68c58255a6759c528bb78db656327 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 20 Jun 2021 13:26:01 +0800
-Subject: cpufreq: amd: add amd-pstate frequencies attributes
Introduce sysfs attributes to get the different level processor
frequencies.
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- drivers/cpufreq/amd-pstate.c | 80 +++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 79 insertions(+), 1 deletion(-)
+ drivers/cpufreq/amd-pstate.c | 46 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 46 insertions(+)
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index 48dedd5af1016..3c727a22cb69d 100644
+index 0c335a917307..09c5fd8bd9da 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
-@@ -577,16 +577,94 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
+@@ -476,6 +476,51 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
return 0;
}
-
--static ssize_t show_is_amd_pstate_enabled(struct cpufreq_policy *policy,
+
+/* Sysfs attributes */
+
++/* This frequency is to indicate the maximum hardware frequency.
++ * If boost is not active but supported, the frequency will be larger than the
++ * one in cpuinfo.
++ */
+static ssize_t show_amd_pstate_max_freq(struct cpufreq_policy *policy,
- char *buf)
++ char *buf)
+{
-+ int ret = 0, max_freq;
++ int max_freq;
+ struct amd_cpudata *cpudata;
+
+ cpudata = policy->driver_data;
@@ -1466,201 +1350,91 @@ index 48dedd5af1016..3c727a22cb69d 100644
+ if (max_freq < 0)
+ return max_freq;
+
-+ ret += sprintf(&buf[ret], "%u\n", max_freq);
-+
-+ return ret;
-+}
-+
-+static ssize_t show_amd_pstate_nominal_freq(struct cpufreq_policy *policy,
-+ char *buf)
-+{
-+ int ret = 0, nominal_freq;
-+ struct amd_cpudata *cpudata;
-+
-+ cpudata = policy->driver_data;
-+
-+ nominal_freq = amd_get_nominal_freq(cpudata);
-+ if (nominal_freq < 0)
-+ return nominal_freq;
-+
-+ ret += sprintf(&buf[ret], "%u\n", nominal_freq);
-+
-+ return ret;
-+}
-+
-+static ssize_t
-+show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *policy, char *buf)
-+{
-+ int ret = 0, freq;
-+ struct amd_cpudata *cpudata;
-+
-+ cpudata = policy->driver_data;
-+
-+ freq = amd_get_lowest_nonlinear_freq(cpudata);
-+ if (freq < 0)
-+ return freq;
-+
-+ ret += sprintf(&buf[ret], "%u\n", freq);
-+
-+ return ret;
++ return sprintf(&buf[0], "%u\n", max_freq);
+}
+
-+static ssize_t show_amd_pstate_min_freq(struct cpufreq_policy *policy, char *buf)
++static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *policy,
++ char *buf)
+{
-+ int ret = 0;
+ int freq;
+ struct amd_cpudata *cpudata;
+
+ cpudata = policy->driver_data;
+
-+ freq = amd_get_min_freq(cpudata);
++ freq = amd_get_lowest_nonlinear_freq(cpudata);
+ if (freq < 0)
+ return freq;
+
-+ ret += sprintf(&buf[ret], "%u\n", freq);
-+
-+ return ret;
++ return sprintf(&buf[0], "%u\n", freq);
+}
+
-+static ssize_t show_is_amd_pstate_enabled(struct cpufreq_policy *policy,
-+ char *buf)
- {
- return sprintf(&buf[0], "%d\n", acpi_cpc_valid() ? 1 : 0);
- }
-
- cpufreq_freq_attr_ro(is_amd_pstate_enabled);
+cpufreq_freq_attr_ro(amd_pstate_max_freq);
-+cpufreq_freq_attr_ro(amd_pstate_nominal_freq);
+cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
-+cpufreq_freq_attr_ro(amd_pstate_min_freq);
-
- static struct freq_attr *amd_pstate_attr[] = {
- &is_amd_pstate_enabled,
++
++static struct freq_attr *amd_pstate_attr[] = {
+ &amd_pstate_max_freq,
-+ &amd_pstate_nominal_freq,
+ &amd_pstate_lowest_nonlinear_freq,
-+ &amd_pstate_min_freq,
- NULL,
++ NULL,
++};
++
+ static struct cpufreq_driver amd_pstate_driver = {
+ .flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
+ .verify = amd_pstate_verify,
+@@ -484,6 +529,7 @@ static struct cpufreq_driver amd_pstate_driver = {
+ .exit = amd_pstate_cpu_exit,
+ .set_boost = amd_pstate_set_boost,
+ .name = "amd-pstate",
++ .attr = amd_pstate_attr,
};
+
+ static int __init amd_pstate_init(void)
---
-cgit 1.2.3-1.el7
-From 4b56a82d37ecb8e9f9df2d0b055939577ff147cf Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 20 Jun 2021 15:01:08 +0800
-Subject: cpufreq: amd: add amd-pstate performance attributes
Introduce sysfs attributes to get the different level amd-pstate
performances.
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- drivers/cpufreq/amd-pstate.c | 66 ++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 66 insertions(+)
+ drivers/cpufreq/amd-pstate.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index 3c727a22cb69d..9c60388d45edc 100644
+index 09c5fd8bd9da..458313cdba93 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
-@@ -647,6 +647,62 @@ static ssize_t show_amd_pstate_min_freq(struct cpufreq_policy *policy, char *buf
- return ret;
+@@ -512,12 +512,29 @@ static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *poli
+ return sprintf(&buf[0], "%u\n", freq);
}
-
-+static ssize_t
-+show_amd_pstate_highest_perf(struct cpufreq_policy *policy, char *buf)
+
++/* In some of ASICs, the highest_perf is not the one in the _CPC table, so we
++ * need to expose it to sysfs.
++ */
++static ssize_t show_amd_pstate_highest_perf(struct cpufreq_policy *policy,
++ char *buf)
+{
-+ int ret = 0;
+ u32 perf;
+ struct amd_cpudata *cpudata = policy->driver_data;
+
+ perf = READ_ONCE(cpudata->highest_perf);
+
-+ ret += sprintf(&buf[ret], "%u\n", perf);
-+
-+ return ret;
-+}
-+
-+static ssize_t
-+show_amd_pstate_nominal_perf(struct cpufreq_policy *policy, char *buf)
-+{
-+ int ret = 0;
-+ u32 perf;
-+ struct amd_cpudata *cpudata = policy->driver_data;
-+
-+ perf = READ_ONCE(cpudata->nominal_perf);
-+
-+ ret += sprintf(&buf[ret], "%u\n", perf);
-+
-+ return ret;
-+}
-+
-+static ssize_t
-+show_amd_pstate_lowest_nonlinear_perf(struct cpufreq_policy *policy, char *buf)
-+{
-+ int ret = 0;
-+ u32 perf;
-+ struct amd_cpudata *cpudata = policy->driver_data;
-+
-+ perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
-+
-+ ret += sprintf(&buf[ret], "%u\n", perf);
-+
-+ return ret;
-+}
-+
-+static ssize_t
-+show_amd_pstate_lowest_perf(struct cpufreq_policy *policy, char *buf)
-+{
-+ int ret = 0;
-+ u32 perf;
-+ struct amd_cpudata *cpudata = policy->driver_data;
-+
-+ perf = READ_ONCE(cpudata->lowest_perf);
-+
-+ ret += sprintf(&buf[ret], "%u\n", perf);
-+
-+ return ret;
++ return sprintf(&buf[0], "%u\n", perf);
+}
+
- static ssize_t show_is_amd_pstate_enabled(struct cpufreq_policy *policy,
- char *buf)
- {
-@@ -654,17 +710,27 @@ static ssize_t show_is_amd_pstate_enabled(struct cpufreq_policy *policy,
- }
-
- cpufreq_freq_attr_ro(is_amd_pstate_enabled);
-+
cpufreq_freq_attr_ro(amd_pstate_max_freq);
- cpufreq_freq_attr_ro(amd_pstate_nominal_freq);
cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
- cpufreq_freq_attr_ro(amd_pstate_min_freq);
-
+
+cpufreq_freq_attr_ro(amd_pstate_highest_perf);
-+cpufreq_freq_attr_ro(amd_pstate_nominal_perf);
-+cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_perf);
-+cpufreq_freq_attr_ro(amd_pstate_lowest_perf);
+
static struct freq_attr *amd_pstate_attr[] = {
- &is_amd_pstate_enabled,
&amd_pstate_max_freq,
- &amd_pstate_nominal_freq,
&amd_pstate_lowest_nonlinear_freq,
- &amd_pstate_min_freq,
+ &amd_pstate_highest_perf,
-+ &amd_pstate_nominal_perf,
-+ &amd_pstate_lowest_nonlinear_perf,
-+ &amd_pstate_lowest_perf,
NULL,
};
+
---
-cgit 1.2.3-1.el7
-From 5b16452c4363a46a28bd65a00a4a3282bdb7ec69 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Mon, 14 Jun 2021 22:52:01 +0800
-Subject: cpupower: add AMD P-state capability flag
Add AMD P-state capability flag in cpupower to indicate AMD new P-state
kernel module support on Ryzen processors.
@@ -1671,7 +1445,7 @@ Signed-off-by: Huang Rui <ray.huang@amd.com>
1 file changed, 1 insertion(+)
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
-index 33ffacee7fcb9..b4813efdfb009 100644
+index 33ffacee7fcb..b4813efdfb00 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -73,6 +73,7 @@ enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
@@ -1679,83 +1453,106 @@ index 33ffacee7fcb9..b4813efdfb009 100644
#define CPUPOWER_CAP_AMD_PSTATEDEF 0x00000200
#define CPUPOWER_CAP_AMD_CPB_MSR 0x00000400
+#define CPUPOWER_CAP_AMD_PSTATE 0x00000800
-
+
#define CPUPOWER_AMD_CPBDIS 0x02000000
+
---
-cgit 1.2.3-1.el7
-From 456b88736d16414c3cce9dd5101b05dfe38baa18 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 27 Jun 2021 22:25:39 +0800
-Subject: cpupower: add the function to check amd-pstate enabled
-Introduce the cpupower_amd_pstate_enabled() to check whether the kernel
-mode enables amd-pstate.
+The processor with amd-pstate function also supports legacy ACPI
+hardware P-States feature as well. Once driver sets amd-pstate eanbled,
+the processor will respond the finer grain amd-pstate feature instead of
+legacy ACPI P-States. So it introduces the cpupower_amd_pstate_enabled()
+to check whether the current kernel enables amd-pstate or acpi-cpufreq
+module.
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- tools/power/cpupower/utils/helpers/helpers.h | 5 +++++
- tools/power/cpupower/utils/helpers/misc.c | 20 ++++++++++++++++++++
- 2 files changed, 25 insertions(+)
+ tools/power/cpupower/utils/helpers/helpers.h | 10 ++++++++++
+ tools/power/cpupower/utils/helpers/misc.c | 18 ++++++++++++++++++
+ 2 files changed, 28 insertions(+)
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
-index b4813efdfb009..eb43c14d1728e 100644
+index b4813efdfb00..e03cc97297aa 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
-@@ -136,6 +136,11 @@ extern int decode_pstates(unsigned int cpu, int boost_states,
-
+@@ -11,6 +11,7 @@
+
+ #include <libintl.h>
+ #include <locale.h>
++#include <stdbool.h>
+
+ #include "helpers/bitmask.h"
+ #include <cpupower.h>
+@@ -136,6 +137,12 @@ extern int decode_pstates(unsigned int cpu, int boost_states,
+
extern int cpufreq_has_boost_support(unsigned int cpu, int *support,
int *active, int * states);
+
-+/* AMD PSTATE enabling **************************/
++/* AMD P-States stuff **************************/
++extern bool cpupower_amd_pstate_enabled(void);
+
-+extern unsigned long cpupower_amd_pstate_enabled(unsigned int cpu);
++/* AMD P-States stuff **************************/
+
/*
* CPUID functions returning a single datum
*/
+@@ -168,6 +175,9 @@ static inline int cpufreq_has_boost_support(unsigned int cpu, int *support,
+ int *active, int * states)
+ { return -1; }
+
++static inline bool cpupower_amd_pstate_enabled(void)
++{ return false; }
++
+ /* cpuid and cpuinfo helpers **************************/
+
+ static inline unsigned int cpuid_eax(unsigned int op) { return 0; };
diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
-index fc6e345117216..07d80775fb680 100644
+index fc6e34511721..0c483cdefcc2 100644
--- a/tools/power/cpupower/utils/helpers/misc.c
+++ b/tools/power/cpupower/utils/helpers/misc.c
-@@ -83,6 +83,26 @@ int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val)
+@@ -3,9 +3,11 @@
+ #include <stdio.h>
+ #include <errno.h>
+ #include <stdlib.h>
++#include <string.h>
+
+ #include "helpers/helpers.h"
+ #include "helpers/sysfs.h"
++#include "cpufreq.h"
+
+ #if defined(__i386__) || defined(__x86_64__)
+
+@@ -83,6 +85,22 @@ int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val)
return 0;
}
-
-+unsigned long cpupower_amd_pstate_enabled(unsigned int cpu)
+
++bool cpupower_amd_pstate_enabled(void)
+{
-+ char linebuf[MAX_LINE_LEN];
-+ char path[SYSFS_PATH_MAX];
-+ unsigned long val;
-+ char *endp;
++ char *driver = cpufreq_get_driver(0);
++ bool ret = false;
+
-+ snprintf(path, sizeof(path),
-+ PATH_TO_CPU "cpu%u/cpufreq/is_amd_pstate_enabled", cpu);
++ if (!driver)
++ return ret;
+
-+ if (cpupower_read_sysfs(path, linebuf, MAX_LINE_LEN) == 0)
-+ return 0;
++ if (!strcmp(driver, "amd-pstate"))
++ ret = true;
+
-+ val = strtoul(linebuf, &endp, 0);
-+ if (endp == linebuf || errno == ERANGE)
-+ return 0;
++ cpufreq_put_driver(driver);
+
-+ return val;
++ return ret;
+}
+
#endif /* #if defined(__i386__) || defined(__x86_64__) */
-
+
/* get_cpustate
---
-cgit 1.2.3-1.el7
-From 9537cd2a2aa718faba5d61c1196d7b05c52a89f4 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 27 Jun 2021 22:40:14 +0800
-Subject: cpupower: initial AMD P-state capability
-If kernel enables AMD P-state, cpupower won't need to respond ACPI
-hardware P-states function anymore.
+
+If kernel starts the amd-pstate module, the cpupower will initial the
+capability flag as CPUPOWER_CAP_AMD_PSTATE. And once amd-pstate
+capability is set, it won't need to set legacy ACPI relative
+capabilities anymore.
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
@@ -1763,15 +1560,15 @@ Signed-off-by: Huang Rui <ray.huang@amd.com>
1 file changed, 13 insertions(+)
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
-index 72eb435931803..78218c54acca9 100644
+index 72eb43593180..2a6dc104e76b 100644
--- a/tools/power/cpupower/utils/helpers/cpuid.c
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
-@@ -149,6 +149,19 @@ out:
+@@ -149,6 +149,19 @@ int get_cpu_info(struct cpupower_cpu_info *cpu_info)
if (ext_cpuid_level >= 0x80000008 &&
cpuid_ebx(0x80000008) & (1 << 4))
cpu_info->caps |= CPUPOWER_CAP_AMD_RDPRU;
+
-+ if (cpupower_amd_pstate_enabled(0)) {
++ if (cpupower_amd_pstate_enabled()) {
+ cpu_info->caps |= CPUPOWER_CAP_AMD_PSTATE;
+
+ /*
@@ -1784,206 +1581,573 @@ index 72eb435931803..78218c54acca9 100644
+ cpu_info->caps &= ~CPUPOWER_CAP_AMD_PSTATEDEF;
+ }
}
-
+
if (cpu_info->vendor == X86_VENDOR_INTEL) {
---
-cgit 1.2.3-1.el7
-From d3f392c951479c73e5a4b0c8d94901aafd5b9da7 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 20 Jun 2021 17:07:25 +0800
-Subject: cpupower: add amd-pstate sysfs entries into libcpufreq
-These amd-pstate sysfs entries will be used on cpupower for amd-pstate
-kernel module.
+
+Expose the helper into cpufreq header, then cpufreq driver can use this
+function to get the sysfs value if it has any specific sysfs interfaces.
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- tools/power/cpupower/lib/cpufreq.c | 18 +++++++++++++++++-
- 1 file changed, 17 insertions(+), 1 deletion(-)
+ tools/power/cpupower/lib/cpufreq.c | 21 +++++++++++++++------
+ tools/power/cpupower/lib/cpufreq.h | 12 ++++++++++++
+ 2 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
-index c3b56db8b9214..3f92ddadaad26 100644
+index c3b56db8b921..02719cc400a1 100644
--- a/tools/power/cpupower/lib/cpufreq.c
+++ b/tools/power/cpupower/lib/cpufreq.c
-@@ -69,6 +69,14 @@ enum cpufreq_value {
- SCALING_MIN_FREQ,
- SCALING_MAX_FREQ,
- STATS_NUM_TRANSITIONS,
-+ AMD_PSTATE_HIGHEST_PERF,
-+ AMD_PSTATE_NOMINAL_PERF,
-+ AMD_PSTATE_LOWEST_NONLINEAR_PERF,
-+ AMD_PSTATE_LOWEST_PERF,
-+ AMD_PSTATE_MAX_FREQ,
-+ AMD_PSTATE_NOMINAL_FREQ,
-+ AMD_PSTATE_LOWEST_NONLINEAR_FREQ,
-+ AMD_PSTATE_MIN_FREQ,
- MAX_CPUFREQ_VALUE_READ_FILES
+@@ -83,20 +83,21 @@ static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
+ [STATS_NUM_TRANSITIONS] = "stats/total_trans"
};
+
+-
+-static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
+- enum cpufreq_value which)
++unsigned long cpufreq_get_sysfs_value_from_table(unsigned int cpu,
++ const char **table,
++ unsigned index,
++ unsigned size)
+ {
+ unsigned long value;
+ unsigned int len;
+ char linebuf[MAX_LINE_LEN];
+ char *endp;
+
+- if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
++ if (!table && !table[index] && index >= size)
+ return 0;
+
+- len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
+- linebuf, sizeof(linebuf));
++ len = sysfs_cpufreq_read_file(cpu, table[index], linebuf,
++ sizeof(linebuf));
+
+ if (len == 0)
+ return 0;
+@@ -109,6 +110,14 @@ static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
+ return value;
+ }
+
++static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
++ enum cpufreq_value which)
++{
++ return cpufreq_get_sysfs_value_from_table(cpu, cpufreq_value_files,
++ which,
++ MAX_CPUFREQ_VALUE_READ_FILES);
++}
++
+ /* read access to files which contain one string */
+
+ enum cpufreq_string {
+diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h
+index 95f4fd9e2656..107668c0c454 100644
+--- a/tools/power/cpupower/lib/cpufreq.h
++++ b/tools/power/cpupower/lib/cpufreq.h
+@@ -203,6 +203,18 @@ int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
+ int cpufreq_set_frequency(unsigned int cpu,
+ unsigned long target_frequency);
+
++/*
++ * get the sysfs value from specific table
++ *
++ * Read the value with the sysfs file name from specific table. Does
++ * only work if the cpufreq driver has the specific sysfs interfaces.
++ */
++
++unsigned long cpufreq_get_sysfs_value_from_table(unsigned int cpu,
++ const char **table,
++ unsigned index,
++ unsigned size);
++
+ #ifdef __cplusplus
+ }
+ #endif
-@@ -80,7 +88,15 @@ static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
- [SCALING_CUR_FREQ] = "scaling_cur_freq",
- [SCALING_MIN_FREQ] = "scaling_min_freq",
- [SCALING_MAX_FREQ] = "scaling_max_freq",
-- [STATS_NUM_TRANSITIONS] = "stats/total_trans"
-+ [STATS_NUM_TRANSITIONS] = "stats/total_trans",
-+ [AMD_PSTATE_HIGHEST_PERF] = "amd_pstate_highest_perf",
-+ [AMD_PSTATE_NOMINAL_PERF] = "amd_pstate_nominal_perf",
-+ [AMD_PSTATE_LOWEST_NONLINEAR_PERF] = "amd_pstate_lowest_nonlinear_perf",
-+ [AMD_PSTATE_LOWEST_PERF] = "amd_pstate_lowest_perf",
-+ [AMD_PSTATE_MAX_FREQ] = "amd_pstate_max_freq",
-+ [AMD_PSTATE_NOMINAL_FREQ] = "amd_pstate_nominal_freq",
-+ [AMD_PSTATE_LOWEST_NONLINEAR_FREQ] = "amd_pstate_lowest_nonlinear_freq",
-+ [AMD_PSTATE_MIN_FREQ] = "amd_pstate_min_freq"
- };
---
-cgit 1.2.3-1.el7
+Kernel ACPI subsytem introduced the sysfs attributes for acpi cppc
+library in below path:
-From c7249e524ce793bfe0575f45a0f8245f51b02af7 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 20 Jun 2021 17:35:45 +0800
-Subject: cpupower: enable boost state support for amd-pstate module
+/sys/devices/system/cpu/cpuX/acpi_cppc/
-The AMD P-state boost API is different from ACPI hardware P-states, so
-implement the support for amd-pstate kernel module.
+And these attributes will be used for amd-pstate driver to provide some
+performance and frequency values.
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- tools/power/cpupower/lib/cpufreq.c | 20 ++++++++++++++++++++
- tools/power/cpupower/lib/cpufreq.h | 3 +++
- tools/power/cpupower/utils/helpers/misc.c | 7 +++++++
- 3 files changed, 30 insertions(+)
+ tools/power/cpupower/Makefile | 6 +--
+ tools/power/cpupower/lib/acpi_cppc.c | 59 ++++++++++++++++++++++++++++
+ tools/power/cpupower/lib/acpi_cppc.h | 21 ++++++++++
+ 3 files changed, 83 insertions(+), 3 deletions(-)
+ create mode 100644 tools/power/cpupower/lib/acpi_cppc.c
+ create mode 100644 tools/power/cpupower/lib/acpi_cppc.h
+
+diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
+index 3b1594447f29..e9b6de314654 100644
+--- a/tools/power/cpupower/Makefile
++++ b/tools/power/cpupower/Makefile
+@@ -143,9 +143,9 @@ UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \
+ utils/helpers/bitmask.h \
+ utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def
+
+-LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h
+-LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c
+-LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o
++LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h lib/acpi_cppc.h
++LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c lib/acpi_cppc.c
++LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o lib/acpi_cppc.o
+ LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS))
+
+ override CFLAGS += -pipe
+diff --git a/tools/power/cpupower/lib/acpi_cppc.c b/tools/power/cpupower/lib/acpi_cppc.c
+new file mode 100644
+index 000000000000..a07a8922eca2
+--- /dev/null
++++ b/tools/power/cpupower/lib/acpi_cppc.c
+@@ -0,0 +1,59 @@
++// SPDX-License-Identifier: GPL-2.0-only
++
++#include <stdio.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <unistd.h>
++
++#include "cpupower_intern.h"
++#include "acpi_cppc.h"
++
++/* ACPI CPPC sysfs access ***********************************************/
++
++static int acpi_cppc_read_file(unsigned int cpu, const char *fname,
++ char *buf, size_t buflen)
++{
++ char path[SYSFS_PATH_MAX];
++
++ snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/acpi_cppc/%s",
++ cpu, fname);
++ return cpupower_read_sysfs(path, buf, buflen);
++}
++
++static const char *acpi_cppc_value_files[] = {
++ [HIGHEST_PERF] = "highest_perf",
++ [LOWEST_PERF] = "lowest_perf",
++ [NOMINAL_PERF] = "nominal_perf",
++ [LOWEST_NONLINEAR_PERF] = "lowest_nonlinear_perf",
++ [LOWEST_FREQ] = "lowest_freq",
++ [NOMINAL_FREQ] = "nominal_freq",
++ [REFERENCE_PERF] = "reference_perf",
++ [WRAPAROUND_TIME] = "wraparound_time"
++};
++
++unsigned long acpi_cppc_get_data(unsigned cpu, enum acpi_cppc_value which)
++{
++ unsigned long long value;
++ unsigned int len;
++ char linebuf[MAX_LINE_LEN];
++ char *endp;
++
++ if (which >= MAX_CPPC_VALUE_FILES)
++ return 0;
++
++ len = acpi_cppc_read_file(cpu, acpi_cppc_value_files[which],
++ linebuf, sizeof(linebuf));
++ if (len == 0)
++ return 0;
++
++ value = strtoull(linebuf, &endp, 0);
++
++ if (endp == linebuf || errno == ERANGE)
++ return 0;
++
++ return value;
++}
+diff --git a/tools/power/cpupower/lib/acpi_cppc.h b/tools/power/cpupower/lib/acpi_cppc.h
+new file mode 100644
+index 000000000000..576291155224
+--- /dev/null
++++ b/tools/power/cpupower/lib/acpi_cppc.h
+@@ -0,0 +1,21 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++
++#ifndef __ACPI_CPPC_H__
++#define __ACPI_CPPC_H__
++
++enum acpi_cppc_value {
++ HIGHEST_PERF,
++ LOWEST_PERF,
++ NOMINAL_PERF,
++ LOWEST_NONLINEAR_PERF,
++ LOWEST_FREQ,
++ NOMINAL_FREQ,
++ REFERENCE_PERF,
++ WRAPAROUND_TIME,
++ MAX_CPPC_VALUE_FILES
++};
++
++extern unsigned long acpi_cppc_get_data(unsigned cpu,
++ enum acpi_cppc_value which);
++
++#endif /* _ACPI_CPPC_H */
-diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
-index 3f92ddadaad26..37da87bdcfb1c 100644
---- a/tools/power/cpupower/lib/cpufreq.c
-+++ b/tools/power/cpupower/lib/cpufreq.c
-@@ -790,3 +790,23 @@ unsigned long cpufreq_get_transitions(unsigned int cpu)
- {
- return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
+
+
+Introduce the marco definitions and access helper function for
+amd-pstate sysfs interfaces such as each performance goals and frequency
+levels in amd helper file. They will be used to read the sysfs attribute
+from amd-pstate cpufreq driver for cpupower utilities.
+
+Signed-off-by: Huang Rui <ray.huang@amd.com>
+---
+ tools/power/cpupower/utils/helpers/amd.c | 30 ++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c
+index 97f2c857048e..14c658daba4b 100644
+--- a/tools/power/cpupower/utils/helpers/amd.c
++++ b/tools/power/cpupower/utils/helpers/amd.c
+@@ -8,7 +8,10 @@
+ #include <pci/pci.h>
+
+ #include "helpers/helpers.h"
++#include "cpufreq.h"
++#include "acpi_cppc.h"
+
++/* ACPI P-States Helper Functions for AMD Processors ***************/
+ #define MSR_AMD_PSTATE_STATUS 0xc0010063
+ #define MSR_AMD_PSTATE 0xc0010064
+ #define MSR_AMD_PSTATE_LIMIT 0xc0010061
+@@ -146,4 +149,31 @@ int amd_pci_get_num_boost_states(int *active, int *states)
+ pci_cleanup(pci_acc);
+ return 0;
}
+
-+int amd_pstate_boost_support(unsigned int cpu)
-+{
-+ unsigned int highest_perf, nominal_perf;
++/* ACPI P-States Helper Functions for AMD Processors ***************/
+
-+ highest_perf = sysfs_cpufreq_get_one_value(cpu, AMD_PSTATE_HIGHEST_PERF);
-+ nominal_perf = sysfs_cpufreq_get_one_value(cpu, AMD_PSTATE_NOMINAL_PERF);
++/* AMD P-States Helper Functions ***************/
++enum amd_pstate_value {
++ AMD_PSTATE_HIGHEST_PERF,
++ AMD_PSTATE_MAX_FREQ,
++ AMD_PSTATE_LOWEST_NONLINEAR_FREQ,
++ MAX_AMD_PSTATE_VALUE_READ_FILES,
++};
+
-+ return highest_perf > nominal_perf ? 1 : 0;
++static const char *amd_pstate_value_files[MAX_AMD_PSTATE_VALUE_READ_FILES] = {
++ [AMD_PSTATE_HIGHEST_PERF] = "amd_pstate_highest_perf",
++ [AMD_PSTATE_MAX_FREQ] = "amd_pstate_max_freq",
++ [AMD_PSTATE_LOWEST_NONLINEAR_FREQ] = "amd_pstate_lowest_nonlinear_freq",
++};
++
++static unsigned long amd_pstate_get_data(unsigned int cpu,
++ enum amd_pstate_value value)
++{
++ return cpufreq_get_sysfs_value_from_table(cpu,
++ amd_pstate_value_files,
++ value,
++ MAX_AMD_PSTATE_VALUE_READ_FILES);
+}
+
-+int amd_pstate_boost_enabled(unsigned int cpu)
++/* AMD P-States Helper Functions ***************/
+ #endif /* defined(__i386__) || defined(__x86_64__) */
+
+
+
+The legacy ACPI hardware P-States function has 3 P-States on ACPI table,
+the CPU frequency only can be switched between the 3 P-States. While the
+processor supports the boost state, it will have another boost state
+that the frequency can be higher than P0 state, and the state can be
+decoded by the function of decode_pstates() and read by
+amd_pci_get_num_boost_states().
+
+However, the new AMD P-States function is different than legacy ACPI
+hardware P-State on AMD processors. That has a finer grain frequency
+range between the highest and lowest frequency. And boost frequency is
+actually the frequency which is mapped on highest performance ratio. The
+similiar previous P0 frequency is mapped on nominal performance ratio.
+If the highest performance on the processor is higher than nominal
+performance, then we think the current processor supports the boost
+state. And it uses amd_pstate_boost_init() to initialize boost for AMD
+P-States function.
+
+Signed-off-by: Huang Rui <ray.huang@amd.com>
+---
+ tools/power/cpupower/utils/helpers/amd.c | 18 ++++++++++++++++++
+ tools/power/cpupower/utils/helpers/helpers.h | 5 +++++
+ tools/power/cpupower/utils/helpers/misc.c | 2 ++
+ 3 files changed, 25 insertions(+)
+
+diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c
+index 14c658daba4b..bde6065cabf4 100644
+--- a/tools/power/cpupower/utils/helpers/amd.c
++++ b/tools/power/cpupower/utils/helpers/amd.c
+@@ -175,5 +175,23 @@ static unsigned long amd_pstate_get_data(unsigned int cpu,
+ MAX_AMD_PSTATE_VALUE_READ_FILES);
+ }
+
++void amd_pstate_boost_init(unsigned int cpu, int *support, int *active)
+{
-+ unsigned int cpuinfo_max, amd_pstate_max;
++ unsigned long highest_perf, nominal_perf, cpuinfo_min,
++ cpuinfo_max, amd_pstate_max;
++
++ highest_perf = amd_pstate_get_data(cpu, AMD_PSTATE_HIGHEST_PERF);
++ nominal_perf = acpi_cppc_get_data(cpu, NOMINAL_PERF);
++
++ *support = highest_perf > nominal_perf ? 1 : 0;
++ if (!(*support))
++ return;
+
-+ cpuinfo_max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
-+ amd_pstate_max = sysfs_cpufreq_get_one_value(cpu, AMD_PSTATE_MAX_FREQ);
++ cpufreq_get_hardware_limits(cpu, &cpuinfo_min, &cpuinfo_max);
++ amd_pstate_max = amd_pstate_get_data(cpu, AMD_PSTATE_MAX_FREQ);
+
-+ return cpuinfo_max == amd_pstate_max ? 1 : 0;
++ *active = cpuinfo_max == amd_pstate_max ? 1 : 0;
+}
-diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h
-index 95f4fd9e2656c..d54d02a7a4f44 100644
---- a/tools/power/cpupower/lib/cpufreq.h
-+++ b/tools/power/cpupower/lib/cpufreq.h
-@@ -203,6 +203,9 @@ int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
- int cpufreq_set_frequency(unsigned int cpu,
- unsigned long target_frequency);
-
-+int amd_pstate_boost_support(unsigned int cpu);
-+int amd_pstate_boost_enabled(unsigned int cpu);
+
- #ifdef __cplusplus
- }
- #endif
+ /* AMD P-States Helper Functions ***************/
+ #endif /* defined(__i386__) || defined(__x86_64__) */
+diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
+index e03cc97297aa..c03925bea655 100644
+--- a/tools/power/cpupower/utils/helpers/helpers.h
++++ b/tools/power/cpupower/utils/helpers/helpers.h
+@@ -140,6 +140,8 @@ extern int cpufreq_has_boost_support(unsigned int cpu, int *support,
+
+ /* AMD P-States stuff **************************/
+ extern bool cpupower_amd_pstate_enabled(void);
++extern void amd_pstate_boost_init(unsigned int cpu,
++ int *support, int *active);
+
+ /* AMD P-States stuff **************************/
+
+@@ -177,6 +179,9 @@ static inline int cpufreq_has_boost_support(unsigned int cpu, int *support,
+
+ static inline bool cpupower_amd_pstate_enabled(void)
+ { return false; }
++static void amd_pstate_boost_init(unsigned int cpu,
++ int *support, int *active)
++{ return; }
+
+ /* cpuid and cpuinfo helpers **************************/
+
diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
-index 07d80775fb680..aba9793207600 100644
+index 0c483cdefcc2..e0d3145434d3 100644
--- a/tools/power/cpupower/utils/helpers/misc.c
+++ b/tools/power/cpupower/utils/helpers/misc.c
-@@ -10,6 +10,7 @@
- #if defined(__i386__) || defined(__x86_64__)
-
- #include "cpupower_intern.h"
-+#include "cpufreq.h"
-
- #define MSR_AMD_HWCR 0xc0010015
-
-@@ -39,6 +40,12 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
+@@ -41,6 +41,8 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
if (ret)
return ret;
}
-+ } if ((cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) &&
-+ amd_pstate_boost_support(cpu)) {
-+ *support = 1;
-+
-+ if (amd_pstate_boost_enabled(cpu))
-+ *active = 1;
++ } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) {
++ amd_pstate_boost_init(cpu, support, active);
} else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA)
*support = *active = 1;
return 0;
---
-cgit 1.2.3-1.el7
-From cf79733de00a260c6d3e5038f00cdb91a71df9af Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 20 Jun 2021 18:25:55 +0800
-Subject: cpupower: add amd-pstate get data function to query the info
-Frequency-info needs an interface to query the current amd-pstate data.
+
+The print_speed can be as a common function, and expose it into misc
+helper header. Then it can be used on other helper files as well.
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- tools/power/cpupower/lib/cpufreq.c | 6 ++++++
- tools/power/cpupower/lib/cpufreq.h | 13 +++++++++++++
- 2 files changed, 19 insertions(+)
+ tools/power/cpupower/utils/cpufreq-info.c | 59 ++++----------------
+ tools/power/cpupower/utils/helpers/helpers.h | 1 +
+ tools/power/cpupower/utils/helpers/misc.c | 42 ++++++++++++++
+ 3 files changed, 54 insertions(+), 48 deletions(-)
-diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
-index 37da87bdcfb1c..1443080868da3 100644
---- a/tools/power/cpupower/lib/cpufreq.c
-+++ b/tools/power/cpupower/lib/cpufreq.c
-@@ -810,3 +810,9 @@ int amd_pstate_boost_enabled(unsigned int cpu)
-
- return cpuinfo_max == amd_pstate_max ? 1 : 0;
+diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
+index f9895e31ff5a..b429454bf3ae 100644
+--- a/tools/power/cpupower/utils/cpufreq-info.c
++++ b/tools/power/cpupower/utils/cpufreq-info.c
+@@ -84,43 +84,6 @@ static void proc_cpufreq_output(void)
+ }
+
+ static int no_rounding;
+-static void print_speed(unsigned long speed)
+-{
+- unsigned long tmp;
+-
+- if (no_rounding) {
+- if (speed > 1000000)
+- printf("%u.%06u GHz", ((unsigned int) speed/1000000),
+- ((unsigned int) speed%1000000));
+- else if (speed > 1000)
+- printf("%u.%03u MHz", ((unsigned int) speed/1000),
+- (unsigned int) (speed%1000));
+- else
+- printf("%lu kHz", speed);
+- } else {
+- if (speed > 1000000) {
+- tmp = speed%10000;
+- if (tmp >= 5000)
+- speed += 10000;
+- printf("%u.%02u GHz", ((unsigned int) speed/1000000),
+- ((unsigned int) (speed%1000000)/10000));
+- } else if (speed > 100000) {
+- tmp = speed%1000;
+- if (tmp >= 500)
+- speed += 1000;
+- printf("%u MHz", ((unsigned int) speed/1000));
+- } else if (speed > 1000) {
+- tmp = speed%100;
+- if (tmp >= 50)
+- speed += 100;
+- printf("%u.%01u MHz", ((unsigned int) speed/1000),
+- ((unsigned int) (speed%1000)/100));
+- }
+- }
+-
+- return;
+-}
+-
+ static void print_duration(unsigned long duration)
+ {
+ unsigned long tmp;
+@@ -254,11 +217,11 @@ static int get_boost_mode(unsigned int cpu)
+ if (freqs) {
+ printf(_(" boost frequency steps: "));
+ while (freqs->next) {
+- print_speed(freqs->frequency);
++ print_speed(freqs->frequency, no_rounding);
+ printf(", ");
+ freqs = freqs->next;
+ }
+- print_speed(freqs->frequency);
++ print_speed(freqs->frequency, no_rounding);
+ printf("\n");
+ cpufreq_put_available_frequencies(freqs);
+ }
+@@ -277,7 +240,7 @@ static int get_freq_kernel(unsigned int cpu, unsigned int human)
+ return -EINVAL;
+ }
+ if (human) {
+- print_speed(freq);
++ print_speed(freq, no_rounding);
+ } else
+ printf("%lu", freq);
+ printf(_(" (asserted by call to kernel)\n"));
+@@ -296,7 +259,7 @@ static int get_freq_hardware(unsigned int cpu, unsigned int human)
+ return -EINVAL;
+ }
+ if (human) {
+- print_speed(freq);
++ print_speed(freq, no_rounding);
+ } else
+ printf("%lu", freq);
+ printf(_(" (asserted by call to hardware)\n"));
+@@ -316,9 +279,9 @@ static int get_hardware_limits(unsigned int cpu, unsigned int human)
+
+ if (human) {
+ printf(_(" hardware limits: "));
+- print_speed(min);
++ print_speed(min, no_rounding);
+ printf(" - ");
+- print_speed(max);
++ print_speed(max, no_rounding);
+ printf("\n");
+ } else {
+ printf("%lu %lu\n", min, max);
+@@ -350,9 +313,9 @@ static int get_policy(unsigned int cpu)
+ return -EINVAL;
+ }
+ printf(_(" current policy: frequency should be within "));
+- print_speed(policy->min);
++ print_speed(policy->min, no_rounding);
+ printf(_(" and "));
+- print_speed(policy->max);
++ print_speed(policy->max, no_rounding);
+
+ printf(".\n ");
+ printf(_("The governor \"%s\" may decide which speed to use\n"
+@@ -436,7 +399,7 @@ static int get_freq_stats(unsigned int cpu, unsigned int human)
+ struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time);
+ while (stats) {
+ if (human) {
+- print_speed(stats->frequency);
++ print_speed(stats->frequency, no_rounding);
+ printf(":%.2f%%",
+ (100.0 * stats->time_in_state) / total_time);
+ } else
+@@ -486,11 +449,11 @@ static void debug_output_one(unsigned int cpu)
+ if (freqs) {
+ printf(_(" available frequency steps: "));
+ while (freqs->next) {
+- print_speed(freqs->frequency);
++ print_speed(freqs->frequency, no_rounding);
+ printf(", ");
+ freqs = freqs->next;
+ }
+- print_speed(freqs->frequency);
++ print_speed(freqs->frequency, no_rounding);
+ printf("\n");
+ cpufreq_put_available_frequencies(freqs);
+ }
+diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
+index c03925bea655..fbbfa6047c83 100644
+--- a/tools/power/cpupower/utils/helpers/helpers.h
++++ b/tools/power/cpupower/utils/helpers/helpers.h
+@@ -200,5 +200,6 @@ extern struct bitmask *offline_cpus;
+ void get_cpustate(void);
+ void print_online_cpus(void);
+ void print_offline_cpus(void);
++void print_speed(unsigned long speed, int no_rounding);
+
+ #endif /* __CPUPOWERUTILS_HELPERS__ */
+diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
+index e0d3145434d3..d693c96cd09c 100644
+--- a/tools/power/cpupower/utils/helpers/misc.c
++++ b/tools/power/cpupower/utils/helpers/misc.c
+@@ -164,3 +164,45 @@ void print_offline_cpus(void)
+ printf(_("cpupower set operation was not performed on them\n"));
+ }
}
+
-+unsigned amd_pstate_get_data(unsigned int cpu, enum amd_pstate_param param)
++/*
++ * print_speed
++ *
++ * Print the exact CPU frequency with appropriate unit
++ */
++void print_speed(unsigned long speed, int no_rounding)
+{
-+ return sysfs_cpufreq_get_one_value(cpu,
-+ param + AMD_PSTATE_HIGHEST_PERF);
++ unsigned long tmp;
++
++ if (no_rounding) {
++ if (speed > 1000000)
++ printf("%u.%06u GHz", ((unsigned int) speed/1000000),
++ ((unsigned int) speed%1000000));
++ else if (speed > 1000)
++ printf("%u.%03u MHz", ((unsigned int) speed/1000),
++ (unsigned int) (speed%1000));
++ else
++ printf("%lu kHz", speed);
++ } else {
++ if (speed > 1000000) {
++ tmp = speed%10000;
++ if (tmp >= 5000)
++ speed += 10000;
++ printf("%u.%02u GHz", ((unsigned int) speed/1000000),
++ ((unsigned int) (speed%1000000)/10000));
++ } else if (speed > 100000) {
++ tmp = speed%1000;
++ if (tmp >= 500)
++ speed += 1000;
++ printf("%u MHz", ((unsigned int) speed/1000));
++ } else if (speed > 1000) {
++ tmp = speed%100;
++ if (tmp >= 50)
++ speed += 100;
++ printf("%u.%01u MHz", ((unsigned int) speed/1000),
++ ((unsigned int) (speed%1000)/100));
++ }
++ }
++
++ return;
+}
-diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h
-index d54d02a7a4f44..954e72704fc07 100644
---- a/tools/power/cpupower/lib/cpufreq.h
-+++ b/tools/power/cpupower/lib/cpufreq.h
-@@ -206,6 +206,19 @@ int cpufreq_set_frequency(unsigned int cpu,
- int amd_pstate_boost_support(unsigned int cpu);
- int amd_pstate_boost_enabled(unsigned int cpu);
-+enum amd_pstate_param {
-+ HIGHEST_PERF,
-+ NOMINAL_PERF,
-+ LOWEST_NONLINEAR_PERF,
-+ LOWEST_PERF,
-+ MAX_FREQ,
-+ NOMINAL_FREQ,
-+ LOWEST_NONLINEAR_FREQ,
-+ MIN_FREQ,
-+};
-+
-+unsigned amd_pstate_get_data(unsigned int cpu, enum amd_pstate_param param);
-+
- #ifdef __cplusplus
- }
- #endif
---
-cgit 1.2.3-1.el7
-From 573a0ff1add6bb6df585d6535abaaa0e1afc61c9 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Thu, 10 Jun 2021 23:48:03 +0800
-Subject: cpupower: print amd-pstate information on cpupower
amd-pstate kernel module is using the fine grain frequency instead of
acpi hardware pstate. So the performance and frequency values should be
@@ -1991,70 +2155,110 @@ printed in frequency-info.
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- tools/power/cpupower/utils/cpufreq-info.c | 27 ++++++++++++++++++++++++---
- 1 file changed, 24 insertions(+), 3 deletions(-)
+ tools/power/cpupower/utils/cpufreq-info.c | 9 ++++---
+ tools/power/cpupower/utils/helpers/amd.c | 28 ++++++++++++++++++++
+ tools/power/cpupower/utils/helpers/helpers.h | 5 ++++
+ 3 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
-index f9895e31ff5ae..9eabed209adcb 100644
+index b429454bf3ae..f828f3c35a6f 100644
--- a/tools/power/cpupower/utils/cpufreq-info.c
+++ b/tools/power/cpupower/utils/cpufreq-info.c
-@@ -183,9 +183,30 @@ static int get_boost_mode_x86(unsigned int cpu)
+@@ -146,9 +146,12 @@ static int get_boost_mode_x86(unsigned int cpu)
printf(_(" Supported: %s\n"), support ? _("yes") : _("no"));
printf(_(" Active: %s\n"), active ? _("yes") : _("no"));
-
+
- if ((cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
- cpupower_cpu_info.family >= 0x10) ||
- cpupower_cpu_info.vendor == X86_VENDOR_HYGON) {
+ if (cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
+ cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) {
-+ printf(_(" AMD PSTATE Highest Performance: %u. Maximum Frequency: "),
-+ amd_pstate_get_data(cpu, HIGHEST_PERF));
-+ print_speed(amd_pstate_get_data(cpu, MAX_FREQ));
-+ printf(".\n");
-+
-+ printf(_(" AMD PSTATE Nominal Performance: %u. Nominal Frequency: "),
-+ amd_pstate_get_data(cpu, NOMINAL_PERF));
-+ print_speed(amd_pstate_get_data(cpu, NOMINAL_FREQ));
-+ printf(".\n");
-+
-+ printf(_(" AMD PSTATE Lowest Non-linear Performance: %u. Lowest Non-linear Frequency: "),
-+ amd_pstate_get_data(cpu, LOWEST_NONLINEAR_PERF));
-+ print_speed(amd_pstate_get_data(cpu, LOWEST_NONLINEAR_FREQ));
-+ printf(".\n");
-+
-+ printf(_(" AMD PSTATE Lowest Performance: %u. Lowest Frequency: "),
-+ amd_pstate_get_data(cpu, LOWEST_PERF));
-+ print_speed(amd_pstate_get_data(cpu, MIN_FREQ));
-+ printf(".\n");
++ amd_pstate_show_perf_and_freq(cpu, no_rounding);
+ } else if ((cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
+ cpupower_cpu_info.family >= 0x10) ||
+ cpupower_cpu_info.vendor == X86_VENDOR_HYGON) {
ret = decode_pstates(cpu, b_states, pstates, &pstate_no);
if (ret)
return ret;
---
-cgit 1.2.3-1.el7
+diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c
+index bde6065cabf4..a1115891d76d 100644
+--- a/tools/power/cpupower/utils/helpers/amd.c
++++ b/tools/power/cpupower/utils/helpers/amd.c
+@@ -193,5 +193,33 @@ void amd_pstate_boost_init(unsigned int cpu, int *support, int *active)
+ *active = cpuinfo_max == amd_pstate_max ? 1 : 0;
+ }
+
++void amd_pstate_show_perf_and_freq(unsigned int cpu, int no_rounding)
++{
++ printf(_(" AMD PSTATE Highest Performance: %lu. Maximum Frequency: "),
++ amd_pstate_get_data(cpu, AMD_PSTATE_HIGHEST_PERF));
++ /* If boost isn't active, the cpuinfo_max doesn't indicate real max
++ * frequency. So we read it back from amd-pstate sysfs entry.
++ */
++ print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_MAX_FREQ), no_rounding);
++ printf(".\n");
++
++ printf(_(" AMD PSTATE Nominal Performance: %lu. Nominal Frequency: "),
++ acpi_cppc_get_data(cpu, NOMINAL_PERF));
++ print_speed(acpi_cppc_get_data(cpu, NOMINAL_FREQ) * 1000,
++ no_rounding);
++ printf(".\n");
++
++ printf(_(" AMD PSTATE Lowest Non-linear Performance: %lu. Lowest Non-linear Frequency: "),
++ acpi_cppc_get_data(cpu, LOWEST_NONLINEAR_PERF));
++ print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_LOWEST_NONLINEAR_FREQ),
++ no_rounding);
++ printf(".\n");
++
++ printf(_(" AMD PSTATE Lowest Performance: %lu. Lowest Frequency: "),
++ acpi_cppc_get_data(cpu, LOWEST_PERF));
++ print_speed(acpi_cppc_get_data(cpu, LOWEST_FREQ) * 1000, no_rounding);
++ printf(".\n");
++}
++
+ /* AMD P-States Helper Functions ***************/
+ #endif /* defined(__i386__) || defined(__x86_64__) */
+diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
+index fbbfa6047c83..5f6862502dbf 100644
+--- a/tools/power/cpupower/utils/helpers/helpers.h
++++ b/tools/power/cpupower/utils/helpers/helpers.h
+@@ -142,6 +142,8 @@ extern int cpufreq_has_boost_support(unsigned int cpu, int *support,
+ extern bool cpupower_amd_pstate_enabled(void);
+ extern void amd_pstate_boost_init(unsigned int cpu,
+ int *support, int *active);
++extern void amd_pstate_show_perf_and_freq(unsigned int cpu,
++ int no_rounding);
+
+ /* AMD P-States stuff **************************/
+
+@@ -182,6 +184,9 @@ static inline bool cpupower_amd_pstate_enabled(void)
+ static void amd_pstate_boost_init(unsigned int cpu,
+ int *support, int *active)
+ { return; }
++static inline void amd_pstate_show_perf_and_freq(unsigned int cpu,
++ int no_rounding)
++{ return; }
+
+ /* cpuid and cpuinfo helpers **************************/
+
+
-From abfcbc164c1aa0c63d5e256854bad977a9645586 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Thu, 10 Jun 2021 23:40:18 +0800
-Subject: Documentation: amd-pstate: add amd-pstate driver introduction
Introduce the amd-pstate driver design and implementation.
Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- Documentation/admin-guide/pm/amd_pstate.rst | 377 +++++++++++++++++++++++++
- Documentation/admin-guide/pm/working-state.rst | 1 +
- 2 files changed, 378 insertions(+)
- create mode 100644 Documentation/admin-guide/pm/amd_pstate.rst
+ Documentation/admin-guide/pm/amd-pstate.rst | 373 ++++++++++++++++++
+ .../admin-guide/pm/working-state.rst | 1 +
+ 2 files changed, 374 insertions(+)
+ create mode 100644 Documentation/admin-guide/pm/amd-pstate.rst
-diff --git a/Documentation/admin-guide/pm/amd_pstate.rst b/Documentation/admin-guide/pm/amd_pstate.rst
+diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
new file mode 100644
-index 0000000000000..c3659dde0cee8
+index 000000000000..24a88476fc69
--- /dev/null
-+++ b/Documentation/admin-guide/pm/amd_pstate.rst
-@@ -0,0 +1,377 @@
++++ b/Documentation/admin-guide/pm/amd-pstate.rst
+@@ -0,0 +1,373 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: <isonum.txt>
+
@@ -2252,8 +2456,8 @@ index 0000000000000..c3659dde0cee8
+
+There are two types of hardware implementations for ``amd-pstate``: one is
+`Full MSR Support <perf_cap_>`_ and another is `Shared Memory Support
-+<perf_cap_>`_. It can use :c:macro:`X86_FEATURE_AMD_CPPC_EXT` feature flag
-+(for details refer to Processor Programming Reference (PPR) for AMD Family
++<perf_cap_>`_. It can use :c:macro:`X86_FEATURE_CPPC` feature flag (for
++details refer to Processor Programming Reference (PPR) for AMD Family
+19h Model 21h, Revision B0 Processors [3]_) to indicate the different
+types. ``amd-pstate`` is to register different ``amd_pstate_perf_funcs``
+instances for different hardware implementations.
@@ -2265,7 +2469,7 @@ index 0000000000000..c3659dde0cee8
+-----------------
+
+Some new Zen3 processors such as Cezanne provide the MSR registers directly
-+while the :c:macro:`X86_FEATURE_AMD_CPPC_EXT` CPU feature flag is set.
++while the :c:macro:`X86_FEATURE_CPPC` CPU feature flag is set.
+``amd-pstate`` can handle the MSR register to implement the fast switch
+function in ``CPUFreq`` that can shrink latency of frequency control on the
+interrupt context.
@@ -2273,10 +2477,10 @@ index 0000000000000..c3659dde0cee8
+Shared Memory Support
+----------------------
+
-+If :c:macro:`X86_FEATURE_AMD_CPPC_EXT` CPU feature flag is not set, that
-+means the processor supports shared memory solution. In this case,
-+``amd-pstate`` uses the ``cppc_acpi`` helper methods to implement the
-+callback functions of ``amd_pstate_perf_funcs``.
++If :c:macro:`X86_FEATURE_CPPC` CPU feature flag is not set, that means the
++processor supports shared memory solution. In this case, ``amd-pstate``
++uses the ``cppc_acpi`` helper methods to implement the callback functions
++of ``amd_pstate_perf_funcs``.
+
+
+AMD P-States and ACPI hardware P-States always can be supported in one
@@ -2301,14 +2505,7 @@ index 0000000000000..c3659dde0cee8
+ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_min_freq
+ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_nominal_freq
+ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_nominal_perf
-+ /sys/devices/system/cpu/cpufreq/policy0/is_amd_pstate_enabled
-+
+
-+``is_amd_pstate_enabled``
-+
-+Query whether current kernel loads ``amd-pstate`` to enable the AMD
-+P-States functionality.
-+This attribute is read-only.
+
+``amd_pstate_highest_perf / amd_pstate_max_freq``
+
@@ -2332,9 +2529,11 @@ index 0000000000000..c3659dde0cee8
+Capability <perf_cap_>`_).
+This attribute is read-only.
+
-+``amd_pstate_lowest_perf / amd_pstate_min_freq``
++``amd_pstate_lowest_perf``
+
-+The lowest physical CPPC performance and CPU frequency.
++The lowest physical CPPC performance. The minimum CPU frequency can be read
++back from ``cpuinfo`` member of ``cpufreq_policy``, so we won't expose it
++here.
+This attribute is read-only.
+
+
@@ -2408,12 +2607,13 @@ index 0000000000000..c3659dde0cee8
+ # ||| / delay
+ # TASK-PID CPU# |||| TIMESTAMP FUNCTION
+ # | | | |||| | |
-+ <idle>-0 [000] d.s. 244057.464842: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
-+ <idle>-0 [000] d.h. 244057.475436: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
-+ <idle>-0 [000] d.h. 244057.476629: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
-+ <idle>-0 [000] d.s. 244057.484847: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
-+ <idle>-0 [000] d.h. 244057.499821: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
-+ avahi-daemon-528 [000] d... 244057.513568: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
++ <idle>-0 [015] dN... 4995.979886: amd_pstate_perf: amd_min_perf=85 amd_des_perf=85 amd_max_perf=166 cpu_id=15 changed=false fast_switch=true
++ <idle>-0 [007] d.h.. 4995.979893: amd_pstate_perf: amd_min_perf=85 amd_des_perf=85 amd_max_perf=166 cpu_id=7 changed=false fast_switch=true
++ cat-2161 [000] d.... 4995.980841: amd_pstate_perf: amd_min_perf=85 amd_des_perf=85 amd_max_perf=166 cpu_id=0 changed=false fast_switch=true
++ sshd-2125 [004] d.s.. 4995.980968: amd_pstate_perf: amd_min_perf=85 amd_des_perf=85 amd_max_perf=166 cpu_id=4 changed=false fast_switch=true
++ <idle>-0 [007] d.s.. 4995.980968: amd_pstate_perf: amd_min_perf=85 amd_des_perf=85 amd_max_perf=166 cpu_id=7 changed=false fast_switch=true
++ <idle>-0 [003] d.s.. 4995.980971: amd_pstate_perf: amd_min_perf=85 amd_des_perf=85 amd_max_perf=166 cpu_id=3 changed=false fast_switch=true
++ <idle>-0 [011] d.s.. 4995.980996: amd_pstate_perf: amd_min_perf=85 amd_des_perf=85 amd_max_perf=166 cpu_id=11 changed=false fast_switch=true
+
+The cpu_frequency trace event will be triggered either by the ``schedutil`` scaling
+governor (for the policies it is attached to), or by the ``CPUFreq`` core (for the
@@ -2433,18 +2633,14 @@ index 0000000000000..c3659dde0cee8
+ https://www.amd.com/system/files/TechDocs/55898_B1_pub_0.50.zip
+
diff --git a/Documentation/admin-guide/pm/working-state.rst b/Documentation/admin-guide/pm/working-state.rst
-index f40994c422dc0..28db6156b55d5 100644
+index f40994c422dc..5d2757e2de65 100644
--- a/Documentation/admin-guide/pm/working-state.rst
+++ b/Documentation/admin-guide/pm/working-state.rst
@@ -11,6 +11,7 @@ Working-State Power Management
intel_idle
cpufreq
intel_pstate
-+ amd_pstate
++ amd-pstate
cpufreq_drivers
intel_epb
intel-speed-select
---
-cgit 1.2.3-1.el7
-
-