diff --git a/Documentation/admin-guide/pm/amd_pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst similarity index 90% rename from Documentation/admin-guide/pm/amd_pstate.rst rename to Documentation/admin-guide/pm/amd-pstate.rst index c3659dde0cee..375374e3eb80 100644 --- a/Documentation/admin-guide/pm/amd_pstate.rst +++ b/Documentation/admin-guide/pm/amd-pstate.rst @@ -195,8 +195,8 @@ driver. There are two types of hardware implementations for ``amd-pstate``: one is `Full MSR Support `_ and another is `Shared Memory Support -`_. It can use :c:macro:`X86_FEATURE_AMD_CPPC_EXT` feature flag -(for details refer to Processor Programming Reference (PPR) for AMD Family +`_. It can use :c:macro:`X86_FEATURE_AMD_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. @@ -208,7 +208,7 @@ Full MSR Support ----------------- 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_AMD_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. @@ -216,10 +216,10 @@ interrupt context. 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_AMD_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 @@ -244,15 +244,8 @@ control its functionality at the system level. They located in the /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`` Maximum CPPC performance and CPU frequency that the driver is allowed to @@ -275,9 +268,11 @@ allowed to set in percent of the maximum supported CPPC performance level Capability `_). 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. @@ -351,12 +346,13 @@ configured to support event tracing). :: # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | - -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 - -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 - -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 - -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 - -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 + -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 + -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 + -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 + -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 + -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 diff --git a/Documentation/admin-guide/pm/working-state.rst b/Documentation/admin-guide/pm/working-state.rst index 28db6156b55d..5d2757e2de65 100644 --- a/Documentation/admin-guide/pm/working-state.rst +++ b/Documentation/admin-guide/pm/working-state.rst @@ -11,7 +11,7 @@ Working-State Power Management intel_idle cpufreq intel_pstate - amd_pstate + amd-pstate cpufreq_drivers intel_epb intel-speed-select diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index b285960c35e7..9d25341fdfc5 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_online_cpu(cpu) { + for_each_present_cpu(cpu) { cpc_ptr = per_cpu(cpc_desc_ptr, cpu); if (!cpc_ptr) return false; @@ -759,9 +759,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; } @@ -936,7 +951,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; @@ -975,7 +1003,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 = ®_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; @@ -1228,21 +1268,17 @@ EXPORT_SYMBOL_GPL(cppc_get_perf_ctrs); * * 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; - - /* check the input value*/ - if (cpu < 0 || cpu > num_possible_cpus() - 1 || enable > 1) - return -ENODEV; + 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]; @@ -1262,9 +1298,10 @@ int cppc_set_enable(int cpu, u32 enable) /* 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); diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index 9cd7e338bdcd..2e798b2c0bdb 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 @@ -35,7 +35,7 @@ config X86_PCC_CPUFREQ If in doubt, say N. config X86_AMD_PSTATE - tristate "AMD Processor P-State driver" + bool "AMD Processor P-State driver" depends on X86 select ACPI_PROCESSOR if ACPI select ACPI_CPPC_LIB if X86_64 && ACPI && SCHED_MC_PRIO @@ -43,7 +43,11 @@ config X86_AMD_PSTATE 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. + performance levels. This driver supports the AMD processors with + _CPC object in the SBIOS. + + For details, take a look at: + . If in doubt, say N. diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 04882bc4b145..5c9a2a1ee8dc 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -17,10 +17,6 @@ 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 - ################################################################################## # x86 drivers. # Link order matters. K8 is preferred to ACPI because of firmware bugs in early @@ -29,7 +25,7 @@ amd_pstate-y := amd-pstate.o amd-pstate-trace.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_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 deleted file mode 100644 index 891b696dcd69..000000000000 --- a/drivers/cpufreq/amd-pstate-trace.c +++ /dev/null @@ -1,2 +0,0 @@ -#define CREATE_TRACE_POINTS -#include "amd-pstate-trace.h" diff --git a/drivers/cpufreq/amd-pstate-trace.h b/drivers/cpufreq/amd-pstate-trace.h deleted file mode 100644 index 50c85e150f30..000000000000 --- a/drivers/cpufreq/amd-pstate-trace.h +++ /dev/null @@ -1,96 +0,0 @@ -/* 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 - */ - -#if !defined(_AMD_PSTATE_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) -#define _AMD_PSTATE_TRACE_H - -#include -#include -#include - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM amd_cpu - -#undef TRACE_INCLUDE_FILE -#define TRACE_INCLUDE_FILE amd-pstate-trace - -#define TPS(x) tracepoint_string(x) - -TRACE_EVENT(amd_pstate_perf, - - TP_PROTO(unsigned long min_perf, - unsigned long target_perf, - unsigned long capacity, - unsigned int cpu_id, - u64 prev, - u64 value, - int type - ), - - TP_ARGS(min_perf, - target_perf, - capacity, - cpu_id, - prev, - value, - type - ), - - TP_STRUCT__entry( - __field(unsigned long, min_perf) - __field(unsigned long, target_perf) - __field(unsigned long, capacity) - __field(unsigned int, cpu_id) - __field(u64, prev) - __field(u64, value) - __field(int, type) - ), - - TP_fast_assign( - __entry->min_perf = min_perf; - __entry->target_perf = target_perf; - __entry->capacity = capacity; - __entry->cpu_id = cpu_id; - __entry->prev = prev; - __entry->value = value; - __entry->type = type; - ), - - 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", - (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 - ) -); - -#endif /* _AMD_PSTATE_TRACE_H */ - -/* This part must be outside protection */ -#undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . - -#include diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c index b0353d13f74a..58ee50bf492b 100644 --- a/drivers/cpufreq/amd-pstate.c +++ b/drivers/cpufreq/amd-pstate.c @@ -1,4 +1,3 @@ -// SPDX-License-Identifier: GPL-2.0-or-later /* * amd-pstate.c - AMD Processor P-state Frequency Driver * @@ -37,6 +36,7 @@ #include #include #include +#include #include #include @@ -45,24 +45,16 @@ #include #include #include -#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 -}; - static struct cpufreq_driver amd_pstate_driver; struct amd_cpudata { int cpu; struct freq_qos_request req[2]; - struct cpufreq_policy *policy; u64 cppc_req_cached; @@ -153,8 +145,7 @@ static inline int amd_pstate_init_perf(struct amd_cpudata *cpudata) } static void pstate_update_perf(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) { if (fast_switch) wrmsrl(MSR_AMD_CPPC_REQ, READ_ONCE(cpudata->cppc_req_cached)); @@ -178,21 +169,19 @@ static void cppc_update_perf(struct amd_cpudata *cpudata, DEFINE_STATIC_CALL(amd_pstate_update_perf, pstate_update_perf); -static inline void -amd_pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf, - u32 des_perf, u32 max_perf, bool fast_switch) +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 void -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; - enum switch_type type = fast_switch ? AMD_ADJUST_PERF : AMD_TARGET; value &= ~REQ_MIN_PERF(~0L); value |= REQ_MIN_PERF(min_perf); @@ -203,8 +192,8 @@ 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); + trace_amd_pstate_perf(min_perf, des_perf, max_perf, cpudata->cpu, + (value != prev), fast_switch); if (value == prev) return; @@ -401,23 +390,6 @@ static void amd_pstate_boost_init(struct amd_cpudata *cpudata) 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, - 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 int amd_pstate_cpu_init(struct cpufreq_policy *policy) { int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret; @@ -434,7 +406,6 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy) return -ENOMEM; cpudata->cpu = cpu; - cpudata->policy = policy; ret = amd_pstate_init_perf(cpudata); if (ret) @@ -481,13 +452,11 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy) 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; @@ -495,7 +464,6 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy) return 0; -free_cpudata3: freq_qos_remove_request(&cpudata->req[1]); free_cpudata2: freq_qos_remove_request(&cpudata->req[0]); @@ -519,6 +487,10 @@ static int amd_pstate_cpu_exit(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) { @@ -549,8 +521,8 @@ static ssize_t show_amd_pstate_nominal_freq(struct cpufreq_policy *policy, return sprintf(&buf[0], "%u\n", nominal_freq); } -static ssize_t -show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *policy, char *buf) +static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *policy, + char *buf) { int freq; struct amd_cpudata *cpudata; @@ -564,22 +536,8 @@ show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *policy, char *buf) return sprintf(&buf[0], "%u\n", freq); } -static ssize_t show_amd_pstate_min_freq(struct cpufreq_policy *policy, char *buf) -{ - int min_freq; - struct amd_cpudata *cpudata; - - cpudata = policy->driver_data; - - min_freq = amd_get_min_freq(cpudata); - if (min_freq < 0) - return min_freq; - - return sprintf(&buf[0], "%u\n", min_freq); -} - -static ssize_t -show_amd_pstate_highest_perf(struct cpufreq_policy *policy, char *buf) +static ssize_t show_amd_pstate_highest_perf(struct cpufreq_policy *policy, + char *buf) { u32 perf; struct amd_cpudata *cpudata = policy->driver_data; @@ -589,8 +547,8 @@ show_amd_pstate_highest_perf(struct cpufreq_policy *policy, char *buf) return sprintf(&buf[0], "%u\n", perf); } -static ssize_t -show_amd_pstate_nominal_perf(struct cpufreq_policy *policy, char *buf) +static ssize_t show_amd_pstate_nominal_perf(struct cpufreq_policy *policy, + char *buf) { u32 perf; struct amd_cpudata *cpudata = policy->driver_data; @@ -600,8 +558,8 @@ show_amd_pstate_nominal_perf(struct cpufreq_policy *policy, char *buf) return sprintf(&buf[0], "%u\n", perf); } -static ssize_t -show_amd_pstate_lowest_nonlinear_perf(struct cpufreq_policy *policy, char *buf) +static ssize_t show_amd_pstate_lowest_nonlinear_perf(struct cpufreq_policy *policy, + char *buf) { u32 perf; struct amd_cpudata *cpudata = policy->driver_data; @@ -611,8 +569,8 @@ show_amd_pstate_lowest_nonlinear_perf(struct cpufreq_policy *policy, char *buf) return sprintf(&buf[0], "%u\n", perf); } -static ssize_t -show_amd_pstate_lowest_perf(struct cpufreq_policy *policy, char *buf) +static ssize_t show_amd_pstate_lowest_perf(struct cpufreq_policy *policy, + char *buf) { u32 perf; struct amd_cpudata *cpudata = policy->driver_data; @@ -622,18 +580,9 @@ show_amd_pstate_lowest_perf(struct cpufreq_policy *policy, char *buf) return sprintf(&buf[0], "%u\n", perf); } -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); cpufreq_freq_attr_ro(amd_pstate_highest_perf); cpufreq_freq_attr_ro(amd_pstate_nominal_perf); @@ -641,11 +590,9 @@ 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, @@ -661,7 +608,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, + .attr = amd_pstate_attr, }; static int __init amd_pstate_init(void) @@ -709,15 +656,7 @@ static int __init amd_pstate_init(void) return 0; } -static void __exit amd_pstate_exit(void) -{ - cpufreq_unregister_driver(&amd_pstate_driver); - - amd_pstate_enable(false); -} - -module_init(amd_pstate_init); -module_exit(amd_pstate_exit); +device_initcall(amd_pstate_init); MODULE_AUTHOR("Huang Rui "); MODULE_DESCRIPTION("AMD Processor P-state Frequency Driver"); diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h index 3fdae40a75fc..550fa88cff86 100644 --- a/include/acpi/cppc_acpi.h +++ b/include/acpi/cppc_acpi.h @@ -137,7 +137,7 @@ struct cppc_cpudata { extern int cppc_get_desired_perf(int cpunum, u64 *desired_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); @@ -158,7 +158,7 @@ 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; } diff --git a/include/trace/events/power.h b/include/trace/events/power.h index af5018aa9517..c95c0b8d443d 100644 --- a/include/trace/events/power.h +++ b/include/trace/events/power.h @@ -173,6 +173,52 @@ TRACE_EVENT(cpu_frequency_limits, (unsigned long)__entry->cpu_id) ); +TRACE_EVENT(amd_pstate_perf, + + TP_PROTO(unsigned long min_perf, + unsigned long target_perf, + unsigned long capacity, + unsigned int cpu_id, + bool changed, + bool fast_switch + ), + + TP_ARGS(min_perf, + target_perf, + capacity, + cpu_id, + changed, + fast_switch + ), + + TP_STRUCT__entry( + __field(unsigned long, min_perf) + __field(unsigned long, target_perf) + __field(unsigned long, capacity) + __field(unsigned int, cpu_id) + __field(bool, changed) + __field(bool, fast_switch) + ), + + TP_fast_assign( + __entry->min_perf = min_perf; + __entry->target_perf = target_perf; + __entry->capacity = capacity; + __entry->cpu_id = cpu_id; + __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 changed=%s fast_switch=%s", + (unsigned long)__entry->min_perf, + (unsigned long)__entry->target_perf, + (unsigned long)__entry->capacity, + (unsigned int)__entry->cpu_id, + (__entry->changed) ? "true" : "false", + (__entry->fast_switch) ? "true" : "false" + ) +); + TRACE_EVENT(device_pm_callback_start, TP_PROTO(struct device *dev, const char *pm_ops, int event), diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c index d68d052ee4cb..fa38d3da42ce 100644 --- a/tools/power/cpupower/utils/helpers/amd.c +++ b/tools/power/cpupower/utils/helpers/amd.c @@ -160,7 +160,6 @@ enum amd_pstate_value { AMD_PSTATE_MAX_FREQ, AMD_PSTATE_NOMINAL_FREQ, AMD_PSTATE_LOWEST_NONLINEAR_FREQ, - AMD_PSTATE_MIN_FREQ, MAX_AMD_PSTATE_VALUE_READ_FILES }; @@ -172,7 +171,6 @@ static const char *amd_pstate_value_files[MAX_AMD_PSTATE_VALUE_READ_FILES] = { [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" }; static unsigned long amd_pstate_get_data(unsigned int cpu, @@ -204,8 +202,15 @@ void amd_pstate_boost_init(unsigned int cpu, int *support, int *active) void amd_pstate_show_perf_and_freq(unsigned int cpu, int no_rounding) { + unsigned long cpuinfo_max, cpuinfo_min; + + cpufreq_get_hardware_limits(cpu, &cpuinfo_min, &cpuinfo_max); + 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"); @@ -223,7 +228,7 @@ void amd_pstate_show_perf_and_freq(unsigned int cpu, int no_rounding) printf(_(" AMD PSTATE Lowest Performance: %lu. Lowest Frequency: "), amd_pstate_get_data(cpu, AMD_PSTATE_LOWEST_PERF)); - print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_MIN_FREQ), no_rounding); + print_speed(cpuinfo_min, no_rounding); printf(".\n"); } diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h index 80755568afc4..5f6862502dbf 100644 --- a/tools/power/cpupower/utils/helpers/helpers.h +++ b/tools/power/cpupower/utils/helpers/helpers.h @@ -11,6 +11,7 @@ #include #include +#include #include "helpers/bitmask.h" #include @@ -138,7 +139,7 @@ extern int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active, int * states); /* AMD P-States stuff **************************/ -extern unsigned long cpupower_amd_pstate_enabled(void); +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, @@ -178,8 +179,8 @@ static inline int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active, int * states) { return -1; } -static inline unsigned long cpupower_amd_pstate_enabled(void) -{ return 0; } +static inline bool cpupower_amd_pstate_enabled(void) +{ return false; } static void amd_pstate_boost_init(unsigned int cpu, int *support, int *active) { return; } diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c index 730f670ab90d..d693c96cd09c 100644 --- a/tools/power/cpupower/utils/helpers/misc.c +++ b/tools/power/cpupower/utils/helpers/misc.c @@ -3,9 +3,11 @@ #include #include #include +#include #include "helpers/helpers.h" #include "helpers/sysfs.h" +#include "cpufreq.h" #if defined(__i386__) || defined(__x86_64__) @@ -85,24 +87,20 @@ int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val) return 0; } -unsigned long cpupower_amd_pstate_enabled(void) +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 "cpu0/cpufreq/is_amd_pstate_enabled"); + 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__) */