Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'pm-cpufreq'

Merge cpufreq updates for 7.1-rc1:

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

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

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

- Add MAINTAINERS entry for CPPC driver (Viresh Kumar)

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

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

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

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

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

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

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

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

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

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

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

* pm-cpufreq: (38 commits)
cpufreq/amd-pstate: Add POWER_SUPPLY select for dynamic EPP
MAINTAINERS: amd-pstate: Step down as maintainer, add Prateek as reviewer
cpufreq: Pass the policy to cpufreq_driver->adjust_perf()
cpufreq/amd-pstate: Pass the policy to amd_pstate_update()
cpufreq/amd-pstate-ut: Add a unit test for raw EPP
cpufreq/amd-pstate: Add support for raw EPP writes
cpufreq/amd-pstate: Add support for platform profile class
cpufreq/amd-pstate: add kernel command line to override dynamic epp
cpufreq/amd-pstate: Add dynamic energy performance preference
Documentation: amd-pstate: fix dead links in the reference section
cpufreq/amd-pstate: Cache the max frequency in cpudata
Documentation/amd-pstate: Add documentation for amd_pstate_floor_{freq,count}
Documentation/amd-pstate: List amd_pstate_prefcore_ranking sysfs file
Documentation/amd-pstate: List amd_pstate_hw_prefcore sysfs file
amd-pstate-ut: Add a testcase to validate the visibility of driver attributes
amd-pstate-ut: Add module parameter to select testcases
amd-pstate: Introduce a tracepoint trace_amd_pstate_cppc_req2()
amd-pstate: Add sysfs support for floor_freq and floor_count
amd-pstate: Add support for CPPC_REQ2 and FLOOR_PERF
x86/cpufeatures: Add AMD CPPC Performance Priority feature.
...

