From fd8af343a299df264c41b1219358f502c7b5b18a Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 14 Feb 2022 18:14:47 +0800 Subject: x86/ACPI: CPPC: Rename cppc_msr.c to cppc.c Rename the cppc_msr.c to cppc.c in x86 ACPI, that expects to use this file to cover more function implementation for ACPI CPPC beside MSR helpers. Naming as "cppc" is more straightforward as one of the functionalities under ACPI subsystem. Signed-off-by: Huang Rui [ rjw: Subject ] Signed-off-by: Rafael J. Wysocki --- arch/x86/kernel/acpi/cppc.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 arch/x86/kernel/acpi/cppc.c (limited to 'arch/x86/kernel/acpi/cppc.c') diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c new file mode 100644 index 000000000000..08d823d72586 --- /dev/null +++ b/arch/x86/kernel/acpi/cppc.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * cppc.c: CPPC Interface for x86 + * Copyright (c) 2016, Intel Corporation. + */ + +#include +#include + +/* Refer to drivers/acpi/cppc_acpi.c for the description of functions */ + +bool cpc_ffh_supported(void) +{ + return true; +} + +int cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val) +{ + int err; + + err = rdmsrl_safe_on_cpu(cpunum, reg->address, val); + if (!err) { + u64 mask = GENMASK_ULL(reg->bit_offset + reg->bit_width - 1, + reg->bit_offset); + + *val &= mask; + *val >>= reg->bit_offset; + } + return err; +} + +int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val) +{ + u64 rd_val; + int err; + + err = rdmsrl_safe_on_cpu(cpunum, reg->address, &rd_val); + if (!err) { + u64 mask = GENMASK_ULL(reg->bit_offset + reg->bit_width - 1, + reg->bit_offset); + + val <<= reg->bit_offset; + val &= mask; + rd_val &= ~mask; + rd_val |= val; + err = wrmsrl_safe_on_cpu(cpunum, reg->address, rd_val); + } + return err; +} -- cgit v1.2.3 From 82d89369141b8fab56deff540121b8d09d289bfd Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 14 Feb 2022 18:14:48 +0800 Subject: x86/ACPI: CPPC: Move AMD maximum frequency ratio setting function into x86 CPPC The AMD maximum frequency ratio setting function depends on CPPC, so the x86 CPPC implementation file is better space for this function. Signed-off-by: Huang Rui [ rjw: Subject adjustment ] Signed-off-by: Rafael J. Wysocki --- arch/x86/kernel/acpi/cppc.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'arch/x86/kernel/acpi/cppc.c') diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c index 08d823d72586..f0be5058e3e3 100644 --- a/arch/x86/kernel/acpi/cppc.c +++ b/arch/x86/kernel/acpi/cppc.c @@ -6,6 +6,8 @@ #include #include +#include +#include /* Refer to drivers/acpi/cppc_acpi.c for the description of functions */ @@ -47,3 +49,41 @@ int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val) } return err; } + +bool amd_set_max_freq_ratio(u64 *ratio) +{ + struct cppc_perf_caps perf_caps; + u64 highest_perf, nominal_perf; + u64 perf_ratio; + int rc; + + if (!ratio) + return false; + + rc = cppc_get_perf_caps(0, &perf_caps); + if (rc) { + pr_debug("Could not retrieve perf counters (%d)\n", rc); + return false; + } + + highest_perf = amd_get_highest_perf(); + nominal_perf = perf_caps.nominal_perf; + + if (!highest_perf || !nominal_perf) { + pr_debug("Could not retrieve highest or nominal performance\n"); + return false; + } + + perf_ratio = div_u64(highest_perf * SCHED_CAPACITY_SCALE, nominal_perf); + /* midpoint between max_boost and max_P */ + perf_ratio = (perf_ratio + SCHED_CAPACITY_SCALE) >> 1; + if (!perf_ratio) { + pr_debug("Non-zero highest/nominal perf values led to a 0 ratio\n"); + return false; + } + + *ratio = perf_ratio; + arch_set_max_freq_ratio(false); + + return true; +} -- cgit v1.2.3 From eb5616d4adeebf958a42822ee440d79e9f803bf7 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 14 Feb 2022 18:14:50 +0800 Subject: x86/ACPI: CPPC: Move init_freq_invariance_cppc() into x86 CPPC The init_freq_invariance_cppc code actually doesn't need the SMP functionality. So setting the CONFIG_SMP as the check condition for init_freq_invariance_cppc may cause the confusion to misunderstand the CPPC. And the x86 CPPC file is better space to store the CPPC related functions, while the init_freq_invariance_cppc is out of smpboot, that means, the CONFIG_SMP won't be mandatory condition any more. And It's more clear than before. Signed-off-by: Huang Rui [ rjw: Subject adjustment ] Signed-off-by: Rafael J. Wysocki --- arch/x86/kernel/acpi/cppc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch/x86/kernel/acpi/cppc.c') diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c index f0be5058e3e3..df1644d9b3b6 100644 --- a/arch/x86/kernel/acpi/cppc.c +++ b/arch/x86/kernel/acpi/cppc.c @@ -87,3 +87,17 @@ bool amd_set_max_freq_ratio(u64 *ratio) return true; } + +static DEFINE_MUTEX(freq_invariance_lock); + +void init_freq_invariance_cppc(void) +{ + static bool secondary; + + mutex_lock(&freq_invariance_lock); + + init_freq_invariance(secondary, true); + secondary = true; + + mutex_unlock(&freq_invariance_lock); +} -- cgit v1.2.3