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 tag 'pm-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management updates from Rafael Wysocki:
"The majority of these are cpufreq changes, which has been a recurring
pattern for a few recent cycles.

Those changes include new hardware support (AN7583 SoC support in the
airoha cpufreq driver, ipq5424 support in the qcom-nvmem cpufreq
driver, MT8196 support in the mediatek cpufreq driver, AM62D2 support
in the ti cpufreq driver), DT bindings and Rust code updates, cleanups
of the core and governors, and multiple driver fixes and cleanups.

Beyond that, there are hibernation fixes (some remaining 6.16 cycle
fallout and an issue related to hybrid suspend in the amdgpu driver),
cleanups of the PM core code, runtime PM documentation update, cpuidle
and power capping cleanups, and tooling updates.

Specifics:

- Rearrange variable declarations involving __free() in the cpufreq
core and intel_pstate driver to follow common coding style (Rafael
Wysocki)

- Fix object lifecycle issue in update_qos_request(), rearrange freq
QoS updates using __free(), and adjust frequency percentage
computations in the intel_pstate driver (Rafael Wysocki)

- Update intel_pstate to allow it to enable HWP without EPP if the
new DEC (Dynamic Efficiency Control) HW feature is enabled (Rafael
Wysocki)

- Use on_each_cpu_mask() in drv_write() in the ACPI cpufreq driver to
simplify the code (Rafael Wysocki)

- Use likely() optimization in intel_pstate_sample() (Yaxiong Tian)

- Remove dead EPB-related code from intel_pstate (Srinivas
Pandruvada)

- Use scope-based cleanup for cpufreq policy references in multiple
cpufreq drivers (Zihuan Zhang)

- Avoid calling get_governor() for the first policy in the cpufreq
core to simplify the initial policy path (Zihuan Zhang)

- Clean up the cpufreq core in multiple places (Zihuan Zhang)

- Use int type to store negative error codes in the cpufreq core and
update the speedstep-lib to use int for error codes (Qianfeng Rong)

- Update the efficient idle check for Intel extended Families in the
ondemand cpufreq governor (Sohil Mehta)

- Replace sscanf() with kstrtouint() in the conservative cpufreq
governor (Kaushlendra Kumar)

- Rename CpumaskVar::as[_mut]_ref to from_raw[_mut] in the cpumask
Rust code and mark CpumaskVar as transparent (Alice Ryhl, Baptiste
Lepers)

- Update ARef and AlwaysRefCounted imports from sync::aref in the OPP
Rust code (Shankari Anand)

- Add support for AN7583 SoC to the airoha cpufreq driver (Christian
Marangi)

- Enable cpufreq for ipq5424 in the qcom-nvmem cpufreq driver (Md
Sadre Alam)

- Add support for MT8196 to the mediatek-hw cpufreq driver, refactor
that driver and add mediatek,mt8196-cpufreq-hw DT binding (Nicolas
Frattaroli)

- Avoid redundant conditions in the mediatek cpufreq driver (Liao
Yuanhong)

- Add support for AM62D2 to the ti cpufreq driver and blocklist
ti,am62d2 SoC in dt-platdev (Paresh Bhagat)

- Support more speed grades on AM62Px SoC in the ti cpufreq driver,
allow all silicon revisions to support OPPs in it, and fix
supported hardware for 1GHz OPP (Judith Mendez)

- Add QCS615 compatible to DT bindings for cpufreq-qcom-hw (Taniya
Das)

- Minor assorted updates of the scmi, longhaul, CPPC, and armada-37xx
cpufreq drivers (Akhilesh Patil, BowenYu, Dennis Beier, and Florian
Fainelli)

- Remove outdated cpufreq-dt.txt (Frank Li)

- Fix python gnuplot package names in the amd_pstate_tracer utility
(Kuan-Wei Chiu)

- Saravana Kannan will maintain the virtual-cpufreq driver (Saravana
Kannan)

- Prevent CPU capacity updates after registering a perf domain from
failing on a first CPU that is not present (Christian Loehle)

- Add support for the cases in which frequency alone is not
sufficient to uniquely identify an OPP (Krishna Chaitanya Chundru)

- Use to_result() for OPP error handling in Rust (Onur Özkan)

- Add support for LPDDR5 on Rockhip RK3588 SoC to rockchip-dfi
devfreq driver (Nicolas Frattaroli)

- Fix an issue where DDR cycle counts on RK3588/RK3528 with LPDDR4(X)
are reported as half by adding a cycle multiplier to the DFI driver
in rockchip-dfi devfreq-event driver (Nicolas Frattaroli)

- Fix missing error pointer dereference check of regulator instance
in the mtk-cci devfreq driver probe and remove a redundant
condition from an if () statement in that driver (Dan Carpenter,
Liao Yuanhong)

- Fail cpuidle device registration if there is one already to avoid
sysfs-related issues (Rafael Wysocki)

- Use sysfs_emit()/sysfs_emit_at() instead of sprintf()/scnprintf()
in cpuidle (Vivek Yadav)

- Fix device and OF node leaks at probe in the qcom-spm cpuidle
driver and drop unnecessary initialisations from it (Johan Hovold)

- Remove unnecessary address-of operators from the intel_idle cpuidle
driver (Kaushlendra Kumar)

- Rearrange main loop in menu_select() to make the code in that
funtion easier to follow (Rafael Wysocki)

- Convert values in microseconds to ktime using us_to_ktime() where
applicable in the intel_idle power capping driver (Xichao Zhao)

- Annotate loops walking device links in the power management core
code as _srcu and add macros for walking device links to reduce the
likelihood of coding mistakes related to them (Rafael Wysocki)

- Document time units for *_time functions in the runtime PM API
(Brian Norris)

- Clear power.must_resume in noirq suspend error path to avoid
resuming a dependant device under a suspended parent or supplier
(Rafael Wysocki)

- Fix GFP mask handling during hybrid suspend and make the amdgpu
driver handle hybrid suspend correctly (Mario Limonciello, Rafael
Wysocki)

- Fix GFP mask handling after aborted hibernation in platform mode
and combine exit paths in power_down() to avoid code duplication
(Rafael Wysocki)

- Use vmalloc_array() and vcalloc() in the hibernation core to avoid
open-coded size computations (Qianfeng Rong)

- Fix typo in hibernation core code comment (Li Jun)

- Call pm_wakeup_clear() in the same place where other functions that
do bookkeeping prior to suspend_prepare() are called (Samuel Wu)

- Fix and clean up the x86_energy_perf_policy utility and update its
documentation (Len Brown, Kaushlendra Kumar)

- Fix incorrect sorting of PMT telemetry in turbostat (Kaushlendra
Kumar)

- Fix incorrect size in cpuidle_state_disable() and the error return
value of cpupower_write_sysfs() in cpupower (Kaushlendra Kumar)"

* tag 'pm-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (86 commits)
PM: hibernate: Combine return paths in power_down()
PM: hibernate: Restrict GFP mask in power_down()
PM: hibernate: Fix pm_hibernation_mode_is_suspend() build breakage
PM: runtime: Documentation: ABI: Document time units for *_time
tools/power x86_energy_perf_policy.8: Emphasize preference for SW interfaces
tools/power x86_energy_perf_policy: Add make snapshot target
tools/power x86_energy_perf_policy: Prefer driver HWP limits
tools/power x86_energy_perf_policy: EPB access is only via sysfs
tools/power x86_energy_perf_policy: Prepare for MSR/sysfs refactoring
tools/power x86_energy_perf_policy: Enhance HWP enable
tools/power x86_energy_perf_policy: Enhance HWP enabled check
tools/power x86_energy_perf_policy: Fix incorrect fopen mode usage
tools/power turbostat: Fix incorrect sorting of PMT telemetry
drm/amd: Fix hybrid sleep
PM: hibernate: Add pm_hibernation_mode_is_suspend()
PM: hibernate: Fix hybrid-sleep
tools/cpupower: Fix incorrect size in cpuidle_state_disable()
tools/power/x86/amd_pstate_tracer: Fix python gnuplot package names
cpufreq: Replace pointer subtraction with iteration macro
cpuidle: Fail cpuidle device registration if there is one already
...

+1059 -650
+4 -4
Documentation/ABI/testing/sysfs-devices-power
··· 274 274 Date: Jul 2010 275 275 Contact: Arjan van de Ven <arjan@linux.intel.com> 276 276 Description: 277 - Reports the total time that the device has been active. 278 - Used for runtime PM statistics. 277 + Reports the total time that the device has been active, in 278 + milliseconds. Used for runtime PM statistics. 279 279 280 280 What: /sys/devices/.../power/runtime_suspended_time 281 281 Date: Jul 2010 282 282 Contact: Arjan van de Ven <arjan@linux.intel.com> 283 283 Description: 284 - Reports total time that the device has been suspended. 285 - Used for runtime PM statistics. 284 + Reports total time that the device has been suspended, in 285 + milliseconds. Used for runtime PM statistics. 286 286 287 287 What: /sys/devices/.../power/runtime_usage 288 288 Date: Apr 2010
-61
Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt
··· 1 - Generic cpufreq driver 2 - 3 - It is a generic DT based cpufreq driver for frequency management. It supports 4 - both uniprocessor (UP) and symmetric multiprocessor (SMP) systems which share 5 - clock and voltage across all CPUs. 6 - 7 - Both required and optional properties listed below must be defined 8 - under node /cpus/cpu@0. 9 - 10 - Required properties: 11 - - None 12 - 13 - Optional properties: 14 - - operating-points: Refer to Documentation/devicetree/bindings/opp/opp-v1.yaml for 15 - details. OPPs *must* be supplied either via DT, i.e. this property, or 16 - populated at runtime. 17 - - clock-latency: Specify the possible maximum transition latency for clock, 18 - in unit of nanoseconds. 19 - - voltage-tolerance: Specify the CPU voltage tolerance in percentage. 20 - - #cooling-cells: 21 - Please refer to 22 - Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml. 23 - 24 - Examples: 25 - 26 - cpus { 27 - #address-cells = <1>; 28 - #size-cells = <0>; 29 - 30 - cpu@0 { 31 - compatible = "arm,cortex-a9"; 32 - reg = <0>; 33 - next-level-cache = <&L2>; 34 - operating-points = < 35 - /* kHz uV */ 36 - 792000 1100000 37 - 396000 950000 38 - 198000 850000 39 - >; 40 - clock-latency = <61036>; /* two CLK32 periods */ 41 - #cooling-cells = <2>; 42 - }; 43 - 44 - cpu@1 { 45 - compatible = "arm,cortex-a9"; 46 - reg = <1>; 47 - next-level-cache = <&L2>; 48 - }; 49 - 50 - cpu@2 { 51 - compatible = "arm,cortex-a9"; 52 - reg = <2>; 53 - next-level-cache = <&L2>; 54 - }; 55 - 56 - cpu@3 { 57 - compatible = "arm,cortex-a9"; 58 - reg = <3>; 59 - next-level-cache = <&L2>; 60 - }; 61 - };
+2
Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
··· 22 22 items: 23 23 - enum: 24 24 - qcom,qcm2290-cpufreq-hw 25 + - qcom,qcs615-cpufreq-hw 25 26 - qcom,sc7180-cpufreq-hw 26 27 - qcom,sc8180x-cpufreq-hw 27 28 - qcom,sdm670-cpufreq-hw ··· 133 132 compatible: 134 133 contains: 135 134 enum: 135 + - qcom,qcs615-cpufreq-hw 136 136 - qcom,qdu1000-cpufreq-epss 137 137 - qcom,sa8255p-cpufreq-epss 138 138 - qcom,sa8775p-cpufreq-epss
+82
Documentation/devicetree/bindings/cpufreq/mediatek,mt8196-cpufreq-hw.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/cpufreq/mediatek,mt8196-cpufreq-hw.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: MediaTek Hybrid CPUFreq for MT8196/MT6991 series SoCs 8 + 9 + maintainers: 10 + - Nicolas Frattaroli <nicolas.frattaroli@collabora.com> 11 + 12 + description: 13 + MT8196 uses CPUFreq management hardware that supports dynamic voltage 14 + frequency scaling (dvfs), and can support several performance domains. 15 + 16 + properties: 17 + compatible: 18 + const: mediatek,mt8196-cpufreq-hw 19 + 20 + reg: 21 + items: 22 + - description: FDVFS control register region 23 + - description: OPP tables and control for performance domain 0 24 + - description: OPP tables and control for performance domain 1 25 + - description: OPP tables and control for performance domain 2 26 + 27 + "#performance-domain-cells": 28 + const: 1 29 + 30 + required: 31 + - compatible 32 + - reg 33 + - "#performance-domain-cells" 34 + 35 + additionalProperties: false 36 + 37 + examples: 38 + - | 39 + cpus { 40 + #address-cells = <1>; 41 + #size-cells = <0>; 42 + 43 + cpu0: cpu@0 { 44 + device_type = "cpu"; 45 + compatible = "arm,cortex-a720"; 46 + enable-method = "psci"; 47 + performance-domains = <&performance 0>; 48 + reg = <0x000>; 49 + }; 50 + 51 + /* ... */ 52 + 53 + cpu6: cpu@600 { 54 + device_type = "cpu"; 55 + compatible = "arm,cortex-x4"; 56 + enable-method = "psci"; 57 + performance-domains = <&performance 1>; 58 + reg = <0x600>; 59 + }; 60 + 61 + cpu7: cpu@700 { 62 + device_type = "cpu"; 63 + compatible = "arm,cortex-x925"; 64 + enable-method = "psci"; 65 + performance-domains = <&performance 2>; 66 + reg = <0x700>; 67 + }; 68 + }; 69 + 70 + /* ... */ 71 + 72 + soc { 73 + #address-cells = <2>; 74 + #size-cells = <2>; 75 + 76 + performance: performance-controller@c2c2034 { 77 + compatible = "mediatek,mt8196-cpufreq-hw"; 78 + reg = <0 0xc220400 0 0x20>, <0 0xc2c0f20 0 0x120>, 79 + <0 0xc2c1040 0 0x120>, <0 0xc2c1160 0 0x120>; 80 + #performance-domain-cells = <1>; 81 + }; 82 + };
+6
MAINTAINERS
··· 6360 6360 F: rust/kernel/cpufreq.rs 6361 6361 F: tools/testing/selftests/cpufreq/ 6362 6362 6363 + CPU FREQUENCY DRIVERS - VIRTUAL MACHINE CPUFREQ 6364 + M: Saravana Kannan <saravanak@google.com> 6365 + L: linux-pm@vger.kernel.org 6366 + S: Maintained 6367 + F: drivers/cpufreq/virtual-cpufreq.c 6368 + 6363 6369 CPU HOTPLUG 6364 6370 M: Thomas Gleixner <tglx@linutronix.de> 6365 6371 M: Peter Zijlstra <peterz@infradead.org>
+1 -1
arch/arm64/boot/dts/ti/k3-am62p5.dtsi
··· 135 135 136 136 opp-1000000000 { 137 137 opp-hz = /bits/ 64 <1000000000>; 138 - opp-supported-hw = <0x01 0x0006>; 138 + opp-supported-hw = <0x01 0x0007>; 139 139 clock-latency-ns = <6000000>; 140 140 }; 141 141
+8
drivers/base/base.h
··· 251 251 void fw_devlink_drivers_done(void); 252 252 void fw_devlink_probing_done(void); 253 253 254 + #define dev_for_each_link_to_supplier(__link, __dev) \ 255 + list_for_each_entry_srcu(__link, &(__dev)->links.suppliers, c_node, \ 256 + device_links_read_lock_held()) 257 + 258 + #define dev_for_each_link_to_consumer(__link, __dev) \ 259 + list_for_each_entry_srcu(__link, &(__dev)->links.consumers, s_node, \ 260 + device_links_read_lock_held()) 261 + 254 262 /* device pm support */ 255 263 void device_pm_move_to_tail(struct device *dev); 256 264
+20 -12
drivers/base/power/main.c
··· 40 40 41 41 typedef int (*pm_callback_t)(struct device *); 42 42 43 - #define list_for_each_entry_rcu_locked(pos, head, member) \ 44 - list_for_each_entry_rcu(pos, head, member, \ 45 - device_links_read_lock_held()) 46 - 47 43 /* 48 44 * The entries in the dpm_list list are in a depth first order, simply 49 45 * because children are guaranteed to be discovered after parents, and ··· 277 281 * callbacks freeing the link objects for the links in the list we're 278 282 * walking. 279 283 */ 280 - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) 284 + dev_for_each_link_to_supplier(link, dev) 281 285 if (READ_ONCE(link->status) != DL_STATE_DORMANT) 282 286 dpm_wait(link->supplier, async); 283 287 ··· 334 338 * continue instead of trying to continue in parallel with its 335 339 * unregistration). 336 340 */ 337 - list_for_each_entry_rcu_locked(link, &dev->links.consumers, s_node) 341 + dev_for_each_link_to_consumer(link, dev) 338 342 if (READ_ONCE(link->status) != DL_STATE_DORMANT) 339 343 dpm_wait(link->consumer, async); 340 344 ··· 671 675 idx = device_links_read_lock(); 672 676 673 677 /* Start processing the device's "async" consumers. */ 674 - list_for_each_entry_rcu_locked(link, &dev->links.consumers, s_node) 678 + dev_for_each_link_to_consumer(link, dev) 675 679 if (READ_ONCE(link->status) != DL_STATE_DORMANT) 676 680 dpm_async_with_cleanup(link->consumer, func); 677 681 ··· 720 724 if (dev->power.syscore || dev->power.direct_complete) 721 725 goto Out; 722 726 723 - if (!dev->power.is_noirq_suspended) 727 + if (!dev->power.is_noirq_suspended) { 728 + /* 729 + * This means that system suspend has been aborted in the noirq 730 + * phase before invoking the noirq suspend callback for the 731 + * device, so if device_suspend_late() has left it in suspend, 732 + * device_resume_early() should leave it in suspend either in 733 + * case the early resume of it depends on the noirq resume that 734 + * has not run. 735 + */ 736 + if (dev_pm_skip_suspend(dev)) 737 + dev->power.must_resume = false; 738 + 724 739 goto Out; 740 + } 725 741 726 742 if (!dpm_wait_for_superior(dev, async)) 727 743 goto Out; ··· 1338 1330 idx = device_links_read_lock(); 1339 1331 1340 1332 /* Start processing the device's "async" suppliers. */ 1341 - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) 1333 + dev_for_each_link_to_supplier(link, dev) 1342 1334 if (READ_ONCE(link->status) != DL_STATE_DORMANT) 1343 1335 dpm_async_with_cleanup(link->supplier, func); 1344 1336 ··· 1392 1384 1393 1385 idx = device_links_read_lock(); 1394 1386 1395 - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) 1387 + dev_for_each_link_to_supplier(link, dev) 1396 1388 link->supplier->power.must_resume = true; 1397 1389 1398 1390 device_links_read_unlock(idx); ··· 1821 1813 1822 1814 idx = device_links_read_lock(); 1823 1815 1824 - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) { 1816 + dev_for_each_link_to_supplier(link, dev) { 1825 1817 spin_lock_irq(&link->supplier->power.lock); 1826 1818 link->supplier->power.direct_complete = false; 1827 1819 spin_unlock_irq(&link->supplier->power.lock); ··· 2073 2065 2074 2066 idx = device_links_read_lock(); 2075 2067 2076 - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) { 2068 + dev_for_each_link_to_supplier(link, dev) { 2077 2069 if (!device_link_test(link, DL_FLAG_PM_RUNTIME)) 2078 2070 continue; 2079 2071
+1 -2
drivers/base/power/runtime.c
··· 1903 1903 1904 1904 idx = device_links_read_lock(); 1905 1905 1906 - list_for_each_entry_rcu(link, &dev->links.suppliers, c_node, 1907 - device_links_read_lock_held()) 1906 + dev_for_each_link_to_supplier(link, dev) 1908 1907 if (device_link_test(link, DL_FLAG_PM_RUNTIME)) { 1909 1908 link->supplier_preactivated = true; 1910 1909 pm_runtime_get_sync(link->supplier);
+1 -8
drivers/cpufreq/acpi-cpufreq.c
··· 318 318 return cmd.val; 319 319 } 320 320 321 - /* Called via smp_call_function_many(), on the target CPUs */ 322 321 static void do_drv_write(void *_cmd) 323 322 { 324 323 struct drv_cmd *cmd = _cmd; ··· 334 335 .val = val, 335 336 .func.write = data->cpu_freq_write, 336 337 }; 337 - int this_cpu; 338 338 339 - this_cpu = get_cpu(); 340 - if (cpumask_test_cpu(this_cpu, mask)) 341 - do_drv_write(&cmd); 342 - 343 - smp_call_function_many(mask, do_drv_write, &cmd, 1); 344 - put_cpu(); 339 + on_each_cpu_mask(mask, do_drv_write, &cmd, true); 345 340 } 346 341 347 342 static u32 get_cur_val(const struct cpumask *mask, struct acpi_cpufreq_data *data)
+1
drivers/cpufreq/airoha-cpufreq.c
··· 107 107 }; 108 108 109 109 static const struct of_device_id airoha_cpufreq_match_list[] __initconst = { 110 + { .compatible = "airoha,an7583" }, 110 111 { .compatible = "airoha,en7581" }, 111 112 {}, 112 113 };
+2 -2
drivers/cpufreq/armada-37xx-cpufreq.c
··· 265 265 */ 266 266 267 267 target_vm = avs_map[l0_vdd_min] - 100; 268 - target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV; 268 + target_vm = max(target_vm, MIN_VOLT_MV); 269 269 dvfs->avs[1] = armada_37xx_avs_val_match(target_vm); 270 270 271 271 /* ··· 273 273 * be larger than 1000mv 274 274 */ 275 275 target_vm = avs_map[l0_vdd_min] - 150; 276 - target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV; 276 + target_vm = max(target_vm, MIN_VOLT_MV); 277 277 dvfs->avs[2] = dvfs->avs[3] = armada_37xx_avs_val_match(target_vm); 278 278 279 279 /*
+1 -3
drivers/cpufreq/brcmstb-avs-cpufreq.c
··· 480 480 481 481 static unsigned int brcm_avs_cpufreq_get(unsigned int cpu) 482 482 { 483 - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 483 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 484 484 struct private_data *priv; 485 485 486 486 if (!policy) 487 487 return 0; 488 488 489 489 priv = policy->driver_data; 490 - 491 - cpufreq_cpu_put(policy); 492 490 493 491 return brcm_avs_get_frequency(priv->base); 494 492 }
+5 -11
drivers/cpufreq/cppc_cpufreq.c
··· 50 50 static DEFINE_PER_CPU(struct cppc_freq_invariance, cppc_freq_inv); 51 51 static struct kthread_worker *kworker_fie; 52 52 53 - static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data, 54 - struct cppc_perf_fb_ctrs *fb_ctrs_t0, 53 + static int cppc_perf_from_fbctrs(struct cppc_perf_fb_ctrs *fb_ctrs_t0, 55 54 struct cppc_perf_fb_ctrs *fb_ctrs_t1); 56 55 57 56 /** ··· 86 87 return; 87 88 } 88 89 89 - perf = cppc_perf_from_fbctrs(cpu_data, &cppc_fi->prev_perf_fb_ctrs, 90 - &fb_ctrs); 90 + perf = cppc_perf_from_fbctrs(&cppc_fi->prev_perf_fb_ctrs, &fb_ctrs); 91 91 if (!perf) 92 92 return; 93 93 ··· 682 684 return (u32)t1 - (u32)t0; 683 685 } 684 686 685 - static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data, 686 - struct cppc_perf_fb_ctrs *fb_ctrs_t0, 687 + static int cppc_perf_from_fbctrs(struct cppc_perf_fb_ctrs *fb_ctrs_t0, 687 688 struct cppc_perf_fb_ctrs *fb_ctrs_t1) 688 689 { 689 690 u64 delta_reference, delta_delivered; ··· 722 725 723 726 static unsigned int cppc_cpufreq_get_rate(unsigned int cpu) 724 727 { 728 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 725 729 struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0}; 726 - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 727 730 struct cppc_cpudata *cpu_data; 728 731 u64 delivered_perf; 729 732 int ret; ··· 732 735 return 0; 733 736 734 737 cpu_data = policy->driver_data; 735 - 736 - cpufreq_cpu_put(policy); 737 738 738 739 ret = cppc_get_perf_ctrs_sample(cpu, &fb_ctrs_t0, &fb_ctrs_t1); 739 740 if (ret) { ··· 742 747 return 0; 743 748 } 744 749 745 - delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0, 746 - &fb_ctrs_t1); 750 + delivered_perf = cppc_perf_from_fbctrs(&fb_ctrs_t0, &fb_ctrs_t1); 747 751 if (!delivered_perf) 748 752 goto out_invalid_counters; 749 753
+3
drivers/cpufreq/cpufreq-dt-platdev.c
··· 103 103 * platforms using "operating-points-v2" property. 104 104 */ 105 105 static const struct of_device_id blocklist[] __initconst = { 106 + { .compatible = "airoha,an7583", }, 106 107 { .compatible = "airoha,en7581", }, 107 108 108 109 { .compatible = "allwinner,sun50i-a100" }, ··· 189 188 { .compatible = "ti,omap3", }, 190 189 { .compatible = "ti,am625", }, 191 190 { .compatible = "ti,am62a7", }, 191 + { .compatible = "ti,am62d2", }, 192 192 { .compatible = "ti,am62p5", }, 193 193 194 194 { .compatible = "qcom,ipq5332", }, 195 + { .compatible = "qcom,ipq5424", }, 195 196 { .compatible = "qcom,ipq6018", }, 196 197 { .compatible = "qcom,ipq8064", }, 197 198 { .compatible = "qcom,ipq8074", },
+15 -29
drivers/cpufreq/cpufreq.c
··· 664 664 665 665 static unsigned int cpufreq_parse_policy(char *str_governor) 666 666 { 667 - if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) 667 + if (!strncasecmp(str_governor, "performance", strlen("performance"))) 668 668 return CPUFREQ_POLICY_PERFORMANCE; 669 669 670 - if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) 670 + if (!strncasecmp(str_governor, "powersave", strlen("powersave"))) 671 671 return CPUFREQ_POLICY_POWERSAVE; 672 672 673 673 return CPUFREQ_POLICY_UNKNOWN; ··· 914 914 const char *buf, size_t count) 915 915 { 916 916 unsigned int freq = 0; 917 - unsigned int ret; 917 + int ret; 918 918 919 919 if (!policy->governor || !policy->governor->store_setspeed) 920 920 return -EINVAL; ··· 1121 1121 1122 1122 if (has_target()) { 1123 1123 /* Update policy governor to the one used before hotplug. */ 1124 - gov = get_governor(policy->last_governor); 1124 + if (policy->last_governor[0] != '\0') 1125 + gov = get_governor(policy->last_governor); 1125 1126 if (gov) { 1126 1127 pr_debug("Restoring governor %s for cpu %d\n", 1127 1128 gov->name, policy->cpu); ··· 1845 1844 */ 1846 1845 unsigned int cpufreq_quick_get(unsigned int cpu) 1847 1846 { 1848 - struct cpufreq_policy *policy __free(put_cpufreq_policy) = NULL; 1849 1847 unsigned long flags; 1850 1848 1851 1849 read_lock_irqsave(&cpufreq_driver_lock, flags); ··· 1859 1859 1860 1860 read_unlock_irqrestore(&cpufreq_driver_lock, flags); 1861 1861 1862 - policy = cpufreq_cpu_get(cpu); 1862 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 1863 1863 if (policy) 1864 1864 return policy->cur; 1865 1865 ··· 1875 1875 */ 1876 1876 unsigned int cpufreq_quick_get_max(unsigned int cpu) 1877 1877 { 1878 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 1879 - 1880 - policy = cpufreq_cpu_get(cpu); 1878 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 1881 1879 if (policy) 1882 1880 return policy->max; 1883 1881 ··· 1891 1893 */ 1892 1894 __weak unsigned int cpufreq_get_hw_max_freq(unsigned int cpu) 1893 1895 { 1894 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 1895 - 1896 - policy = cpufreq_cpu_get(cpu); 1896 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 1897 1897 if (policy) 1898 1898 return policy->cpuinfo.max_freq; 1899 1899 ··· 1915 1919 */ 1916 1920 unsigned int cpufreq_get(unsigned int cpu) 1917 1921 { 1918 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 1919 - 1920 - policy = cpufreq_cpu_get(cpu); 1922 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 1921 1923 if (!policy) 1922 1924 return 0; 1923 1925 ··· 2744 2750 */ 2745 2751 void cpufreq_update_policy(unsigned int cpu) 2746 2752 { 2747 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 2748 - 2749 - policy = cpufreq_cpu_get(cpu); 2753 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 2750 2754 if (!policy) 2751 2755 return; 2752 2756 ··· 2761 2769 */ 2762 2770 void cpufreq_update_limits(unsigned int cpu) 2763 2771 { 2764 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 2765 - 2766 - policy = cpufreq_cpu_get(cpu); 2772 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 2767 2773 if (!policy) 2768 2774 return; 2769 2775 ··· 2782 2792 if (!policy->freq_table) 2783 2793 return -ENXIO; 2784 2794 2785 - ret = cpufreq_frequency_table_cpuinfo(policy, policy->freq_table); 2795 + ret = cpufreq_frequency_table_cpuinfo(policy); 2786 2796 if (ret) { 2787 2797 pr_err("%s: Policy frequency update failed\n", __func__); 2788 2798 return ret; ··· 2911 2921 return -EPROBE_DEFER; 2912 2922 2913 2923 if (!driver_data || !driver_data->verify || !driver_data->init || 2914 - !(driver_data->setpolicy || driver_data->target_index || 2915 - driver_data->target) || 2916 - (driver_data->setpolicy && (driver_data->target_index || 2917 - driver_data->target)) || 2924 + (driver_data->target_index && driver_data->target) || 2925 + (!!driver_data->setpolicy == (driver_data->target_index || driver_data->target)) || 2918 2926 (!driver_data->get_intermediate != !driver_data->target_intermediate) || 2919 2927 (!driver_data->online != !driver_data->offline) || 2920 2928 (driver_data->adjust_perf && !driver_data->fast_switch)) ··· 3046 3058 3047 3059 static bool cpufreq_policy_is_good_for_eas(unsigned int cpu) 3048 3060 { 3049 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 3050 - 3051 - policy = cpufreq_cpu_get(cpu); 3061 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 3052 3062 if (!policy) { 3053 3063 pr_debug("cpufreq policy not set for CPU: %d\n", cpu); 3054 3064 return false;
+12 -12
drivers/cpufreq/cpufreq_conservative.c
··· 152 152 struct dbs_data *dbs_data = to_dbs_data(attr_set); 153 153 unsigned int input; 154 154 int ret; 155 - ret = sscanf(buf, "%u", &input); 155 + ret = kstrtouint(buf, 0, &input); 156 156 157 - if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) 157 + if (ret || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) 158 158 return -EINVAL; 159 159 160 160 dbs_data->sampling_down_factor = input; ··· 168 168 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 169 169 unsigned int input; 170 170 int ret; 171 - ret = sscanf(buf, "%u", &input); 171 + ret = kstrtouint(buf, 0, &input); 172 172 173 - if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold) 173 + if (ret || input > 100 || input <= cs_tuners->down_threshold) 174 174 return -EINVAL; 175 175 176 176 dbs_data->up_threshold = input; ··· 184 184 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 185 185 unsigned int input; 186 186 int ret; 187 - ret = sscanf(buf, "%u", &input); 187 + ret = kstrtouint(buf, 0, &input); 188 188 189 189 /* cannot be lower than 1 otherwise freq will not fall */ 190 - if (ret != 1 || input < 1 || input >= dbs_data->up_threshold) 190 + if (ret || input < 1 || input >= dbs_data->up_threshold) 191 191 return -EINVAL; 192 192 193 193 cs_tuners->down_threshold = input; ··· 201 201 unsigned int input; 202 202 int ret; 203 203 204 - ret = sscanf(buf, "%u", &input); 205 - if (ret != 1) 206 - return -EINVAL; 204 + ret = kstrtouint(buf, 0, &input); 205 + if (ret) 206 + return ret; 207 207 208 208 if (input > 1) 209 209 input = 1; ··· 226 226 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 227 227 unsigned int input; 228 228 int ret; 229 - ret = sscanf(buf, "%u", &input); 229 + ret = kstrtouint(buf, 0, &input); 230 230 231 - if (ret != 1) 232 - return -EINVAL; 231 + if (ret) 232 + return ret; 233 233 234 234 if (input > 100) 235 235 input = 100;
+1 -24
drivers/cpufreq/cpufreq_ondemand.c
··· 30 30 static unsigned int default_powersave_bias; 31 31 32 32 /* 33 - * Not all CPUs want IO time to be accounted as busy; this depends on how 34 - * efficient idling at a higher frequency/voltage is. 35 - * Pavel Machek says this is not so for various generations of AMD and old 36 - * Intel systems. 37 - * Mike Chan (android.com) claims this is also not true for ARM. 38 - * Because of this, whitelist specific known (series) of CPUs by default, and 39 - * leave all others up to the user. 40 - */ 41 - static int should_io_be_busy(void) 42 - { 43 - #if defined(CONFIG_X86) 44 - /* 45 - * For Intel, Core 2 (model 15) and later have an efficient idle. 46 - */ 47 - if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && 48 - boot_cpu_data.x86 == 6 && 49 - boot_cpu_data.x86_model >= 15) 50 - return 1; 51 - #endif 52 - return 0; 53 - } 54 - 55 - /* 56 33 * Find right freq to be set now with powersave_bias on. 57 34 * Returns the freq_hi to be used right now and will set freq_hi_delay_us, 58 35 * freq_lo, and freq_lo_delay_us in percpu area for averaging freqs. ··· 354 377 dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; 355 378 dbs_data->ignore_nice_load = 0; 356 379 tuners->powersave_bias = default_powersave_bias; 357 - dbs_data->io_is_busy = should_io_be_busy(); 380 + dbs_data->io_is_busy = od_should_io_be_busy(); 358 381 359 382 dbs_data->tuners = tuners; 360 383 return 0;
+23
drivers/cpufreq/cpufreq_ondemand.h
··· 24 24 struct od_dbs_tuners { 25 25 unsigned int powersave_bias; 26 26 }; 27 + 28 + #ifdef CONFIG_X86 29 + #include <asm/cpu_device_id.h> 30 + 31 + /* 32 + * Not all CPUs want IO time to be accounted as busy; this depends on 33 + * how efficient idling at a higher frequency/voltage is. 34 + * 35 + * Pavel Machek says this is not so for various generations of AMD and 36 + * old Intel systems. Mike Chan (android.com) claims this is also not 37 + * true for ARM. 38 + * 39 + * Because of this, select a known series of Intel CPUs (Family 6 and 40 + * later) by default, and leave all others up to the user. 41 + */ 42 + static inline bool od_should_io_be_busy(void) 43 + { 44 + return (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && 45 + boot_cpu_data.x86_vfm >= INTEL_PENTIUM_PRO); 46 + } 47 + #else 48 + static inline bool od_should_io_be_busy(void) { return false; } 49 + #endif
+10 -12
drivers/cpufreq/freq_table.c
··· 28 28 return false; 29 29 } 30 30 31 - int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, 32 - struct cpufreq_frequency_table *table) 31 + int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy) 33 32 { 34 - struct cpufreq_frequency_table *pos; 33 + struct cpufreq_frequency_table *pos, *table = policy->freq_table; 35 34 unsigned int min_freq = ~0; 36 35 unsigned int max_freq = 0; 37 - unsigned int freq; 36 + unsigned int freq, i; 38 37 39 - cpufreq_for_each_valid_entry(pos, table) { 38 + cpufreq_for_each_valid_entry_idx(pos, table, i) { 40 39 freq = pos->frequency; 41 40 42 41 if ((!cpufreq_boost_enabled() || !policy->boost_enabled) 43 42 && (pos->flags & CPUFREQ_BOOST_FREQ)) 44 43 continue; 45 44 46 - pr_debug("table entry %u: %u kHz\n", (int)(pos - table), freq); 45 + pr_debug("table entry %u: %u kHz\n", i, freq); 47 46 if (freq < min_freq) 48 47 min_freq = freq; 49 48 if (freq > max_freq) ··· 64 65 return 0; 65 66 } 66 67 67 - int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy, 68 - struct cpufreq_frequency_table *table) 68 + int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy) 69 69 { 70 - struct cpufreq_frequency_table *pos; 70 + struct cpufreq_frequency_table *pos, *table = policy->freq_table; 71 71 unsigned int freq, prev_smaller = 0; 72 72 bool found = false; 73 73 ··· 108 110 if (!policy->freq_table) 109 111 return -ENODEV; 110 112 111 - return cpufreq_frequency_table_verify(policy, policy->freq_table); 113 + return cpufreq_frequency_table_verify(policy); 112 114 } 113 115 EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify); 114 116 ··· 126 128 }; 127 129 struct cpufreq_frequency_table *pos; 128 130 struct cpufreq_frequency_table *table = policy->freq_table; 129 - unsigned int freq, diff, i = 0; 131 + unsigned int freq, diff, i; 130 132 int index; 131 133 132 134 pr_debug("request for target %u kHz (relation: %u) for cpu %u\n", ··· 352 354 return 0; 353 355 } 354 356 355 - ret = cpufreq_frequency_table_cpuinfo(policy, policy->freq_table); 357 + ret = cpufreq_frequency_table_cpuinfo(policy); 356 358 if (ret) 357 359 return ret; 358 360
+94 -98
drivers/cpufreq/intel_pstate.c
··· 620 620 (cpu->pstate.min_pstate * 100 / turbo_pstate) : 0; 621 621 } 622 622 623 - static s16 intel_pstate_get_epb(struct cpudata *cpu_data) 624 - { 625 - u64 epb; 626 - int ret; 627 - 628 - if (!boot_cpu_has(X86_FEATURE_EPB)) 629 - return -ENXIO; 630 - 631 - ret = rdmsrq_on_cpu(cpu_data->cpu, MSR_IA32_ENERGY_PERF_BIAS, &epb); 632 - if (ret) 633 - return (s16)ret; 634 - 635 - return (s16)(epb & 0x0f); 636 - } 637 - 638 623 static s16 intel_pstate_get_epp(struct cpudata *cpu_data, u64 hwp_req_data) 639 624 { 640 - s16 epp; 625 + s16 epp = -EOPNOTSUPP; 641 626 642 627 if (boot_cpu_has(X86_FEATURE_HWP_EPP)) { 643 628 /* ··· 636 651 return epp; 637 652 } 638 653 epp = (hwp_req_data >> 24) & 0xff; 639 - } else { 640 - /* When there is no EPP present, HWP uses EPB settings */ 641 - epp = intel_pstate_get_epb(cpu_data); 642 654 } 643 655 644 656 return epp; 645 657 } 646 658 647 - static int intel_pstate_set_epb(int cpu, s16 pref) 648 - { 649 - u64 epb; 650 - int ret; 651 - 652 - if (!boot_cpu_has(X86_FEATURE_EPB)) 653 - return -ENXIO; 654 - 655 - ret = rdmsrq_on_cpu(cpu, MSR_IA32_ENERGY_PERF_BIAS, &epb); 656 - if (ret) 657 - return ret; 658 - 659 - epb = (epb & ~0x0f) | pref; 660 - wrmsrq_on_cpu(cpu, MSR_IA32_ENERGY_PERF_BIAS, epb); 661 - 662 - return 0; 663 - } 664 - 665 659 /* 666 - * EPP/EPB display strings corresponding to EPP index in the 660 + * EPP display strings corresponding to EPP index in the 667 661 * energy_perf_strings[] 668 662 * index String 669 663 *------------------------------------- ··· 746 782 u32 raw_epp) 747 783 { 748 784 int epp = -EINVAL; 749 - int ret; 785 + int ret = -EOPNOTSUPP; 750 786 751 787 if (!pref_index) 752 788 epp = cpu_data->epp_default; ··· 766 802 return -EBUSY; 767 803 768 804 ret = intel_pstate_set_epp(cpu_data, epp); 769 - } else { 770 - if (epp == -EINVAL) 771 - epp = (pref_index - 1) << 2; 772 - ret = intel_pstate_set_epb(cpu_data->cpu, epp); 773 805 } 774 806 775 807 return ret; ··· 897 937 898 938 cpufreq_freq_attr_ro(base_frequency); 899 939 940 + enum hwp_cpufreq_attr_index { 941 + HWP_BASE_FREQUENCY_INDEX = 0, 942 + HWP_PERFORMANCE_PREFERENCE_INDEX, 943 + HWP_PERFORMANCE_AVAILABLE_PREFERENCES_INDEX, 944 + HWP_CPUFREQ_ATTR_COUNT, 945 + }; 946 + 900 947 static struct freq_attr *hwp_cpufreq_attrs[] = { 901 - &energy_performance_preference, 902 - &energy_performance_available_preferences, 903 - &base_frequency, 904 - NULL, 948 + [HWP_BASE_FREQUENCY_INDEX] = &base_frequency, 949 + [HWP_PERFORMANCE_PREFERENCE_INDEX] = &energy_performance_preference, 950 + [HWP_PERFORMANCE_AVAILABLE_PREFERENCES_INDEX] = 951 + &energy_performance_available_preferences, 952 + [HWP_CPUFREQ_ATTR_COUNT] = NULL, 905 953 }; 906 954 907 955 static bool no_cas __ro_after_init; ··· 1305 1337 if (boot_cpu_has(X86_FEATURE_HWP_EPP)) { 1306 1338 value &= ~GENMASK_ULL(31, 24); 1307 1339 value |= (u64)epp << 24; 1308 - } else { 1309 - intel_pstate_set_epb(cpu, epp); 1310 1340 } 1341 + 1311 1342 skip_epp: 1312 1343 WRITE_ONCE(cpu_data->hwp_req_cached, value); 1313 1344 wrmsrq_on_cpu(cpu, MSR_HWP_REQUEST, value); ··· 1377 1410 1378 1411 #define POWER_CTL_EE_ENABLE 1 1379 1412 #define POWER_CTL_EE_DISABLE 2 1413 + 1414 + /* Enable bit for Dynamic Efficiency Control (DEC) */ 1415 + #define POWER_CTL_DEC_ENABLE 27 1380 1416 1381 1417 static int power_ctl_ee_state; 1382 1418 ··· 1472 1502 1473 1503 static bool intel_pstate_update_max_freq(struct cpudata *cpudata) 1474 1504 { 1475 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 1476 - 1477 - policy = cpufreq_cpu_get(cpudata->cpu); 1505 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu); 1478 1506 if (!policy) 1479 1507 return false; 1480 1508 ··· 1663 1695 return count; 1664 1696 } 1665 1697 1666 - static void update_qos_request(enum freq_qos_req_type type) 1698 + static void update_cpu_qos_request(int cpu, enum freq_qos_req_type type) 1667 1699 { 1700 + struct cpudata *cpudata = all_cpu_data[cpu]; 1701 + unsigned int freq = cpudata->pstate.turbo_freq; 1668 1702 struct freq_qos_request *req; 1669 - struct cpufreq_policy *policy; 1703 + 1704 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 1705 + if (!policy) 1706 + return; 1707 + 1708 + req = policy->driver_data; 1709 + if (!req) 1710 + return; 1711 + 1712 + if (hwp_active) 1713 + intel_pstate_get_hwp_cap(cpudata); 1714 + 1715 + if (type == FREQ_QOS_MIN) { 1716 + freq = DIV_ROUND_UP(freq * global.min_perf_pct, 100); 1717 + } else { 1718 + req++; 1719 + freq = (freq * global.max_perf_pct) / 100; 1720 + } 1721 + 1722 + if (freq_qos_update_request(req, freq) < 0) 1723 + pr_warn("Failed to update freq constraint: CPU%d\n", cpu); 1724 + } 1725 + 1726 + static void update_qos_requests(enum freq_qos_req_type type) 1727 + { 1670 1728 int i; 1671 1729 1672 - for_each_possible_cpu(i) { 1673 - struct cpudata *cpu = all_cpu_data[i]; 1674 - unsigned int freq, perf_pct; 1675 - 1676 - policy = cpufreq_cpu_get(i); 1677 - if (!policy) 1678 - continue; 1679 - 1680 - req = policy->driver_data; 1681 - cpufreq_cpu_put(policy); 1682 - 1683 - if (!req) 1684 - continue; 1685 - 1686 - if (hwp_active) 1687 - intel_pstate_get_hwp_cap(cpu); 1688 - 1689 - if (type == FREQ_QOS_MIN) { 1690 - perf_pct = global.min_perf_pct; 1691 - } else { 1692 - req++; 1693 - perf_pct = global.max_perf_pct; 1694 - } 1695 - 1696 - freq = DIV_ROUND_UP(cpu->pstate.turbo_freq * perf_pct, 100); 1697 - 1698 - if (freq_qos_update_request(req, freq) < 0) 1699 - pr_warn("Failed to update freq constraint: CPU%d\n", i); 1700 - } 1730 + for_each_possible_cpu(i) 1731 + update_cpu_qos_request(i, type); 1701 1732 } 1702 1733 1703 1734 static ssize_t store_max_perf_pct(struct kobject *a, struct kobj_attribute *b, ··· 1725 1758 if (intel_pstate_driver == &intel_pstate) 1726 1759 intel_pstate_update_policies(); 1727 1760 else 1728 - update_qos_request(FREQ_QOS_MAX); 1761 + update_qos_requests(FREQ_QOS_MAX); 1729 1762 1730 1763 mutex_unlock(&intel_pstate_driver_lock); 1731 1764 ··· 1759 1792 if (intel_pstate_driver == &intel_pstate) 1760 1793 intel_pstate_update_policies(); 1761 1794 else 1762 - update_qos_request(FREQ_QOS_MIN); 1795 + update_qos_requests(FREQ_QOS_MIN); 1763 1796 1764 1797 mutex_unlock(&intel_pstate_driver_lock); 1765 1798 ··· 2542 2575 * that sample.time will always be reset before setting the utilization 2543 2576 * update hook and make the caller skip the sample then. 2544 2577 */ 2545 - if (cpu->last_sample_time) { 2578 + if (likely(cpu->last_sample_time)) { 2546 2579 intel_pstate_calc_avg_perf(cpu); 2547 2580 return true; 2548 2581 } ··· 3769 3802 {} 3770 3803 }; 3771 3804 3805 + static bool hwp_check_epp(void) 3806 + { 3807 + if (boot_cpu_has(X86_FEATURE_HWP_EPP)) 3808 + return true; 3809 + 3810 + /* Without EPP support, don't expose EPP-related sysfs attributes. */ 3811 + hwp_cpufreq_attrs[HWP_PERFORMANCE_PREFERENCE_INDEX] = NULL; 3812 + hwp_cpufreq_attrs[HWP_PERFORMANCE_AVAILABLE_PREFERENCES_INDEX] = NULL; 3813 + 3814 + return false; 3815 + } 3816 + 3817 + static bool hwp_check_dec(void) 3818 + { 3819 + u64 power_ctl; 3820 + 3821 + rdmsrq(MSR_IA32_POWER_CTL, power_ctl); 3822 + return !!(power_ctl & BIT(POWER_CTL_DEC_ENABLE)); 3823 + } 3824 + 3772 3825 static int __init intel_pstate_init(void) 3773 3826 { 3774 3827 static struct cpudata **_all_cpu_data; ··· 3809 3822 3810 3823 id = x86_match_cpu(hwp_support_ids); 3811 3824 if (id) { 3812 - hwp_forced = intel_pstate_hwp_is_enabled(); 3825 + bool epp_present = hwp_check_epp(); 3813 3826 3814 - if (hwp_forced) 3827 + /* 3828 + * If HWP is enabled already, there is no choice but to deal 3829 + * with it. 3830 + */ 3831 + hwp_forced = intel_pstate_hwp_is_enabled(); 3832 + if (hwp_forced) { 3815 3833 pr_info("HWP enabled by BIOS\n"); 3816 - else if (no_load) 3834 + no_hwp = 0; 3835 + } else if (no_load) { 3817 3836 return -ENODEV; 3837 + } else if (!epp_present && !hwp_check_dec()) { 3838 + /* 3839 + * Avoid enabling HWP for processors without EPP support 3840 + * unless the Dynamic Efficiency Control (DEC) enable 3841 + * bit (MSR_IA32_POWER_CTL, bit 27) is set because that 3842 + * means incomplete HWP implementation which is a corner 3843 + * case and supporting it is generally problematic. 3844 + */ 3845 + no_hwp = 1; 3846 + } 3818 3847 3819 3848 copy_cpu_funcs(&core_funcs); 3820 - /* 3821 - * Avoid enabling HWP for processors without EPP support, 3822 - * because that means incomplete HWP implementation which is a 3823 - * corner case and supporting it is generally problematic. 3824 - * 3825 - * If HWP is enabled already, though, there is no choice but to 3826 - * deal with it. 3827 - */ 3828 - if ((!no_hwp && boot_cpu_has(X86_FEATURE_HWP_EPP)) || hwp_forced) { 3849 + 3850 + if (!no_hwp) { 3829 3851 hwp_active = true; 3830 3852 hwp_mode_bdw = id->driver_data; 3831 3853 intel_pstate.attr = hwp_cpufreq_attrs;
+3
drivers/cpufreq/longhaul.c
··· 953 953 struct cpufreq_policy *policy = cpufreq_cpu_get(0); 954 954 int i; 955 955 956 + if (unlikely(!policy)) 957 + return; 958 + 956 959 for (i = 0; i < numscales; i++) { 957 960 if (mults[i] == maxmult) { 958 961 struct cpufreq_freqs freqs;
+109 -23
drivers/cpufreq/mediatek-cpufreq-hw.c
··· 24 24 #define POLL_USEC 1000 25 25 #define TIMEOUT_USEC 300000 26 26 27 + #define FDVFS_FDIV_HZ (26 * 1000) 28 + 27 29 enum { 28 30 REG_FREQ_LUT_TABLE, 29 31 REG_FREQ_ENABLE, ··· 37 35 REG_ARRAY_SIZE, 38 36 }; 39 37 40 - struct mtk_cpufreq_data { 38 + struct mtk_cpufreq_priv { 39 + struct device *dev; 40 + const struct mtk_cpufreq_variant *variant; 41 + void __iomem *fdvfs; 42 + }; 43 + 44 + struct mtk_cpufreq_domain { 45 + struct mtk_cpufreq_priv *parent; 41 46 struct cpufreq_frequency_table *table; 42 47 void __iomem *reg_bases[REG_ARRAY_SIZE]; 43 48 struct resource *res; ··· 52 43 int nr_opp; 53 44 }; 54 45 55 - static const u16 cpufreq_mtk_offsets[REG_ARRAY_SIZE] = { 56 - [REG_FREQ_LUT_TABLE] = 0x0, 57 - [REG_FREQ_ENABLE] = 0x84, 58 - [REG_FREQ_PERF_STATE] = 0x88, 59 - [REG_FREQ_HW_STATE] = 0x8c, 60 - [REG_EM_POWER_TBL] = 0x90, 61 - [REG_FREQ_LATENCY] = 0x110, 46 + struct mtk_cpufreq_variant { 47 + int (*init)(struct mtk_cpufreq_priv *priv); 48 + const u16 reg_offsets[REG_ARRAY_SIZE]; 49 + const bool is_hybrid_dvfs; 50 + }; 51 + 52 + static const struct mtk_cpufreq_variant cpufreq_mtk_base_variant = { 53 + .reg_offsets = { 54 + [REG_FREQ_LUT_TABLE] = 0x0, 55 + [REG_FREQ_ENABLE] = 0x84, 56 + [REG_FREQ_PERF_STATE] = 0x88, 57 + [REG_FREQ_HW_STATE] = 0x8c, 58 + [REG_EM_POWER_TBL] = 0x90, 59 + [REG_FREQ_LATENCY] = 0x110, 60 + }, 61 + }; 62 + 63 + static int mtk_cpufreq_hw_mt8196_init(struct mtk_cpufreq_priv *priv) 64 + { 65 + priv->fdvfs = devm_of_iomap(priv->dev, priv->dev->of_node, 0, NULL); 66 + if (IS_ERR(priv->fdvfs)) 67 + return dev_err_probe(priv->dev, PTR_ERR(priv->fdvfs), 68 + "failed to get fdvfs iomem\n"); 69 + 70 + return 0; 71 + } 72 + 73 + static const struct mtk_cpufreq_variant cpufreq_mtk_mt8196_variant = { 74 + .init = mtk_cpufreq_hw_mt8196_init, 75 + .reg_offsets = { 76 + [REG_FREQ_LUT_TABLE] = 0x0, 77 + [REG_FREQ_ENABLE] = 0x84, 78 + [REG_FREQ_PERF_STATE] = 0x88, 79 + [REG_FREQ_HW_STATE] = 0x8c, 80 + [REG_EM_POWER_TBL] = 0x90, 81 + [REG_FREQ_LATENCY] = 0x114, 82 + }, 83 + .is_hybrid_dvfs = true, 62 84 }; 63 85 64 86 static int __maybe_unused 65 87 mtk_cpufreq_get_cpu_power(struct device *cpu_dev, unsigned long *uW, 66 88 unsigned long *KHz) 67 89 { 68 - struct mtk_cpufreq_data *data; 90 + struct mtk_cpufreq_domain *data; 69 91 struct cpufreq_policy *policy; 70 92 int i; 71 93 ··· 120 80 return 0; 121 81 } 122 82 83 + static void mtk_cpufreq_hw_fdvfs_switch(unsigned int target_freq, 84 + struct cpufreq_policy *policy) 85 + { 86 + struct mtk_cpufreq_domain *data = policy->driver_data; 87 + struct mtk_cpufreq_priv *priv = data->parent; 88 + unsigned int cpu; 89 + 90 + target_freq = DIV_ROUND_UP(target_freq, FDVFS_FDIV_HZ); 91 + for_each_cpu(cpu, policy->real_cpus) { 92 + writel_relaxed(target_freq, priv->fdvfs + cpu * 4); 93 + } 94 + } 95 + 123 96 static int mtk_cpufreq_hw_target_index(struct cpufreq_policy *policy, 124 97 unsigned int index) 125 98 { 126 - struct mtk_cpufreq_data *data = policy->driver_data; 99 + struct mtk_cpufreq_domain *data = policy->driver_data; 100 + unsigned int target_freq; 127 101 128 - writel_relaxed(index, data->reg_bases[REG_FREQ_PERF_STATE]); 102 + if (data->parent->fdvfs) { 103 + target_freq = policy->freq_table[index].frequency; 104 + mtk_cpufreq_hw_fdvfs_switch(target_freq, policy); 105 + } else { 106 + writel_relaxed(index, data->reg_bases[REG_FREQ_PERF_STATE]); 107 + } 129 108 130 109 return 0; 131 110 } 132 111 133 112 static unsigned int mtk_cpufreq_hw_get(unsigned int cpu) 134 113 { 135 - struct mtk_cpufreq_data *data; 114 + struct mtk_cpufreq_domain *data; 136 115 struct cpufreq_policy *policy; 137 116 unsigned int index; 138 117 ··· 170 111 static unsigned int mtk_cpufreq_hw_fast_switch(struct cpufreq_policy *policy, 171 112 unsigned int target_freq) 172 113 { 173 - struct mtk_cpufreq_data *data = policy->driver_data; 114 + struct mtk_cpufreq_domain *data = policy->driver_data; 174 115 unsigned int index; 175 116 176 117 index = cpufreq_table_find_index_dl(policy, target_freq, false); 177 118 178 - writel_relaxed(index, data->reg_bases[REG_FREQ_PERF_STATE]); 119 + if (data->parent->fdvfs) 120 + mtk_cpufreq_hw_fdvfs_switch(target_freq, policy); 121 + else 122 + writel_relaxed(index, data->reg_bases[REG_FREQ_PERF_STATE]); 179 123 180 124 return policy->freq_table[index].frequency; 181 125 } 182 126 183 127 static int mtk_cpu_create_freq_table(struct platform_device *pdev, 184 - struct mtk_cpufreq_data *data) 128 + struct mtk_cpufreq_domain *data) 185 129 { 186 130 struct device *dev = &pdev->dev; 187 131 u32 temp, i, freq, prev_freq = 0; ··· 219 157 220 158 static int mtk_cpu_resources_init(struct platform_device *pdev, 221 159 struct cpufreq_policy *policy, 222 - const u16 *offsets) 160 + struct mtk_cpufreq_priv *priv) 223 161 { 224 - struct mtk_cpufreq_data *data; 162 + struct mtk_cpufreq_domain *data; 225 163 struct device *dev = &pdev->dev; 226 164 struct resource *res; 227 165 struct of_phandle_args args; ··· 241 179 242 180 index = args.args[0]; 243 181 of_node_put(args.np); 182 + 183 + /* 184 + * In a cpufreq with hybrid DVFS, such as the MT8196, the first declared 185 + * register range is for FDVFS, followed by the frequency domain MMIOs. 186 + */ 187 + if (priv->variant->is_hybrid_dvfs) 188 + index++; 189 + 190 + data->parent = priv; 244 191 245 192 res = platform_get_resource(pdev, IORESOURCE_MEM, index); 246 193 if (!res) { ··· 273 202 data->res = res; 274 203 275 204 for (i = REG_FREQ_LUT_TABLE; i < REG_ARRAY_SIZE; i++) 276 - data->reg_bases[i] = base + offsets[i]; 205 + data->reg_bases[i] = base + priv->variant->reg_offsets[i]; 277 206 278 207 ret = mtk_cpu_create_freq_table(pdev, data); 279 208 if (ret) { ··· 294 223 { 295 224 struct platform_device *pdev = cpufreq_get_driver_data(); 296 225 int sig, pwr_hw = CPUFREQ_HW_STATUS | SVS_HW_STATUS; 297 - struct mtk_cpufreq_data *data; 226 + struct mtk_cpufreq_domain *data; 298 227 unsigned int latency; 299 228 int ret; 300 229 ··· 333 262 334 263 static void mtk_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy) 335 264 { 336 - struct mtk_cpufreq_data *data = policy->driver_data; 265 + struct mtk_cpufreq_domain *data = policy->driver_data; 337 266 struct resource *res = data->res; 338 267 void __iomem *base = data->base; 339 268 ··· 346 275 static void mtk_cpufreq_register_em(struct cpufreq_policy *policy) 347 276 { 348 277 struct em_data_callback em_cb = EM_DATA_CB(mtk_cpufreq_get_cpu_power); 349 - struct mtk_cpufreq_data *data = policy->driver_data; 278 + struct mtk_cpufreq_domain *data = policy->driver_data; 350 279 351 280 em_dev_register_perf_domain(get_cpu_device(policy->cpu), data->nr_opp, 352 281 &em_cb, policy->cpus, true); ··· 368 297 369 298 static int mtk_cpufreq_hw_driver_probe(struct platform_device *pdev) 370 299 { 300 + struct mtk_cpufreq_priv *priv; 371 301 const void *data; 372 302 int ret, cpu; 373 303 struct device *cpu_dev; ··· 392 320 if (!data) 393 321 return -EINVAL; 394 322 395 - platform_set_drvdata(pdev, (void *) data); 323 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 324 + if (!priv) 325 + return -ENOMEM; 326 + 327 + priv->variant = data; 328 + priv->dev = &pdev->dev; 329 + 330 + if (priv->variant->init) { 331 + ret = priv->variant->init(priv); 332 + if (ret) 333 + return ret; 334 + } 335 + 336 + platform_set_drvdata(pdev, priv); 396 337 cpufreq_mtk_hw_driver.driver_data = pdev; 397 338 398 339 ret = cpufreq_register_driver(&cpufreq_mtk_hw_driver); ··· 421 336 } 422 337 423 338 static const struct of_device_id mtk_cpufreq_hw_match[] = { 424 - { .compatible = "mediatek,cpufreq-hw", .data = &cpufreq_mtk_offsets }, 339 + { .compatible = "mediatek,cpufreq-hw", .data = &cpufreq_mtk_base_variant }, 340 + { .compatible = "mediatek,mt8196-cpufreq-hw", .data = &cpufreq_mtk_mt8196_variant }, 425 341 {} 426 342 }; 427 343 MODULE_DEVICE_TABLE(of, mtk_cpufreq_hw_match);
+5 -6
drivers/cpufreq/mediatek-cpufreq.c
··· 123 123 soc_data->sram_max_volt); 124 124 return ret; 125 125 } 126 - } else if (pre_vproc > new_vproc) { 126 + } else { 127 127 vproc = max(new_vproc, 128 128 pre_vsram - soc_data->max_volt_shift); 129 129 ret = regulator_set_voltage(proc_reg, vproc, ··· 320 320 struct dev_pm_opp *new_opp; 321 321 struct mtk_cpu_dvfs_info *info; 322 322 unsigned long freq, volt; 323 - struct cpufreq_policy *policy; 324 323 int ret = 0; 325 324 326 325 info = container_of(nb, struct mtk_cpu_dvfs_info, opp_nb); ··· 352 353 } 353 354 354 355 dev_pm_opp_put(new_opp); 355 - policy = cpufreq_cpu_get(info->opp_cpu); 356 - if (policy) { 356 + 357 + struct cpufreq_policy *policy __free(put_cpufreq_policy) 358 + = cpufreq_cpu_get(info->opp_cpu); 359 + if (policy) 357 360 cpufreq_driver_target(policy, freq / 1000, 358 361 CPUFREQ_RELATION_L); 359 - cpufreq_cpu_put(policy); 360 - } 361 362 } 362 363 } 363 364
+5
drivers/cpufreq/qcom-cpufreq-nvmem.c
··· 200 200 case QCOM_ID_IPQ9574: 201 201 drv->versions = 1 << (unsigned int)(*speedbin); 202 202 break; 203 + case QCOM_ID_IPQ5424: 204 + case QCOM_ID_IPQ5404: 205 + drv->versions = (*speedbin == 0x3b) ? BIT(1) : BIT(0); 206 + break; 203 207 case QCOM_ID_MSM8996SG: 204 208 case QCOM_ID_APQ8096SG: 205 209 drv->versions = 1 << ((unsigned int)(*speedbin) + 4); ··· 595 591 { .compatible = "qcom,msm8996", .data = &match_data_kryo }, 596 592 { .compatible = "qcom,qcs404", .data = &match_data_qcs404 }, 597 593 { .compatible = "qcom,ipq5332", .data = &match_data_kryo }, 594 + { .compatible = "qcom,ipq5424", .data = &match_data_kryo }, 598 595 { .compatible = "qcom,ipq6018", .data = &match_data_ipq6018 }, 599 596 { .compatible = "qcom,ipq8064", .data = &match_data_ipq8064 }, 600 597 { .compatible = "qcom,ipq8074", .data = &match_data_ipq8074 },
+1 -3
drivers/cpufreq/s5pv210-cpufreq.c
··· 554 554 static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this, 555 555 unsigned long event, void *ptr) 556 556 { 557 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(0); 557 558 int ret; 558 - struct cpufreq_policy *policy; 559 559 560 - policy = cpufreq_cpu_get(0); 561 560 if (!policy) { 562 561 pr_debug("cpufreq: get no policy for cpu0\n"); 563 562 return NOTIFY_BAD; 564 563 } 565 564 566 565 ret = cpufreq_driver_target(policy, SLEEP_FREQ, 0); 567 - cpufreq_cpu_put(policy); 568 566 569 567 if (ret < 0) 570 568 return NOTIFY_BAD;
+10
drivers/cpufreq/scmi-cpufreq.c
··· 15 15 #include <linux/energy_model.h> 16 16 #include <linux/export.h> 17 17 #include <linux/module.h> 18 + #include <linux/of.h> 18 19 #include <linux/pm_opp.h> 19 20 #include <linux/pm_qos.h> 20 21 #include <linux/slab.h> ··· 424 423 if (np == scmi_np) 425 424 return true; 426 425 } 426 + 427 + /* 428 + * Older Broadcom STB chips had a "clocks" property for CPU node(s) 429 + * that did not match the SCMI performance protocol node, if we got 430 + * there, it means we had such an older Device Tree, therefore return 431 + * true to preserve backwards compatibility. 432 + */ 433 + if (of_machine_is_compatible("brcm,brcmstb")) 434 + return true; 427 435 428 436 return false; 429 437 }
+2 -4
drivers/cpufreq/sh-cpufreq.c
··· 89 89 static int sh_cpufreq_verify(struct cpufreq_policy_data *policy) 90 90 { 91 91 struct clk *cpuclk = &per_cpu(sh_cpuclk, policy->cpu); 92 - struct cpufreq_frequency_table *freq_table; 93 92 94 - freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL; 95 - if (freq_table) 96 - return cpufreq_frequency_table_verify(policy, freq_table); 93 + if (policy->freq_table) 94 + return cpufreq_frequency_table_verify(policy); 97 95 98 96 cpufreq_verify_within_cpu_limits(policy); 99 97
+6 -6
drivers/cpufreq/speedstep-lib.c
··· 378 378 * DETECT SPEEDSTEP SPEEDS * 379 379 *********************************************************************/ 380 380 381 - unsigned int speedstep_get_freqs(enum speedstep_processor processor, 382 - unsigned int *low_speed, 383 - unsigned int *high_speed, 384 - unsigned int *transition_latency, 385 - void (*set_state) (unsigned int state)) 381 + int speedstep_get_freqs(enum speedstep_processor processor, 382 + unsigned int *low_speed, 383 + unsigned int *high_speed, 384 + unsigned int *transition_latency, 385 + void (*set_state)(unsigned int state)) 386 386 { 387 387 unsigned int prev_speed; 388 - unsigned int ret = 0; 389 388 unsigned long flags; 390 389 ktime_t tv1, tv2; 390 + int ret = 0; 391 391 392 392 if ((!processor) || (!low_speed) || (!high_speed) || (!set_state)) 393 393 return -EINVAL;
+5 -5
drivers/cpufreq/speedstep-lib.h
··· 41 41 * SPEEDSTEP_LOW; the second argument is zero so that no 42 42 * cpufreq_notify_transition calls are initiated. 43 43 */ 44 - extern unsigned int speedstep_get_freqs(enum speedstep_processor processor, 45 - unsigned int *low_speed, 46 - unsigned int *high_speed, 47 - unsigned int *transition_latency, 48 - void (*set_state) (unsigned int state)); 44 + extern int speedstep_get_freqs(enum speedstep_processor processor, 45 + unsigned int *low_speed, 46 + unsigned int *high_speed, 47 + unsigned int *transition_latency, 48 + void (*set_state)(unsigned int state));
+1 -3
drivers/cpufreq/tegra186-cpufreq.c
··· 103 103 104 104 static unsigned int tegra186_cpufreq_get(unsigned int cpu) 105 105 { 106 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 106 107 struct tegra186_cpufreq_data *data = cpufreq_get_driver_data(); 107 108 struct tegra186_cpufreq_cluster *cluster; 108 - struct cpufreq_policy *policy; 109 109 unsigned int edvd_offset, cluster_id; 110 110 u32 ndiv; 111 111 112 - policy = cpufreq_cpu_get(cpu); 113 112 if (!policy) 114 113 return 0; 115 114 ··· 116 117 ndiv = readl(data->regs + edvd_offset) & EDVD_CORE_VOLT_FREQ_F_MASK; 117 118 cluster_id = data->cpus[policy->cpu].bpmp_cluster_id; 118 119 cluster = &data->clusters[cluster_id]; 119 - cpufreq_cpu_put(policy); 120 120 121 121 return (cluster->ref_clk_khz * ndiv) / cluster->div; 122 122 }
+9 -3
drivers/cpufreq/ti-cpufreq.c
··· 72 72 73 73 #define AM62P5_EFUSE_O_MPU_OPP 15 74 74 #define AM62P5_EFUSE_S_MPU_OPP 19 75 + #define AM62P5_EFUSE_T_MPU_OPP 20 75 76 #define AM62P5_EFUSE_U_MPU_OPP 21 77 + #define AM62P5_EFUSE_V_MPU_OPP 22 76 78 77 79 #define AM62P5_SUPPORT_O_MPU_OPP BIT(0) 78 80 #define AM62P5_SUPPORT_U_MPU_OPP BIT(2) ··· 155 153 unsigned long calculated_efuse = AM62P5_SUPPORT_O_MPU_OPP; 156 154 157 155 switch (efuse) { 156 + case AM62P5_EFUSE_V_MPU_OPP: 158 157 case AM62P5_EFUSE_U_MPU_OPP: 158 + case AM62P5_EFUSE_T_MPU_OPP: 159 159 case AM62P5_EFUSE_S_MPU_OPP: 160 160 calculated_efuse |= AM62P5_SUPPORT_U_MPU_OPP; 161 161 fallthrough; ··· 311 307 }; 312 308 313 309 static const struct soc_device_attribute k3_cpufreq_soc[] = { 314 - { .family = "AM62X", .revision = "SR1.0" }, 315 - { .family = "AM62AX", .revision = "SR1.0" }, 316 - { .family = "AM62PX", .revision = "SR1.0" }, 310 + { .family = "AM62X", }, 311 + { .family = "AM62AX", }, 312 + { .family = "AM62PX", }, 313 + { .family = "AM62DX", }, 317 314 { /* sentinel */ } 318 315 }; 319 316 ··· 462 457 { .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, }, 463 458 { .compatible = "ti,am625", .data = &am625_soc_data, }, 464 459 { .compatible = "ti,am62a7", .data = &am62a7_soc_data, }, 460 + { .compatible = "ti,am62d2", .data = &am62a7_soc_data, }, 465 461 { .compatible = "ti,am62p5", .data = &am62p5_soc_data, }, 466 462 /* legacy */ 467 463 { .compatible = "ti,omap3430", .data = &omap34xx_soc_data, },
+1 -1
drivers/cpufreq/virtual-cpufreq.c
··· 250 250 static int virt_cpufreq_verify_policy(struct cpufreq_policy_data *policy) 251 251 { 252 252 if (policy->freq_table) 253 - return cpufreq_frequency_table_verify(policy, policy->freq_table); 253 + return cpufreq_frequency_table_verify(policy); 254 254 255 255 cpufreq_verify_within_cpu_limits(policy); 256 256 return 0;
+7 -4
drivers/cpuidle/cpuidle-qcom-spm.c
··· 86 86 87 87 static int spm_cpuidle_register(struct device *cpuidle_dev, int cpu) 88 88 { 89 - struct platform_device *pdev = NULL; 89 + struct platform_device *pdev; 90 90 struct device_node *cpu_node, *saw_node; 91 - struct cpuidle_qcom_spm_data *data = NULL; 91 + struct cpuidle_qcom_spm_data *data; 92 92 int ret; 93 93 94 94 cpu_node = of_cpu_device_node_get(cpu); ··· 96 96 return -ENODEV; 97 97 98 98 saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0); 99 + of_node_put(cpu_node); 99 100 if (!saw_node) 100 101 return -ENODEV; 101 102 102 103 pdev = of_find_device_by_node(saw_node); 103 104 of_node_put(saw_node); 104 - of_node_put(cpu_node); 105 105 if (!pdev) 106 106 return -ENODEV; 107 107 108 108 data = devm_kzalloc(cpuidle_dev, sizeof(*data), GFP_KERNEL); 109 - if (!data) 109 + if (!data) { 110 + put_device(&pdev->dev); 110 111 return -ENOMEM; 112 + } 111 113 112 114 data->spm = dev_get_drvdata(&pdev->dev); 115 + put_device(&pdev->dev); 113 116 if (!data->spm) 114 117 return -EINVAL; 115 118
+7 -1
drivers/cpuidle/cpuidle.c
··· 635 635 static int __cpuidle_register_device(struct cpuidle_device *dev) 636 636 { 637 637 struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); 638 + unsigned int cpu = dev->cpu; 638 639 int i, ret; 640 + 641 + if (per_cpu(cpuidle_devices, cpu)) { 642 + pr_info("CPU%d: cpuidle device already registered\n", cpu); 643 + return -EEXIST; 644 + } 639 645 640 646 if (!try_module_get(drv->owner)) 641 647 return -EINVAL; ··· 654 648 dev->states_usage[i].disable |= CPUIDLE_STATE_DISABLED_BY_USER; 655 649 } 656 650 657 - per_cpu(cpuidle_devices, dev->cpu) = dev; 651 + per_cpu(cpuidle_devices, cpu) = dev; 658 652 list_add(&dev->device_list, &cpuidle_detected_devices); 659 653 660 654 ret = cpuidle_coupled_register_device(dev);
+39 -37
drivers/cpuidle/governors/menu.c
··· 314 314 if (s->exit_latency_ns > latency_req) 315 315 break; 316 316 317 - if (s->target_residency_ns > predicted_ns) { 318 - /* 319 - * Use a physical idle state, not busy polling, unless 320 - * a timer is going to trigger soon enough. 321 - */ 322 - if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) && 323 - s->target_residency_ns <= data->next_timer_ns) { 324 - predicted_ns = s->target_residency_ns; 325 - idx = i; 326 - break; 327 - } 328 - if (predicted_ns < TICK_NSEC) 329 - break; 330 - 331 - if (!tick_nohz_tick_stopped()) { 332 - /* 333 - * If the state selected so far is shallow, 334 - * waking up early won't hurt, so retain the 335 - * tick in that case and let the governor run 336 - * again in the next iteration of the loop. 337 - */ 338 - predicted_ns = drv->states[idx].target_residency_ns; 339 - break; 340 - } 341 - 342 - /* 343 - * If the state selected so far is shallow and this 344 - * state's target residency matches the time till the 345 - * closest timer event, select this one to avoid getting 346 - * stuck in the shallow one for too long. 347 - */ 348 - if (drv->states[idx].target_residency_ns < TICK_NSEC && 349 - s->target_residency_ns <= delta_tick) 350 - idx = i; 351 - 352 - return idx; 317 + if (s->target_residency_ns <= predicted_ns) { 318 + idx = i; 319 + continue; 353 320 } 354 321 355 - idx = i; 322 + /* 323 + * Use a physical idle state, not busy polling, unless a timer 324 + * is going to trigger soon enough. 325 + */ 326 + if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) && 327 + s->target_residency_ns <= data->next_timer_ns) { 328 + predicted_ns = s->target_residency_ns; 329 + idx = i; 330 + break; 331 + } 332 + 333 + if (predicted_ns < TICK_NSEC) 334 + break; 335 + 336 + if (!tick_nohz_tick_stopped()) { 337 + /* 338 + * If the state selected so far is shallow, waking up 339 + * early won't hurt, so retain the tick in that case and 340 + * let the governor run again in the next iteration of 341 + * the idle loop. 342 + */ 343 + predicted_ns = drv->states[idx].target_residency_ns; 344 + break; 345 + } 346 + 347 + /* 348 + * If the state selected so far is shallow and this state's 349 + * target residency matches the time till the closest timer 350 + * event, select this one to avoid getting stuck in the shallow 351 + * one for too long. 352 + */ 353 + if (drv->states[idx].target_residency_ns < TICK_NSEC && 354 + s->target_residency_ns <= delta_tick) 355 + idx = i; 356 + 357 + return idx; 356 358 } 357 359 358 360 if (idx == -1)
+17 -17
drivers/cpuidle/sysfs.c
··· 27 27 28 28 mutex_lock(&cpuidle_lock); 29 29 list_for_each_entry(tmp, &cpuidle_governors, governor_list) { 30 - if (i >= (ssize_t) (PAGE_SIZE - (CPUIDLE_NAME_LEN + 2))) 30 + if (i >= (ssize_t)(PAGE_SIZE - (CPUIDLE_NAME_LEN + 2))) 31 31 goto out; 32 32 33 - i += scnprintf(&buf[i], CPUIDLE_NAME_LEN + 1, "%s ", tmp->name); 33 + i += sysfs_emit_at(buf, i, "%.*s ", CPUIDLE_NAME_LEN, tmp->name); 34 34 } 35 35 36 36 out: 37 - i+= sprintf(&buf[i], "\n"); 37 + i += sysfs_emit_at(buf, i, "\n"); 38 38 mutex_unlock(&cpuidle_lock); 39 39 return i; 40 40 } ··· 49 49 spin_lock(&cpuidle_driver_lock); 50 50 drv = cpuidle_get_driver(); 51 51 if (drv) 52 - ret = sprintf(buf, "%s\n", drv->name); 52 + ret = sysfs_emit(buf, "%s\n", drv->name); 53 53 else 54 - ret = sprintf(buf, "none\n"); 54 + ret = sysfs_emit(buf, "none\n"); 55 55 spin_unlock(&cpuidle_driver_lock); 56 56 57 57 return ret; ··· 65 65 66 66 mutex_lock(&cpuidle_lock); 67 67 if (cpuidle_curr_governor) 68 - ret = sprintf(buf, "%s\n", cpuidle_curr_governor->name); 68 + ret = sysfs_emit(buf, "%s\n", cpuidle_curr_governor->name); 69 69 else 70 - ret = sprintf(buf, "none\n"); 70 + ret = sysfs_emit(buf, "none\n"); 71 71 mutex_unlock(&cpuidle_lock); 72 72 73 73 return ret; ··· 230 230 static ssize_t show_state_##_name(struct cpuidle_state *state, \ 231 231 struct cpuidle_state_usage *state_usage, char *buf) \ 232 232 { \ 233 - return sprintf(buf, "%u\n", state->_name);\ 233 + return sysfs_emit(buf, "%u\n", state->_name);\ 234 234 } 235 235 236 236 #define define_show_state_ull_function(_name) \ ··· 238 238 struct cpuidle_state_usage *state_usage, \ 239 239 char *buf) \ 240 240 { \ 241 - return sprintf(buf, "%llu\n", state_usage->_name);\ 241 + return sysfs_emit(buf, "%llu\n", state_usage->_name);\ 242 242 } 243 243 244 244 #define define_show_state_str_function(_name) \ ··· 247 247 char *buf) \ 248 248 { \ 249 249 if (state->_name[0] == '\0')\ 250 - return sprintf(buf, "<null>\n");\ 251 - return sprintf(buf, "%s\n", state->_name);\ 250 + return sysfs_emit(buf, "<null>\n");\ 251 + return sysfs_emit(buf, "%s\n", state->_name);\ 252 252 } 253 253 254 254 #define define_show_state_time_function(_name) \ ··· 256 256 struct cpuidle_state_usage *state_usage, \ 257 257 char *buf) \ 258 258 { \ 259 - return sprintf(buf, "%llu\n", ktime_to_us(state->_name##_ns)); \ 259 + return sysfs_emit(buf, "%llu\n", ktime_to_us(state->_name##_ns)); \ 260 260 } 261 261 262 262 define_show_state_time_function(exit_latency) ··· 273 273 struct cpuidle_state_usage *state_usage, 274 274 char *buf) 275 275 { 276 - return sprintf(buf, "%llu\n", ktime_to_us(state_usage->time_ns)); 276 + return sysfs_emit(buf, "%llu\n", ktime_to_us(state_usage->time_ns)); 277 277 } 278 278 279 279 static ssize_t show_state_disable(struct cpuidle_state *state, 280 280 struct cpuidle_state_usage *state_usage, 281 281 char *buf) 282 282 { 283 - return sprintf(buf, "%llu\n", 283 + return sysfs_emit(buf, "%llu\n", 284 284 state_usage->disable & CPUIDLE_STATE_DISABLED_BY_USER); 285 285 } 286 286 ··· 310 310 struct cpuidle_state_usage *state_usage, 311 311 char *buf) 312 312 { 313 - return sprintf(buf, "%s\n", 313 + return sysfs_emit(buf, "%s\n", 314 314 state->flags & CPUIDLE_FLAG_OFF ? "disabled" : "enabled"); 315 315 } 316 316 ··· 358 358 struct cpuidle_state_usage *state_usage, \ 359 359 char *buf) \ 360 360 { \ 361 - return sprintf(buf, "%llu\n", state_usage->s2idle_##_name);\ 361 + return sysfs_emit(buf, "%llu\n", state_usage->s2idle_##_name);\ 362 362 } 363 363 364 364 define_show_state_s2idle_ull_function(usage); ··· 550 550 ssize_t ret; 551 551 552 552 spin_lock(&cpuidle_driver_lock); 553 - ret = sprintf(buf, "%s\n", drv ? drv->name : "none"); 553 + ret = sysfs_emit(buf, "%s\n", drv ? drv->name : "none"); 554 554 spin_unlock(&cpuidle_driver_lock); 555 555 556 556 return ret;
+72 -19
drivers/devfreq/event/rockchip-dfi.c
··· 34 34 35 35 /* DDRMON_CTRL */ 36 36 #define DDRMON_CTRL 0x04 37 + #define DDRMON_CTRL_LPDDR5 BIT(6) 37 38 #define DDRMON_CTRL_DDR4 BIT(5) 38 39 #define DDRMON_CTRL_LPDDR4 BIT(4) 39 40 #define DDRMON_CTRL_HARDWARE_EN BIT(3) 40 41 #define DDRMON_CTRL_LPDDR23 BIT(2) 41 42 #define DDRMON_CTRL_SOFTWARE_EN BIT(1) 42 43 #define DDRMON_CTRL_TIMER_CNT_EN BIT(0) 43 - #define DDRMON_CTRL_DDR_TYPE_MASK (DDRMON_CTRL_DDR4 | \ 44 + #define DDRMON_CTRL_DDR_TYPE_MASK (DDRMON_CTRL_LPDDR5 | \ 45 + DDRMON_CTRL_DDR4 | \ 44 46 DDRMON_CTRL_LPDDR4 | \ 45 47 DDRMON_CTRL_LPDDR23) 48 + #define DDRMON_CTRL_LP5_BANK_MODE_MASK GENMASK(8, 7) 46 49 47 50 #define DDRMON_CH0_WR_NUM 0x20 48 51 #define DDRMON_CH0_RD_NUM 0x24 ··· 119 116 int buswidth[DMC_MAX_CHANNELS]; 120 117 int ddrmon_stride; 121 118 bool ddrmon_ctrl_single; 119 + u32 lp5_bank_mode; 120 + bool lp5_ckr; /* true if in 4:1 command-to-data clock ratio mode */ 121 + unsigned int count_multiplier; /* number of data clocks per count */ 122 122 }; 123 + 124 + static int rockchip_dfi_ddrtype_to_ctrl(struct rockchip_dfi *dfi, u32 *ctrl, 125 + u32 *mask) 126 + { 127 + u32 ddrmon_ver; 128 + 129 + *mask = DDRMON_CTRL_DDR_TYPE_MASK; 130 + 131 + switch (dfi->ddr_type) { 132 + case ROCKCHIP_DDRTYPE_LPDDR2: 133 + case ROCKCHIP_DDRTYPE_LPDDR3: 134 + *ctrl = DDRMON_CTRL_LPDDR23; 135 + break; 136 + case ROCKCHIP_DDRTYPE_LPDDR4: 137 + case ROCKCHIP_DDRTYPE_LPDDR4X: 138 + *ctrl = DDRMON_CTRL_LPDDR4; 139 + break; 140 + case ROCKCHIP_DDRTYPE_LPDDR5: 141 + ddrmon_ver = readl_relaxed(dfi->regs); 142 + if (ddrmon_ver < 0x40) { 143 + *ctrl = DDRMON_CTRL_LPDDR5 | dfi->lp5_bank_mode; 144 + *mask |= DDRMON_CTRL_LP5_BANK_MODE_MASK; 145 + break; 146 + } 147 + 148 + /* 149 + * As it is unknown whether the unpleasant special case 150 + * behaviour used by the vendor kernel is needed for any 151 + * shipping hardware, ask users to report if they have 152 + * some of that hardware. 153 + */ 154 + dev_err(&dfi->edev->dev, 155 + "unsupported DDRMON version 0x%04X, please let linux-rockchip know!\n", 156 + ddrmon_ver); 157 + return -EOPNOTSUPP; 158 + default: 159 + dev_err(&dfi->edev->dev, "unsupported memory type 0x%X\n", 160 + dfi->ddr_type); 161 + return -EOPNOTSUPP; 162 + } 163 + 164 + return 0; 165 + } 123 166 124 167 static int rockchip_dfi_enable(struct rockchip_dfi *dfi) 125 168 { 126 169 void __iomem *dfi_regs = dfi->regs; 127 170 int i, ret = 0; 171 + u32 ctrl; 172 + u32 ctrl_mask; 128 173 129 174 mutex_lock(&dfi->mutex); 130 175 ··· 186 135 goto out; 187 136 } 188 137 138 + ret = rockchip_dfi_ddrtype_to_ctrl(dfi, &ctrl, &ctrl_mask); 139 + if (ret) 140 + goto out; 141 + 189 142 for (i = 0; i < dfi->max_channels; i++) { 190 - u32 ctrl = 0; 191 143 192 144 if (!(dfi->channel_mask & BIT(i))) 193 145 continue; ··· 200 146 DDRMON_CTRL_SOFTWARE_EN | DDRMON_CTRL_HARDWARE_EN), 201 147 dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL); 202 148 203 - /* set ddr type to dfi */ 204 - switch (dfi->ddr_type) { 205 - case ROCKCHIP_DDRTYPE_LPDDR2: 206 - case ROCKCHIP_DDRTYPE_LPDDR3: 207 - ctrl = DDRMON_CTRL_LPDDR23; 208 - break; 209 - case ROCKCHIP_DDRTYPE_LPDDR4: 210 - case ROCKCHIP_DDRTYPE_LPDDR4X: 211 - ctrl = DDRMON_CTRL_LPDDR4; 212 - break; 213 - default: 214 - break; 215 - } 216 - 217 - writel_relaxed(HIWORD_UPDATE(ctrl, DDRMON_CTRL_DDR_TYPE_MASK), 149 + writel_relaxed(HIWORD_UPDATE(ctrl, ctrl_mask), 218 150 dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL); 219 151 220 152 /* enable count, use software mode */ ··· 475 435 476 436 switch (event->attr.config) { 477 437 case PERF_EVENT_CYCLES: 478 - count = total.c[0].clock_cycles; 438 + count = total.c[0].clock_cycles * dfi->count_multiplier; 479 439 break; 480 440 case PERF_EVENT_READ_BYTES: 481 441 for (i = 0; i < dfi->max_channels; i++) ··· 691 651 break; 692 652 case ROCKCHIP_DDRTYPE_LPDDR4: 693 653 case ROCKCHIP_DDRTYPE_LPDDR4X: 654 + case ROCKCHIP_DDRTYPE_LPDDR5: 694 655 dfi->burst_len = 16; 695 656 break; 696 657 } 658 + 659 + if (!dfi->count_multiplier) 660 + dfi->count_multiplier = 1; 697 661 698 662 ret = perf_pmu_register(pmu, "rockchip_ddr", -1); 699 663 if (ret) ··· 770 726 static int rk3588_dfi_init(struct rockchip_dfi *dfi) 771 727 { 772 728 struct regmap *regmap_pmu = dfi->regmap_pmu; 773 - u32 reg2, reg3, reg4; 729 + u32 reg2, reg3, reg4, reg6; 774 730 775 731 regmap_read(regmap_pmu, RK3588_PMUGRF_OS_REG2, &reg2); 776 732 regmap_read(regmap_pmu, RK3588_PMUGRF_OS_REG3, &reg3); ··· 795 751 dfi->max_channels = 4; 796 752 797 753 dfi->ddrmon_stride = 0x4000; 754 + dfi->count_multiplier = 2; 755 + 756 + if (dfi->ddr_type == ROCKCHIP_DDRTYPE_LPDDR5) { 757 + regmap_read(regmap_pmu, RK3588_PMUGRF_OS_REG6, &reg6); 758 + dfi->lp5_bank_mode = FIELD_GET(RK3588_PMUGRF_OS_REG6_LP5_BANK_MODE, reg6) << 7; 759 + dfi->lp5_ckr = FIELD_GET(RK3588_PMUGRF_OS_REG6_LP5_CKR, reg6); 760 + if (dfi->lp5_ckr) 761 + dfi->count_multiplier *= 2; 762 + } 798 763 799 764 return 0; 800 765 };
+3 -2
drivers/devfreq/mtk-cci-devfreq.c
··· 86 86 soc_data->sram_max_volt); 87 87 return ret; 88 88 } 89 - } else if (pre_voltage > new_voltage) { 89 + } else { 90 90 voltage = max(new_voltage, 91 91 pre_vsram - soc_data->max_volt_shift); 92 92 ret = regulator_set_voltage(drv->proc_reg, voltage, ··· 386 386 out_free_resources: 387 387 if (regulator_is_enabled(drv->proc_reg)) 388 388 regulator_disable(drv->proc_reg); 389 - if (drv->sram_reg && regulator_is_enabled(drv->sram_reg)) 389 + if (!IS_ERR_OR_NULL(drv->sram_reg) && 390 + regulator_is_enabled(drv->sram_reg)) 390 391 regulator_disable(drv->sram_reg); 391 392 392 393 return ret;
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
··· 2665 2665 struct drm_device *drm_dev = dev_get_drvdata(dev); 2666 2666 2667 2667 /* do not resume device if it's normal hibernation */ 2668 - if (!pm_hibernate_is_recovering()) 2668 + if (!pm_hibernate_is_recovering() && !pm_hibernation_mode_is_suspend()) 2669 2669 return 0; 2670 2670 2671 2671 return amdgpu_device_resume(drm_dev, true);
+128 -128
drivers/idle/intel_idle.c
··· 259 259 .flags = MWAIT2flg(0x00), 260 260 .exit_latency = 3, 261 261 .target_residency = 6, 262 - .enter = &intel_idle, 262 + .enter = intel_idle, 263 263 .enter_s2idle = intel_idle_s2idle, }, 264 264 { 265 265 .name = "C1E", ··· 267 267 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 268 268 .exit_latency = 10, 269 269 .target_residency = 20, 270 - .enter = &intel_idle, 270 + .enter = intel_idle, 271 271 .enter_s2idle = intel_idle_s2idle, }, 272 272 { 273 273 .name = "C3", ··· 275 275 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 276 276 .exit_latency = 20, 277 277 .target_residency = 80, 278 - .enter = &intel_idle, 278 + .enter = intel_idle, 279 279 .enter_s2idle = intel_idle_s2idle, }, 280 280 { 281 281 .name = "C6", ··· 283 283 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 284 284 .exit_latency = 200, 285 285 .target_residency = 800, 286 - .enter = &intel_idle, 286 + .enter = intel_idle, 287 287 .enter_s2idle = intel_idle_s2idle, }, 288 288 { 289 289 .enter = NULL } ··· 296 296 .flags = MWAIT2flg(0x00), 297 297 .exit_latency = 2, 298 298 .target_residency = 2, 299 - .enter = &intel_idle, 299 + .enter = intel_idle, 300 300 .enter_s2idle = intel_idle_s2idle, }, 301 301 { 302 302 .name = "C1E", ··· 304 304 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 305 305 .exit_latency = 10, 306 306 .target_residency = 20, 307 - .enter = &intel_idle, 307 + .enter = intel_idle, 308 308 .enter_s2idle = intel_idle_s2idle, }, 309 309 { 310 310 .name = "C3", ··· 312 312 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 313 313 .exit_latency = 80, 314 314 .target_residency = 211, 315 - .enter = &intel_idle, 315 + .enter = intel_idle, 316 316 .enter_s2idle = intel_idle_s2idle, }, 317 317 { 318 318 .name = "C6", ··· 320 320 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 321 321 .exit_latency = 104, 322 322 .target_residency = 345, 323 - .enter = &intel_idle, 323 + .enter = intel_idle, 324 324 .enter_s2idle = intel_idle_s2idle, }, 325 325 { 326 326 .name = "C7", ··· 328 328 .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, 329 329 .exit_latency = 109, 330 330 .target_residency = 345, 331 - .enter = &intel_idle, 331 + .enter = intel_idle, 332 332 .enter_s2idle = intel_idle_s2idle, }, 333 333 { 334 334 .enter = NULL } ··· 341 341 .flags = MWAIT2flg(0x00), 342 342 .exit_latency = 1, 343 343 .target_residency = 1, 344 - .enter = &intel_idle, 344 + .enter = intel_idle, 345 345 .enter_s2idle = intel_idle_s2idle, }, 346 346 { 347 347 .name = "C6N", ··· 349 349 .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, 350 350 .exit_latency = 300, 351 351 .target_residency = 275, 352 - .enter = &intel_idle, 352 + .enter = intel_idle, 353 353 .enter_s2idle = intel_idle_s2idle, }, 354 354 { 355 355 .name = "C6S", ··· 357 357 .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, 358 358 .exit_latency = 500, 359 359 .target_residency = 560, 360 - .enter = &intel_idle, 360 + .enter = intel_idle, 361 361 .enter_s2idle = intel_idle_s2idle, }, 362 362 { 363 363 .name = "C7", ··· 365 365 .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 366 366 .exit_latency = 1200, 367 367 .target_residency = 4000, 368 - .enter = &intel_idle, 368 + .enter = intel_idle, 369 369 .enter_s2idle = intel_idle_s2idle, }, 370 370 { 371 371 .name = "C7S", ··· 373 373 .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, 374 374 .exit_latency = 10000, 375 375 .target_residency = 20000, 376 - .enter = &intel_idle, 376 + .enter = intel_idle, 377 377 .enter_s2idle = intel_idle_s2idle, }, 378 378 { 379 379 .enter = NULL } ··· 386 386 .flags = MWAIT2flg(0x00), 387 387 .exit_latency = 1, 388 388 .target_residency = 1, 389 - .enter = &intel_idle, 389 + .enter = intel_idle, 390 390 .enter_s2idle = intel_idle_s2idle, }, 391 391 { 392 392 .name = "C6N", ··· 394 394 .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, 395 395 .exit_latency = 80, 396 396 .target_residency = 275, 397 - .enter = &intel_idle, 397 + .enter = intel_idle, 398 398 .enter_s2idle = intel_idle_s2idle, }, 399 399 { 400 400 .name = "C6S", ··· 402 402 .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, 403 403 .exit_latency = 200, 404 404 .target_residency = 560, 405 - .enter = &intel_idle, 405 + .enter = intel_idle, 406 406 .enter_s2idle = intel_idle_s2idle, }, 407 407 { 408 408 .name = "C7", ··· 410 410 .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 411 411 .exit_latency = 1200, 412 412 .target_residency = 4000, 413 - .enter = &intel_idle, 413 + .enter = intel_idle, 414 414 .enter_s2idle = intel_idle_s2idle, }, 415 415 { 416 416 .name = "C7S", ··· 418 418 .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, 419 419 .exit_latency = 10000, 420 420 .target_residency = 20000, 421 - .enter = &intel_idle, 421 + .enter = intel_idle, 422 422 .enter_s2idle = intel_idle_s2idle, }, 423 423 { 424 424 .enter = NULL } ··· 431 431 .flags = MWAIT2flg(0x00), 432 432 .exit_latency = 1, 433 433 .target_residency = 1, 434 - .enter = &intel_idle, 434 + .enter = intel_idle, 435 435 .enter_s2idle = intel_idle_s2idle, }, 436 436 { 437 437 .name = "C1E", ··· 439 439 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 440 440 .exit_latency = 10, 441 441 .target_residency = 20, 442 - .enter = &intel_idle, 442 + .enter = intel_idle, 443 443 .enter_s2idle = intel_idle_s2idle, }, 444 444 { 445 445 .name = "C3", ··· 447 447 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 448 448 .exit_latency = 59, 449 449 .target_residency = 156, 450 - .enter = &intel_idle, 450 + .enter = intel_idle, 451 451 .enter_s2idle = intel_idle_s2idle, }, 452 452 { 453 453 .name = "C6", ··· 455 455 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 456 456 .exit_latency = 80, 457 457 .target_residency = 300, 458 - .enter = &intel_idle, 458 + .enter = intel_idle, 459 459 .enter_s2idle = intel_idle_s2idle, }, 460 460 { 461 461 .name = "C7", ··· 463 463 .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, 464 464 .exit_latency = 87, 465 465 .target_residency = 300, 466 - .enter = &intel_idle, 466 + .enter = intel_idle, 467 467 .enter_s2idle = intel_idle_s2idle, }, 468 468 { 469 469 .enter = NULL } ··· 476 476 .flags = MWAIT2flg(0x00), 477 477 .exit_latency = 1, 478 478 .target_residency = 1, 479 - .enter = &intel_idle, 479 + .enter = intel_idle, 480 480 .enter_s2idle = intel_idle_s2idle, }, 481 481 { 482 482 .name = "C1E", ··· 484 484 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 485 485 .exit_latency = 10, 486 486 .target_residency = 80, 487 - .enter = &intel_idle, 487 + .enter = intel_idle, 488 488 .enter_s2idle = intel_idle_s2idle, }, 489 489 { 490 490 .name = "C3", ··· 492 492 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 493 493 .exit_latency = 59, 494 494 .target_residency = 156, 495 - .enter = &intel_idle, 495 + .enter = intel_idle, 496 496 .enter_s2idle = intel_idle_s2idle, }, 497 497 { 498 498 .name = "C6", ··· 500 500 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 501 501 .exit_latency = 82, 502 502 .target_residency = 300, 503 - .enter = &intel_idle, 503 + .enter = intel_idle, 504 504 .enter_s2idle = intel_idle_s2idle, }, 505 505 { 506 506 .enter = NULL } ··· 513 513 .flags = MWAIT2flg(0x00), 514 514 .exit_latency = 1, 515 515 .target_residency = 1, 516 - .enter = &intel_idle, 516 + .enter = intel_idle, 517 517 .enter_s2idle = intel_idle_s2idle, }, 518 518 { 519 519 .name = "C1E", ··· 521 521 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 522 522 .exit_latency = 10, 523 523 .target_residency = 250, 524 - .enter = &intel_idle, 524 + .enter = intel_idle, 525 525 .enter_s2idle = intel_idle_s2idle, }, 526 526 { 527 527 .name = "C3", ··· 529 529 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 530 530 .exit_latency = 59, 531 531 .target_residency = 300, 532 - .enter = &intel_idle, 532 + .enter = intel_idle, 533 533 .enter_s2idle = intel_idle_s2idle, }, 534 534 { 535 535 .name = "C6", ··· 537 537 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 538 538 .exit_latency = 84, 539 539 .target_residency = 400, 540 - .enter = &intel_idle, 540 + .enter = intel_idle, 541 541 .enter_s2idle = intel_idle_s2idle, }, 542 542 { 543 543 .enter = NULL } ··· 550 550 .flags = MWAIT2flg(0x00), 551 551 .exit_latency = 1, 552 552 .target_residency = 1, 553 - .enter = &intel_idle, 553 + .enter = intel_idle, 554 554 .enter_s2idle = intel_idle_s2idle, }, 555 555 { 556 556 .name = "C1E", ··· 558 558 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 559 559 .exit_latency = 10, 560 560 .target_residency = 500, 561 - .enter = &intel_idle, 561 + .enter = intel_idle, 562 562 .enter_s2idle = intel_idle_s2idle, }, 563 563 { 564 564 .name = "C3", ··· 566 566 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 567 567 .exit_latency = 59, 568 568 .target_residency = 600, 569 - .enter = &intel_idle, 569 + .enter = intel_idle, 570 570 .enter_s2idle = intel_idle_s2idle, }, 571 571 { 572 572 .name = "C6", ··· 574 574 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 575 575 .exit_latency = 88, 576 576 .target_residency = 700, 577 - .enter = &intel_idle, 577 + .enter = intel_idle, 578 578 .enter_s2idle = intel_idle_s2idle, }, 579 579 { 580 580 .enter = NULL } ··· 587 587 .flags = MWAIT2flg(0x00), 588 588 .exit_latency = 2, 589 589 .target_residency = 2, 590 - .enter = &intel_idle, 590 + .enter = intel_idle, 591 591 .enter_s2idle = intel_idle_s2idle, }, 592 592 { 593 593 .name = "C1E", ··· 595 595 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 596 596 .exit_latency = 10, 597 597 .target_residency = 20, 598 - .enter = &intel_idle, 598 + .enter = intel_idle, 599 599 .enter_s2idle = intel_idle_s2idle, }, 600 600 { 601 601 .name = "C3", ··· 603 603 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 604 604 .exit_latency = 33, 605 605 .target_residency = 100, 606 - .enter = &intel_idle, 606 + .enter = intel_idle, 607 607 .enter_s2idle = intel_idle_s2idle, }, 608 608 { 609 609 .name = "C6", ··· 611 611 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 612 612 .exit_latency = 133, 613 613 .target_residency = 400, 614 - .enter = &intel_idle, 614 + .enter = intel_idle, 615 615 .enter_s2idle = intel_idle_s2idle, }, 616 616 { 617 617 .name = "C7s", ··· 619 619 .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED, 620 620 .exit_latency = 166, 621 621 .target_residency = 500, 622 - .enter = &intel_idle, 622 + .enter = intel_idle, 623 623 .enter_s2idle = intel_idle_s2idle, }, 624 624 { 625 625 .name = "C8", ··· 627 627 .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 628 628 .exit_latency = 300, 629 629 .target_residency = 900, 630 - .enter = &intel_idle, 630 + .enter = intel_idle, 631 631 .enter_s2idle = intel_idle_s2idle, }, 632 632 { 633 633 .name = "C9", ··· 635 635 .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, 636 636 .exit_latency = 600, 637 637 .target_residency = 1800, 638 - .enter = &intel_idle, 638 + .enter = intel_idle, 639 639 .enter_s2idle = intel_idle_s2idle, }, 640 640 { 641 641 .name = "C10", ··· 643 643 .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 644 644 .exit_latency = 2600, 645 645 .target_residency = 7700, 646 - .enter = &intel_idle, 646 + .enter = intel_idle, 647 647 .enter_s2idle = intel_idle_s2idle, }, 648 648 { 649 649 .enter = NULL } ··· 655 655 .flags = MWAIT2flg(0x00), 656 656 .exit_latency = 2, 657 657 .target_residency = 2, 658 - .enter = &intel_idle, 658 + .enter = intel_idle, 659 659 .enter_s2idle = intel_idle_s2idle, }, 660 660 { 661 661 .name = "C1E", ··· 663 663 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 664 664 .exit_latency = 10, 665 665 .target_residency = 20, 666 - .enter = &intel_idle, 666 + .enter = intel_idle, 667 667 .enter_s2idle = intel_idle_s2idle, }, 668 668 { 669 669 .name = "C3", ··· 671 671 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 672 672 .exit_latency = 40, 673 673 .target_residency = 100, 674 - .enter = &intel_idle, 674 + .enter = intel_idle, 675 675 .enter_s2idle = intel_idle_s2idle, }, 676 676 { 677 677 .name = "C6", ··· 679 679 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 680 680 .exit_latency = 133, 681 681 .target_residency = 400, 682 - .enter = &intel_idle, 682 + .enter = intel_idle, 683 683 .enter_s2idle = intel_idle_s2idle, }, 684 684 { 685 685 .name = "C7s", ··· 687 687 .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED, 688 688 .exit_latency = 166, 689 689 .target_residency = 500, 690 - .enter = &intel_idle, 690 + .enter = intel_idle, 691 691 .enter_s2idle = intel_idle_s2idle, }, 692 692 { 693 693 .name = "C8", ··· 695 695 .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 696 696 .exit_latency = 300, 697 697 .target_residency = 900, 698 - .enter = &intel_idle, 698 + .enter = intel_idle, 699 699 .enter_s2idle = intel_idle_s2idle, }, 700 700 { 701 701 .name = "C9", ··· 703 703 .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, 704 704 .exit_latency = 600, 705 705 .target_residency = 1800, 706 - .enter = &intel_idle, 706 + .enter = intel_idle, 707 707 .enter_s2idle = intel_idle_s2idle, }, 708 708 { 709 709 .name = "C10", ··· 711 711 .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 712 712 .exit_latency = 2600, 713 713 .target_residency = 7700, 714 - .enter = &intel_idle, 714 + .enter = intel_idle, 715 715 .enter_s2idle = intel_idle_s2idle, }, 716 716 { 717 717 .enter = NULL } ··· 724 724 .flags = MWAIT2flg(0x00), 725 725 .exit_latency = 2, 726 726 .target_residency = 2, 727 - .enter = &intel_idle, 727 + .enter = intel_idle, 728 728 .enter_s2idle = intel_idle_s2idle, }, 729 729 { 730 730 .name = "C1E", ··· 732 732 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 733 733 .exit_latency = 10, 734 734 .target_residency = 20, 735 - .enter = &intel_idle, 735 + .enter = intel_idle, 736 736 .enter_s2idle = intel_idle_s2idle, }, 737 737 { 738 738 .name = "C3", ··· 740 740 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 741 741 .exit_latency = 70, 742 742 .target_residency = 100, 743 - .enter = &intel_idle, 743 + .enter = intel_idle, 744 744 .enter_s2idle = intel_idle_s2idle, }, 745 745 { 746 746 .name = "C6", ··· 748 748 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS, 749 749 .exit_latency = 85, 750 750 .target_residency = 200, 751 - .enter = &intel_idle, 751 + .enter = intel_idle, 752 752 .enter_s2idle = intel_idle_s2idle, }, 753 753 { 754 754 .name = "C7s", ··· 756 756 .flags = MWAIT2flg(0x33) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS, 757 757 .exit_latency = 124, 758 758 .target_residency = 800, 759 - .enter = &intel_idle, 759 + .enter = intel_idle, 760 760 .enter_s2idle = intel_idle_s2idle, }, 761 761 { 762 762 .name = "C8", ··· 764 764 .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS, 765 765 .exit_latency = 200, 766 766 .target_residency = 800, 767 - .enter = &intel_idle, 767 + .enter = intel_idle, 768 768 .enter_s2idle = intel_idle_s2idle, }, 769 769 { 770 770 .name = "C9", ··· 772 772 .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS, 773 773 .exit_latency = 480, 774 774 .target_residency = 5000, 775 - .enter = &intel_idle, 775 + .enter = intel_idle, 776 776 .enter_s2idle = intel_idle_s2idle, }, 777 777 { 778 778 .name = "C10", ··· 780 780 .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS, 781 781 .exit_latency = 890, 782 782 .target_residency = 5000, 783 - .enter = &intel_idle, 783 + .enter = intel_idle, 784 784 .enter_s2idle = intel_idle_s2idle, }, 785 785 { 786 786 .enter = NULL } ··· 793 793 .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE, 794 794 .exit_latency = 2, 795 795 .target_residency = 2, 796 - .enter = &intel_idle, 796 + .enter = intel_idle, 797 797 .enter_s2idle = intel_idle_s2idle, }, 798 798 { 799 799 .name = "C1E", ··· 801 801 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 802 802 .exit_latency = 10, 803 803 .target_residency = 20, 804 - .enter = &intel_idle, 804 + .enter = intel_idle, 805 805 .enter_s2idle = intel_idle_s2idle, }, 806 806 { 807 807 .name = "C6", ··· 809 809 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS, 810 810 .exit_latency = 133, 811 811 .target_residency = 600, 812 - .enter = &intel_idle, 812 + .enter = intel_idle, 813 813 .enter_s2idle = intel_idle_s2idle, }, 814 814 { 815 815 .enter = NULL } ··· 822 822 .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE, 823 823 .exit_latency = 1, 824 824 .target_residency = 1, 825 - .enter = &intel_idle, 825 + .enter = intel_idle, 826 826 .enter_s2idle = intel_idle_s2idle, }, 827 827 { 828 828 .name = "C1E", ··· 830 830 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 831 831 .exit_latency = 4, 832 832 .target_residency = 4, 833 - .enter = &intel_idle, 833 + .enter = intel_idle, 834 834 .enter_s2idle = intel_idle_s2idle, }, 835 835 { 836 836 .name = "C6", ··· 838 838 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 839 839 .exit_latency = 170, 840 840 .target_residency = 600, 841 - .enter = &intel_idle, 841 + .enter = intel_idle, 842 842 .enter_s2idle = intel_idle_s2idle, }, 843 843 { 844 844 .enter = NULL } ··· 861 861 .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE, 862 862 .exit_latency = 1, 863 863 .target_residency = 1, 864 - .enter = &intel_idle, 864 + .enter = intel_idle, 865 865 .enter_s2idle = intel_idle_s2idle, }, 866 866 { 867 867 .name = "C1E", ··· 869 869 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 870 870 .exit_latency = 2, 871 871 .target_residency = 4, 872 - .enter = &intel_idle, 872 + .enter = intel_idle, 873 873 .enter_s2idle = intel_idle_s2idle, }, 874 874 { 875 875 .name = "C6", ··· 877 877 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 878 878 .exit_latency = 220, 879 879 .target_residency = 600, 880 - .enter = &intel_idle, 880 + .enter = intel_idle, 881 881 .enter_s2idle = intel_idle_s2idle, }, 882 882 { 883 883 .name = "C8", ··· 885 885 .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 886 886 .exit_latency = 280, 887 887 .target_residency = 800, 888 - .enter = &intel_idle, 888 + .enter = intel_idle, 889 889 .enter_s2idle = intel_idle_s2idle, }, 890 890 { 891 891 .name = "C10", ··· 893 893 .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 894 894 .exit_latency = 680, 895 895 .target_residency = 2000, 896 - .enter = &intel_idle, 896 + .enter = intel_idle, 897 897 .enter_s2idle = intel_idle_s2idle, }, 898 898 { 899 899 .enter = NULL } ··· 906 906 .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE, 907 907 .exit_latency = 1, 908 908 .target_residency = 1, 909 - .enter = &intel_idle, 909 + .enter = intel_idle, 910 910 .enter_s2idle = intel_idle_s2idle, }, 911 911 { 912 912 .name = "C1E", ··· 914 914 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 915 915 .exit_latency = 2, 916 916 .target_residency = 4, 917 - .enter = &intel_idle, 917 + .enter = intel_idle, 918 918 .enter_s2idle = intel_idle_s2idle, }, 919 919 { 920 920 .name = "C6", ··· 922 922 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 923 923 .exit_latency = 170, 924 924 .target_residency = 500, 925 - .enter = &intel_idle, 925 + .enter = intel_idle, 926 926 .enter_s2idle = intel_idle_s2idle, }, 927 927 { 928 928 .name = "C8", ··· 930 930 .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 931 931 .exit_latency = 200, 932 932 .target_residency = 600, 933 - .enter = &intel_idle, 933 + .enter = intel_idle, 934 934 .enter_s2idle = intel_idle_s2idle, }, 935 935 { 936 936 .name = "C10", ··· 938 938 .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 939 939 .exit_latency = 230, 940 940 .target_residency = 700, 941 - .enter = &intel_idle, 941 + .enter = intel_idle, 942 942 .enter_s2idle = intel_idle_s2idle, }, 943 943 { 944 944 .enter = NULL } ··· 951 951 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 952 952 .exit_latency = 1, 953 953 .target_residency = 1, 954 - .enter = &intel_idle, 954 + .enter = intel_idle, 955 955 .enter_s2idle = intel_idle_s2idle, }, 956 956 { 957 957 .name = "C6", ··· 959 959 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 960 960 .exit_latency = 140, 961 961 .target_residency = 420, 962 - .enter = &intel_idle, 962 + .enter = intel_idle, 963 963 .enter_s2idle = intel_idle_s2idle, }, 964 964 { 965 965 .name = "C10", ··· 967 967 .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 968 968 .exit_latency = 310, 969 969 .target_residency = 930, 970 - .enter = &intel_idle, 970 + .enter = intel_idle, 971 971 .enter_s2idle = intel_idle_s2idle, }, 972 972 { 973 973 .enter = NULL } ··· 980 980 .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE, 981 981 .exit_latency = 1, 982 982 .target_residency = 1, 983 - .enter = &intel_idle, 983 + .enter = intel_idle, 984 984 .enter_s2idle = intel_idle_s2idle, }, 985 985 { 986 986 .name = "C1E", ··· 988 988 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 989 989 .exit_latency = 2, 990 990 .target_residency = 4, 991 - .enter = &intel_idle, 991 + .enter = intel_idle, 992 992 .enter_s2idle = intel_idle_s2idle, }, 993 993 { 994 994 .name = "C6", ··· 996 996 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 997 997 .exit_latency = 195, 998 998 .target_residency = 585, 999 - .enter = &intel_idle, 999 + .enter = intel_idle, 1000 1000 .enter_s2idle = intel_idle_s2idle, }, 1001 1001 { 1002 1002 .name = "C8", ··· 1004 1004 .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 1005 1005 .exit_latency = 260, 1006 1006 .target_residency = 1040, 1007 - .enter = &intel_idle, 1007 + .enter = intel_idle, 1008 1008 .enter_s2idle = intel_idle_s2idle, }, 1009 1009 { 1010 1010 .name = "C10", ··· 1012 1012 .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 1013 1013 .exit_latency = 660, 1014 1014 .target_residency = 1980, 1015 - .enter = &intel_idle, 1015 + .enter = intel_idle, 1016 1016 .enter_s2idle = intel_idle_s2idle, }, 1017 1017 { 1018 1018 .enter = NULL } ··· 1025 1025 .flags = MWAIT2flg(0x00), 1026 1026 .exit_latency = 1, 1027 1027 .target_residency = 1, 1028 - .enter = &intel_idle, 1028 + .enter = intel_idle, 1029 1029 .enter_s2idle = intel_idle_s2idle, }, 1030 1030 { 1031 1031 .name = "C1E", ··· 1033 1033 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 1034 1034 .exit_latency = 2, 1035 1035 .target_residency = 4, 1036 - .enter = &intel_idle, 1036 + .enter = intel_idle, 1037 1037 .enter_s2idle = intel_idle_s2idle, }, 1038 1038 { 1039 1039 .name = "C6", ··· 1042 1042 CPUIDLE_FLAG_INIT_XSTATE, 1043 1043 .exit_latency = 290, 1044 1044 .target_residency = 800, 1045 - .enter = &intel_idle, 1045 + .enter = intel_idle, 1046 1046 .enter_s2idle = intel_idle_s2idle, }, 1047 1047 { 1048 1048 .enter = NULL } ··· 1055 1055 .flags = MWAIT2flg(0x00), 1056 1056 .exit_latency = 1, 1057 1057 .target_residency = 1, 1058 - .enter = &intel_idle, 1058 + .enter = intel_idle, 1059 1059 .enter_s2idle = intel_idle_s2idle, }, 1060 1060 { 1061 1061 .name = "C1E", ··· 1063 1063 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 1064 1064 .exit_latency = 4, 1065 1065 .target_residency = 4, 1066 - .enter = &intel_idle, 1066 + .enter = intel_idle, 1067 1067 .enter_s2idle = intel_idle_s2idle, }, 1068 1068 { 1069 1069 .name = "C6", ··· 1073 1073 CPUIDLE_FLAG_PARTIAL_HINT_MATCH, 1074 1074 .exit_latency = 170, 1075 1075 .target_residency = 650, 1076 - .enter = &intel_idle, 1076 + .enter = intel_idle, 1077 1077 .enter_s2idle = intel_idle_s2idle, }, 1078 1078 { 1079 1079 .name = "C6P", ··· 1083 1083 CPUIDLE_FLAG_PARTIAL_HINT_MATCH, 1084 1084 .exit_latency = 210, 1085 1085 .target_residency = 1000, 1086 - .enter = &intel_idle, 1086 + .enter = intel_idle, 1087 1087 .enter_s2idle = intel_idle_s2idle, }, 1088 1088 { 1089 1089 .enter = NULL } ··· 1096 1096 .flags = MWAIT2flg(0x00), 1097 1097 .exit_latency = 1, 1098 1098 .target_residency = 1, 1099 - .enter = &intel_idle, 1099 + .enter = intel_idle, 1100 1100 .enter_s2idle = intel_idle_s2idle, }, 1101 1101 { 1102 1102 .name = "C1E", ··· 1104 1104 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 1105 1105 .exit_latency = 4, 1106 1106 .target_residency = 4, 1107 - .enter = &intel_idle, 1107 + .enter = intel_idle, 1108 1108 .enter_s2idle = intel_idle_s2idle, }, 1109 1109 { 1110 1110 .name = "C6", ··· 1114 1114 CPUIDLE_FLAG_PARTIAL_HINT_MATCH, 1115 1115 .exit_latency = 220, 1116 1116 .target_residency = 650, 1117 - .enter = &intel_idle, 1117 + .enter = intel_idle, 1118 1118 .enter_s2idle = intel_idle_s2idle, }, 1119 1119 { 1120 1120 .name = "C6P", ··· 1124 1124 CPUIDLE_FLAG_PARTIAL_HINT_MATCH, 1125 1125 .exit_latency = 240, 1126 1126 .target_residency = 750, 1127 - .enter = &intel_idle, 1127 + .enter = intel_idle, 1128 1128 .enter_s2idle = intel_idle_s2idle, }, 1129 1129 { 1130 1130 .enter = NULL } ··· 1137 1137 .flags = MWAIT2flg(0x00), 1138 1138 .exit_latency = 10, 1139 1139 .target_residency = 20, 1140 - .enter = &intel_idle, 1140 + .enter = intel_idle, 1141 1141 .enter_s2idle = intel_idle_s2idle, }, 1142 1142 { 1143 1143 .name = "C2", ··· 1145 1145 .flags = MWAIT2flg(0x10), 1146 1146 .exit_latency = 20, 1147 1147 .target_residency = 80, 1148 - .enter = &intel_idle, 1148 + .enter = intel_idle, 1149 1149 .enter_s2idle = intel_idle_s2idle, }, 1150 1150 { 1151 1151 .name = "C4", ··· 1153 1153 .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, 1154 1154 .exit_latency = 100, 1155 1155 .target_residency = 400, 1156 - .enter = &intel_idle, 1156 + .enter = intel_idle, 1157 1157 .enter_s2idle = intel_idle_s2idle, }, 1158 1158 { 1159 1159 .name = "C6", ··· 1161 1161 .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, 1162 1162 .exit_latency = 140, 1163 1163 .target_residency = 560, 1164 - .enter = &intel_idle, 1164 + .enter = intel_idle, 1165 1165 .enter_s2idle = intel_idle_s2idle, }, 1166 1166 { 1167 1167 .enter = NULL } ··· 1173 1173 .flags = MWAIT2flg(0x00), 1174 1174 .exit_latency = 1, 1175 1175 .target_residency = 4, 1176 - .enter = &intel_idle, 1176 + .enter = intel_idle, 1177 1177 .enter_s2idle = intel_idle_s2idle, }, 1178 1178 { 1179 1179 .name = "C4", ··· 1181 1181 .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, 1182 1182 .exit_latency = 100, 1183 1183 .target_residency = 400, 1184 - .enter = &intel_idle, 1184 + .enter = intel_idle, 1185 1185 .enter_s2idle = intel_idle_s2idle, }, 1186 1186 { 1187 1187 .name = "C6", ··· 1189 1189 .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, 1190 1190 .exit_latency = 140, 1191 1191 .target_residency = 560, 1192 - .enter = &intel_idle, 1192 + .enter = intel_idle, 1193 1193 .enter_s2idle = intel_idle_s2idle, }, 1194 1194 { 1195 1195 .name = "C7", ··· 1197 1197 .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 1198 1198 .exit_latency = 1200, 1199 1199 .target_residency = 4000, 1200 - .enter = &intel_idle, 1200 + .enter = intel_idle, 1201 1201 .enter_s2idle = intel_idle_s2idle, }, 1202 1202 { 1203 1203 .name = "C9", ··· 1205 1205 .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, 1206 1206 .exit_latency = 10000, 1207 1207 .target_residency = 20000, 1208 - .enter = &intel_idle, 1208 + .enter = intel_idle, 1209 1209 .enter_s2idle = intel_idle_s2idle, }, 1210 1210 { 1211 1211 .enter = NULL } ··· 1217 1217 .flags = MWAIT2flg(0x00), 1218 1218 .exit_latency = 2, 1219 1219 .target_residency = 2, 1220 - .enter = &intel_idle, 1220 + .enter = intel_idle, 1221 1221 .enter_s2idle = intel_idle_s2idle, }, 1222 1222 { 1223 1223 .name = "C6", ··· 1225 1225 .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TLB_FLUSHED, 1226 1226 .exit_latency = 15, 1227 1227 .target_residency = 45, 1228 - .enter = &intel_idle, 1228 + .enter = intel_idle, 1229 1229 .enter_s2idle = intel_idle_s2idle, }, 1230 1230 { 1231 1231 .enter = NULL } ··· 1237 1237 .flags = MWAIT2flg(0x00), 1238 1238 .exit_latency = 1, 1239 1239 .target_residency = 2, 1240 - .enter = &intel_idle, 1240 + .enter = intel_idle, 1241 1241 .enter_s2idle = intel_idle_s2idle }, 1242 1242 { 1243 1243 .name = "C6", ··· 1245 1245 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 1246 1246 .exit_latency = 120, 1247 1247 .target_residency = 500, 1248 - .enter = &intel_idle, 1248 + .enter = intel_idle, 1249 1249 .enter_s2idle = intel_idle_s2idle }, 1250 1250 { 1251 1251 .enter = NULL } ··· 1258 1258 .flags = MWAIT2flg(0x00), 1259 1259 .exit_latency = 2, 1260 1260 .target_residency = 2, 1261 - .enter = &intel_idle, 1261 + .enter = intel_idle, 1262 1262 .enter_s2idle = intel_idle_s2idle, }, 1263 1263 { 1264 1264 .name = "C1E", ··· 1266 1266 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 1267 1267 .exit_latency = 10, 1268 1268 .target_residency = 20, 1269 - .enter = &intel_idle, 1269 + .enter = intel_idle, 1270 1270 .enter_s2idle = intel_idle_s2idle, }, 1271 1271 { 1272 1272 .name = "C6", ··· 1274 1274 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 1275 1275 .exit_latency = 133, 1276 1276 .target_residency = 133, 1277 - .enter = &intel_idle, 1277 + .enter = intel_idle, 1278 1278 .enter_s2idle = intel_idle_s2idle, }, 1279 1279 { 1280 1280 .name = "C7s", ··· 1282 1282 .flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED, 1283 1283 .exit_latency = 155, 1284 1284 .target_residency = 155, 1285 - .enter = &intel_idle, 1285 + .enter = intel_idle, 1286 1286 .enter_s2idle = intel_idle_s2idle, }, 1287 1287 { 1288 1288 .name = "C8", ··· 1290 1290 .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 1291 1291 .exit_latency = 1000, 1292 1292 .target_residency = 1000, 1293 - .enter = &intel_idle, 1293 + .enter = intel_idle, 1294 1294 .enter_s2idle = intel_idle_s2idle, }, 1295 1295 { 1296 1296 .name = "C9", ··· 1298 1298 .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, 1299 1299 .exit_latency = 2000, 1300 1300 .target_residency = 2000, 1301 - .enter = &intel_idle, 1301 + .enter = intel_idle, 1302 1302 .enter_s2idle = intel_idle_s2idle, }, 1303 1303 { 1304 1304 .name = "C10", ··· 1306 1306 .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 1307 1307 .exit_latency = 10000, 1308 1308 .target_residency = 10000, 1309 - .enter = &intel_idle, 1309 + .enter = intel_idle, 1310 1310 .enter_s2idle = intel_idle_s2idle, }, 1311 1311 { 1312 1312 .enter = NULL } ··· 1319 1319 .flags = MWAIT2flg(0x00), 1320 1320 .exit_latency = 2, 1321 1321 .target_residency = 2, 1322 - .enter = &intel_idle, 1322 + .enter = intel_idle, 1323 1323 .enter_s2idle = intel_idle_s2idle, }, 1324 1324 { 1325 1325 .name = "C1E", ··· 1327 1327 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 1328 1328 .exit_latency = 10, 1329 1329 .target_residency = 20, 1330 - .enter = &intel_idle, 1330 + .enter = intel_idle, 1331 1331 .enter_s2idle = intel_idle_s2idle, }, 1332 1332 { 1333 1333 .name = "C6", ··· 1335 1335 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 1336 1336 .exit_latency = 50, 1337 1337 .target_residency = 500, 1338 - .enter = &intel_idle, 1338 + .enter = intel_idle, 1339 1339 .enter_s2idle = intel_idle_s2idle, }, 1340 1340 { 1341 1341 .enter = NULL } ··· 1352 1352 .flags = MWAIT2flg(0x00), 1353 1353 .exit_latency = 2, 1354 1354 .target_residency = 2, 1355 - .enter = &intel_idle, 1355 + .enter = intel_idle, 1356 1356 .enter_s2idle = intel_idle_s2idle, }, 1357 1357 { 1358 1358 .name = "C1E", ··· 1360 1360 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 1361 1361 .exit_latency = 15, 1362 1362 .target_residency = 25, 1363 - .enter = &intel_idle, 1363 + .enter = intel_idle, 1364 1364 .enter_s2idle = intel_idle_s2idle, }, 1365 1365 { 1366 1366 .name = "C6", ··· 1368 1368 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 1369 1369 .exit_latency = 130, 1370 1370 .target_residency = 500, 1371 - .enter = &intel_idle, 1371 + .enter = intel_idle, 1372 1372 .enter_s2idle = intel_idle_s2idle, }, 1373 1373 { 1374 1374 .enter = NULL } ··· 1381 1381 .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_ALWAYS_ENABLE, 1382 1382 .exit_latency = 1, 1383 1383 .target_residency = 1, 1384 - .enter = &intel_idle, 1384 + .enter = intel_idle, 1385 1385 .enter_s2idle = intel_idle_s2idle, }, 1386 1386 { 1387 1387 .name = "C1E", ··· 1389 1389 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 1390 1390 .exit_latency = 2, 1391 1391 .target_residency = 10, 1392 - .enter = &intel_idle, 1392 + .enter = intel_idle, 1393 1393 .enter_s2idle = intel_idle_s2idle, }, 1394 1394 { 1395 1395 .name = "C6S", ··· 1397 1397 .flags = MWAIT2flg(0x22) | CPUIDLE_FLAG_TLB_FLUSHED, 1398 1398 .exit_latency = 140, 1399 1399 .target_residency = 500, 1400 - .enter = &intel_idle, 1400 + .enter = intel_idle, 1401 1401 .enter_s2idle = intel_idle_s2idle, }, 1402 1402 { 1403 1403 .enter = NULL } ··· 1410 1410 .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_ALWAYS_ENABLE, 1411 1411 .exit_latency = 1, 1412 1412 .target_residency = 1, 1413 - .enter = &intel_idle, 1413 + .enter = intel_idle, 1414 1414 .enter_s2idle = intel_idle_s2idle, }, 1415 1415 { 1416 1416 .name = "C1E", ··· 1418 1418 .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 1419 1419 .exit_latency = 2, 1420 1420 .target_residency = 10, 1421 - .enter = &intel_idle, 1421 + .enter = intel_idle, 1422 1422 .enter_s2idle = intel_idle_s2idle, }, 1423 1423 { 1424 1424 .name = "C6S", ··· 1427 1427 CPUIDLE_FLAG_PARTIAL_HINT_MATCH, 1428 1428 .exit_latency = 270, 1429 1429 .target_residency = 700, 1430 - .enter = &intel_idle, 1430 + .enter = intel_idle, 1431 1431 .enter_s2idle = intel_idle_s2idle, }, 1432 1432 { 1433 1433 .name = "C6SP", ··· 1436 1436 CPUIDLE_FLAG_PARTIAL_HINT_MATCH, 1437 1437 .exit_latency = 310, 1438 1438 .target_residency = 900, 1439 - .enter = &intel_idle, 1439 + .enter = intel_idle, 1440 1440 .enter_s2idle = intel_idle_s2idle, }, 1441 1441 { 1442 1442 .enter = NULL }
+99
drivers/opp/core.c
··· 476 476 return opp->bandwidth[index].peak; 477 477 } 478 478 479 + static unsigned long _read_opp_key(struct dev_pm_opp *opp, int index, 480 + struct dev_pm_opp_key *key) 481 + { 482 + key->bw = opp->bandwidth ? opp->bandwidth[index].peak : 0; 483 + key->freq = opp->rates[index]; 484 + key->level = opp->level; 485 + 486 + return true; 487 + } 488 + 479 489 /* Generic comparison helpers */ 480 490 static bool _compare_exact(struct dev_pm_opp **opp, struct dev_pm_opp *temp_opp, 481 491 unsigned long opp_key, unsigned long key) ··· 519 509 return false; 520 510 } 521 511 512 + static bool _compare_opp_key_exact(struct dev_pm_opp **opp, 513 + struct dev_pm_opp *temp_opp, struct dev_pm_opp_key *opp_key, 514 + struct dev_pm_opp_key *key) 515 + { 516 + bool level_match = (key->level == OPP_LEVEL_UNSET || opp_key->level == key->level); 517 + bool freq_match = (key->freq == 0 || opp_key->freq == key->freq); 518 + bool bw_match = (key->bw == 0 || opp_key->bw == key->bw); 519 + 520 + if (freq_match && level_match && bw_match) { 521 + *opp = temp_opp; 522 + return true; 523 + } 524 + 525 + return false; 526 + } 527 + 522 528 /* Generic key finding helpers */ 523 529 static struct dev_pm_opp *_opp_table_find_key(struct opp_table *opp_table, 524 530 unsigned long *key, int index, bool available, ··· 562 536 if (!IS_ERR(opp)) { 563 537 *key = read(opp, index); 564 538 dev_pm_opp_get(opp); 539 + } 540 + 541 + return opp; 542 + } 543 + 544 + static struct dev_pm_opp *_opp_table_find_opp_key(struct opp_table *opp_table, 545 + struct dev_pm_opp_key *key, bool available, 546 + unsigned long (*read)(struct dev_pm_opp *opp, int index, 547 + struct dev_pm_opp_key *key), 548 + bool (*compare)(struct dev_pm_opp **opp, struct dev_pm_opp *temp_opp, 549 + struct dev_pm_opp_key *opp_key, struct dev_pm_opp_key *key), 550 + bool (*assert)(struct opp_table *opp_table, unsigned int index)) 551 + { 552 + struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); 553 + struct dev_pm_opp_key temp_key; 554 + 555 + /* Assert that the requirement is met */ 556 + if (!assert(opp_table, 0)) 557 + return ERR_PTR(-EINVAL); 558 + 559 + guard(mutex)(&opp_table->lock); 560 + 561 + list_for_each_entry(temp_opp, &opp_table->opp_list, node) { 562 + if (temp_opp->available == available) { 563 + read(temp_opp, 0, &temp_key); 564 + if (compare(&opp, temp_opp, &temp_key, key)) { 565 + /* Increment the reference count of OPP */ 566 + dev_pm_opp_get(opp); 567 + break; 568 + } 569 + } 565 570 } 566 571 567 572 return opp; ··· 688 631 assert_single_clk); 689 632 } 690 633 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact); 634 + 635 + /** 636 + * dev_pm_opp_find_key_exact() - Search for an OPP with exact key set 637 + * @dev: Device for which the OPP is being searched 638 + * @key: OPP key set to match 639 + * @available: true/false - match for available OPP 640 + * 641 + * Search for an exact match of the key set in the OPP table. 642 + * 643 + * Return: A matching opp on success, else ERR_PTR in case of error. 644 + * Possible error values: 645 + * EINVAL: for bad pointers 646 + * ERANGE: no match found for search 647 + * ENODEV: if device not found in list of registered devices 648 + * 649 + * Note: 'available' is a modifier for the search. If 'available' == true, 650 + * then the match is for exact matching key and is available in the stored 651 + * OPP table. If false, the match is for exact key which is not available. 652 + * 653 + * This provides a mechanism to enable an OPP which is not available currently 654 + * or the opposite as well. 655 + * 656 + * The callers are required to call dev_pm_opp_put() for the returned OPP after 657 + * use. 658 + */ 659 + struct dev_pm_opp *dev_pm_opp_find_key_exact(struct device *dev, 660 + struct dev_pm_opp_key *key, 661 + bool available) 662 + { 663 + struct opp_table *opp_table __free(put_opp_table) = _find_opp_table(dev); 664 + 665 + if (IS_ERR(opp_table)) { 666 + dev_err(dev, "%s: OPP table not found (%ld)\n", __func__, 667 + PTR_ERR(opp_table)); 668 + return ERR_CAST(opp_table); 669 + } 670 + 671 + return _opp_table_find_opp_key(opp_table, key, available, 672 + _read_opp_key, _compare_opp_key_exact, 673 + assert_single_clk); 674 + } 675 + EXPORT_SYMBOL_GPL(dev_pm_opp_find_key_exact); 691 676 692 677 /** 693 678 * dev_pm_opp_find_freq_exact_indexed() - Search for an exact freq for the
+2 -3
drivers/powercap/idle_inject.c
··· 133 133 duration_us = READ_ONCE(ii_dev->run_duration_us); 134 134 duration_us += READ_ONCE(ii_dev->idle_duration_us); 135 135 136 - hrtimer_forward_now(timer, ns_to_ktime(duration_us * NSEC_PER_USEC)); 136 + hrtimer_forward_now(timer, us_to_ktime(duration_us)); 137 137 138 138 return HRTIMER_RESTART; 139 139 } ··· 232 232 idle_inject_wakeup(ii_dev); 233 233 234 234 hrtimer_start(&ii_dev->timer, 235 - ns_to_ktime((idle_duration_us + run_duration_us) * 236 - NSEC_PER_USEC), 235 + us_to_ktime(idle_duration_us + run_duration_us), 237 236 HRTIMER_MODE_REL); 238 237 239 238 return 0;
+3 -4
include/linux/cpufreq.h
··· 780 780 else 781 781 782 782 783 - int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, 784 - struct cpufreq_frequency_table *table); 783 + int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy); 785 784 786 - int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy, 787 - struct cpufreq_frequency_table *table); 785 + int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy); 786 + 788 787 int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy); 789 788 790 789 int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
+30
include/linux/pm_opp.h
··· 98 98 unsigned long u_volt; 99 99 }; 100 100 101 + /** 102 + * struct dev_pm_opp_key - Key used to identify OPP entries 103 + * @freq: Frequency in Hz. Use 0 if frequency is not to be matched. 104 + * @level: Performance level associated with the OPP entry. 105 + * Use OPP_LEVEL_UNSET if level is not to be matched. 106 + * @bw: Bandwidth associated with the OPP entry. 107 + * Use 0 if bandwidth is not to be matched. 108 + * 109 + * This structure is used to uniquely identify an OPP entry based on 110 + * frequency, performance level, and bandwidth. Each field can be 111 + * selectively ignored during matching by setting it to its respective 112 + * NOP value. 113 + */ 114 + struct dev_pm_opp_key { 115 + unsigned long freq; 116 + unsigned int level; 117 + u32 bw; 118 + }; 119 + 101 120 #if defined(CONFIG_PM_OPP) 102 121 103 122 struct opp_table *dev_pm_opp_get_opp_table(struct device *dev); ··· 149 130 struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, 150 131 unsigned long freq, 151 132 bool available); 133 + 134 + struct dev_pm_opp *dev_pm_opp_find_key_exact(struct device *dev, 135 + struct dev_pm_opp_key *key, 136 + bool available); 152 137 153 138 struct dev_pm_opp * 154 139 dev_pm_opp_find_freq_exact_indexed(struct device *dev, unsigned long freq, ··· 308 285 309 286 static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, 310 287 unsigned long freq, bool available) 288 + { 289 + return ERR_PTR(-EOPNOTSUPP); 290 + } 291 + 292 + static inline struct dev_pm_opp *dev_pm_opp_find_key_exact(struct device *dev, 293 + struct dev_pm_opp_key *key, 294 + bool available) 311 295 { 312 296 return ERR_PTR(-EOPNOTSUPP); 313 297 }
+6
include/linux/suspend.h
··· 418 418 } 419 419 #endif /* CONFIG_HIBERNATION */ 420 420 421 + #if defined(CONFIG_HIBERNATION) && defined(CONFIG_SUSPEND) 422 + bool pm_hibernation_mode_is_suspend(void); 423 + #else 424 + static inline bool pm_hibernation_mode_is_suspend(void) { return false; } 425 + #endif 426 + 421 427 int arch_resume_nosmt(void); 422 428 423 429 #ifdef CONFIG_HIBERNATION_SNAPSHOT_DEV
+6 -2
include/soc/rockchip/rk3588_grf.h
··· 12 12 #define RK3588_PMUGRF_OS_REG3_DRAMTYPE_INFO_V3 GENMASK(13, 12) 13 13 #define RK3588_PMUGRF_OS_REG3_SYSREG_VERSION GENMASK(31, 28) 14 14 15 - #define RK3588_PMUGRF_OS_REG4 0x210 16 - #define RK3588_PMUGRF_OS_REG5 0x214 15 + #define RK3588_PMUGRF_OS_REG4 0x210 16 + #define RK3588_PMUGRF_OS_REG5 0x214 17 + #define RK3588_PMUGRF_OS_REG6 0x218 18 + #define RK3588_PMUGRF_OS_REG6_LP5_BANK_MODE GENMASK(2, 1) 19 + /* Whether the LPDDR5 is in 2:1 (= 0) or 4:1 (= 1) CKR a.k.a. DQS mode */ 20 + #define RK3588_PMUGRF_OS_REG6_LP5_CKR BIT(0) 17 21 18 22 #endif /* __SOC_RK3588_GRF_H */
+1
include/soc/rockchip/rockchip_grf.h
··· 13 13 ROCKCHIP_DDRTYPE_LPDDR3 = 6, 14 14 ROCKCHIP_DDRTYPE_LPDDR4 = 7, 15 15 ROCKCHIP_DDRTYPE_LPDDR4X = 8, 16 + ROCKCHIP_DDRTYPE_LPDDR5 = 9, 16 17 }; 17 18 18 19 #endif /* __SOC_ROCKCHIP_GRF_H */
+6 -5
kernel/power/energy_model.c
··· 799 799 static void em_check_capacity_update(void) 800 800 { 801 801 cpumask_var_t cpu_done_mask; 802 - int cpu; 802 + int cpu, failed_cpus = 0; 803 803 804 804 if (!zalloc_cpumask_var(&cpu_done_mask, GFP_KERNEL)) { 805 805 pr_warn("no free memory\n"); ··· 817 817 818 818 policy = cpufreq_cpu_get(cpu); 819 819 if (!policy) { 820 - pr_debug("Accessing cpu%d policy failed\n", cpu); 821 - schedule_delayed_work(&em_update_work, 822 - msecs_to_jiffies(1000)); 823 - break; 820 + failed_cpus++; 821 + continue; 824 822 } 825 823 cpufreq_cpu_put(policy); 826 824 ··· 832 834 833 835 em_adjust_new_capacity(cpu, dev, pd); 834 836 } 837 + 838 + if (failed_cpus) 839 + schedule_delayed_work(&em_update_work, msecs_to_jiffies(1000)); 835 840 836 841 free_cpumask_var(cpu_done_mask); 837 842 }
+26 -13
kernel/power/hibernate.c
··· 80 80 81 81 static atomic_t hibernate_atomic = ATOMIC_INIT(1); 82 82 83 + #ifdef CONFIG_SUSPEND 84 + /** 85 + * pm_hibernation_mode_is_suspend - Check if hibernation has been set to suspend 86 + */ 87 + bool pm_hibernation_mode_is_suspend(void) 88 + { 89 + return hibernation_mode == HIBERNATION_SUSPEND; 90 + } 91 + EXPORT_SYMBOL_GPL(pm_hibernation_mode_is_suspend); 92 + #endif 93 + 83 94 bool hibernate_acquire(void) 84 95 { 85 96 return atomic_add_unless(&hibernate_atomic, -1, 0); ··· 706 695 707 696 #ifdef CONFIG_SUSPEND 708 697 if (hibernation_mode == HIBERNATION_SUSPEND) { 698 + pm_restore_gfp_mask(); 709 699 error = suspend_devices_and_enter(mem_sleep_current); 710 - if (error) { 711 - hibernation_mode = hibernation_ops ? 712 - HIBERNATION_PLATFORM : 713 - HIBERNATION_SHUTDOWN; 714 - } else { 715 - /* Restore swap signature. */ 716 - error = swsusp_unmark(); 717 - if (error) 718 - pr_err("Swap will be unusable! Try swapon -a.\n"); 700 + if (!error) 701 + goto exit; 719 702 720 - return; 721 - } 703 + hibernation_mode = hibernation_ops ? HIBERNATION_PLATFORM : 704 + HIBERNATION_SHUTDOWN; 722 705 } 723 706 #endif 724 707 ··· 723 718 case HIBERNATION_PLATFORM: 724 719 error = hibernation_platform_enter(); 725 720 if (error == -EAGAIN || error == -EBUSY) { 726 - swsusp_unmark(); 727 721 events_check_enabled = false; 728 722 pr_info("Wakeup event detected during hibernation, rolling back.\n"); 729 - return; 723 + goto exit; 730 724 } 731 725 fallthrough; 732 726 case HIBERNATION_SHUTDOWN: ··· 744 740 pr_crit("Power down manually\n"); 745 741 while (1) 746 742 cpu_relax(); 743 + 744 + exit: 745 + /* Match the pm_restore_gfp_mask() call in hibernate(). */ 746 + pm_restrict_gfp_mask(); 747 + 748 + /* Restore swap signature. */ 749 + error = swsusp_unmark(); 750 + if (error) 751 + pr_err("Swap will be unusable! Try swapon -a.\n"); 747 752 } 748 753 749 754 static int load_image_and_restore(void)
-1
kernel/power/process.c
··· 132 132 if (!pm_freezing) 133 133 static_branch_inc(&freezer_active); 134 134 135 - pm_wakeup_clear(0); 136 135 pm_freezing = true; 137 136 error = try_to_freeze_tasks(true); 138 137 if (!error)
+1 -1
kernel/power/snapshot.c
··· 363 363 * 364 364 * One radix tree is represented by one struct mem_zone_bm_rtree. There are 365 365 * two linked lists for the nodes of the tree, one for the inner nodes and 366 - * one for the leave nodes. The linked leave nodes are used for fast linear 366 + * one for the leaf nodes. The linked leaf nodes are used for fast linear 367 367 * access of the memory bitmap. 368 368 * 369 369 * The struct rtree_node represents one node of the radix tree.
+1
kernel/power/suspend.c
··· 595 595 } 596 596 597 597 pm_pr_dbg("Preparing system for sleep (%s)\n", mem_sleep_labels[state]); 598 + pm_wakeup_clear(0); 598 599 pm_suspend_clear_flags(); 599 600 error = suspend_prepare(state); 600 601 if (error)
+3 -3
kernel/power/swap.c
··· 712 712 goto out_clean; 713 713 } 714 714 715 - data = vzalloc(array_size(nr_threads, sizeof(*data))); 715 + data = vcalloc(nr_threads, sizeof(*data)); 716 716 if (!data) { 717 717 pr_err("Failed to allocate %s data\n", hib_comp_algo); 718 718 ret = -ENOMEM; ··· 1225 1225 nr_threads = num_online_cpus() - 1; 1226 1226 nr_threads = clamp_val(nr_threads, 1, CMP_THREADS); 1227 1227 1228 - page = vmalloc(array_size(CMP_MAX_RD_PAGES, sizeof(*page))); 1228 + page = vmalloc_array(CMP_MAX_RD_PAGES, sizeof(*page)); 1229 1229 if (!page) { 1230 1230 pr_err("Failed to allocate %s page\n", hib_comp_algo); 1231 1231 ret = -ENOMEM; 1232 1232 goto out_clean; 1233 1233 } 1234 1234 1235 - data = vzalloc(array_size(nr_threads, sizeof(*data))); 1235 + data = vcalloc(nr_threads, sizeof(*data)); 1236 1236 if (!data) { 1237 1237 pr_err("Failed to allocate %s data\n", hib_comp_algo); 1238 1238 ret = -ENOMEM;
+1 -1
rust/kernel/cpufreq.rs
··· 542 542 pub fn cpus(&mut self) -> &mut cpumask::Cpumask { 543 543 // SAFETY: The pointer to `cpus` is valid for writing and remains valid for the lifetime of 544 544 // the returned reference. 545 - unsafe { cpumask::CpumaskVar::as_mut_ref(&mut self.as_mut_ref().cpus) } 545 + unsafe { cpumask::CpumaskVar::from_raw_mut(&mut self.as_mut_ref().cpus) } 546 546 } 547 547 548 548 /// Sets clock for the [`Policy`].
+3 -2
rust/kernel/cpumask.rs
··· 212 212 /// } 213 213 /// assert_eq!(mask2.weight(), count); 214 214 /// ``` 215 + #[repr(transparent)] 215 216 pub struct CpumaskVar { 216 217 #[cfg(CONFIG_CPUMASK_OFFSTACK)] 217 218 ptr: NonNull<Cpumask>, ··· 271 270 /// 272 271 /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime 273 272 /// of the returned reference. 274 - pub unsafe fn as_mut_ref<'a>(ptr: *mut bindings::cpumask_var_t) -> &'a mut Self { 273 + pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpumask_var_t) -> &'a mut Self { 275 274 // SAFETY: Guaranteed by the safety requirements of the function. 276 275 // 277 276 // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the ··· 285 284 /// 286 285 /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime 287 286 /// of the returned reference. 288 - pub unsafe fn as_ref<'a>(ptr: *const bindings::cpumask_var_t) -> &'a Self { 287 + pub unsafe fn from_raw<'a>(ptr: *const bindings::cpumask_var_t) -> &'a Self { 289 288 // SAFETY: Guaranteed by the safety requirements of the function. 290 289 // 291 290 // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the
+12 -17
rust/kernel/opp.rs
··· 12 12 clk::Hertz, 13 13 cpumask::{Cpumask, CpumaskVar}, 14 14 device::Device, 15 - error::{code::*, from_err_ptr, from_result, to_result, Error, Result, VTABLE_DEFAULT_ERROR}, 15 + error::{code::*, from_err_ptr, from_result, to_result, Result, VTABLE_DEFAULT_ERROR}, 16 16 ffi::c_ulong, 17 17 prelude::*, 18 18 str::CString, 19 - types::{ARef, AlwaysRefCounted, Opaque}, 19 + sync::aref::{ARef, AlwaysRefCounted}, 20 + types::Opaque, 20 21 }; 21 22 22 23 #[cfg(CONFIG_CPU_FREQ)] ··· 163 162 /// use kernel::device::Device; 164 163 /// use kernel::error::Result; 165 164 /// use kernel::opp::{Data, MicroVolt, Token}; 166 - /// use kernel::types::ARef; 165 + /// use kernel::sync::aref::ARef; 167 166 /// 168 167 /// fn create_opp(dev: &ARef<Device>, freq: Hertz, volt: MicroVolt, level: u32) -> Result<Token> { 169 168 /// let data = Data::new(freq, volt, level, false); ··· 212 211 /// use kernel::device::Device; 213 212 /// use kernel::error::Result; 214 213 /// use kernel::opp::{Data, MicroVolt, Token}; 215 - /// use kernel::types::ARef; 214 + /// use kernel::sync::aref::ARef; 216 215 /// 217 216 /// fn create_opp(dev: &ARef<Device>, freq: Hertz, volt: MicroVolt, level: u32) -> Result<Token> { 218 217 /// let data = Data::new(freq, volt, level, false); ··· 263 262 /// use kernel::clk::Hertz; 264 263 /// use kernel::error::Result; 265 264 /// use kernel::opp::{OPP, SearchType, Table}; 266 - /// use kernel::types::ARef; 265 + /// use kernel::sync::aref::ARef; 267 266 /// 268 267 /// fn find_opp(table: &Table, freq: Hertz) -> Result<ARef<OPP>> { 269 268 /// let opp = table.opp_from_freq(freq, Some(true), None, SearchType::Exact)?; ··· 336 335 /// use kernel::error::Result; 337 336 /// use kernel::opp::{Config, ConfigOps, ConfigToken}; 338 337 /// use kernel::str::CString; 339 - /// use kernel::types::ARef; 338 + /// use kernel::sync::aref::ARef; 340 339 /// use kernel::macros::vtable; 341 340 /// 342 341 /// #[derive(Default)] ··· 501 500 // requirements. The OPP core guarantees not to access fields of [`Config`] after this call 502 501 // and so we don't need to save a copy of them for future use. 503 502 let ret = unsafe { bindings::dev_pm_opp_set_config(dev.as_raw(), &mut config) }; 504 - if ret < 0 { 505 - Err(Error::from_errno(ret)) 506 - } else { 507 - Ok(ConfigToken(ret)) 508 - } 503 + 504 + to_result(ret).map(|()| ConfigToken(ret)) 509 505 } 510 506 511 507 /// Config's clk callback. ··· 579 581 /// use kernel::device::Device; 580 582 /// use kernel::error::Result; 581 583 /// use kernel::opp::Table; 582 - /// use kernel::types::ARef; 584 + /// use kernel::sync::aref::ARef; 583 585 /// 584 586 /// fn get_table(dev: &ARef<Device>, mask: &mut Cpumask, freq: Hertz) -> Result<Table> { 585 587 /// let mut opp_table = Table::from_of_cpumask(dev, mask)?; ··· 711 713 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 712 714 // requirements. 713 715 let ret = unsafe { bindings::dev_pm_opp_get_opp_count(self.dev.as_raw()) }; 714 - if ret < 0 { 715 - Err(Error::from_errno(ret)) 716 - } else { 717 - Ok(ret as u32) 718 - } 716 + 717 + to_result(ret).map(|()| ret as u32) 719 718 } 720 719 721 720 /// Returns max clock latency (in nanoseconds) of the [`OPP`]s in the [`Table`].
+3 -2
tools/power/cpupower/lib/cpuidle.c
··· 233 233 { 234 234 char value[SYSFS_PATH_MAX]; 235 235 int bytes_written; 236 + int len; 236 237 237 238 if (cpuidle_state_count(cpu) <= idlestate) 238 239 return -1; ··· 242 241 idlestate_value_files[IDLESTATE_DISABLE])) 243 242 return -2; 244 243 245 - snprintf(value, SYSFS_PATH_MAX, "%u", disable); 244 + len = snprintf(value, SYSFS_PATH_MAX, "%u", disable); 246 245 247 246 bytes_written = cpuidle_state_write_file(cpu, idlestate, "disable", 248 - value, sizeof(disable)); 247 + value, len); 249 248 if (bytes_written) 250 249 return 0; 251 250 return -3;
+1 -1
tools/power/cpupower/lib/cpupower.c
··· 56 56 if (numwritten < 1) { 57 57 perror(path); 58 58 close(fd); 59 - return -1; 59 + return 0; 60 60 } 61 61 62 62 close(fd);
+1 -1
tools/power/x86/amd_pstate_tracer/amd_pstate_trace.py
··· 11 11 gnuplot 5.0 or higher 12 12 gnuplot-py 1.8 or higher 13 13 (Most of the distributions have these required packages. They may be called 14 - gnuplot-py, phython-gnuplot or phython3-gnuplot, gnuplot-nox, ... ) 14 + gnuplot-py, python-gnuplot or python3-gnuplot, gnuplot-nox, ... ) 15 15 16 16 Kernel config for Linux trace is enabled 17 17
+1 -1
tools/power/x86/turbostat/turbostat.c
··· 1890 1890 sscanf((*a)->d_name, "telem%u", &aidx); 1891 1891 sscanf((*b)->d_name, "telem%u", &bidx); 1892 1892 1893 - return aidx >= bidx; 1893 + return (aidx > bidx) ? 1 : (aidx < bidx) ? -1 : 0; 1894 1894 } 1895 1895 1896 1896 const struct dirent *pmt_diriter_next(struct pmt_diriter_t *iter)
+28 -1
tools/power/x86/x86_energy_perf_policy/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 CC = $(CROSS_COMPILE)gcc 3 - BUILD_OUTPUT := $(CURDIR) 3 + BUILD_OUTPUT := $(CURDIR) 4 4 PREFIX := /usr 5 5 DESTDIR := 6 + DAY := $(shell date +%Y.%m.%d) 7 + SNAPSHOT = x86_energy_perf_policy-$(DAY) 8 + 9 + 6 10 7 11 ifeq ("$(origin O)", "command line") 8 12 BUILD_OUTPUT := $(O) ··· 30 26 install $(BUILD_OUTPUT)/x86_energy_perf_policy $(DESTDIR)$(PREFIX)/bin/x86_energy_perf_policy 31 27 install -d $(DESTDIR)$(PREFIX)/share/man/man8 32 28 install -m 644 x86_energy_perf_policy.8 $(DESTDIR)$(PREFIX)/share/man/man8 29 + 30 + snapshot: x86_energy_perf_policy 31 + @rm -rf $(SNAPSHOT) 32 + @mkdir $(SNAPSHOT) 33 + @cp x86_energy_perf_policy Makefile x86_energy_perf_policy.c x86_energy_perf_policy.8 $(SNAPSHOT) 34 + 35 + @sed -e 's/^#include <linux\/bits.h>/#include "bits.h"/' -e 's/u64/unsigned long long/' ../../../../arch/x86/include/asm/msr-index.h > $(SNAPSHOT)/msr-index.h 36 + @echo '#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))' >> $(SNAPSHOT)/msr-index.h 37 + @echo "#define BIT(x) (1 << (x))" > $(SNAPSHOT)/bits.h 38 + @echo "#define BIT_ULL(nr) (1ULL << (nr))" >> $(SNAPSHOT)/bits.h 39 + @echo "#define GENMASK(h, l) (((~0UL) << (l)) & (~0UL >> (sizeof(long) * 8 - 1 - (h))))" >> $(SNAPSHOT)/bits.h 40 + @echo "#define GENMASK_ULL(h, l) (((~0ULL) << (l)) & (~0ULL >> (sizeof(long long) * 8 - 1 - (h))))" >> $(SNAPSHOT)/bits.h 41 + 42 + @echo '#define BUILD_BUG_ON(cond) do { enum { compile_time_check ## __COUNTER__ = 1/(!(cond)) }; } while (0)' > $(SNAPSHOT)/build_bug.h 43 + @echo '#define __must_be_array(arr) 0' >> $(SNAPSHOT)/build_bug.h 44 + 45 + @echo PWD=. > $(SNAPSHOT)/Makefile 46 + @echo "CFLAGS += -DMSRHEADER='\"msr-index.h\"'" >> $(SNAPSHOT)/Makefile 47 + @echo "CFLAGS += -DBUILD_BUG_HEADER='\"build_bug.h\"'" >> $(SNAPSHOT)/Makefile 48 + @sed -e's/.*MSRHEADER.*//' Makefile >> $(SNAPSHOT)/Makefile 49 + 50 + @rm -f $(SNAPSHOT).tar.gz 51 + tar cvzf $(SNAPSHOT).tar.gz $(SNAPSHOT) 33 52
+11 -4
tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
··· 2 2 .\" Distributed under the GPL, Copyleft 1994. 3 3 .TH X86_ENERGY_PERF_POLICY 8 4 4 .SH NAME 5 - x86_energy_perf_policy \- Manage Energy vs. Performance Policy via x86 Model Specific Registers 5 + x86_energy_perf_policy \- Manage Energy vs. Performance Policy 6 6 .SH SYNOPSIS 7 7 .B x86_energy_perf_policy 8 8 .RB "[ options ] [ scope ] [field \ value]" ··· 19 19 .SH DESCRIPTION 20 20 \fBx86_energy_perf_policy\fP 21 21 displays and updates energy-performance policy settings specific to 22 - Intel Architecture Processors. Settings are accessed via Model Specific Register (MSR) 23 - updates, no matter if the Linux cpufreq sub-system is enabled or not. 22 + Intel Architecture Processors. It summarizes settings available 23 + in standard Linux interfaces (eg. cpufreq), 24 + and also decodes underlying Model Specific Register (MSRs). 25 + While \fBx86_energy_perf_policy\fP can manage energy-performance policy 26 + using only MSR access, it prefers standard 27 + Linux kernel interfaces, when they are available. 24 28 29 + .SH BACKGROUND 25 30 Policy in MSR_IA32_ENERGY_PERF_BIAS (EPB) 26 31 may affect a wide range of hardware decisions, 27 32 such as how aggressively the hardware enters and exits CPU idle states (C-states) ··· 205 200 .SH FILES 206 201 .ta 207 202 .nf 208 - /dev/cpu/*/msr 203 + EPB: /sys/devices/system/cpu/cpu*/power/energy_perf_bias 204 + EPP: /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference 205 + MSR: /dev/cpu/*/msr 209 206 .fi 210 207 .SH "SEE ALSO" 211 208 .nf
+91 -46
tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
··· 4 4 * policy preference bias on recent X86 processors. 5 5 */ 6 6 /* 7 - * Copyright (c) 2010 - 2017 Intel Corporation. 7 + * Copyright (c) 2010 - 2025 Intel Corporation. 8 8 * Len Brown <len.brown@intel.com> 9 9 */ 10 10 ··· 62 62 unsigned char update_hwp_epp; 63 63 unsigned char update_hwp_min; 64 64 unsigned char update_hwp_max; 65 + unsigned char hwp_limits_done_via_sysfs; 65 66 unsigned char update_hwp_desired; 66 67 unsigned char update_hwp_window; 67 68 unsigned char update_hwp_use_pkg; ··· 518 517 519 518 void print_version(void) 520 519 { 521 - printf("x86_energy_perf_policy 17.05.11 (C) Len Brown <len.brown@intel.com>\n"); 520 + printf("x86_energy_perf_policy 2025.9.19 Len Brown <lenb@kernel.org>\n"); 522 521 } 523 522 524 523 void cmdline(int argc, char **argv) ··· 631 630 */ 632 631 FILE *fopen_or_die(const char *path, const char *mode) 633 632 { 634 - FILE *filep = fopen(path, "r"); 633 + FILE *filep = fopen(path, mode); 635 634 636 635 if (!filep) 637 636 err(1, "%s: open failed", path); ··· 645 644 char *buffer; 646 645 647 646 /* On VMs /proc/cpuinfo contains a "flags" entry for hypervisor */ 648 - cpuinfo = fopen_or_die("/proc/cpuinfo", "ro"); 647 + cpuinfo = fopen_or_die("/proc/cpuinfo", "r"); 649 648 650 649 buffer = malloc(4096); 651 650 if (!buffer) { ··· 810 809 h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp, 811 810 h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7); 812 811 } 813 - void read_hwp_request(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset) 812 + void read_hwp_request_msr(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset) 814 813 { 815 814 unsigned long long msr; 816 815 ··· 824 823 hwp_req->hwp_use_pkg = (((msr) >> 42) & 0x1); 825 824 } 826 825 827 - void write_hwp_request(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset) 826 + void write_hwp_request_msr(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset) 828 827 { 829 828 unsigned long long msr = 0; 830 829 ··· 844 843 put_msr(cpu, msr_offset, msr); 845 844 } 846 845 847 - static int get_epb(int cpu) 846 + static int get_epb_sysfs(int cpu) 848 847 { 849 848 char path[SYSFS_PATH_MAX]; 850 849 char linebuf[3]; ··· 866 865 return (int)val; 867 866 } 868 867 869 - static int set_epb(int cpu, int val) 868 + static int set_epb_sysfs(int cpu, int val) 870 869 { 871 870 char path[SYSFS_PATH_MAX]; 872 871 char linebuf[3]; ··· 896 895 struct msr_hwp_cap cap; 897 896 int epb; 898 897 899 - epb = get_epb(cpu); 898 + epb = get_epb_sysfs(cpu); 900 899 if (epb >= 0) 901 900 printf("cpu%d: EPB %u\n", cpu, (unsigned int) epb); 902 901 903 902 if (!has_hwp) 904 903 return 0; 905 904 906 - read_hwp_request(cpu, &req, MSR_HWP_REQUEST); 905 + read_hwp_request_msr(cpu, &req, MSR_HWP_REQUEST); 907 906 print_hwp_request(cpu, &req, ""); 908 907 909 908 read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES); ··· 920 919 if (!has_hwp) 921 920 return 0; 922 921 923 - read_hwp_request(first_cpu_in_pkg[pkg], &req, MSR_HWP_REQUEST_PKG); 922 + read_hwp_request_msr(first_cpu_in_pkg[pkg], &req, MSR_HWP_REQUEST_PKG); 924 923 print_hwp_request_pkg(pkg, &req, ""); 925 924 926 925 if (has_hwp_notify) { ··· 952 951 } 953 952 /* 954 953 * If HWP is enabled and cpufreq sysfs attribtes are present, 955 - * then update sysfs, so that it will not become 956 - * stale when we write to MSRs. 954 + * then update via sysfs. The intel_pstate driver may modify (clip) 955 + * this request, say, when HWP_CAP is outside of PLATFORM_INFO limits, 956 + * and the driver-chosen value takes precidence. 957 + * 957 958 * (intel_pstate's max_perf_pct and min_perf_pct will follow cpufreq, 958 959 * so we don't have to touch that.) 959 960 */ ··· 1009 1006 1010 1007 if (update_hwp_max) 1011 1008 update_cpufreq_scaling_freq(1, cpu, req_update.hwp_max); 1009 + 1010 + hwp_limits_done_via_sysfs = 1; 1012 1011 1013 1012 return 0; 1014 1013 } ··· 1079 1074 return 0; 1080 1075 } 1081 1076 1082 - int update_hwp_request(int cpu) 1077 + int update_hwp_request_msr(int cpu) 1083 1078 { 1084 1079 struct msr_hwp_request req; 1085 1080 struct msr_hwp_cap cap; 1086 1081 1087 1082 int msr_offset = MSR_HWP_REQUEST; 1088 1083 1089 - read_hwp_request(cpu, &req, msr_offset); 1084 + read_hwp_request_msr(cpu, &req, msr_offset); 1090 1085 if (debug) 1091 1086 print_hwp_request(cpu, &req, "old: "); 1092 1087 1093 - if (update_hwp_min) 1088 + if (update_hwp_min && !hwp_limits_done_via_sysfs) 1094 1089 req.hwp_min = req_update.hwp_min; 1095 1090 1096 - if (update_hwp_max) 1091 + if (update_hwp_max && !hwp_limits_done_via_sysfs) 1097 1092 req.hwp_max = req_update.hwp_max; 1098 1093 1099 1094 if (update_hwp_desired) ··· 1116 1111 1117 1112 verify_hwp_req_self_consistency(cpu, &req); 1118 1113 1119 - write_hwp_request(cpu, &req, msr_offset); 1114 + write_hwp_request_msr(cpu, &req, msr_offset); 1120 1115 1121 1116 if (debug) { 1122 - read_hwp_request(cpu, &req, msr_offset); 1117 + read_hwp_request_msr(cpu, &req, msr_offset); 1123 1118 print_hwp_request(cpu, &req, "new: "); 1124 1119 } 1125 1120 return 0; 1126 1121 } 1127 - int update_hwp_request_pkg(int pkg) 1122 + int update_hwp_request_pkg_msr(int pkg) 1128 1123 { 1129 1124 struct msr_hwp_request req; 1130 1125 struct msr_hwp_cap cap; ··· 1132 1127 1133 1128 int msr_offset = MSR_HWP_REQUEST_PKG; 1134 1129 1135 - read_hwp_request(cpu, &req, msr_offset); 1130 + read_hwp_request_msr(cpu, &req, msr_offset); 1136 1131 if (debug) 1137 1132 print_hwp_request_pkg(pkg, &req, "old: "); 1138 1133 ··· 1160 1155 1161 1156 verify_hwp_req_self_consistency(cpu, &req); 1162 1157 1163 - write_hwp_request(cpu, &req, msr_offset); 1158 + write_hwp_request_msr(cpu, &req, msr_offset); 1164 1159 1165 1160 if (debug) { 1166 - read_hwp_request(cpu, &req, msr_offset); 1161 + read_hwp_request_msr(cpu, &req, msr_offset); 1167 1162 print_hwp_request_pkg(pkg, &req, "new: "); 1168 1163 } 1169 1164 return 0; ··· 1171 1166 1172 1167 int enable_hwp_on_cpu(int cpu) 1173 1168 { 1174 - unsigned long long msr; 1169 + unsigned long long old_msr, new_msr; 1175 1170 1176 - get_msr(cpu, MSR_PM_ENABLE, &msr); 1177 - put_msr(cpu, MSR_PM_ENABLE, 1); 1171 + get_msr(cpu, MSR_PM_ENABLE, &old_msr); 1172 + 1173 + if (old_msr & 1) 1174 + return 0; /* already enabled */ 1175 + 1176 + new_msr = old_msr | 1; 1177 + put_msr(cpu, MSR_PM_ENABLE, new_msr); 1178 1178 1179 1179 if (verbose) 1180 - printf("cpu%d: MSR_PM_ENABLE old: %d new: %d\n", cpu, (unsigned int) msr, 1); 1180 + printf("cpu%d: MSR_PM_ENABLE old: %llX new: %llX\n", cpu, old_msr, new_msr); 1181 + 1182 + return 0; 1183 + } 1184 + 1185 + int update_cpu_epb_sysfs(int cpu) 1186 + { 1187 + int epb; 1188 + 1189 + epb = get_epb_sysfs(cpu); 1190 + set_epb_sysfs(cpu, new_epb); 1191 + 1192 + if (verbose) 1193 + printf("cpu%d: ENERGY_PERF_BIAS old: %d new: %d\n", 1194 + cpu, epb, (unsigned int) new_epb); 1181 1195 1182 1196 return 0; 1183 1197 } ··· 1204 1180 int update_cpu_msrs(int cpu) 1205 1181 { 1206 1182 unsigned long long msr; 1207 - int epb; 1208 - 1209 - if (update_epb) { 1210 - epb = get_epb(cpu); 1211 - set_epb(cpu, new_epb); 1212 - 1213 - if (verbose) 1214 - printf("cpu%d: ENERGY_PERF_BIAS old: %d new: %d\n", 1215 - cpu, epb, (unsigned int) new_epb); 1216 - } 1217 1183 1218 1184 if (update_turbo) { 1219 1185 int turbo_is_present_and_disabled; ··· 1238 1224 if (!hwp_update_enabled()) 1239 1225 return 0; 1240 1226 1241 - update_hwp_request(cpu); 1227 + update_hwp_request_msr(cpu); 1242 1228 return 0; 1243 1229 } 1244 1230 ··· 1326 1312 if (CPU_ISSET_S(cpu_num, set_size, cpu_set)) 1327 1313 func(cpu_num); 1328 1314 } 1315 + int for_all_cpus_in_set_and(size_t set_size, cpu_set_t *cpu_set, int (func)(int)) 1316 + { 1317 + int cpu_num; 1318 + int retval = 1; 1319 + 1320 + for (cpu_num = 0; cpu_num <= max_cpu_num; ++cpu_num) 1321 + if (CPU_ISSET_S(cpu_num, set_size, cpu_set)) 1322 + retval &= func(cpu_num); 1323 + 1324 + return retval; 1325 + } 1329 1326 1330 1327 void init_data_structures(void) 1331 1328 { ··· 1351 1326 for_all_proc_cpus(mark_cpu_present); 1352 1327 } 1353 1328 1354 - /* clear has_hwp if it is not enable (or being enabled) */ 1355 - 1356 - void verify_hwp_is_enabled(void) 1329 + int is_hwp_enabled_on_cpu(int cpu_num) 1357 1330 { 1358 1331 unsigned long long msr; 1332 + int retval; 1333 + 1334 + /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */ 1335 + get_msr(cpu_num, MSR_PM_ENABLE, &msr); 1336 + retval = (msr & 1); 1337 + 1338 + if (verbose) 1339 + fprintf(stderr, "cpu%d: %sHWP\n", cpu_num, retval ? "" : "No-"); 1340 + 1341 + return retval; 1342 + } 1343 + 1344 + /* 1345 + * verify_hwp_is_enabled() 1346 + * 1347 + * Set (has_hwp=0) if no HWP feature or any of selected CPU set does not have HWP enabled 1348 + */ 1349 + void verify_hwp_is_enabled(void) 1350 + { 1351 + int retval; 1359 1352 1360 1353 if (!has_hwp) /* set in early_cpuid() */ 1361 1354 return; 1362 1355 1363 - /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */ 1364 - get_msr(base_cpu, MSR_PM_ENABLE, &msr); 1365 - if ((msr & 1) == 0) { 1356 + retval = for_all_cpus_in_set_and(cpu_setsize, cpu_selected_set, is_hwp_enabled_on_cpu); 1357 + 1358 + if (retval == 0) { 1366 1359 fprintf(stderr, "HWP can be enabled using '--hwp-enable'\n"); 1367 1360 has_hwp = 0; 1368 - return; 1369 1361 } 1370 1362 } 1371 1363 ··· 1593 1551 1594 1552 /* update CPU set */ 1595 1553 if (cpu_selected_set) { 1554 + if (update_epb) 1555 + for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_cpu_epb_sysfs); 1596 1556 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_sysfs); 1597 1557 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_cpu_msrs); 1558 + 1598 1559 } else if (pkg_selected_set) 1599 - for_packages(pkg_selected_set, update_hwp_request_pkg); 1560 + for_packages(pkg_selected_set, update_hwp_request_pkg_msr); 1600 1561 1601 1562 return 0; 1602 1563 }