+1105 -200
+7
Documentation/admin-guide/kernel-parameters.txt
··· 493 493 disable 494 494 Disable amd-pstate preferred core. 495 495 496 + amd_dynamic_epp= 497 + [X86] 498 + disable 499 + Disable amd-pstate dynamic EPP. 500 + enable 501 + Enable amd-pstate dynamic EPP. 502 + 496 503 amijoy.map= [HW,JOY] Amiga joystick support 497 504 Map of devices attached to JOY0DAT and JOY1DAT 498 505 Format: <a>,<b>
+77 -10
Documentation/admin-guide/pm/amd-pstate.rst
··· 239 239 240 240 root@hr-test1:/home/ray# ls /sys/devices/system/cpu/cpufreq/policy0/*amd* 241 241 /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_highest_perf 242 + /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_hw_prefcore 242 243 /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_lowest_nonlinear_freq 243 244 /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_max_freq 245 + /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_floor_freq 246 + /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_floor_count 247 + /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_prefcore_ranking 244 248 245 249 246 250 ``amd_pstate_highest_perf / amd_pstate_max_freq`` ··· 268 264 269 265 ``amd_pstate_hw_prefcore`` 270 266 271 - Whether the platform supports the preferred core feature and it has been 272 - enabled. This attribute is read-only. 267 + Whether the platform supports the preferred core feature and it has 268 + been enabled. This attribute is read-only. This file is only visible 269 + on platforms which support the preferred core feature. 273 270 274 271 ``amd_pstate_prefcore_ranking`` 275 272 276 273 The performance ranking of the core. This number doesn't have any unit, but 277 274 larger numbers are preferred at the time of reading. This can change at 278 - runtime based on platform conditions. This attribute is read-only. 275 + runtime based on platform conditions. This attribute is read-only. This file 276 + is only visible on platforms which support the preferred core feature. 277 + 278 + ``amd_pstate_floor_freq`` 279 + 280 + The floor frequency associated with each CPU. Userspace can write any 281 + value between ``cpuinfo_min_freq`` and ``scaling_max_freq`` into this 282 + file. When the system is under power or thermal constraints, the 283 + platform firmware will attempt to throttle the CPU frequency to the 284 + value specified in ``amd_pstate_floor_freq`` before throttling it 285 + further. This allows userspace to specify different floor frequencies 286 + to different CPUs. For optimal results, threads of the same core 287 + should have the same floor frequency value. This file is only visible 288 + on platforms that support the CPPC Performance Priority feature. 289 + 290 + 291 + ``amd_pstate_floor_count`` 292 + 293 + The number of distinct Floor Performance levels supported by the 294 + platform. For example, if this value is 2, then the number of unique 295 + values obtained from the command ``cat 296 + /sys/devices/system/cpu/cpufreq/policy*/amd_pstate_floor_freq | 297 + sort -n | uniq`` should be at most this number for the behavior 298 + described in ``amd_pstate_floor_freq`` to take effect. A zero value 299 + implies that the platform supports unlimited floor performance levels. 300 + This file is only visible on platforms that support the CPPC 301 + Performance Priority feature. 302 + 303 + **Note**: When ``amd_pstate_floor_count`` is non-zero, the frequency to 304 + which the CPU is throttled under power or thermal constraints is 305 + undefined when the number of unique values of ``amd_pstate_floor_freq`` 306 + across all CPUs in the system exceeds ``amd_pstate_floor_count``. 279 307 280 308 ``energy_performance_available_preferences`` 281 309 ··· 316 280 These profiles represent different hints that are provided 317 281 to the low-level firmware about the user's desired energy vs efficiency 318 282 tradeoff. ``default`` represents the epp value is set by platform 319 - firmware. This attribute is read-only. 283 + firmware. ``custom`` designates that integer values 0-255 may be written 284 + as well. This attribute is read-only. 320 285 321 286 ``energy_performance_preference`` 322 287 323 288 The current energy performance preference can be read from this attribute. 324 289 and user can change current preference according to energy or performance needs 325 - Please get all support profiles list from 326 - ``energy_performance_available_preferences`` attribute, all the profiles are 327 - integer values defined between 0 to 255 when EPP feature is enabled by platform 328 - firmware, if EPP feature is disabled, driver will ignore the written value 290 + Coarse named profiles are available in the attribute 291 + ``energy_performance_available_preferences``. 292 + Users can also write individual integer values between 0 to 255. 293 + When dynamic EPP is enabled, writes to energy_performance_preference are blocked 294 + even when EPP feature is enabled by platform firmware. Lower epp values shift the bias 295 + towards improved performance while a higher epp value shifts the bias towards 296 + power-savings. The exact impact can change from one platform to the other. 297 + If a valid integer was last written, then a number will be returned on future reads. 298 + If a valid string was last written then a string will be returned on future reads. 329 299 This attribute is read-write. 330 300 331 301 ``boost`` ··· 353 311 Other performance and frequency values can be read back from 354 312 ``/sys/devices/system/cpu/cpuX/acpi_cppc/``, see :ref:`cppc_sysfs`. 355 313 314 + Dynamic energy performance profile 315 + ================================== 316 + The amd-pstate driver supports dynamically selecting the energy performance 317 + profile based on whether the machine is running on AC or DC power. 318 + 319 + Whether this behavior is enabled by default depends on the kernel 320 + config option `CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`. This behavior can also be overridden 321 + at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``. 322 + 323 + When set to enabled, the driver will select a different energy performance 324 + profile when the machine is running on battery or AC power. The driver will 325 + also register with the platform profile handler to receive notifications of 326 + user desired power state and react to those. 327 + When set to disabled, the driver will not change the energy performance profile 328 + based on the power source and will not react to user desired power state. 329 + 330 + Attempting to manually write to the ``energy_performance_preference`` sysfs 331 + file will fail when ``dynamic_epp`` is enabled. 356 332 357 333 ``amd-pstate`` vs ``acpi-cpufreq`` 358 334 ====================================== ··· 481 421 For systems that support ``amd-pstate`` preferred core, the core rankings will 482 422 always be advertised by the platform. But OS can choose to ignore that via the 483 423 kernel parameter ``amd_prefcore=disable``. 424 + 425 + ``amd_dynamic_epp`` 426 + 427 + When AMD pstate is in auto mode, dynamic EPP will control whether the kernel 428 + autonomously changes the EPP mode. The default is configured by 429 + ``CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`` but can be explicitly enabled with 430 + ``amd_dynamic_epp=enable`` or disabled with ``amd_dynamic_epp=disable``. 484 431 485 432 User Space Interface in ``sysfs`` - General 486 433 =========================================== ··· 857 790 =========== 858 791 859 792 .. [1] AMD64 Architecture Programmer's Manual Volume 2: System Programming, 860 - https://www.amd.com/system/files/TechDocs/24593.pdf 793 + https://docs.amd.com/v/u/en-US/24593_3.44_APM_Vol2 861 794 862 795 .. [2] Advanced Configuration and Power Interface Specification, 863 796 https://uefi.org/sites/default/files/resources/ACPI_Spec_6_4_Jan22.pdf 864 797 865 798 .. [3] Processor Programming Reference (PPR) for AMD Family 19h Model 51h, Revision A1 Processors 866 - https://www.amd.com/system/files/TechDocs/56569-A1-PUB.zip 799 + https://docs.amd.com/v/u/en-US/56569-A1-PUB_3.03 867 800 868 801 .. [4] Linux Kernel Selftests, 869 802 https://www.kernel.org/doc/html/latest/dev-tools/kselftest.html
+1
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra-ccplex-cluster.yaml
··· 24 24 enum: 25 25 - nvidia,tegra186-ccplex-cluster 26 26 - nvidia,tegra234-ccplex-cluster 27 + - nvidia,tegra238-ccplex-cluster 27 28 28 29 reg: 29 30 maxItems: 1
+1
Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
··· 35 35 - description: v2 of CPUFREQ HW (EPSS) 36 36 items: 37 37 - enum: 38 + - qcom,eliza-cpufreq-epss 38 39 - qcom,milos-cpufreq-epss 39 40 - qcom,qcs8300-cpufreq-epss 40 41 - qcom,qdu1000-cpufreq-epss
+18 -7
MAINTAINERS
··· 1234 1234 1235 1235 AMD PSTATE DRIVER 1236 1236 M: Huang Rui <ray.huang@amd.com> 1237 - M: Gautham R. Shenoy <gautham.shenoy@amd.com> 1238 1237 M: Mario Limonciello <mario.limonciello@amd.com> 1239 1238 R: Perry Yuan <perry.yuan@amd.com> 1239 + R: K Prateek Nayak <kprateek.nayak@amd.com> 1240 1240 L: linux-pm@vger.kernel.org 1241 1241 S: Supported 1242 1242 F: Documentation/admin-guide/pm/amd-pstate.rst ··· 6616 6616 S: Maintained 6617 6617 F: drivers/i2c/busses/i2c-cp2615.c 6618 6618 6619 + CPU FREQUENCY DRIVERS - CPPC CPUFREQ 6620 + M: "Rafael J. Wysocki" <rafael@kernel.org> 6621 + M: Viresh Kumar <viresh.kumar@linaro.org> 6622 + R: Jie Zhan <zhanjie9@hisilicon.com> 6623 + R: Lifeng Zheng <zhenglifeng1@huawei.com> 6624 + R: Pierre Gondois <pierre.gondois@arm.com> 6625 + R: Sumit Gupta <sumitg@nvidia.com> 6626 + L: linux-pm@vger.kernel.org 6627 + S: Maintained 6628 + F: drivers/cpufreq/cppc_cpufreq.c 6629 + 6619 6630 CPU FREQUENCY DRIVERS - VEXPRESS SPC ARM BIG LITTLE 6620 6631 M: Viresh Kumar <viresh.kumar@linaro.org> 6621 6632 M: Sudeep Holla <sudeep.holla@kernel.org> ··· 6634 6623 S: Maintained 6635 6624 W: http://www.arm.com/products/processors/technologies/biglittleprocessing.php 6636 6625 F: drivers/cpufreq/vexpress-spc-cpufreq.c 6626 + 6627 + CPU FREQUENCY DRIVERS - VIRTUAL MACHINE CPUFREQ 6628 + M: Saravana Kannan <saravanak@kernel.org> 6629 + L: linux-pm@vger.kernel.org 6630 + S: Maintained 6631 + F: drivers/cpufreq/virtual-cpufreq.c 6637 6632 6638 6633 CPU FREQUENCY SCALING FRAMEWORK 6639 6634 M: "Rafael J. Wysocki" <rafael@kernel.org> ··· 6659 6642 F: kernel/sched/cpufreq*.c 6660 6643 F: rust/kernel/cpufreq.rs 6661 6644 F: tools/testing/selftests/cpufreq/ 6662 - 6663 - CPU FREQUENCY DRIVERS - VIRTUAL MACHINE CPUFREQ 6664 - M: Saravana Kannan <saravanak@kernel.org> 6665 - L: linux-pm@vger.kernel.org 6666 - S: Maintained 6667 - F: drivers/cpufreq/virtual-cpufreq.c 6668 6645 6669 6646 CPU HOTPLUG 6670 6647 M: Thomas Gleixner <tglx@kernel.org>
+1 -1
arch/x86/include/asm/cpufeatures.h
··· 415 415 */ 416 416 #define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* "overflow_recov" MCA overflow recovery support */ 417 417 #define X86_FEATURE_SUCCOR (17*32+ 1) /* "succor" Uncorrectable error containment and recovery */ 418 - 418 + #define X86_FEATURE_CPPC_PERF_PRIO (17*32+ 2) /* CPPC Floor Perf support */ 419 419 #define X86_FEATURE_SMCA (17*32+ 3) /* "smca" Scalable MCA */ 420 420 421 421 /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
+5
arch/x86/include/asm/msr-index.h
··· 765 765 #define MSR_AMD_CPPC_CAP2 0xc00102b2 766 766 #define MSR_AMD_CPPC_REQ 0xc00102b3 767 767 #define MSR_AMD_CPPC_STATUS 0xc00102b4 768 + #define MSR_AMD_CPPC_REQ2 0xc00102b5 768 769 769 770 /* Masks for use with MSR_AMD_CPPC_CAP1 */ 770 771 #define AMD_CPPC_LOWEST_PERF_MASK GENMASK(7, 0) 771 772 #define AMD_CPPC_LOWNONLIN_PERF_MASK GENMASK(15, 8) 772 773 #define AMD_CPPC_NOMINAL_PERF_MASK GENMASK(23, 16) 773 774 #define AMD_CPPC_HIGHEST_PERF_MASK GENMASK(31, 24) 775 + #define AMD_CPPC_FLOOR_PERF_CNT_MASK GENMASK_ULL(39, 32) 774 776 775 777 /* Masks for use with MSR_AMD_CPPC_REQ */ 776 778 #define AMD_CPPC_MAX_PERF_MASK GENMASK(7, 0) 777 779 #define AMD_CPPC_MIN_PERF_MASK GENMASK(15, 8) 778 780 #define AMD_CPPC_DES_PERF_MASK GENMASK(23, 16) 779 781 #define AMD_CPPC_EPP_PERF_MASK GENMASK(31, 24) 782 + 783 + /* Masks for use with MSR_AMD_CPPC_REQ2 */ 784 + #define AMD_CPPC_FLOOR_PERF_MASK GENMASK(7, 0) 780 785 781 786 /* AMD Performance Counter Global Status and Control MSRs */ 782 787 #define MSR_AMD64_PERF_CNTR_GLOBAL_STATUS 0xc0000300
+1
arch/x86/kernel/cpu/scattered.c
··· 52 52 { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 }, 53 53 { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 }, 54 54 { X86_FEATURE_AMD_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 }, 55 + { X86_FEATURE_CPPC_PERF_PRIO, CPUID_EDX, 16, 0x80000007, 0 }, 55 56 { X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 }, 56 57 { X86_FEATURE_X2AVIC_EXT, CPUID_ECX, 6, 0x8000000a, 0 }, 57 58 { X86_FEATURE_COHERENCY_SFW_NO, CPUID_EBX, 31, 0x8000001f, 0 },
+2 -1
drivers/acpi/cppc_acpi.c
··· 1944 1944 } 1945 1945 1946 1946 /* Look up the max frequency in DMI */ 1947 - static u64 cppc_get_dmi_max_khz(void) 1947 + u64 cppc_get_dmi_max_khz(void) 1948 1948 { 1949 1949 u16 mhz = 0; 1950 1950 ··· 1958 1958 1959 1959 return KHZ_PER_MHZ * mhz; 1960 1960 } 1961 + EXPORT_SYMBOL_GPL(cppc_get_dmi_max_khz); 1961 1962 1962 1963 /* 1963 1964 * If CPPC lowest_freq and nominal_freq registers are exposed then we can
+2 -3
drivers/cpufreq/Kconfig
··· 163 163 164 164 config CPU_FREQ_GOV_CONSERVATIVE 165 165 tristate "'conservative' cpufreq governor" 166 - depends on CPU_FREQ 167 166 select CPU_FREQ_GOV_COMMON 168 167 help 169 168 'conservative' - this driver is rather similar to the 'ondemand' ··· 187 188 188 189 config CPU_FREQ_GOV_SCHEDUTIL 189 190 bool "'schedutil' cpufreq policy governor" 190 - depends on CPU_FREQ && SMP 191 + depends on SMP 191 192 select CPU_FREQ_GOV_ATTR_SET 192 193 select IRQ_WORK 193 194 help ··· 364 365 365 366 If in doubt, say N. 366 367 367 - endif 368 + endif # CPU_FREQ 368 369 369 370 endmenu
+1 -1
drivers/cpufreq/Kconfig.arm
··· 248 248 249 249 config ARM_TEGRA194_CPUFREQ 250 250 tristate "Tegra194 CPUFreq support" 251 - depends on ARCH_TEGRA_194_SOC || ARCH_TEGRA_234_SOC || (64BIT && COMPILE_TEST) 251 + depends on ARCH_TEGRA_194_SOC || ARCH_TEGRA_234_SOC 252 252 depends on TEGRA_BPMP 253 253 default ARCH_TEGRA_194_SOC || ARCH_TEGRA_234_SOC 254 254 help
+14
drivers/cpufreq/Kconfig.x86
··· 40 40 select ACPI_PROCESSOR 41 41 select ACPI_CPPC_LIB if X86_64 42 42 select CPU_FREQ_GOV_SCHEDUTIL if SMP 43 + select ACPI_PLATFORM_PROFILE 44 + select POWER_SUPPLY 43 45 help 44 46 This driver adds a CPUFreq driver which utilizes a fine grain 45 47 processor performance frequency control range instead of legacy ··· 69 67 70 68 For details, take a look at: 71 69 <file:Documentation/admin-guide/pm/amd-pstate.rst>. 70 + 71 + config X86_AMD_PSTATE_DYNAMIC_EPP 72 + bool "AMD Processor P-State dynamic EPP support" 73 + depends on X86_AMD_PSTATE 74 + default n 75 + help 76 + Allow the kernel to dynamically change the energy performance 77 + value from events like ACPI platform profile and AC adapter plug 78 + events. 79 + 80 + This feature can also be changed at runtime, this configuration 81 + option only sets the kernel default value behavior. 72 82 73 83 config X86_AMD_PSTATE_UT 74 84 tristate "selftest for AMD Processor P-State driver"
+24 -7
drivers/cpufreq/acpi-cpufreq.c
··· 675 675 } 676 676 #endif 677 677 678 + static void acpi_cpufreq_resolve_max_freq(struct cpufreq_policy *policy, 679 + unsigned int pss_max_freq) 680 + { 681 + #ifdef CONFIG_ACPI_CPPC_LIB 682 + u64 max_speed = cppc_get_dmi_max_khz(); 683 + /* 684 + * Use DMI "Max Speed" if it looks plausible: must be 685 + * above _PSS P0 frequency and within 2x of it. 686 + */ 687 + if (max_speed > pss_max_freq && max_speed < pss_max_freq * 2) { 688 + policy->cpuinfo.max_freq = max_speed; 689 + return; 690 + } 691 + #endif 692 + /* 693 + * If the maximum "boost" frequency is unknown, ask the arch 694 + * scale-invariance code to use the "nominal" performance for 695 + * CPU utilization scaling so as to prevent the schedutil 696 + * governor from selecting inadequate CPU frequencies. 697 + */ 698 + arch_set_max_freq_ratio(true); 699 + } 700 + 678 701 static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) 679 702 { 680 703 struct cpufreq_frequency_table *freq_table; ··· 872 849 873 850 policy->cpuinfo.max_freq = freq * max_boost_ratio >> SCHED_CAPACITY_SHIFT; 874 851 } else { 875 - /* 876 - * If the maximum "boost" frequency is unknown, ask the arch 877 - * scale-invariance code to use the "nominal" performance for 878 - * CPU utilization scaling so as to prevent the schedutil 879 - * governor from selecting inadequate CPU frequencies. 880 - */ 881 - arch_set_max_freq_ratio(true); 852 + acpi_cpufreq_resolve_max_freq(policy, freq_table[0].frequency); 882 853 } 883 854 884 855 policy->freq_table = freq_table;
+35
drivers/cpufreq/amd-pstate-trace.h
··· 133 133 ) 134 134 ); 135 135 136 + TRACE_EVENT(amd_pstate_cppc_req2, 137 + 138 + TP_PROTO(unsigned int cpu_id, 139 + u8 floor_perf, 140 + bool changed, 141 + int err_code 142 + ), 143 + 144 + TP_ARGS(cpu_id, 145 + floor_perf, 146 + changed, 147 + err_code), 148 + 149 + TP_STRUCT__entry( 150 + __field(unsigned int, cpu_id) 151 + __field(u8, floor_perf) 152 + __field(bool, changed) 153 + __field(int, err_code) 154 + ), 155 + 156 + TP_fast_assign( 157 + __entry->cpu_id = cpu_id; 158 + __entry->floor_perf = floor_perf; 159 + __entry->changed = changed; 160 + __entry->err_code = err_code; 161 + ), 162 + 163 + TP_printk("cpu%u: floor_perf=%u, changed=%u (error = %d)", 164 + __entry->cpu_id, 165 + __entry->floor_perf, 166 + __entry->changed, 167 + __entry->err_code 168 + ) 169 + ); 170 + 136 171 #endif /* _AMD_PSTATE_TRACE_H */ 137 172 138 173 /* This part must be outside protection */
+273 -6
drivers/cpufreq/amd-pstate-ut.c
··· 23 23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 24 24 25 25 #include <linux/bitfield.h> 26 + #include <linux/cpufeature.h> 27 + #include <linux/cpufreq.h> 26 28 #include <linux/kernel.h> 27 29 #include <linux/module.h> 28 30 #include <linux/moduleparam.h> 31 + #include <linux/mm.h> 29 32 #include <linux/fs.h> 30 33 #include <linux/cleanup.h> 31 34 ··· 38 35 39 36 #include "amd-pstate.h" 40 37 38 + static char *test_list; 39 + module_param(test_list, charp, 0444); 40 + MODULE_PARM_DESC(test_list, 41 + "Comma-delimited list of tests to run (empty means run all tests)"); 42 + DEFINE_FREE(cleanup_page, void *, if (_T) free_page((unsigned long)_T)) 41 43 42 44 struct amd_pstate_ut_struct { 43 45 const char *name; ··· 56 48 static int amd_pstate_ut_check_enabled(u32 index); 57 49 static int amd_pstate_ut_check_perf(u32 index); 58 50 static int amd_pstate_ut_check_freq(u32 index); 51 + static int amd_pstate_ut_epp(u32 index); 59 52 static int amd_pstate_ut_check_driver(u32 index); 53 + static int amd_pstate_ut_check_freq_attrs(u32 index); 60 54 61 55 static struct amd_pstate_ut_struct amd_pstate_ut_cases[] = { 62 - {"amd_pstate_ut_acpi_cpc_valid", amd_pstate_ut_acpi_cpc_valid }, 63 - {"amd_pstate_ut_check_enabled", amd_pstate_ut_check_enabled }, 64 - {"amd_pstate_ut_check_perf", amd_pstate_ut_check_perf }, 65 - {"amd_pstate_ut_check_freq", amd_pstate_ut_check_freq }, 66 - {"amd_pstate_ut_check_driver", amd_pstate_ut_check_driver } 56 + {"amd_pstate_ut_acpi_cpc_valid", amd_pstate_ut_acpi_cpc_valid }, 57 + {"amd_pstate_ut_check_enabled", amd_pstate_ut_check_enabled }, 58 + {"amd_pstate_ut_check_perf", amd_pstate_ut_check_perf }, 59 + {"amd_pstate_ut_check_freq", amd_pstate_ut_check_freq }, 60 + {"amd_pstate_ut_epp", amd_pstate_ut_epp }, 61 + {"amd_pstate_ut_check_driver", amd_pstate_ut_check_driver }, 62 + {"amd_pstate_ut_check_freq_attrs", amd_pstate_ut_check_freq_attrs }, 67 63 }; 64 + 65 + static bool test_in_list(const char *list, const char *name) 66 + { 67 + size_t name_len = strlen(name); 68 + const char *p = list; 69 + 70 + while (*p) { 71 + const char *sep = strchr(p, ','); 72 + size_t token_len = sep ? sep - p : strlen(p); 73 + 74 + if (token_len == name_len && !strncmp(p, name, token_len)) 75 + return true; 76 + if (!sep) 77 + break; 78 + p = sep + 1; 79 + } 80 + 81 + return false; 82 + } 68 83 69 84 static bool get_shared_mem(void) 70 85 { ··· 272 241 return amd_pstate_update_status(mode_str, strlen(mode_str)); 273 242 } 274 243 244 + static int amd_pstate_ut_epp(u32 index) 245 + { 246 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = NULL; 247 + char *buf __free(cleanup_page) = NULL; 248 + static const char * const epp_strings[] = { 249 + "performance", 250 + "balance_performance", 251 + "balance_power", 252 + "power", 253 + }; 254 + struct amd_cpudata *cpudata; 255 + enum amd_pstate_mode orig_mode; 256 + bool orig_dynamic_epp; 257 + int ret, cpu = 0; 258 + int i; 259 + u16 epp; 260 + 261 + policy = cpufreq_cpu_get(cpu); 262 + if (!policy) 263 + return -ENODEV; 264 + 265 + cpudata = policy->driver_data; 266 + orig_mode = amd_pstate_get_status(); 267 + orig_dynamic_epp = cpudata->dynamic_epp; 268 + 269 + /* disable dynamic EPP before running test */ 270 + if (cpudata->dynamic_epp) { 271 + pr_debug("Dynamic EPP is enabled, disabling it\n"); 272 + amd_pstate_clear_dynamic_epp(policy); 273 + } 274 + 275 + buf = (char *)__get_free_page(GFP_KERNEL); 276 + if (!buf) 277 + return -ENOMEM; 278 + 279 + ret = amd_pstate_set_mode(AMD_PSTATE_ACTIVE); 280 + if (ret) 281 + goto out; 282 + 283 + for (epp = 0; epp <= U8_MAX; epp++) { 284 + u8 val; 285 + 286 + /* write all EPP values */ 287 + memset(buf, 0, PAGE_SIZE); 288 + snprintf(buf, PAGE_SIZE, "%d", epp); 289 + ret = store_energy_performance_preference(policy, buf, strlen(buf)); 290 + if (ret < 0) 291 + goto out; 292 + 293 + /* check if the EPP value reads back correctly for raw numbers */ 294 + memset(buf, 0, PAGE_SIZE); 295 + ret = show_energy_performance_preference(policy, buf); 296 + if (ret < 0) 297 + goto out; 298 + strreplace(buf, '\n', '\0'); 299 + ret = kstrtou8(buf, 0, &val); 300 + if (!ret && epp != val) { 301 + pr_err("Raw EPP value mismatch: %d != %d\n", epp, val); 302 + ret = -EINVAL; 303 + goto out; 304 + } 305 + } 306 + 307 + for (i = 0; i < ARRAY_SIZE(epp_strings); i++) { 308 + memset(buf, 0, PAGE_SIZE); 309 + snprintf(buf, PAGE_SIZE, "%s", epp_strings[i]); 310 + ret = store_energy_performance_preference(policy, buf, strlen(buf)); 311 + if (ret < 0) 312 + goto out; 313 + 314 + memset(buf, 0, PAGE_SIZE); 315 + ret = show_energy_performance_preference(policy, buf); 316 + if (ret < 0) 317 + goto out; 318 + strreplace(buf, '\n', '\0'); 319 + 320 + if (strcmp(buf, epp_strings[i])) { 321 + pr_err("String EPP value mismatch: %s != %s\n", buf, epp_strings[i]); 322 + ret = -EINVAL; 323 + goto out; 324 + } 325 + } 326 + 327 + ret = 0; 328 + 329 + out: 330 + if (orig_dynamic_epp) { 331 + int ret2; 332 + 333 + ret2 = amd_pstate_set_mode(AMD_PSTATE_DISABLE); 334 + if (!ret && ret2) 335 + ret = ret2; 336 + } 337 + 338 + if (orig_mode != amd_pstate_get_status()) { 339 + int ret2; 340 + 341 + ret2 = amd_pstate_set_mode(orig_mode); 342 + if (!ret && ret2) 343 + ret = ret2; 344 + } 345 + 346 + return ret; 347 + } 348 + 275 349 static int amd_pstate_ut_check_driver(u32 index) 276 350 { 277 351 enum amd_pstate_mode mode1, mode2 = AMD_PSTATE_DISABLE; ··· 406 270 return ret; 407 271 } 408 272 273 + enum attr_category { 274 + ATTR_ALWAYS, 275 + ATTR_PREFCORE, 276 + ATTR_EPP, 277 + ATTR_FLOOR_FREQ, 278 + }; 279 + 280 + static const struct { 281 + const char *name; 282 + enum attr_category category; 283 + } expected_freq_attrs[] = { 284 + {"amd_pstate_max_freq", ATTR_ALWAYS}, 285 + {"amd_pstate_lowest_nonlinear_freq", ATTR_ALWAYS}, 286 + {"amd_pstate_highest_perf", ATTR_ALWAYS}, 287 + {"amd_pstate_prefcore_ranking", ATTR_PREFCORE}, 288 + {"amd_pstate_hw_prefcore", ATTR_PREFCORE}, 289 + {"energy_performance_preference", ATTR_EPP}, 290 + {"energy_performance_available_preferences", ATTR_EPP}, 291 + {"amd_pstate_floor_freq", ATTR_FLOOR_FREQ}, 292 + {"amd_pstate_floor_count", ATTR_FLOOR_FREQ}, 293 + }; 294 + 295 + static bool attr_in_driver(struct freq_attr **driver_attrs, const char *name) 296 + { 297 + int j; 298 + 299 + for (j = 0; driver_attrs[j]; j++) { 300 + if (!strcmp(driver_attrs[j]->attr.name, name)) 301 + return true; 302 + } 303 + return false; 304 + } 305 + 306 + /* 307 + * Verify that for each mode the driver's live ->attr array contains exactly 308 + * the attributes that should be visible. Expected visibility is derived 309 + * independently from hw_prefcore, cpu features, and the current mode — 310 + * not from the driver's own visibility functions. 311 + */ 312 + static int amd_pstate_ut_check_freq_attrs(u32 index) 313 + { 314 + enum amd_pstate_mode orig_mode = amd_pstate_get_status(); 315 + static const enum amd_pstate_mode modes[] = { 316 + AMD_PSTATE_PASSIVE, AMD_PSTATE_ACTIVE, AMD_PSTATE_GUIDED, 317 + }; 318 + bool has_prefcore, has_floor_freq; 319 + int m, i, ret; 320 + 321 + has_floor_freq = cpu_feature_enabled(X86_FEATURE_CPPC_PERF_PRIO); 322 + 323 + /* 324 + * Determine prefcore support from any online CPU's cpudata. 325 + * hw_prefcore reflects the platform-wide decision made at init. 326 + */ 327 + has_prefcore = false; 328 + for_each_online_cpu(i) { 329 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = NULL; 330 + struct amd_cpudata *cpudata; 331 + 332 + policy = cpufreq_cpu_get(i); 333 + if (!policy) 334 + continue; 335 + cpudata = policy->driver_data; 336 + has_prefcore = cpudata->hw_prefcore; 337 + break; 338 + } 339 + 340 + for (m = 0; m < ARRAY_SIZE(modes); m++) { 341 + struct freq_attr **driver_attrs; 342 + 343 + ret = amd_pstate_set_mode(modes[m]); 344 + if (ret) 345 + goto out; 346 + 347 + driver_attrs = amd_pstate_get_current_attrs(); 348 + if (!driver_attrs) { 349 + pr_err("%s: no driver attrs in mode %s\n", 350 + __func__, amd_pstate_get_mode_string(modes[m])); 351 + ret = -EINVAL; 352 + goto out; 353 + } 354 + 355 + for (i = 0; i < ARRAY_SIZE(expected_freq_attrs); i++) { 356 + bool expected, found; 357 + 358 + switch (expected_freq_attrs[i].category) { 359 + case ATTR_ALWAYS: 360 + expected = true; 361 + break; 362 + case ATTR_PREFCORE: 363 + expected = has_prefcore; 364 + break; 365 + case ATTR_EPP: 366 + expected = (modes[m] == AMD_PSTATE_ACTIVE); 367 + break; 368 + case ATTR_FLOOR_FREQ: 369 + expected = has_floor_freq; 370 + break; 371 + default: 372 + expected = false; 373 + break; 374 + } 375 + 376 + found = attr_in_driver(driver_attrs, 377 + expected_freq_attrs[i].name); 378 + 379 + if (expected != found) { 380 + pr_err("%s: mode %s: attr %s expected %s but is %s\n", 381 + __func__, 382 + amd_pstate_get_mode_string(modes[m]), 383 + expected_freq_attrs[i].name, 384 + expected ? "visible" : "hidden", 385 + found ? "visible" : "hidden"); 386 + ret = -EINVAL; 387 + goto out; 388 + } 389 + } 390 + } 391 + 392 + ret = 0; 393 + out: 394 + amd_pstate_set_mode(orig_mode); 395 + return ret; 396 + } 397 + 409 398 static int __init amd_pstate_ut_init(void) 410 399 { 411 400 u32 i = 0, arr_size = ARRAY_SIZE(amd_pstate_ut_cases); 412 401 413 402 for (i = 0; i < arr_size; i++) { 414 - int ret = amd_pstate_ut_cases[i].func(i); 403 + int ret; 404 + 405 + if (test_list && *test_list && 406 + !test_in_list(test_list, amd_pstate_ut_cases[i].name)) 407 + continue; 408 + 409 + ret = amd_pstate_ut_cases[i].func(i); 415 410 416 411 if (ret) 417 412 pr_err("%-4d %-20s\t fail: %d!\n", i+1, amd_pstate_ut_cases[i].name, ret);
+543 -84
drivers/cpufreq/amd-pstate.c
··· 36 36 #include <linux/io.h> 37 37 #include <linux/delay.h> 38 38 #include <linux/uaccess.h> 39 + #include <linux/power_supply.h> 39 40 #include <linux/static_call.h> 40 41 #include <linux/topology.h> 41 42 ··· 87 86 static struct cpufreq_driver amd_pstate_epp_driver; 88 87 static int cppc_state = AMD_PSTATE_UNDEFINED; 89 88 static bool amd_pstate_prefcore = true; 89 + #ifdef CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP 90 + static bool dynamic_epp = CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP; 91 + #else 92 + static bool dynamic_epp; 93 + #endif 90 94 static struct quirk_entry *quirks; 91 95 92 96 /* ··· 109 103 * 2 balance_performance 110 104 * 3 balance_power 111 105 * 4 power 106 + * 5 custom (for raw EPP values) 112 107 */ 113 108 enum energy_perf_value_index { 114 109 EPP_INDEX_DEFAULT = 0, ··· 117 110 EPP_INDEX_BALANCE_PERFORMANCE, 118 111 EPP_INDEX_BALANCE_POWERSAVE, 119 112 EPP_INDEX_POWERSAVE, 113 + EPP_INDEX_CUSTOM, 120 114 EPP_INDEX_MAX, 121 115 }; 122 116 ··· 127 119 [EPP_INDEX_BALANCE_PERFORMANCE] = "balance_performance", 128 120 [EPP_INDEX_BALANCE_POWERSAVE] = "balance_power", 129 121 [EPP_INDEX_POWERSAVE] = "power", 122 + [EPP_INDEX_CUSTOM] = "custom", 130 123 }; 131 124 static_assert(ARRAY_SIZE(energy_perf_strings) == EPP_INDEX_MAX); 132 125 ··· 138 129 [EPP_INDEX_BALANCE_POWERSAVE] = AMD_CPPC_EPP_BALANCE_POWERSAVE, 139 130 [EPP_INDEX_POWERSAVE] = AMD_CPPC_EPP_POWERSAVE, 140 131 }; 141 - static_assert(ARRAY_SIZE(epp_values) == EPP_INDEX_MAX); 132 + static_assert(ARRAY_SIZE(epp_values) == EPP_INDEX_MAX - 1); 142 133 143 134 typedef int (*cppc_mode_transition_fn)(int); 144 135 ··· 270 261 271 262 if (fast_switch) { 272 263 wrmsrq(MSR_AMD_CPPC_REQ, value); 273 - return 0; 274 264 } else { 275 265 int ret = wrmsrq_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value); 276 266 ··· 336 328 static inline int amd_pstate_set_epp(struct cpufreq_policy *policy, u8 epp) 337 329 { 338 330 return static_call(amd_pstate_set_epp)(policy, epp); 331 + } 332 + 333 + static int amd_pstate_set_floor_perf(struct cpufreq_policy *policy, u8 perf) 334 + { 335 + struct amd_cpudata *cpudata = policy->driver_data; 336 + u64 value, prev; 337 + bool changed; 338 + int ret; 339 + 340 + if (!cpu_feature_enabled(X86_FEATURE_CPPC_PERF_PRIO)) 341 + return 0; 342 + 343 + value = prev = READ_ONCE(cpudata->cppc_req2_cached); 344 + FIELD_MODIFY(AMD_CPPC_FLOOR_PERF_MASK, &value, perf); 345 + 346 + changed = value != prev; 347 + if (!changed) { 348 + ret = 0; 349 + goto out_trace; 350 + } 351 + 352 + ret = wrmsrq_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ2, value); 353 + if (ret) { 354 + changed = false; 355 + pr_err("failed to set CPPC REQ2 value. Error (%d)\n", ret); 356 + goto out_trace; 357 + } 358 + 359 + WRITE_ONCE(cpudata->cppc_req2_cached, value); 360 + 361 + out_trace: 362 + if (trace_amd_pstate_cppc_req2_enabled()) 363 + trace_amd_pstate_cppc_req2(cpudata->cpu, perf, changed, ret); 364 + return ret; 365 + } 366 + 367 + static int amd_pstate_init_floor_perf(struct cpufreq_policy *policy) 368 + { 369 + struct amd_cpudata *cpudata = policy->driver_data; 370 + u8 floor_perf; 371 + u64 value; 372 + int ret; 373 + 374 + if (!cpu_feature_enabled(X86_FEATURE_CPPC_PERF_PRIO)) 375 + return 0; 376 + 377 + ret = rdmsrq_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ2, &value); 378 + if (ret) { 379 + pr_err("failed to read CPPC REQ2 value. Error (%d)\n", ret); 380 + return ret; 381 + } 382 + 383 + WRITE_ONCE(cpudata->cppc_req2_cached, value); 384 + floor_perf = FIELD_GET(AMD_CPPC_FLOOR_PERF_MASK, 385 + cpudata->cppc_req2_cached); 386 + 387 + /* Set a sane value for floor_perf if the default value is invalid */ 388 + if (floor_perf < cpudata->perf.lowest_perf) { 389 + floor_perf = cpudata->perf.nominal_perf; 390 + ret = amd_pstate_set_floor_perf(policy, floor_perf); 391 + if (ret) 392 + return ret; 393 + } 394 + 395 + 396 + cpudata->bios_floor_perf = floor_perf; 397 + cpudata->floor_freq = perf_to_freq(cpudata->perf, cpudata->nominal_freq, 398 + floor_perf); 399 + return 0; 339 400 } 340 401 341 402 static int shmem_set_epp(struct cpufreq_policy *policy, u8 epp) ··· 504 427 perf.lowest_perf = FIELD_GET(AMD_CPPC_LOWEST_PERF_MASK, cap1); 505 428 WRITE_ONCE(cpudata->perf, perf); 506 429 WRITE_ONCE(cpudata->prefcore_ranking, FIELD_GET(AMD_CPPC_HIGHEST_PERF_MASK, cap1)); 430 + WRITE_ONCE(cpudata->floor_perf_cnt, FIELD_GET(AMD_CPPC_FLOOR_PERF_CNT_MASK, cap1)); 507 431 508 432 return 0; 509 433 } ··· 643 565 return true; 644 566 } 645 567 646 - static void amd_pstate_update(struct amd_cpudata *cpudata, u8 min_perf, 568 + static void amd_pstate_update(struct cpufreq_policy *policy, u8 min_perf, 647 569 u8 des_perf, u8 max_perf, bool fast_switch, int gov_flags) 648 570 { 649 - struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu); 571 + struct amd_cpudata *cpudata = policy->driver_data; 650 572 union perf_cached perf = READ_ONCE(cpudata->perf); 651 - 652 - if (!policy) 653 - return; 654 573 655 574 /* limit the max perf when core performance boost feature is disabled */ 656 575 if (!cpudata->boost_supported) ··· 763 688 if (!fast_switch) 764 689 cpufreq_freq_transition_begin(policy, &freqs); 765 690 766 - amd_pstate_update(cpudata, perf.min_limit_perf, des_perf, 691 + amd_pstate_update(policy, perf.min_limit_perf, des_perf, 767 692 perf.max_limit_perf, fast_switch, 768 693 policy->governor->flags); 769 694 ··· 788 713 return policy->cur; 789 714 } 790 715 791 - static void amd_pstate_adjust_perf(unsigned int cpu, 716 + static void amd_pstate_adjust_perf(struct cpufreq_policy *policy, 792 717 unsigned long _min_perf, 793 718 unsigned long target_perf, 794 719 unsigned long capacity) 795 720 { 796 721 u8 max_perf, min_perf, des_perf, cap_perf; 797 - struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 798 722 struct amd_cpudata *cpudata; 799 723 union perf_cached perf; 800 724 ··· 824 750 if (max_perf < min_perf) 825 751 max_perf = min_perf; 826 752 827 - amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true, 753 + amd_pstate_update(policy, min_perf, des_perf, max_perf, true, 828 754 policy->governor->flags); 829 755 } 830 756 831 757 static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on) 832 758 { 833 759 struct amd_cpudata *cpudata = policy->driver_data; 834 - union perf_cached perf = READ_ONCE(cpudata->perf); 835 - u32 nominal_freq, max_freq; 760 + u32 nominal_freq; 836 761 int ret = 0; 837 762 838 763 nominal_freq = READ_ONCE(cpudata->nominal_freq); 839 - max_freq = perf_to_freq(perf, cpudata->nominal_freq, perf.highest_perf); 840 764 841 765 if (on) 842 - policy->cpuinfo.max_freq = max_freq; 766 + policy->cpuinfo.max_freq = cpudata->max_freq; 843 767 else if (policy->cpuinfo.max_freq > nominal_freq) 844 768 policy->cpuinfo.max_freq = nominal_freq; 845 - 846 - policy->max = policy->cpuinfo.max_freq; 847 769 848 770 if (cppc_state == AMD_PSTATE_PASSIVE) { 849 771 ret = freq_qos_update_request(&cpudata->req[1], policy->cpuinfo.max_freq); ··· 1022 952 1023 953 WRITE_ONCE(cpudata->nominal_freq, nominal_freq); 1024 954 955 + /* max_freq is calculated according to (nominal_freq * highest_perf)/nominal_perf */ 1025 956 max_freq = perf_to_freq(perf, nominal_freq, perf.highest_perf); 957 + WRITE_ONCE(cpudata->max_freq, max_freq); 958 + 1026 959 lowest_nonlinear_freq = perf_to_freq(perf, nominal_freq, perf.lowest_nonlinear_perf); 1027 960 WRITE_ONCE(cpudata->lowest_nonlinear_freq, lowest_nonlinear_freq); 1028 961 1029 962 /** 1030 963 * Below values need to be initialized correctly, otherwise driver will fail to load 1031 - * max_freq is calculated according to (nominal_freq * highest_perf)/nominal_perf 1032 964 * lowest_nonlinear_freq is a value between [min_freq, nominal_freq] 1033 965 * Check _CPC in ACPI table objects if any values are incorrect 1034 966 */ ··· 1093 1021 policy->cpuinfo.min_freq = policy->min = perf_to_freq(perf, 1094 1022 cpudata->nominal_freq, 1095 1023 perf.lowest_perf); 1096 - policy->cpuinfo.max_freq = policy->max = perf_to_freq(perf, 1097 - cpudata->nominal_freq, 1098 - perf.highest_perf); 1024 + policy->cpuinfo.max_freq = policy->max = cpudata->max_freq; 1099 1025 1026 + policy->driver_data = cpudata; 1100 1027 ret = amd_pstate_cppc_enable(policy); 1101 1028 if (ret) 1102 1029 goto free_cpudata1; ··· 1107 1036 1108 1037 if (cpu_feature_enabled(X86_FEATURE_CPPC)) 1109 1038 policy->fast_switch_possible = true; 1039 + 1040 + ret = amd_pstate_init_floor_perf(policy); 1041 + if (ret) { 1042 + dev_err(dev, "Failed to initialize Floor Perf (%d)\n", ret); 1043 + goto free_cpudata1; 1044 + } 1110 1045 1111 1046 ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0], 1112 1047 FREQ_QOS_MIN, FREQ_QOS_MIN_DEFAULT_VALUE); ··· 1128 1051 goto free_cpudata2; 1129 1052 } 1130 1053 1131 - policy->driver_data = cpudata; 1132 1054 1133 1055 if (!current_pstate_driver->adjust_perf) 1134 1056 current_pstate_driver->adjust_perf = amd_pstate_adjust_perf; ··· 1139 1063 free_cpudata1: 1140 1064 pr_warn("Failed to initialize CPU %d: %d\n", policy->cpu, ret); 1141 1065 kfree(cpudata); 1066 + policy->driver_data = NULL; 1142 1067 return ret; 1143 1068 } 1144 1069 ··· 1150 1073 1151 1074 /* Reset CPPC_REQ MSR to the BIOS value */ 1152 1075 amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false); 1076 + amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf); 1153 1077 1154 1078 freq_qos_remove_request(&cpudata->req[1]); 1155 1079 freq_qos_remove_request(&cpudata->req[0]); 1156 1080 policy->fast_switch_possible = false; 1157 1081 kfree(cpudata); 1082 + } 1083 + 1084 + static int amd_pstate_get_balanced_epp(struct cpufreq_policy *policy) 1085 + { 1086 + struct amd_cpudata *cpudata = policy->driver_data; 1087 + 1088 + if (power_supply_is_system_supplied()) 1089 + return cpudata->epp_default_ac; 1090 + else 1091 + return cpudata->epp_default_dc; 1092 + } 1093 + 1094 + static int amd_pstate_power_supply_notifier(struct notifier_block *nb, 1095 + unsigned long event, void *data) 1096 + { 1097 + struct amd_cpudata *cpudata = container_of(nb, struct amd_cpudata, power_nb); 1098 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu); 1099 + u8 epp; 1100 + int ret; 1101 + 1102 + if (event != PSY_EVENT_PROP_CHANGED) 1103 + return NOTIFY_OK; 1104 + 1105 + /* dynamic actions are only applied while platform profile is in balanced */ 1106 + if (cpudata->current_profile != PLATFORM_PROFILE_BALANCED) 1107 + return 0; 1108 + 1109 + epp = amd_pstate_get_balanced_epp(policy); 1110 + 1111 + ret = amd_pstate_set_epp(policy, epp); 1112 + if (ret) 1113 + pr_warn("Failed to set CPU %d EPP %u: %d\n", cpudata->cpu, epp, ret); 1114 + 1115 + return NOTIFY_OK; 1116 + } 1117 + 1118 + static int amd_pstate_profile_probe(void *drvdata, unsigned long *choices) 1119 + { 1120 + set_bit(PLATFORM_PROFILE_LOW_POWER, choices); 1121 + set_bit(PLATFORM_PROFILE_BALANCED, choices); 1122 + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 1123 + 1124 + return 0; 1125 + } 1126 + 1127 + static int amd_pstate_profile_get(struct device *dev, 1128 + enum platform_profile_option *profile) 1129 + { 1130 + struct amd_cpudata *cpudata = dev_get_drvdata(dev); 1131 + 1132 + *profile = cpudata->current_profile; 1133 + 1134 + return 0; 1135 + } 1136 + 1137 + static int amd_pstate_profile_set(struct device *dev, 1138 + enum platform_profile_option profile) 1139 + { 1140 + struct amd_cpudata *cpudata = dev_get_drvdata(dev); 1141 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu); 1142 + int ret; 1143 + 1144 + switch (profile) { 1145 + case PLATFORM_PROFILE_LOW_POWER: 1146 + ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_POWERSAVE); 1147 + if (ret) 1148 + return ret; 1149 + break; 1150 + case PLATFORM_PROFILE_BALANCED: 1151 + ret = amd_pstate_set_epp(policy, 1152 + amd_pstate_get_balanced_epp(policy)); 1153 + if (ret) 1154 + return ret; 1155 + break; 1156 + case PLATFORM_PROFILE_PERFORMANCE: 1157 + ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_PERFORMANCE); 1158 + if (ret) 1159 + return ret; 1160 + break; 1161 + default: 1162 + pr_err("Unknown Platform Profile %d\n", profile); 1163 + return -EOPNOTSUPP; 1164 + } 1165 + 1166 + cpudata->current_profile = profile; 1167 + 1168 + return 0; 1169 + } 1170 + 1171 + static const struct platform_profile_ops amd_pstate_profile_ops = { 1172 + .probe = amd_pstate_profile_probe, 1173 + .profile_set = amd_pstate_profile_set, 1174 + .profile_get = amd_pstate_profile_get, 1175 + }; 1176 + 1177 + void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy) 1178 + { 1179 + struct amd_cpudata *cpudata = policy->driver_data; 1180 + 1181 + if (cpudata->power_nb.notifier_call) 1182 + power_supply_unreg_notifier(&cpudata->power_nb); 1183 + if (cpudata->ppdev) { 1184 + platform_profile_remove(cpudata->ppdev); 1185 + cpudata->ppdev = NULL; 1186 + } 1187 + kfree(cpudata->profile_name); 1188 + cpudata->dynamic_epp = false; 1189 + } 1190 + EXPORT_SYMBOL_GPL(amd_pstate_clear_dynamic_epp); 1191 + 1192 + static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy) 1193 + { 1194 + struct amd_cpudata *cpudata = policy->driver_data; 1195 + int ret; 1196 + u8 epp; 1197 + 1198 + switch (cpudata->current_profile) { 1199 + case PLATFORM_PROFILE_PERFORMANCE: 1200 + epp = AMD_CPPC_EPP_PERFORMANCE; 1201 + break; 1202 + case PLATFORM_PROFILE_LOW_POWER: 1203 + epp = AMD_CPPC_EPP_POWERSAVE; 1204 + break; 1205 + case PLATFORM_PROFILE_BALANCED: 1206 + epp = amd_pstate_get_balanced_epp(policy); 1207 + break; 1208 + default: 1209 + pr_err("Unknown Platform Profile %d\n", cpudata->current_profile); 1210 + return -EOPNOTSUPP; 1211 + } 1212 + ret = amd_pstate_set_epp(policy, epp); 1213 + if (ret) 1214 + return ret; 1215 + 1216 + cpudata->profile_name = kasprintf(GFP_KERNEL, "amd-pstate-epp-cpu%d", cpudata->cpu); 1217 + 1218 + cpudata->ppdev = platform_profile_register(get_cpu_device(policy->cpu), 1219 + cpudata->profile_name, 1220 + policy->driver_data, 1221 + &amd_pstate_profile_ops); 1222 + if (IS_ERR(cpudata->ppdev)) { 1223 + ret = PTR_ERR(cpudata->ppdev); 1224 + goto cleanup; 1225 + } 1226 + 1227 + /* only enable notifier if things will actually change */ 1228 + if (cpudata->epp_default_ac != cpudata->epp_default_dc) { 1229 + cpudata->power_nb.notifier_call = amd_pstate_power_supply_notifier; 1230 + ret = power_supply_reg_notifier(&cpudata->power_nb); 1231 + if (ret) 1232 + goto cleanup; 1233 + } 1234 + 1235 + cpudata->dynamic_epp = true; 1236 + 1237 + return 0; 1238 + 1239 + cleanup: 1240 + amd_pstate_clear_dynamic_epp(policy); 1241 + 1242 + return ret; 1158 1243 } 1159 1244 1160 1245 /* Sysfs attributes */ ··· 1329 1090 static ssize_t show_amd_pstate_max_freq(struct cpufreq_policy *policy, 1330 1091 char *buf) 1331 1092 { 1332 - struct amd_cpudata *cpudata; 1333 - union perf_cached perf; 1093 + struct amd_cpudata *cpudata = policy->driver_data; 1334 1094 1335 - cpudata = policy->driver_data; 1336 - perf = READ_ONCE(cpudata->perf); 1337 - 1338 - return sysfs_emit(buf, "%u\n", 1339 - perf_to_freq(perf, cpudata->nominal_freq, perf.highest_perf)); 1095 + return sysfs_emit(buf, "%u\n", cpudata->max_freq); 1340 1096 } 1341 1097 1342 1098 static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *policy, ··· 1401 1167 return offset; 1402 1168 } 1403 1169 1404 - static ssize_t store_energy_performance_preference( 1405 - struct cpufreq_policy *policy, const char *buf, size_t count) 1170 + ssize_t store_energy_performance_preference(struct cpufreq_policy *policy, 1171 + const char *buf, size_t count) 1406 1172 { 1407 1173 struct amd_cpudata *cpudata = policy->driver_data; 1408 1174 ssize_t ret; 1175 + bool raw_epp = false; 1409 1176 u8 epp; 1410 1177 1411 - ret = sysfs_match_string(energy_perf_strings, buf); 1412 - if (ret < 0) 1413 - return -EINVAL; 1178 + if (cpudata->dynamic_epp) { 1179 + pr_debug("EPP cannot be set when dynamic EPP is enabled\n"); 1180 + return -EBUSY; 1181 + } 1414 1182 1415 - if (!ret) 1416 - epp = cpudata->epp_default; 1417 - else 1418 - epp = epp_values[ret]; 1183 + /* 1184 + * if the value matches a number, use that, otherwise see if 1185 + * matches an index in the energy_perf_strings array 1186 + */ 1187 + ret = kstrtou8(buf, 0, &epp); 1188 + raw_epp = !ret; 1189 + if (ret) { 1190 + ret = sysfs_match_string(energy_perf_strings, buf); 1191 + if (ret < 0 || ret == EPP_INDEX_CUSTOM) 1192 + return -EINVAL; 1193 + if (ret) 1194 + epp = epp_values[ret]; 1195 + else 1196 + epp = amd_pstate_get_balanced_epp(policy); 1197 + } 1419 1198 1420 - if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) { 1199 + if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) { 1421 1200 pr_debug("EPP cannot be set under performance policy\n"); 1422 1201 return -EBUSY; 1423 1202 } 1424 1203 1425 1204 ret = amd_pstate_set_epp(policy, epp); 1205 + if (ret) 1206 + return ret; 1426 1207 1427 - return ret ? ret : count; 1208 + cpudata->raw_epp = raw_epp; 1209 + 1210 + return count; 1428 1211 } 1212 + EXPORT_SYMBOL_GPL(store_energy_performance_preference); 1429 1213 1430 - static ssize_t show_energy_performance_preference( 1431 - struct cpufreq_policy *policy, char *buf) 1214 + ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf) 1432 1215 { 1433 1216 struct amd_cpudata *cpudata = policy->driver_data; 1434 1217 u8 preference, epp; 1435 1218 1436 1219 epp = FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached); 1220 + 1221 + if (cpudata->raw_epp) 1222 + return sysfs_emit(buf, "%u\n", epp); 1437 1223 1438 1224 switch (epp) { 1439 1225 case AMD_CPPC_EPP_PERFORMANCE: ··· 1474 1220 1475 1221 return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]); 1476 1222 } 1223 + EXPORT_SYMBOL_GPL(show_energy_performance_preference); 1224 + 1225 + static ssize_t store_amd_pstate_floor_freq(struct cpufreq_policy *policy, 1226 + const char *buf, size_t count) 1227 + { 1228 + struct amd_cpudata *cpudata = policy->driver_data; 1229 + union perf_cached perf = READ_ONCE(cpudata->perf); 1230 + unsigned int freq; 1231 + u8 floor_perf; 1232 + int ret; 1233 + 1234 + ret = kstrtouint(buf, 0, &freq); 1235 + if (ret) 1236 + return ret; 1237 + 1238 + if (freq < policy->cpuinfo.min_freq || freq > policy->max) 1239 + return -EINVAL; 1240 + 1241 + floor_perf = freq_to_perf(perf, cpudata->nominal_freq, freq); 1242 + ret = amd_pstate_set_floor_perf(policy, floor_perf); 1243 + 1244 + if (!ret) 1245 + cpudata->floor_freq = freq; 1246 + 1247 + return ret ?: count; 1248 + } 1249 + 1250 + static ssize_t show_amd_pstate_floor_freq(struct cpufreq_policy *policy, char *buf) 1251 + { 1252 + struct amd_cpudata *cpudata = policy->driver_data; 1253 + 1254 + return sysfs_emit(buf, "%u\n", cpudata->floor_freq); 1255 + } 1256 + 1257 + static ssize_t show_amd_pstate_floor_count(struct cpufreq_policy *policy, char *buf) 1258 + { 1259 + struct amd_cpudata *cpudata = policy->driver_data; 1260 + u8 count = cpudata->floor_perf_cnt; 1261 + 1262 + return sysfs_emit(buf, "%u\n", count); 1263 + } 1264 + 1265 + cpufreq_freq_attr_ro(amd_pstate_max_freq); 1266 + cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq); 1267 + 1268 + cpufreq_freq_attr_ro(amd_pstate_highest_perf); 1269 + cpufreq_freq_attr_ro(amd_pstate_prefcore_ranking); 1270 + cpufreq_freq_attr_ro(amd_pstate_hw_prefcore); 1271 + cpufreq_freq_attr_rw(energy_performance_preference); 1272 + cpufreq_freq_attr_ro(energy_performance_available_preferences); 1273 + cpufreq_freq_attr_rw(amd_pstate_floor_freq); 1274 + cpufreq_freq_attr_ro(amd_pstate_floor_count); 1275 + 1276 + struct freq_attr_visibility { 1277 + struct freq_attr *attr; 1278 + bool (*visibility_fn)(void); 1279 + }; 1280 + 1281 + /* For attributes which are always visible */ 1282 + static bool always_visible(void) 1283 + { 1284 + return true; 1285 + } 1286 + 1287 + /* Determines whether prefcore related attributes should be visible */ 1288 + static bool prefcore_visibility(void) 1289 + { 1290 + return amd_pstate_prefcore; 1291 + } 1292 + 1293 + /* Determines whether energy performance preference should be visible */ 1294 + static bool epp_visibility(void) 1295 + { 1296 + return cppc_state == AMD_PSTATE_ACTIVE; 1297 + } 1298 + 1299 + /* Determines whether amd_pstate_floor_freq related attributes should be visible */ 1300 + static bool floor_freq_visibility(void) 1301 + { 1302 + return cpu_feature_enabled(X86_FEATURE_CPPC_PERF_PRIO); 1303 + } 1304 + 1305 + static struct freq_attr_visibility amd_pstate_attr_visibility[] = { 1306 + {&amd_pstate_max_freq, always_visible}, 1307 + {&amd_pstate_lowest_nonlinear_freq, always_visible}, 1308 + {&amd_pstate_highest_perf, always_visible}, 1309 + {&amd_pstate_prefcore_ranking, prefcore_visibility}, 1310 + {&amd_pstate_hw_prefcore, prefcore_visibility}, 1311 + {&energy_performance_preference, epp_visibility}, 1312 + {&energy_performance_available_preferences, epp_visibility}, 1313 + {&amd_pstate_floor_freq, floor_freq_visibility}, 1314 + {&amd_pstate_floor_count, floor_freq_visibility}, 1315 + }; 1316 + 1317 + struct freq_attr **amd_pstate_get_current_attrs(void) 1318 + { 1319 + if (!current_pstate_driver) 1320 + return NULL; 1321 + return current_pstate_driver->attr; 1322 + } 1323 + EXPORT_SYMBOL_GPL(amd_pstate_get_current_attrs); 1324 + 1325 + static struct freq_attr **get_freq_attrs(void) 1326 + { 1327 + bool attr_visible[ARRAY_SIZE(amd_pstate_attr_visibility)]; 1328 + struct freq_attr **attrs; 1329 + int i, j, count; 1330 + 1331 + for (i = 0, count = 0; i < ARRAY_SIZE(amd_pstate_attr_visibility); i++) { 1332 + struct freq_attr_visibility *v = &amd_pstate_attr_visibility[i]; 1333 + 1334 + attr_visible[i] = v->visibility_fn(); 1335 + if (attr_visible[i]) 1336 + count++; 1337 + } 1338 + 1339 + /* amd_pstate_{max_freq, lowest_nonlinear_freq, highest_perf} should always be visible */ 1340 + BUG_ON(!count); 1341 + 1342 + attrs = kcalloc(count + 1, sizeof(struct freq_attr *), GFP_KERNEL); 1343 + if (!attrs) 1344 + return ERR_PTR(-ENOMEM); 1345 + 1346 + for (i = 0, j = 0; i < ARRAY_SIZE(amd_pstate_attr_visibility); i++) { 1347 + if (!attr_visible[i]) 1348 + continue; 1349 + 1350 + attrs[j++] = amd_pstate_attr_visibility[i].attr; 1351 + } 1352 + 1353 + return attrs; 1354 + } 1477 1355 1478 1356 static void amd_pstate_driver_cleanup(void) 1479 1357 { ··· 1613 1227 sched_clear_itmt_support(); 1614 1228 1615 1229 cppc_state = AMD_PSTATE_DISABLE; 1230 + kfree(current_pstate_driver->attr); 1231 + current_pstate_driver->attr = NULL; 1616 1232 current_pstate_driver = NULL; 1617 1233 } 1618 1234 ··· 1639 1251 1640 1252 static int amd_pstate_register_driver(int mode) 1641 1253 { 1254 + struct freq_attr **attr = NULL; 1642 1255 int ret; 1643 1256 1644 1257 ret = amd_pstate_set_driver(mode); ··· 1647 1258 return ret; 1648 1259 1649 1260 cppc_state = mode; 1261 + 1262 + /* 1263 + * Note: It is important to compute the attrs _after_ 1264 + * re-initializing the cppc_state. Some attributes become 1265 + * visible only when cppc_state is AMD_PSTATE_ACTIVE. 1266 + */ 1267 + attr = get_freq_attrs(); 1268 + if (IS_ERR(attr)) { 1269 + ret = (int) PTR_ERR(attr); 1270 + pr_err("Couldn't compute freq_attrs for current mode %s [%d]\n", 1271 + amd_pstate_get_mode_string(cppc_state), ret); 1272 + amd_pstate_driver_cleanup(); 1273 + return ret; 1274 + } 1275 + 1276 + current_pstate_driver->attr = attr; 1650 1277 1651 1278 /* at least one CPU supports CPB */ 1652 1279 current_pstate_driver->boost_enabled = cpu_feature_enabled(X86_FEATURE_CPB); ··· 1805 1400 return sysfs_emit(buf, "%s\n", str_enabled_disabled(amd_pstate_prefcore)); 1806 1401 } 1807 1402 1808 - cpufreq_freq_attr_ro(amd_pstate_max_freq); 1809 - cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq); 1403 + static ssize_t dynamic_epp_show(struct device *dev, 1404 + struct device_attribute *attr, char *buf) 1405 + { 1406 + return sysfs_emit(buf, "%s\n", str_enabled_disabled(dynamic_epp)); 1407 + } 1810 1408 1811 - cpufreq_freq_attr_ro(amd_pstate_highest_perf); 1812 - cpufreq_freq_attr_ro(amd_pstate_prefcore_ranking); 1813 - cpufreq_freq_attr_ro(amd_pstate_hw_prefcore); 1814 - cpufreq_freq_attr_rw(energy_performance_preference); 1815 - cpufreq_freq_attr_ro(energy_performance_available_preferences); 1409 + static ssize_t dynamic_epp_store(struct device *a, struct device_attribute *b, 1410 + const char *buf, size_t count) 1411 + { 1412 + bool enabled; 1413 + int ret; 1414 + 1415 + ret = kstrtobool(buf, &enabled); 1416 + if (ret) 1417 + return ret; 1418 + 1419 + if (dynamic_epp == enabled) 1420 + return -EINVAL; 1421 + 1422 + /* reinitialize with desired dynamic EPP value */ 1423 + dynamic_epp = enabled; 1424 + ret = amd_pstate_change_driver_mode(cppc_state); 1425 + if (ret) 1426 + dynamic_epp = false; 1427 + 1428 + return ret ? ret : count; 1429 + } 1430 + 1816 1431 static DEVICE_ATTR_RW(status); 1817 1432 static DEVICE_ATTR_RO(prefcore); 1818 - 1819 - static struct freq_attr *amd_pstate_attr[] = { 1820 - &amd_pstate_max_freq, 1821 - &amd_pstate_lowest_nonlinear_freq, 1822 - &amd_pstate_highest_perf, 1823 - &amd_pstate_prefcore_ranking, 1824 - &amd_pstate_hw_prefcore, 1825 - NULL, 1826 - }; 1827 - 1828 - static struct freq_attr *amd_pstate_epp_attr[] = { 1829 - &amd_pstate_max_freq, 1830 - &amd_pstate_lowest_nonlinear_freq, 1831 - &amd_pstate_highest_perf, 1832 - &amd_pstate_prefcore_ranking, 1833 - &amd_pstate_hw_prefcore, 1834 - &energy_performance_preference, 1835 - &energy_performance_available_preferences, 1836 - NULL, 1837 - }; 1433 + static DEVICE_ATTR_RW(dynamic_epp); 1838 1434 1839 1435 static struct attribute *pstate_global_attributes[] = { 1840 1436 &dev_attr_status.attr, 1841 1437 &dev_attr_prefcore.attr, 1438 + &dev_attr_dynamic_epp.attr, 1842 1439 NULL 1843 1440 }; 1844 1441 ··· 1910 1503 policy->cpuinfo.min_freq = policy->min = perf_to_freq(perf, 1911 1504 cpudata->nominal_freq, 1912 1505 perf.lowest_perf); 1913 - policy->cpuinfo.max_freq = policy->max = perf_to_freq(perf, 1914 - cpudata->nominal_freq, 1915 - perf.highest_perf); 1506 + policy->cpuinfo.max_freq = policy->max = cpudata->max_freq; 1916 1507 policy->driver_data = cpudata; 1917 1508 1918 1509 ret = amd_pstate_cppc_enable(policy); ··· 1930 1525 if (amd_pstate_acpi_pm_profile_server() || 1931 1526 amd_pstate_acpi_pm_profile_undefined()) { 1932 1527 policy->policy = CPUFREQ_POLICY_PERFORMANCE; 1933 - cpudata->epp_default = amd_pstate_get_epp(cpudata); 1528 + cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata); 1529 + cpudata->current_profile = PLATFORM_PROFILE_PERFORMANCE; 1934 1530 } else { 1935 1531 policy->policy = CPUFREQ_POLICY_POWERSAVE; 1936 - cpudata->epp_default = AMD_CPPC_EPP_BALANCE_PERFORMANCE; 1532 + cpudata->epp_default_ac = AMD_CPPC_EPP_PERFORMANCE; 1533 + cpudata->epp_default_dc = AMD_CPPC_EPP_BALANCE_PERFORMANCE; 1534 + cpudata->current_profile = PLATFORM_PROFILE_BALANCED; 1937 1535 } 1938 1536 1939 - ret = amd_pstate_set_epp(policy, cpudata->epp_default); 1537 + if (dynamic_epp) 1538 + ret = amd_pstate_set_dynamic_epp(policy); 1539 + else 1540 + ret = amd_pstate_set_epp(policy, amd_pstate_get_balanced_epp(policy)); 1940 1541 if (ret) 1941 - return ret; 1542 + goto free_cpudata1; 1543 + 1544 + ret = amd_pstate_init_floor_perf(policy); 1545 + if (ret) { 1546 + dev_err(dev, "Failed to initialize Floor Perf (%d)\n", ret); 1547 + goto free_cpudata1; 1548 + } 1942 1549 1943 1550 current_pstate_driver->adjust_perf = NULL; 1944 1551 ··· 1959 1542 free_cpudata1: 1960 1543 pr_warn("Failed to initialize CPU %d: %d\n", policy->cpu, ret); 1961 1544 kfree(cpudata); 1545 + policy->driver_data = NULL; 1962 1546 return ret; 1963 1547 } 1964 1548 ··· 1972 1554 1973 1555 /* Reset CPPC_REQ MSR to the BIOS value */ 1974 1556 amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false); 1557 + amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf); 1975 1558 1559 + if (cpudata->dynamic_epp) 1560 + amd_pstate_clear_dynamic_epp(policy); 1976 1561 kfree(cpudata); 1977 1562 policy->driver_data = NULL; 1978 1563 } ··· 2030 1609 2031 1610 static int amd_pstate_cpu_online(struct cpufreq_policy *policy) 2032 1611 { 2033 - return amd_pstate_cppc_enable(policy); 1612 + struct amd_cpudata *cpudata = policy->driver_data; 1613 + union perf_cached perf = READ_ONCE(cpudata->perf); 1614 + u8 cached_floor_perf; 1615 + int ret; 1616 + 1617 + ret = amd_pstate_cppc_enable(policy); 1618 + if (ret) 1619 + return ret; 1620 + 1621 + cached_floor_perf = freq_to_perf(perf, cpudata->nominal_freq, cpudata->floor_freq); 1622 + return amd_pstate_set_floor_perf(policy, cached_floor_perf); 2034 1623 } 2035 1624 2036 1625 static int amd_pstate_cpu_offline(struct cpufreq_policy *policy) 2037 1626 { 2038 1627 struct amd_cpudata *cpudata = policy->driver_data; 2039 1628 union perf_cached perf = READ_ONCE(cpudata->perf); 1629 + int ret; 2040 1630 2041 1631 /* 2042 1632 * Reset CPPC_REQ MSR to the BIOS value, this will allow us to retain the BIOS specified 2043 1633 * min_perf value across kexec reboots. If this CPU is just onlined normally after this, the 2044 1634 * limits, epp and desired perf will get reset to the cached values in cpudata struct 2045 1635 */ 2046 - return amd_pstate_update_perf(policy, perf.bios_min_perf, 1636 + ret = amd_pstate_update_perf(policy, perf.bios_min_perf, 2047 1637 FIELD_GET(AMD_CPPC_DES_PERF_MASK, cpudata->cppc_req_cached), 2048 1638 FIELD_GET(AMD_CPPC_MAX_PERF_MASK, cpudata->cppc_req_cached), 2049 1639 FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached), 2050 1640 false); 1641 + if (ret) 1642 + return ret; 1643 + 1644 + return amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf); 2051 1645 } 2052 1646 2053 1647 static int amd_pstate_suspend(struct cpufreq_policy *policy) ··· 2084 1648 if (ret) 2085 1649 return ret; 2086 1650 1651 + ret = amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf); 1652 + if (ret) 1653 + return ret; 1654 + 2087 1655 /* set this flag to avoid setting core offline*/ 2088 1656 cpudata->suspended = true; 2089 1657 ··· 2099 1659 struct amd_cpudata *cpudata = policy->driver_data; 2100 1660 union perf_cached perf = READ_ONCE(cpudata->perf); 2101 1661 int cur_perf = freq_to_perf(perf, cpudata->nominal_freq, policy->cur); 1662 + u8 cached_floor_perf; 1663 + int ret; 2102 1664 2103 1665 /* Set CPPC_REQ to last sane value until the governor updates it */ 2104 - return amd_pstate_update_perf(policy, perf.min_limit_perf, cur_perf, perf.max_limit_perf, 2105 - 0U, false); 1666 + ret = amd_pstate_update_perf(policy, perf.min_limit_perf, cur_perf, perf.max_limit_perf, 1667 + 0U, false); 1668 + if (ret) 1669 + return ret; 1670 + 1671 + cached_floor_perf = freq_to_perf(perf, cpudata->nominal_freq, cpudata->floor_freq); 1672 + return amd_pstate_set_floor_perf(policy, cached_floor_perf); 2106 1673 } 2107 1674 2108 1675 static int amd_pstate_epp_resume(struct cpufreq_policy *policy) 2109 1676 { 2110 1677 struct amd_cpudata *cpudata = policy->driver_data; 1678 + union perf_cached perf = READ_ONCE(cpudata->perf); 1679 + u8 cached_floor_perf; 2111 1680 2112 1681 if (cpudata->suspended) { 2113 1682 int ret; ··· 2129 1680 cpudata->suspended = false; 2130 1681 } 2131 1682 2132 - return 0; 1683 + cached_floor_perf = freq_to_perf(perf, cpudata->nominal_freq, cpudata->floor_freq); 1684 + return amd_pstate_set_floor_perf(policy, cached_floor_perf); 2133 1685 } 2134 1686 2135 1687 static struct cpufreq_driver amd_pstate_driver = { ··· 2147 1697 .set_boost = amd_pstate_set_boost, 2148 1698 .update_limits = amd_pstate_update_limits, 2149 1699 .name = "amd-pstate", 2150 - .attr = amd_pstate_attr, 2151 1700 }; 2152 1701 2153 1702 static struct cpufreq_driver amd_pstate_epp_driver = { ··· 2162 1713 .update_limits = amd_pstate_update_limits, 2163 1714 .set_boost = amd_pstate_set_boost, 2164 1715 .name = "amd-pstate-epp", 2165 - .attr = amd_pstate_epp_attr, 2166 1716 }; 2167 1717 2168 1718 /* ··· 2307 1859 return ret; 2308 1860 2309 1861 global_attr_free: 2310 - cpufreq_unregister_driver(current_pstate_driver); 1862 + amd_pstate_unregister_driver(0); 2311 1863 return ret; 2312 1864 } 2313 1865 device_initcall(amd_pstate_init); ··· 2334 1886 return 0; 2335 1887 } 2336 1888 1889 + static int __init amd_dynamic_epp_param(char *str) 1890 + { 1891 + if (!strcmp(str, "disable")) 1892 + dynamic_epp = false; 1893 + if (!strcmp(str, "enable")) 1894 + dynamic_epp = true; 1895 + 1896 + return 0; 1897 + } 1898 + 2337 1899 early_param("amd_pstate", amd_pstate_param); 2338 1900 early_param("amd_prefcore", amd_prefcore_param); 1901 + early_param("amd_dynamic_epp", amd_dynamic_epp_param); 2339 1902 2340 1903 MODULE_AUTHOR("Huang Rui <ray.huang@amd.com>"); 2341 1904 MODULE_DESCRIPTION("AMD Processor P-state Frequency Driver");
+36 -1
drivers/cpufreq/amd-pstate.h
··· 9 9 #define _LINUX_AMD_PSTATE_H 10 10 11 11 #include <linux/pm_qos.h> 12 + #include <linux/platform_profile.h> 12 13 13 14 /********************************************************************* 14 15 * AMD P-state INTERFACE * ··· 63 62 * @cpu: CPU number 64 63 * @req: constraint request to apply 65 64 * @cppc_req_cached: cached performance request hints 65 + * @cppc_req2_cached: cached value of MSR_AMD_CPPC_REQ2 66 66 * @perf: cached performance-related data 67 67 * @prefcore_ranking: the preferred core ranking, the higher value indicates a higher 68 68 * priority. 69 + * @floor_perf_cnt: Cached value of the number of distinct floor 70 + * performance levels supported 71 + * @bios_floor_perf: Cached value of the boot-time floor performance level from 72 + * MSR_AMD_CPPC_REQ2 69 73 * @min_limit_freq: Cached value of policy->min (in khz) 70 74 * @max_limit_freq: Cached value of policy->max (in khz) 71 75 * @nominal_freq: the frequency (in khz) that mapped to nominal_perf 76 + * @max_freq: in ideal conditions the maximum frequency (in khz) possible frequency 72 77 * @lowest_nonlinear_freq: the frequency (in khz) that mapped to lowest_nonlinear_perf 78 + * @floor_freq: Cached value of the user requested floor_freq 73 79 * @cur: Difference of Aperf/Mperf/tsc count between last and current sample 74 80 * @prev: Last Aperf/Mperf/tsc count value read from register 75 81 * @freq: current cpu frequency value (in khz) ··· 86 78 * AMD P-State driver supports preferred core featue. 87 79 * @epp_cached: Cached CPPC energy-performance preference value 88 80 * @policy: Cpufreq policy value 81 + * @suspended: If CPU core if offlined 82 + * @epp_default_ac: Default EPP value for AC power source 83 + * @epp_default_dc: Default EPP value for DC power source 84 + * @dynamic_epp: Whether dynamic EPP is enabled 85 + * @power_nb: Notifier block for power events 89 86 * 90 87 * The amd_cpudata is key private data for each CPU thread in AMD P-State, and 91 88 * represents all the attributes and goals that AMD P-State requests at runtime. ··· 100 87 101 88 struct freq_qos_request req[2]; 102 89 u64 cppc_req_cached; 90 + u64 cppc_req2_cached; 103 91 104 92 union perf_cached perf; 105 93 106 94 u8 prefcore_ranking; 95 + u8 floor_perf_cnt; 96 + u8 bios_floor_perf; 107 97 u32 min_limit_freq; 108 98 u32 max_limit_freq; 109 99 u32 nominal_freq; 100 + u32 max_freq; 110 101 u32 lowest_nonlinear_freq; 102 + u32 floor_freq; 111 103 112 104 struct amd_aperf_mperf cur; 113 105 struct amd_aperf_mperf prev; ··· 124 106 /* EPP feature related attributes*/ 125 107 u32 policy; 126 108 bool suspended; 127 - u8 epp_default; 109 + u8 epp_default_ac; 110 + u8 epp_default_dc; 111 + bool dynamic_epp; 112 + bool raw_epp; 113 + struct notifier_block power_nb; 114 + 115 + /* platform profile */ 116 + enum platform_profile_option current_profile; 117 + struct device *ppdev; 118 + char *profile_name; 128 119 }; 129 120 130 121 /* ··· 150 123 const char *amd_pstate_get_mode_string(enum amd_pstate_mode mode); 151 124 int amd_pstate_get_status(void); 152 125 int amd_pstate_update_status(const char *buf, size_t size); 126 + ssize_t store_energy_performance_preference(struct cpufreq_policy *policy, 127 + const char *buf, size_t count); 128 + ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf); 129 + void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy); 130 + 131 + struct freq_attr; 132 + 133 + struct freq_attr **amd_pstate_get_current_attrs(void); 153 134 154 135 #endif /* _LINUX_AMD_PSTATE_H */
+2 -8
drivers/cpufreq/cppc_cpufreq.c
··· 807 807 { 808 808 struct cppc_cpudata *cpu_data = policy->driver_data; 809 809 struct cppc_perf_caps *caps = &cpu_data->perf_caps; 810 - int ret; 811 810 812 811 if (state) 813 - policy->max = cppc_perf_to_khz(caps, caps->highest_perf); 812 + policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, caps->highest_perf); 814 813 else 815 - policy->max = cppc_perf_to_khz(caps, caps->nominal_perf); 816 - policy->cpuinfo.max_freq = policy->max; 817 - 818 - ret = freq_qos_update_request(policy->max_freq_req, policy->max); 819 - if (ret < 0) 820 - return ret; 814 + policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, caps->nominal_perf); 821 815 822 816 return 0; 823 817 }
+1
drivers/cpufreq/cpufreq-dt-platdev.c
··· 159 159 { .compatible = "qcom,qcm2290", }, 160 160 { .compatible = "qcom,qcm6490", }, 161 161 { .compatible = "qcom,qcs404", }, 162 + { .compatible = "qcom,qcs8300", }, 162 163 { .compatible = "qcom,qdu1000", }, 163 164 { .compatible = "qcom,sa8155p" }, 164 165 { .compatible = "qcom,sa8540p" },
+36 -49
drivers/cpufreq/cpufreq.c
··· 609 609 policy->boost_enabled = enable; 610 610 611 611 ret = cpufreq_driver->set_boost(policy, enable); 612 - if (ret) 612 + if (ret) { 613 613 policy->boost_enabled = !policy->boost_enabled; 614 + return ret; 615 + } 614 616 615 - return ret; 617 + ret = freq_qos_update_request(&policy->boost_freq_req, policy->cpuinfo.max_freq); 618 + if (ret < 0) { 619 + policy->boost_enabled = !policy->boost_enabled; 620 + cpufreq_driver->set_boost(policy, policy->boost_enabled); 621 + return ret; 622 + } 623 + 624 + return 0; 616 625 } 617 626 618 627 static ssize_t store_local_boost(struct cpufreq_policy *policy, ··· 769 760 if (ret) \ 770 761 return ret; \ 771 762 \ 772 - ret = freq_qos_update_request(policy->object##_freq_req, val);\ 763 + ret = freq_qos_update_request(&policy->object##_freq_req, val); \ 773 764 return ret >= 0 ? count : ret; \ 774 765 } 775 766 ··· 1374 1365 /* Cancel any pending policy->update work before freeing the policy. */ 1375 1366 cancel_work_sync(&policy->update); 1376 1367 1377 - if (policy->max_freq_req) { 1368 + if (freq_qos_request_active(&policy->max_freq_req)) { 1378 1369 /* 1379 1370 * Remove max_freq_req after sending CPUFREQ_REMOVE_POLICY 1380 1371 * notification, since CPUFREQ_CREATE_POLICY notification was ··· 1382 1373 */ 1383 1374 blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 1384 1375 CPUFREQ_REMOVE_POLICY, policy); 1385 - freq_qos_remove_request(policy->max_freq_req); 1376 + freq_qos_remove_request(&policy->max_freq_req); 1386 1377 } 1387 1378 1388 - freq_qos_remove_request(policy->min_freq_req); 1389 - kfree(policy->min_freq_req); 1379 + if (freq_qos_request_active(&policy->min_freq_req)) 1380 + freq_qos_remove_request(&policy->min_freq_req); 1381 + if (freq_qos_request_active(&policy->boost_freq_req)) 1382 + freq_qos_remove_request(&policy->boost_freq_req); 1390 1383 1391 1384 cpufreq_policy_put_kobj(policy); 1392 1385 free_cpumask_var(policy->real_cpus); ··· 1458 1447 add_cpu_dev_symlink(policy, j, get_cpu_device(j)); 1459 1448 } 1460 1449 1461 - policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req), 1462 - GFP_KERNEL); 1463 - if (!policy->min_freq_req) { 1464 - ret = -ENOMEM; 1465 - goto out_destroy_policy; 1450 + if (policy->boost_supported) { 1451 + ret = freq_qos_add_request(&policy->constraints, 1452 + &policy->boost_freq_req, 1453 + FREQ_QOS_MAX, 1454 + policy->cpuinfo.max_freq); 1455 + if (ret < 0) 1456 + goto out_destroy_policy; 1466 1457 } 1467 1458 1468 1459 ret = freq_qos_add_request(&policy->constraints, 1469 - policy->min_freq_req, FREQ_QOS_MIN, 1460 + &policy->min_freq_req, FREQ_QOS_MIN, 1470 1461 FREQ_QOS_MIN_DEFAULT_VALUE); 1471 - if (ret < 0) { 1472 - /* 1473 - * So we don't call freq_qos_remove_request() for an 1474 - * uninitialized request. 1475 - */ 1476 - kfree(policy->min_freq_req); 1477 - policy->min_freq_req = NULL; 1462 + if (ret < 0) 1478 1463 goto out_destroy_policy; 1479 - } 1480 - 1481 - /* 1482 - * This must be initialized right here to avoid calling 1483 - * freq_qos_remove_request() on uninitialized request in case 1484 - * of errors. 1485 - */ 1486 - policy->max_freq_req = policy->min_freq_req + 1; 1487 1464 1488 1465 ret = freq_qos_add_request(&policy->constraints, 1489 - policy->max_freq_req, FREQ_QOS_MAX, 1466 + &policy->max_freq_req, FREQ_QOS_MAX, 1490 1467 FREQ_QOS_MAX_DEFAULT_VALUE); 1491 - if (ret < 0) { 1492 - policy->max_freq_req = NULL; 1468 + if (ret < 0) 1493 1469 goto out_destroy_policy; 1494 - } 1495 1470 1496 1471 blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 1497 1472 CPUFREQ_CREATE_POLICY, policy); 1498 - } else { 1499 - ret = freq_qos_update_request(policy->max_freq_req, policy->max); 1500 - if (ret < 0) 1501 - goto out_destroy_policy; 1502 1473 } 1503 1474 1504 1475 if (cpufreq_driver->get && has_target()) { ··· 2221 2228 2222 2229 /** 2223 2230 * cpufreq_driver_adjust_perf - Adjust CPU performance level in one go. 2224 - * @cpu: Target CPU. 2231 + * @policy: cpufreq policy object of the target CPU. 2225 2232 * @min_perf: Minimum (required) performance level (units of @capacity). 2226 2233 * @target_perf: Target (desired) performance level (units of @capacity). 2227 2234 * @capacity: Capacity of the target CPU. ··· 2240 2247 * parallel with either ->target() or ->target_index() or ->fast_switch() for 2241 2248 * the same CPU. 2242 2249 */ 2243 - void cpufreq_driver_adjust_perf(unsigned int cpu, 2250 + void cpufreq_driver_adjust_perf(struct cpufreq_policy *policy, 2244 2251 unsigned long min_perf, 2245 2252 unsigned long target_perf, 2246 2253 unsigned long capacity) 2247 2254 { 2248 - cpufreq_driver->adjust_perf(cpu, min_perf, target_perf, capacity); 2255 + cpufreq_driver->adjust_perf(policy, min_perf, target_perf, capacity); 2249 2256 } 2250 2257 2251 2258 /** ··· 2357 2364 target_freq = __resolve_freq(policy, target_freq, policy->min, 2358 2365 policy->max, relation); 2359 2366 2360 - pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n", 2361 - policy->cpu, target_freq, relation, old_target_freq); 2367 + pr_debug("CPU %u: cur %u kHz -> target %u kHz (req %u kHz, rel %u)\n", 2368 + policy->cpu, policy->cur, target_freq, old_target_freq, relation); 2362 2369 2363 2370 /* 2364 2371 * This might look like a redundant call as we are checking it again ··· 2782 2789 return -ENXIO; 2783 2790 2784 2791 ret = cpufreq_frequency_table_cpuinfo(policy); 2785 - if (ret) { 2792 + if (ret) 2786 2793 pr_err("%s: Policy frequency update failed\n", __func__); 2787 - return ret; 2788 - } 2789 2794 2790 - ret = freq_qos_update_request(policy->max_freq_req, policy->max); 2791 - if (ret < 0) 2792 - return ret; 2793 - 2794 - return 0; 2795 + return ret; 2795 2796 } 2796 2797 EXPORT_SYMBOL_GPL(cpufreq_boost_set_sw); 2797 2798
+3 -2
drivers/cpufreq/cpufreq_governor.h
··· 21 21 #include <linux/kernel_stat.h> 22 22 #include <linux/module.h> 23 23 #include <linux/mutex.h> 24 + #include <linux/sysfs.h> 24 25 25 26 /* Ondemand Sampling types */ 26 27 enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE}; ··· 58 57 { \ 59 58 struct dbs_data *dbs_data = to_dbs_data(attr_set); \ 60 59 struct _gov##_dbs_tuners *tuners = dbs_data->tuners; \ 61 - return sprintf(buf, "%u\n", tuners->file_name); \ 60 + return sysfs_emit(buf, "%u\n", tuners->file_name); \ 62 61 } 63 62 64 63 #define gov_show_one_common(file_name) \ ··· 66 65 (struct gov_attr_set *attr_set, char *buf) \ 67 66 { \ 68 67 struct dbs_data *dbs_data = to_dbs_data(attr_set); \ 69 - return sprintf(buf, "%u\n", dbs_data->file_name); \ 68 + return sysfs_emit(buf, "%u\n", dbs_data->file_name); \ 70 69 } 71 70 72 71 #define gov_attr_ro(_name) \
+3 -3
drivers/cpufreq/intel_pstate.c
··· 3239 3239 return target_pstate * cpu->pstate.scaling; 3240 3240 } 3241 3241 3242 - static void intel_cpufreq_adjust_perf(unsigned int cpunum, 3242 + static void intel_cpufreq_adjust_perf(struct cpufreq_policy *policy, 3243 3243 unsigned long min_perf, 3244 3244 unsigned long target_perf, 3245 3245 unsigned long capacity) 3246 3246 { 3247 - struct cpudata *cpu = all_cpu_data[cpunum]; 3247 + struct cpudata *cpu = all_cpu_data[policy->cpu]; 3248 3248 u64 hwp_cap = READ_ONCE(cpu->hwp_cap_cached); 3249 3249 int old_pstate = cpu->pstate.current_pstate; 3250 3250 int cap_pstate, min_pstate, max_pstate, target_pstate; ··· 3472 3472 { 3473 3473 if (size == 3 && !strncmp(buf, "off", size)) { 3474 3474 if (!intel_pstate_driver) 3475 - return -EINVAL; 3475 + return 0; 3476 3476 3477 3477 if (hwp_active) 3478 3478 return -EBUSY;
+2 -2
drivers/cpufreq/tegra194-cpufreq.c
··· 196 196 .refclk_delta_min = 16000, 197 197 }; 198 198 199 - static const struct tegra_cpufreq_soc tegra239_cpufreq_soc = { 199 + static const struct tegra_cpufreq_soc tegra238_cpufreq_soc = { 200 200 .ops = &tegra234_cpufreq_ops, 201 201 .actmon_cntr_base = 0x4000, 202 202 .maxcpus_per_cluster = 8, ··· 807 807 static const struct of_device_id tegra194_cpufreq_of_match[] = { 808 808 { .compatible = "nvidia,tegra194-ccplex", .data = &tegra194_cpufreq_soc }, 809 809 { .compatible = "nvidia,tegra234-ccplex-cluster", .data = &tegra234_cpufreq_soc }, 810 - { .compatible = "nvidia,tegra239-ccplex-cluster", .data = &tegra239_cpufreq_soc }, 810 + { .compatible = "nvidia,tegra238-ccplex-cluster", .data = &tegra238_cpufreq_soc }, 811 811 { /* sentinel */ } 812 812 }; 813 813 MODULE_DEVICE_TABLE(of, tegra194_cpufreq_of_match);
+1
include/acpi/cppc_acpi.h
··· 156 156 extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps); 157 157 extern bool cppc_perf_ctrs_in_pcc_cpu(unsigned int cpu); 158 158 extern bool cppc_perf_ctrs_in_pcc(void); 159 + extern u64 cppc_get_dmi_max_khz(void); 159 160 extern unsigned int cppc_perf_to_khz(struct cppc_perf_caps *caps, unsigned int perf); 160 161 extern unsigned int cppc_khz_to_perf(struct cppc_perf_caps *caps, unsigned int freq); 161 162 extern bool acpi_cpc_valid(void);
+6 -5
include/linux/cpufreq.h
··· 79 79 * called, but you're in IRQ context */ 80 80 81 81 struct freq_constraints constraints; 82 - struct freq_qos_request *min_freq_req; 83 - struct freq_qos_request *max_freq_req; 82 + struct freq_qos_request min_freq_req; 83 + struct freq_qos_request max_freq_req; 84 + struct freq_qos_request boost_freq_req; 84 85 85 86 struct cpufreq_frequency_table *freq_table; 86 87 enum cpufreq_table_sorting freq_table_sorted; ··· 233 232 234 233 static inline bool policy_is_shared(struct cpufreq_policy *policy) 235 234 { 236 - return cpumask_weight(policy->cpus) > 1; 235 + return cpumask_nth(1, policy->cpus) < nr_cpumask_bits; 237 236 } 238 237 239 238 #ifdef CONFIG_CPU_FREQ ··· 373 372 * conditions) scale invariance can be disabled, which causes the 374 373 * schedutil governor to fall back to the latter. 375 374 */ 376 - void (*adjust_perf)(unsigned int cpu, 375 + void (*adjust_perf)(struct cpufreq_policy *policy, 377 376 unsigned long min_perf, 378 377 unsigned long target_perf, 379 378 unsigned long capacity); ··· 618 617 /* Pass a target to the cpufreq driver */ 619 618 unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy, 620 619 unsigned int target_freq); 621 - void cpufreq_driver_adjust_perf(unsigned int cpu, 620 + void cpufreq_driver_adjust_perf(struct cpufreq_policy *policy, 622 621 unsigned long min_perf, 623 622 unsigned long target_perf, 624 623 unsigned long capacity);
+3 -2
kernel/sched/cpufreq_schedutil.c
··· 461 461 unsigned int flags) 462 462 { 463 463 struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util); 464 + struct sugov_policy *sg_policy = sg_cpu->sg_policy; 464 465 unsigned long prev_util = sg_cpu->util; 465 466 unsigned long max_cap; 466 467 ··· 483 482 if (sugov_hold_freq(sg_cpu) && sg_cpu->util < prev_util) 484 483 sg_cpu->util = prev_util; 485 484 486 - cpufreq_driver_adjust_perf(sg_cpu->cpu, sg_cpu->bw_min, 485 + cpufreq_driver_adjust_perf(sg_policy->policy, sg_cpu->bw_min, 487 486 sg_cpu->util, max_cap); 488 487 489 - sg_cpu->sg_policy->last_freq_update_time = time; 488 + sg_policy->last_freq_update_time = time; 490 489 } 491 490 492 491 static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time)
+6 -7
rust/kernel/cpufreq.rs
··· 1257 1257 /// # Safety 1258 1258 /// 1259 1259 /// - This function may only be called from the cpufreq C infrastructure. 1260 + /// - The pointer arguments must be valid pointers. 1260 1261 unsafe extern "C" fn adjust_perf_callback( 1261 - cpu: c_uint, 1262 + ptr: *mut bindings::cpufreq_policy, 1262 1263 min_perf: c_ulong, 1263 1264 target_perf: c_ulong, 1264 1265 capacity: c_ulong, 1265 1266 ) { 1266 - // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. 1267 - let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) }; 1268 - 1269 - if let Ok(mut policy) = PolicyCpu::from_cpu(cpu_id) { 1270 - T::adjust_perf(&mut policy, min_perf, target_perf, capacity); 1271 - } 1267 + // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the 1268 + // lifetime of `policy`. 1269 + let policy = unsafe { Policy::from_raw_mut(ptr) }; 1270 + T::adjust_perf(policy, min_perf, target_perf, capacity); 1272 1271 } 1273 1272 1274 1273 /// Driver's `get_intermediate` callback.
+1 -1
tools/arch/x86/include/asm/cpufeatures.h
··· 415 415 */ 416 416 #define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* "overflow_recov" MCA overflow recovery support */ 417 417 #define X86_FEATURE_SUCCOR (17*32+ 1) /* "succor" Uncorrectable error containment and recovery */ 418 - 418 + #define X86_FEATURE_CPPC_PERF_PRIO (17*32+ 2) /* CPPC Floor Perf support */ 419 419 #define X86_FEATURE_SMCA (17*32+ 3) /* "smca" Scalable MCA */ 420 420 421 421 /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */