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

Pull power management updates from Rafael Wysocki:
"The majority of changes here are cpufreq updates which are dominated
by amd-pstate driver changes, like in the previous cycle. Moreover,
changes related to amd-pstate are also the majority of cpupower
utility updates.

Included are some pieces of new hardware support, like the addition of
Clearwater Forest processors support to intel_idle, new cpufreq driver
for Airoha SoCs, and Apple cpufreq driver extensions to support more
SoCs. The intel_pstate driver is also extended to be able to support
new platforms by using ACPI CPPC to compute scaling factors between
HWP performance states and frequency.

The rest is mostly fixes and cleanups in assorted pieces of power
management code.

Specifics:

- Use str_enable_disable()-like helpers in cpufreq (Krzysztof
Kozlowski)

- Extend the Apple cpufreq driver to support more SoCs (Hector
Martin, Nick Chan)

- Add new cpufreq driver for Airoha SoCs (Christian Marangi)

- Fix using cpufreq-dt as module (Andreas Kemnade)

- Minor fixes for Sparc, SCMI, and Qcom cpufreq drivers (Ethan Carter
Edwards, Sibi Sankar, Manivannan Sadhasivam)

- Fix the maximum supported frequency computation in the ACPI cpufreq
driver to avoid relying on unfounded assumptions (Gautham Shenoy)

- Fix an amd-pstate driver regression with preferred core rankings
not being used (Mario Limonciello)

- Fix a precision issue with frequency calculation in the amd-pstate
driver (Naresh Solanki)

- Add ftrace event to the amd-pstate driver for active mode (Mario
Limonciello)

- Set default EPP policy on Ryzen processors in amd-pstate (Mario
Limonciello)

- Clean up the amd-pstate cpufreq driver and optimize it to increase
code reuse (Mario Limonciello, Dhananjay Ugwekar)

- Use CPPC to get scaling factors between HWP performance levels and
frequency in the intel_pstate driver and make it stop using a
built-in scaling factor for Arrow Lake processors (Rafael Wysocki)

- Make intel_pstate initialize epp_policy to CPUFREQ_POLICY_UNKNOWN
for consistency with CPU offline (Christian Loehle)

- Fix superfluous updates caused by need_freq_update in the schedutil
cpufreq governor (Sultan Alsawaf)

- Allow configuring the system suspend-resume (DPM) watchdog to warn
earlier than panic (Douglas Anderson)

- Implement devm_device_init_wakeup() helper and introduce a device-
managed variant of dev_pm_set_wake_irq() (Joe Hattori, Peng Fan)

- Remove direct inclusions of 'pm_wakeup.h' which should be only
included via 'device.h' (Wolfram Sang)

- Clean up two comments in the core system-wide PM code (Rafael
Wysocki, Randy Dunlap)

- Add Clearwater Forest processor support to the intel_idle cpuidle
driver (Artem Bityutskiy)

- Clean up the Exynos devfreq driver and devfreq core (Markus
Elfring, Jeongjun Park)

- Minor cleanups and fixes for OPP (Dan Carpenter, Neil Armstrong,
Joe Hattori)

- Implement dev_pm_opp_get_bw() (Neil Armstrong)

- Expose OPP reference counting helpers for Rust (Viresh Kumar)

- Fix TSC MHz calculation in cpupower (He Rongguang)

- Add install and uninstall options to bindings Makefile and add
header changes for cpufreq.h to SWIG bindings in cpupower (John B.
Wyatt IV)

- Add missing residency header changes in cpuidle.h to SWIG bindings
in cpupower (John B. Wyatt IV)

- Add output files to .gitignore and clean them up in "make clean" in
selftests/cpufreq (Li Zhijian)

- Fix cross-compilation in cpupower Makefile (Peng Fan)

- Revise the is_valid flag handling for idle_monitor in the cpupower
utility (wangfushuai)

- Extend and clean up AMD processors support in cpupower (Mario
Limonciello)"

* tag 'pm-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (67 commits)
PM / OPP: Add reference counting helpers for Rust implementation
PM: sleep: wakeirq: Introduce device-managed variant of dev_pm_set_wake_irq()
cpufreq: Use str_enable_disable()-like helpers
cpufreq: airoha: Add EN7581 CPUFreq SMCCC driver
PM: sleep: Allow configuring the DPM watchdog to warn earlier than panic
PM: sleep: convert comment from kernel-doc to plain comment
cpufreq: ACPI: Fix max-frequency computation
pm: cpupower: Add missing residency header changes in cpuidle.h to SWIG
PM / devfreq: exynos: remove unused function parameter
OPP: OF: Fix an OF node leak in _opp_add_static_v2()
cpufreq/amd-pstate: Refactor max frequency calculation
cpufreq/amd-pstate: Fix prefcore rankings
pm: cpupower: Add header changes for cpufreq.h to SWIG bindings
cpufreq: sparc: change kzalloc to kcalloc
cpufreq: qcom: Implement clk_ops::determine_rate() for qcom_cpufreq* clocks
cpufreq: qcom: Fix qcom_cpufreq_hw_recalc_rate() to query LUT if LMh IRQ is not available
cpufreq: apple-soc: Add Apple A7-A8X SoC cpufreq support
cpufreq: apple-soc: Set fallback transition latency to APPLE_DVFS_TRANSITION_TIMEOUT
cpufreq: apple-soc: Increase cluster switch timeout to 400us
cpufreq: apple-soc: Use 32-bit read for status register
...

+973 -414
+55
Documentation/devicetree/bindings/cpufreq/airoha,en7581-cpufreq.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/airoha,en7581-cpufreq.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Airoha EN7581 CPUFreq 8 + 9 + maintainers: 10 + - Christian Marangi <ansuelsmth@gmail.com> 11 + 12 + description: | 13 + On newer Airoha SoC, CPU Frequency is scaled indirectly with SMC commands 14 + to ATF. 15 + 16 + A virtual clock is exposed. This virtual clock is a get-only clock and 17 + is used to expose the current global CPU clock. The frequency info comes 18 + by the output of the SMC command that reports the clock in MHz. 19 + 20 + The SMC sets the CPU clock by providing an index, this is modelled as 21 + performance states in a power domain. 22 + 23 + CPUs can't be individually scaled as the CPU frequency is shared across 24 + all CPUs and is global. 25 + 26 + properties: 27 + compatible: 28 + const: airoha,en7581-cpufreq 29 + 30 + '#clock-cells': 31 + const: 0 32 + 33 + '#power-domain-cells': 34 + const: 0 35 + 36 + operating-points-v2: true 37 + 38 + required: 39 + - compatible 40 + - '#clock-cells' 41 + - '#power-domain-cells' 42 + - operating-points-v2 43 + 44 + additionalProperties: false 45 + 46 + examples: 47 + - | 48 + performance-domain { 49 + compatible = "airoha,en7581-cpufreq"; 50 + 51 + operating-points-v2 = <&cpu_smcc_opp_table>; 52 + 53 + #power-domain-cells = <0>; 54 + #clock-cells = <0>; 55 + };
+9 -1
Documentation/devicetree/bindings/cpufreq/apple,cluster-cpufreq.yaml
··· 24 24 - apple,t8112-cluster-cpufreq 25 25 - const: apple,cluster-cpufreq 26 26 - items: 27 - - const: apple,t6000-cluster-cpufreq 27 + - enum: 28 + - apple,s8000-cluster-cpufreq 29 + - apple,t8010-cluster-cpufreq 30 + - apple,t8015-cluster-cpufreq 31 + - apple,t6000-cluster-cpufreq 28 32 - const: apple,t8103-cluster-cpufreq 29 33 - const: apple,cluster-cpufreq 34 + - items: 35 + - const: apple,t7000-cluster-cpufreq 36 + - const: apple,s5l8960x-cluster-cpufreq 37 + - const: apple,s5l8960x-cluster-cpufreq 30 38 31 39 reg: 32 40 maxItems: 1
+20 -6
drivers/base/power/main.c
··· 496 496 struct device *dev; 497 497 struct task_struct *tsk; 498 498 struct timer_list timer; 499 + bool fatal; 499 500 }; 500 501 501 502 #define DECLARE_DPM_WATCHDOG_ON_STACK(wd) \ ··· 513 512 static void dpm_watchdog_handler(struct timer_list *t) 514 513 { 515 514 struct dpm_watchdog *wd = from_timer(wd, t, timer); 515 + struct timer_list *timer = &wd->timer; 516 + unsigned int time_left; 516 517 517 - dev_emerg(wd->dev, "**** DPM device timeout ****\n"); 518 - show_stack(wd->tsk, NULL, KERN_EMERG); 519 - panic("%s %s: unrecoverable failure\n", 520 - dev_driver_string(wd->dev), dev_name(wd->dev)); 518 + if (wd->fatal) { 519 + dev_emerg(wd->dev, "**** DPM device timeout ****\n"); 520 + show_stack(wd->tsk, NULL, KERN_EMERG); 521 + panic("%s %s: unrecoverable failure\n", 522 + dev_driver_string(wd->dev), dev_name(wd->dev)); 523 + } 524 + 525 + time_left = CONFIG_DPM_WATCHDOG_TIMEOUT - CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT; 526 + dev_warn(wd->dev, "**** DPM device timeout after %u seconds; %u seconds until panic ****\n", 527 + CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT, time_left); 528 + show_stack(wd->tsk, NULL, KERN_WARNING); 529 + 530 + wd->fatal = true; 531 + mod_timer(timer, jiffies + HZ * time_left); 521 532 } 522 533 523 534 /** ··· 543 530 544 531 wd->dev = dev; 545 532 wd->tsk = current; 533 + wd->fatal = CONFIG_DPM_WATCHDOG_TIMEOUT == CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT; 546 534 547 535 timer_setup_on_stack(timer, dpm_watchdog_handler, 0); 548 536 /* use same timeout value for both suspend and resume */ 549 - timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_TIMEOUT; 537 + timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT; 550 538 add_timer(timer); 551 539 } 552 540 ··· 928 914 goto Complete; 929 915 930 916 if (dev->power.direct_complete) { 931 - /* Match the pm_runtime_disable() in __device_suspend(). */ 917 + /* Match the pm_runtime_disable() in device_suspend(). */ 932 918 pm_runtime_enable(dev); 933 919 goto Complete; 934 920 }
-1
drivers/base/power/sysfs.c
··· 6 6 #include <linux/export.h> 7 7 #include <linux/pm_qos.h> 8 8 #include <linux/pm_runtime.h> 9 - #include <linux/pm_wakeup.h> 10 9 #include <linux/atomic.h> 11 10 #include <linux/jiffies.h> 12 11 #include "power.h"
+26
drivers/base/power/wakeirq.c
··· 103 103 } 104 104 EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq); 105 105 106 + static void devm_pm_clear_wake_irq(void *dev) 107 + { 108 + dev_pm_clear_wake_irq(dev); 109 + } 110 + 111 + /** 112 + * devm_pm_set_wake_irq - device-managed variant of dev_pm_set_wake_irq 113 + * @dev: Device entry 114 + * @irq: Device IO interrupt 115 + * 116 + * 117 + * Attach a device IO interrupt as a wake IRQ, same with dev_pm_set_wake_irq, 118 + * but the device will be auto clear wake capability on driver detach. 119 + */ 120 + int devm_pm_set_wake_irq(struct device *dev, int irq) 121 + { 122 + int ret; 123 + 124 + ret = dev_pm_set_wake_irq(dev, irq); 125 + if (ret) 126 + return ret; 127 + 128 + return devm_add_action_or_reset(dev, devm_pm_clear_wake_irq, dev); 129 + } 130 + EXPORT_SYMBOL_GPL(devm_pm_set_wake_irq); 131 + 106 132 /** 107 133 * handle_threaded_wake_irq - Handler for dedicated wake-up interrupts 108 134 * @irq: Device specific dedicated wake-up interrupt
+1 -1
drivers/cpufreq/Kconfig
··· 232 232 If in doubt, say N. 233 233 234 234 config CPUFREQ_DT_PLATDEV 235 - tristate "Generic DT based cpufreq platdev driver" 235 + bool "Generic DT based cpufreq platdev driver" 236 236 depends on OF 237 237 help 238 238 This adds a generic DT based cpufreq platdev driver for frequency
+8
drivers/cpufreq/Kconfig.arm
··· 15 15 To compile this driver as a module, choose M here: the 16 16 module will be called sun50i-cpufreq-nvmem. 17 17 18 + config ARM_AIROHA_SOC_CPUFREQ 19 + tristate "Airoha EN7581 SoC CPUFreq support" 20 + depends on ARCH_AIROHA || COMPILE_TEST 21 + select PM_OPP 22 + default ARCH_AIROHA 23 + help 24 + This adds the CPUFreq driver for Airoha EN7581 SoCs. 25 + 18 26 config ARM_APPLE_SOC_CPUFREQ 19 27 tristate "Apple Silicon SoC CPUFreq support" 20 28 depends on ARCH_APPLE || (COMPILE_TEST && 64BIT)
+1
drivers/cpufreq/Makefile
··· 53 53 54 54 ################################################################################## 55 55 # ARM SoC drivers 56 + obj-$(CONFIG_ARM_AIROHA_SOC_CPUFREQ) += airoha-cpufreq.o 56 57 obj-$(CONFIG_ARM_APPLE_SOC_CPUFREQ) += apple-soc-cpufreq.o 57 58 obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o 58 59 obj-$(CONFIG_ARM_ARMADA_8K_CPUFREQ) += armada-8k-cpufreq.o
+27 -9
drivers/cpufreq/acpi-cpufreq.c
··· 623 623 #endif 624 624 625 625 #ifdef CONFIG_ACPI_CPPC_LIB 626 - static u64 get_max_boost_ratio(unsigned int cpu) 626 + /* 627 + * get_max_boost_ratio: Computes the max_boost_ratio as the ratio 628 + * between the highest_perf and the nominal_perf. 629 + * 630 + * Returns the max_boost_ratio for @cpu. Returns the CPPC nominal 631 + * frequency via @nominal_freq if it is non-NULL pointer. 632 + */ 633 + static u64 get_max_boost_ratio(unsigned int cpu, u64 *nominal_freq) 627 634 { 628 635 struct cppc_perf_caps perf_caps; 629 636 u64 highest_perf, nominal_perf; ··· 659 652 660 653 nominal_perf = perf_caps.nominal_perf; 661 654 655 + if (nominal_freq) 656 + *nominal_freq = perf_caps.nominal_freq; 657 + 662 658 if (!highest_perf || !nominal_perf) { 663 659 pr_debug("CPU%d: highest or nominal performance missing\n", cpu); 664 660 return 0; ··· 674 664 675 665 return div_u64(highest_perf << SCHED_CAPACITY_SHIFT, nominal_perf); 676 666 } 667 + 677 668 #else 678 - static inline u64 get_max_boost_ratio(unsigned int cpu) { return 0; } 669 + static inline u64 get_max_boost_ratio(unsigned int cpu, u64 *nominal_freq) 670 + { 671 + return 0; 672 + } 679 673 #endif 680 674 681 675 static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) ··· 689 675 struct acpi_cpufreq_data *data; 690 676 unsigned int cpu = policy->cpu; 691 677 struct cpuinfo_x86 *c = &cpu_data(cpu); 678 + u64 max_boost_ratio, nominal_freq = 0; 692 679 unsigned int valid_states = 0; 693 680 unsigned int result = 0; 694 - u64 max_boost_ratio; 695 681 unsigned int i; 696 682 #ifdef CONFIG_SMP 697 683 static int blacklisted; ··· 841 827 } 842 828 freq_table[valid_states].frequency = CPUFREQ_TABLE_END; 843 829 844 - max_boost_ratio = get_max_boost_ratio(cpu); 830 + max_boost_ratio = get_max_boost_ratio(cpu, &nominal_freq); 845 831 if (max_boost_ratio) { 846 - unsigned int freq = freq_table[0].frequency; 832 + unsigned int freq = nominal_freq; 847 833 848 834 /* 849 - * Because the loop above sorts the freq_table entries in the 850 - * descending order, freq is the maximum frequency in the table. 851 - * Assume that it corresponds to the CPPC nominal frequency and 852 - * use it to set cpuinfo.max_freq. 835 + * The loop above sorts the freq_table entries in the 836 + * descending order. If ACPI CPPC has not advertised 837 + * the nominal frequency (this is possible in CPPC 838 + * revisions prior to 3), then use the first entry in 839 + * the pstate table as a proxy for nominal frequency. 853 840 */ 841 + if (!freq) 842 + freq = freq_table[0].frequency; 843 + 854 844 policy->cpuinfo.max_freq = freq * max_boost_ratio >> SCHED_CAPACITY_SHIFT; 855 845 } else { 856 846 /*
+152
drivers/cpufreq/airoha-cpufreq.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/bitfield.h> 4 + #include <linux/cpufreq.h> 5 + #include <linux/module.h> 6 + #include <linux/platform_device.h> 7 + #include <linux/pm_domain.h> 8 + #include <linux/pm_runtime.h> 9 + #include <linux/slab.h> 10 + 11 + #include "cpufreq-dt.h" 12 + 13 + struct airoha_cpufreq_priv { 14 + int opp_token; 15 + struct dev_pm_domain_list *pd_list; 16 + struct platform_device *cpufreq_dt; 17 + }; 18 + 19 + static struct platform_device *cpufreq_pdev; 20 + 21 + /* NOP function to disable OPP from setting clock */ 22 + static int airoha_cpufreq_config_clks_nop(struct device *dev, 23 + struct opp_table *opp_table, 24 + struct dev_pm_opp *opp, 25 + void *data, bool scaling_down) 26 + { 27 + return 0; 28 + } 29 + 30 + static const char * const airoha_cpufreq_clk_names[] = { "cpu", NULL }; 31 + static const char * const airoha_cpufreq_pd_names[] = { "perf" }; 32 + 33 + static int airoha_cpufreq_probe(struct platform_device *pdev) 34 + { 35 + const struct dev_pm_domain_attach_data attach_data = { 36 + .pd_names = airoha_cpufreq_pd_names, 37 + .num_pd_names = ARRAY_SIZE(airoha_cpufreq_pd_names), 38 + .pd_flags = PD_FLAG_DEV_LINK_ON | PD_FLAG_REQUIRED_OPP, 39 + }; 40 + struct dev_pm_opp_config config = { 41 + .clk_names = airoha_cpufreq_clk_names, 42 + .config_clks = airoha_cpufreq_config_clks_nop, 43 + }; 44 + struct platform_device *cpufreq_dt; 45 + struct airoha_cpufreq_priv *priv; 46 + struct device *dev = &pdev->dev; 47 + struct device *cpu_dev; 48 + int ret; 49 + 50 + /* CPUs refer to the same OPP table */ 51 + cpu_dev = get_cpu_device(0); 52 + if (!cpu_dev) 53 + return -ENODEV; 54 + 55 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 56 + if (!priv) 57 + return -ENOMEM; 58 + 59 + /* Set OPP table conf with NOP config_clks */ 60 + priv->opp_token = dev_pm_opp_set_config(cpu_dev, &config); 61 + if (priv->opp_token < 0) 62 + return dev_err_probe(dev, priv->opp_token, "Failed to set OPP config\n"); 63 + 64 + /* Attach PM for OPP */ 65 + ret = dev_pm_domain_attach_list(cpu_dev, &attach_data, 66 + &priv->pd_list); 67 + if (ret) 68 + goto clear_opp_config; 69 + 70 + cpufreq_dt = platform_device_register_simple("cpufreq-dt", -1, NULL, 0); 71 + ret = PTR_ERR_OR_ZERO(cpufreq_dt); 72 + if (ret) { 73 + dev_err(dev, "failed to create cpufreq-dt device: %d\n", ret); 74 + goto detach_pm; 75 + } 76 + 77 + priv->cpufreq_dt = cpufreq_dt; 78 + platform_set_drvdata(pdev, priv); 79 + 80 + return 0; 81 + 82 + detach_pm: 83 + dev_pm_domain_detach_list(priv->pd_list); 84 + clear_opp_config: 85 + dev_pm_opp_clear_config(priv->opp_token); 86 + 87 + return ret; 88 + } 89 + 90 + static void airoha_cpufreq_remove(struct platform_device *pdev) 91 + { 92 + struct airoha_cpufreq_priv *priv = platform_get_drvdata(pdev); 93 + 94 + platform_device_unregister(priv->cpufreq_dt); 95 + 96 + dev_pm_domain_detach_list(priv->pd_list); 97 + 98 + dev_pm_opp_clear_config(priv->opp_token); 99 + } 100 + 101 + static struct platform_driver airoha_cpufreq_driver = { 102 + .probe = airoha_cpufreq_probe, 103 + .remove = airoha_cpufreq_remove, 104 + .driver = { 105 + .name = "airoha-cpufreq", 106 + }, 107 + }; 108 + 109 + static const struct of_device_id airoha_cpufreq_match_list[] __initconst = { 110 + { .compatible = "airoha,en7581" }, 111 + {}, 112 + }; 113 + MODULE_DEVICE_TABLE(of, airoha_cpufreq_match_list); 114 + 115 + static int __init airoha_cpufreq_init(void) 116 + { 117 + struct device_node *np = of_find_node_by_path("/"); 118 + const struct of_device_id *match; 119 + int ret; 120 + 121 + if (!np) 122 + return -ENODEV; 123 + 124 + match = of_match_node(airoha_cpufreq_match_list, np); 125 + of_node_put(np); 126 + if (!match) 127 + return -ENODEV; 128 + 129 + ret = platform_driver_register(&airoha_cpufreq_driver); 130 + if (unlikely(ret < 0)) 131 + return ret; 132 + 133 + cpufreq_pdev = platform_device_register_data(NULL, "airoha-cpufreq", 134 + -1, match, sizeof(*match)); 135 + ret = PTR_ERR_OR_ZERO(cpufreq_pdev); 136 + if (ret) 137 + platform_driver_unregister(&airoha_cpufreq_driver); 138 + 139 + return ret; 140 + } 141 + module_init(airoha_cpufreq_init); 142 + 143 + static void __exit airoha_cpufreq_exit(void) 144 + { 145 + platform_device_unregister(cpufreq_pdev); 146 + platform_driver_unregister(&airoha_cpufreq_driver); 147 + } 148 + module_exit(airoha_cpufreq_exit); 149 + 150 + MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>"); 151 + MODULE_DESCRIPTION("CPUfreq driver for Airoha SoCs"); 152 + MODULE_LICENSE("GPL");
+46 -6
drivers/cpufreq/amd-pstate-trace.h
··· 32 32 u64 aperf, 33 33 u64 tsc, 34 34 unsigned int cpu_id, 35 - bool changed, 36 35 bool fast_switch 37 36 ), 38 37 ··· 43 44 aperf, 44 45 tsc, 45 46 cpu_id, 46 - changed, 47 47 fast_switch 48 48 ), 49 49 ··· 55 57 __field(unsigned long long, aperf) 56 58 __field(unsigned long long, tsc) 57 59 __field(unsigned int, cpu_id) 58 - __field(bool, changed) 59 60 __field(bool, fast_switch) 60 61 ), 61 62 ··· 67 70 __entry->aperf = aperf; 68 71 __entry->tsc = tsc; 69 72 __entry->cpu_id = cpu_id; 70 - __entry->changed = changed; 71 73 __entry->fast_switch = fast_switch; 72 74 ), 73 75 74 - TP_printk("amd_min_perf=%lu amd_des_perf=%lu amd_max_perf=%lu freq=%llu mperf=%llu aperf=%llu tsc=%llu cpu_id=%u changed=%s fast_switch=%s", 76 + TP_printk("amd_min_perf=%lu amd_des_perf=%lu amd_max_perf=%lu freq=%llu mperf=%llu aperf=%llu tsc=%llu cpu_id=%u fast_switch=%s", 75 77 (unsigned long)__entry->min_perf, 76 78 (unsigned long)__entry->target_perf, 77 79 (unsigned long)__entry->capacity, ··· 79 83 (unsigned long long)__entry->aperf, 80 84 (unsigned long long)__entry->tsc, 81 85 (unsigned int)__entry->cpu_id, 82 - (__entry->changed) ? "true" : "false", 83 86 (__entry->fast_switch) ? "true" : "false" 87 + ) 88 + ); 89 + 90 + TRACE_EVENT(amd_pstate_epp_perf, 91 + 92 + TP_PROTO(unsigned int cpu_id, 93 + unsigned int highest_perf, 94 + unsigned int epp, 95 + unsigned int min_perf, 96 + unsigned int max_perf, 97 + bool boost 98 + ), 99 + 100 + TP_ARGS(cpu_id, 101 + highest_perf, 102 + epp, 103 + min_perf, 104 + max_perf, 105 + boost), 106 + 107 + TP_STRUCT__entry( 108 + __field(unsigned int, cpu_id) 109 + __field(unsigned int, highest_perf) 110 + __field(unsigned int, epp) 111 + __field(unsigned int, min_perf) 112 + __field(unsigned int, max_perf) 113 + __field(bool, boost) 114 + ), 115 + 116 + TP_fast_assign( 117 + __entry->cpu_id = cpu_id; 118 + __entry->highest_perf = highest_perf; 119 + __entry->epp = epp; 120 + __entry->min_perf = min_perf; 121 + __entry->max_perf = max_perf; 122 + __entry->boost = boost; 123 + ), 124 + 125 + TP_printk("cpu%u: [%u<->%u]/%u, epp=%u, boost=%u", 126 + (unsigned int)__entry->cpu_id, 127 + (unsigned int)__entry->min_perf, 128 + (unsigned int)__entry->max_perf, 129 + (unsigned int)__entry->highest_perf, 130 + (unsigned int)__entry->epp, 131 + (bool)__entry->boost 84 132 ) 85 133 ); 86 134
+5 -7
drivers/cpufreq/amd-pstate-ut.c
··· 207 207 int cpu = 0; 208 208 struct cpufreq_policy *policy = NULL; 209 209 struct amd_cpudata *cpudata = NULL; 210 - u32 nominal_freq_khz; 211 210 212 211 for_each_possible_cpu(cpu) { 213 212 policy = cpufreq_cpu_get(cpu); ··· 214 215 break; 215 216 cpudata = policy->driver_data; 216 217 217 - nominal_freq_khz = cpudata->nominal_freq*1000; 218 - if (!((cpudata->max_freq >= nominal_freq_khz) && 219 - (nominal_freq_khz > cpudata->lowest_nonlinear_freq) && 218 + if (!((cpudata->max_freq >= cpudata->nominal_freq) && 219 + (cpudata->nominal_freq > cpudata->lowest_nonlinear_freq) && 220 220 (cpudata->lowest_nonlinear_freq > cpudata->min_freq) && 221 221 (cpudata->min_freq > 0))) { 222 222 amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL; 223 223 pr_err("%s cpu%d max=%d >= nominal=%d > lowest_nonlinear=%d > min=%d > 0, the formula is incorrect!\n", 224 - __func__, cpu, cpudata->max_freq, nominal_freq_khz, 224 + __func__, cpu, cpudata->max_freq, cpudata->nominal_freq, 225 225 cpudata->lowest_nonlinear_freq, cpudata->min_freq); 226 226 goto skip_test; 227 227 } ··· 234 236 235 237 if (cpudata->boost_supported) { 236 238 if ((policy->max == cpudata->max_freq) || 237 - (policy->max == nominal_freq_khz)) 239 + (policy->max == cpudata->nominal_freq)) 238 240 amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS; 239 241 else { 240 242 amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL; 241 243 pr_err("%s cpu%d policy_max=%d should be equal cpu_max=%d or cpu_nominal=%d !\n", 242 244 __func__, cpu, policy->max, cpudata->max_freq, 243 - nominal_freq_khz); 245 + cpudata->nominal_freq); 244 246 goto skip_test; 245 247 } 246 248 } else {
+228 -257
drivers/cpufreq/amd-pstate.c
··· 22 22 23 23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 24 24 25 + #include <linux/bitfield.h> 25 26 #include <linux/kernel.h> 26 27 #include <linux/module.h> 27 28 #include <linux/init.h> ··· 88 87 static bool cppc_enabled; 89 88 static bool amd_pstate_prefcore = true; 90 89 static struct quirk_entry *quirks; 90 + 91 + #define AMD_CPPC_MAX_PERF_MASK GENMASK(7, 0) 92 + #define AMD_CPPC_MIN_PERF_MASK GENMASK(15, 8) 93 + #define AMD_CPPC_DES_PERF_MASK GENMASK(23, 16) 94 + #define AMD_CPPC_EPP_PERF_MASK GENMASK(31, 24) 91 95 92 96 /* 93 97 * AMD Energy Preference Performance (EPP) ··· 186 180 static DEFINE_MUTEX(amd_pstate_limits_lock); 187 181 static DEFINE_MUTEX(amd_pstate_driver_lock); 188 182 189 - static s16 amd_pstate_get_epp(struct amd_cpudata *cpudata, u64 cppc_req_cached) 183 + static s16 msr_get_epp(struct amd_cpudata *cpudata) 184 + { 185 + u64 value; 186 + int ret; 187 + 188 + ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value); 189 + if (ret < 0) { 190 + pr_debug("Could not retrieve energy perf value (%d)\n", ret); 191 + return ret; 192 + } 193 + 194 + return FIELD_GET(AMD_CPPC_EPP_PERF_MASK, value); 195 + } 196 + 197 + DEFINE_STATIC_CALL(amd_pstate_get_epp, msr_get_epp); 198 + 199 + static inline s16 amd_pstate_get_epp(struct amd_cpudata *cpudata) 200 + { 201 + return static_call(amd_pstate_get_epp)(cpudata); 202 + } 203 + 204 + static s16 shmem_get_epp(struct amd_cpudata *cpudata) 190 205 { 191 206 u64 epp; 192 207 int ret; 193 208 194 - if (cpu_feature_enabled(X86_FEATURE_CPPC)) { 195 - if (!cppc_req_cached) { 196 - epp = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, 197 - &cppc_req_cached); 198 - if (epp) 199 - return epp; 200 - } 201 - epp = (cppc_req_cached >> 24) & 0xFF; 202 - } else { 203 - ret = cppc_get_epp_perf(cpudata->cpu, &epp); 204 - if (ret < 0) { 205 - pr_debug("Could not retrieve energy perf value (%d)\n", ret); 206 - return -EIO; 207 - } 209 + ret = cppc_get_epp_perf(cpudata->cpu, &epp); 210 + if (ret < 0) { 211 + pr_debug("Could not retrieve energy perf value (%d)\n", ret); 212 + return ret; 208 213 } 209 214 210 215 return (s16)(epp & 0xff); 211 216 } 212 217 213 - static int amd_pstate_get_energy_pref_index(struct amd_cpudata *cpudata) 218 + static int msr_update_perf(struct amd_cpudata *cpudata, u32 min_perf, 219 + u32 des_perf, u32 max_perf, u32 epp, bool fast_switch) 214 220 { 215 - s16 epp; 216 - int index = -EINVAL; 221 + u64 value, prev; 217 222 218 - epp = amd_pstate_get_epp(cpudata, 0); 219 - if (epp < 0) 220 - return epp; 223 + value = prev = READ_ONCE(cpudata->cppc_req_cached); 221 224 222 - switch (epp) { 223 - case AMD_CPPC_EPP_PERFORMANCE: 224 - index = EPP_INDEX_PERFORMANCE; 225 - break; 226 - case AMD_CPPC_EPP_BALANCE_PERFORMANCE: 227 - index = EPP_INDEX_BALANCE_PERFORMANCE; 228 - break; 229 - case AMD_CPPC_EPP_BALANCE_POWERSAVE: 230 - index = EPP_INDEX_BALANCE_POWERSAVE; 231 - break; 232 - case AMD_CPPC_EPP_POWERSAVE: 233 - index = EPP_INDEX_POWERSAVE; 234 - break; 235 - default: 236 - break; 225 + value &= ~(AMD_CPPC_MAX_PERF_MASK | AMD_CPPC_MIN_PERF_MASK | 226 + AMD_CPPC_DES_PERF_MASK | AMD_CPPC_EPP_PERF_MASK); 227 + value |= FIELD_PREP(AMD_CPPC_MAX_PERF_MASK, max_perf); 228 + value |= FIELD_PREP(AMD_CPPC_DES_PERF_MASK, des_perf); 229 + value |= FIELD_PREP(AMD_CPPC_MIN_PERF_MASK, min_perf); 230 + value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp); 231 + 232 + if (value == prev) 233 + return 0; 234 + 235 + if (fast_switch) { 236 + wrmsrl(MSR_AMD_CPPC_REQ, value); 237 + return 0; 238 + } else { 239 + int ret = wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value); 240 + 241 + if (ret) 242 + return ret; 237 243 } 238 244 239 - return index; 240 - } 245 + WRITE_ONCE(cpudata->cppc_req_cached, value); 246 + WRITE_ONCE(cpudata->epp_cached, epp); 241 247 242 - static void msr_update_perf(struct amd_cpudata *cpudata, u32 min_perf, 243 - u32 des_perf, u32 max_perf, bool fast_switch) 244 - { 245 - if (fast_switch) 246 - wrmsrl(MSR_AMD_CPPC_REQ, READ_ONCE(cpudata->cppc_req_cached)); 247 - else 248 - wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, 249 - READ_ONCE(cpudata->cppc_req_cached)); 248 + return 0; 250 249 } 251 250 252 251 DEFINE_STATIC_CALL(amd_pstate_update_perf, msr_update_perf); 253 252 254 - static inline void amd_pstate_update_perf(struct amd_cpudata *cpudata, 253 + static inline int amd_pstate_update_perf(struct amd_cpudata *cpudata, 255 254 u32 min_perf, u32 des_perf, 256 - u32 max_perf, bool fast_switch) 255 + u32 max_perf, u32 epp, 256 + bool fast_switch) 257 257 { 258 - static_call(amd_pstate_update_perf)(cpudata, min_perf, des_perf, 259 - max_perf, fast_switch); 258 + return static_call(amd_pstate_update_perf)(cpudata, min_perf, des_perf, 259 + max_perf, epp, fast_switch); 260 260 } 261 261 262 - static int amd_pstate_set_epp(struct amd_cpudata *cpudata, u32 epp) 262 + static int msr_set_epp(struct amd_cpudata *cpudata, u32 epp) 263 263 { 264 + u64 value, prev; 264 265 int ret; 265 - struct cppc_perf_ctrls perf_ctrls; 266 266 267 - if (cpu_feature_enabled(X86_FEATURE_CPPC)) { 268 - u64 value = READ_ONCE(cpudata->cppc_req_cached); 267 + value = prev = READ_ONCE(cpudata->cppc_req_cached); 268 + value &= ~AMD_CPPC_EPP_PERF_MASK; 269 + value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp); 269 270 270 - value &= ~GENMASK_ULL(31, 24); 271 - value |= (u64)epp << 24; 272 - WRITE_ONCE(cpudata->cppc_req_cached, value); 271 + if (value == prev) 272 + return 0; 273 273 274 - ret = wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value); 275 - if (!ret) 276 - cpudata->epp_cached = epp; 277 - } else { 278 - amd_pstate_update_perf(cpudata, cpudata->min_limit_perf, 0U, 279 - cpudata->max_limit_perf, false); 280 - 281 - perf_ctrls.energy_perf = epp; 282 - ret = cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1); 283 - if (ret) { 284 - pr_debug("failed to set energy perf value (%d)\n", ret); 285 - return ret; 286 - } 287 - cpudata->epp_cached = epp; 274 + ret = wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value); 275 + if (ret) { 276 + pr_err("failed to set energy perf value (%d)\n", ret); 277 + return ret; 288 278 } 279 + 280 + /* update both so that msr_update_perf() can effectively check */ 281 + WRITE_ONCE(cpudata->epp_cached, epp); 282 + WRITE_ONCE(cpudata->cppc_req_cached, value); 289 283 290 284 return ret; 291 285 } 292 286 293 - static int amd_pstate_set_energy_pref_index(struct amd_cpudata *cpudata, 294 - int pref_index) 287 + DEFINE_STATIC_CALL(amd_pstate_set_epp, msr_set_epp); 288 + 289 + static inline int amd_pstate_set_epp(struct amd_cpudata *cpudata, u32 epp) 295 290 { 296 - int epp = -EINVAL; 291 + return static_call(amd_pstate_set_epp)(cpudata, epp); 292 + } 293 + 294 + static int shmem_set_epp(struct amd_cpudata *cpudata, u32 epp) 295 + { 297 296 int ret; 297 + struct cppc_perf_ctrls perf_ctrls; 298 + 299 + if (epp == cpudata->epp_cached) 300 + return 0; 301 + 302 + perf_ctrls.energy_perf = epp; 303 + ret = cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1); 304 + if (ret) { 305 + pr_debug("failed to set energy perf value (%d)\n", ret); 306 + return ret; 307 + } 308 + WRITE_ONCE(cpudata->epp_cached, epp); 309 + 310 + return ret; 311 + } 312 + 313 + static int amd_pstate_set_energy_pref_index(struct cpufreq_policy *policy, 314 + int pref_index) 315 + { 316 + struct amd_cpudata *cpudata = policy->driver_data; 317 + int epp; 298 318 299 319 if (!pref_index) 300 320 epp = cpudata->epp_default; 301 - 302 - if (epp == -EINVAL) 321 + else 303 322 epp = epp_values[pref_index]; 304 323 305 324 if (epp > 0 && cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) { ··· 332 301 return -EBUSY; 333 302 } 334 303 335 - ret = amd_pstate_set_epp(cpudata, epp); 304 + if (trace_amd_pstate_epp_perf_enabled()) { 305 + trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf, 306 + epp, 307 + FIELD_GET(AMD_CPPC_MIN_PERF_MASK, cpudata->cppc_req_cached), 308 + FIELD_GET(AMD_CPPC_MAX_PERF_MASK, cpudata->cppc_req_cached), 309 + policy->boost_enabled); 310 + } 336 311 337 - return ret; 312 + return amd_pstate_set_epp(cpudata, epp); 338 313 } 339 314 340 315 static inline int msr_cppc_enable(bool enable) ··· 479 442 return static_call(amd_pstate_init_perf)(cpudata); 480 443 } 481 444 482 - static void shmem_update_perf(struct amd_cpudata *cpudata, 483 - u32 min_perf, u32 des_perf, 484 - u32 max_perf, bool fast_switch) 445 + static int shmem_update_perf(struct amd_cpudata *cpudata, u32 min_perf, 446 + u32 des_perf, u32 max_perf, u32 epp, bool fast_switch) 485 447 { 486 448 struct cppc_perf_ctrls perf_ctrls; 449 + 450 + if (cppc_state == AMD_PSTATE_ACTIVE) { 451 + int ret = shmem_set_epp(cpudata, epp); 452 + 453 + if (ret) 454 + return ret; 455 + } 487 456 488 457 perf_ctrls.max_perf = max_perf; 489 458 perf_ctrls.min_perf = min_perf; 490 459 perf_ctrls.desired_perf = des_perf; 491 460 492 - cppc_set_perf(cpudata->cpu, &perf_ctrls); 461 + return cppc_set_perf(cpudata->cpu, &perf_ctrls); 493 462 } 494 463 495 464 static inline bool amd_pstate_sample(struct amd_cpudata *cpudata) ··· 536 493 { 537 494 unsigned long max_freq; 538 495 struct cpufreq_policy *policy = cpufreq_cpu_get(cpudata->cpu); 539 - u64 prev = READ_ONCE(cpudata->cppc_req_cached); 540 496 u32 nominal_perf = READ_ONCE(cpudata->nominal_perf); 541 - u64 value = prev; 542 497 543 - min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf, 544 - cpudata->max_limit_perf); 545 - max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_perf, 546 - cpudata->max_limit_perf); 547 498 des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf); 548 499 549 500 max_freq = READ_ONCE(cpudata->max_limit_freq); ··· 548 511 des_perf = 0; 549 512 } 550 513 551 - value &= ~AMD_CPPC_MIN_PERF(~0L); 552 - value |= AMD_CPPC_MIN_PERF(min_perf); 553 - 554 - value &= ~AMD_CPPC_DES_PERF(~0L); 555 - value |= AMD_CPPC_DES_PERF(des_perf); 556 - 557 514 /* limit the max perf when core performance boost feature is disabled */ 558 515 if (!cpudata->boost_supported) 559 516 max_perf = min_t(unsigned long, nominal_perf, max_perf); 560 517 561 - value &= ~AMD_CPPC_MAX_PERF(~0L); 562 - value |= AMD_CPPC_MAX_PERF(max_perf); 563 - 564 518 if (trace_amd_pstate_perf_enabled() && amd_pstate_sample(cpudata)) { 565 519 trace_amd_pstate_perf(min_perf, des_perf, max_perf, cpudata->freq, 566 520 cpudata->cur.mperf, cpudata->cur.aperf, cpudata->cur.tsc, 567 - cpudata->cpu, (value != prev), fast_switch); 521 + cpudata->cpu, fast_switch); 568 522 } 569 523 570 - if (value == prev) 571 - goto cpufreq_policy_put; 524 + amd_pstate_update_perf(cpudata, min_perf, des_perf, max_perf, 0, fast_switch); 572 525 573 - WRITE_ONCE(cpudata->cppc_req_cached, value); 574 - 575 - amd_pstate_update_perf(cpudata, min_perf, des_perf, 576 - max_perf, fast_switch); 577 - 578 - cpufreq_policy_put: 579 526 cpufreq_cpu_put(policy); 580 527 } 581 528 ··· 591 570 592 571 static int amd_pstate_update_min_max_limit(struct cpufreq_policy *policy) 593 572 { 594 - u32 max_limit_perf, min_limit_perf, lowest_perf, max_perf, max_freq; 573 + u32 max_limit_perf, min_limit_perf, max_perf, max_freq; 595 574 struct amd_cpudata *cpudata = policy->driver_data; 596 575 597 576 max_perf = READ_ONCE(cpudata->highest_perf); ··· 599 578 max_limit_perf = div_u64(policy->max * max_perf, max_freq); 600 579 min_limit_perf = div_u64(policy->min * max_perf, max_freq); 601 580 602 - lowest_perf = READ_ONCE(cpudata->lowest_perf); 603 - if (min_limit_perf < lowest_perf) 604 - min_limit_perf = lowest_perf; 605 - 606 - if (max_limit_perf < min_limit_perf) 607 - max_limit_perf = min_limit_perf; 581 + if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) 582 + min_limit_perf = min(cpudata->nominal_perf, max_limit_perf); 608 583 609 584 WRITE_ONCE(cpudata->max_limit_perf, max_limit_perf); 610 585 WRITE_ONCE(cpudata->min_limit_perf, min_limit_perf); ··· 721 704 722 705 if (on) 723 706 policy->cpuinfo.max_freq = max_freq; 724 - else if (policy->cpuinfo.max_freq > nominal_freq * 1000) 725 - policy->cpuinfo.max_freq = nominal_freq * 1000; 707 + else if (policy->cpuinfo.max_freq > nominal_freq) 708 + policy->cpuinfo.max_freq = nominal_freq; 726 709 727 710 policy->max = policy->cpuinfo.max_freq; 728 711 ··· 744 727 pr_err("Boost mode is not supported by this processor or SBIOS\n"); 745 728 return -EOPNOTSUPP; 746 729 } 747 - mutex_lock(&amd_pstate_driver_lock); 730 + guard(mutex)(&amd_pstate_driver_lock); 731 + 748 732 ret = amd_pstate_cpu_boost_update(policy, state); 749 - WRITE_ONCE(cpudata->boost_state, !ret ? state : false); 750 733 policy->boost_enabled = !ret ? state : false; 751 734 refresh_frequency_limits(policy); 752 - mutex_unlock(&amd_pstate_driver_lock); 753 735 754 736 return ret; 755 737 } ··· 767 751 ret = 0; 768 752 goto exit_err; 769 753 } 770 - 771 - /* at least one CPU supports CPB, even if others fail later on to set up */ 772 - current_pstate_driver->boost_enabled = true; 773 754 774 755 ret = rdmsrl_on_cpu(cpudata->cpu, MSR_K7_HWCR, &boost_val); 775 756 if (ret) { ··· 815 802 * sched_set_itmt_support(true) has been called and it is valid to 816 803 * update them at any time after it has been called. 817 804 */ 818 - sched_set_itmt_core_prio((int)READ_ONCE(cpudata->highest_perf), cpudata->cpu); 805 + sched_set_itmt_core_prio((int)READ_ONCE(cpudata->prefcore_ranking), cpudata->cpu); 819 806 820 807 schedule_work(&sched_prefcore_work); 821 808 } ··· 836 823 if (!amd_pstate_prefcore) 837 824 return; 838 825 839 - mutex_lock(&amd_pstate_driver_lock); 826 + guard(mutex)(&amd_pstate_driver_lock); 827 + 840 828 ret = amd_get_highest_perf(cpu, &cur_high); 841 829 if (ret) 842 830 goto free_cpufreq_put; ··· 857 843 if (!highest_perf_changed) 858 844 cpufreq_update_policy(cpu); 859 845 860 - mutex_unlock(&amd_pstate_driver_lock); 861 846 } 862 847 863 848 /* ··· 908 895 { 909 896 int ret; 910 897 u32 min_freq, max_freq; 911 - u32 nominal_perf, nominal_freq; 898 + u32 highest_perf, nominal_perf, nominal_freq; 912 899 u32 lowest_nonlinear_perf, lowest_nonlinear_freq; 913 - u32 boost_ratio, lowest_nonlinear_ratio; 914 900 struct cppc_perf_caps cppc_perf; 915 901 916 902 ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); ··· 917 905 return ret; 918 906 919 907 if (quirks && quirks->lowest_freq) 920 - min_freq = quirks->lowest_freq * 1000; 908 + min_freq = quirks->lowest_freq; 921 909 else 922 - min_freq = cppc_perf.lowest_freq * 1000; 910 + min_freq = cppc_perf.lowest_freq; 923 911 924 912 if (quirks && quirks->nominal_freq) 925 - nominal_freq = quirks->nominal_freq ; 913 + nominal_freq = quirks->nominal_freq; 926 914 else 927 915 nominal_freq = cppc_perf.nominal_freq; 928 916 917 + highest_perf = READ_ONCE(cpudata->highest_perf); 929 918 nominal_perf = READ_ONCE(cpudata->nominal_perf); 930 - 931 - boost_ratio = div_u64(cpudata->highest_perf << SCHED_CAPACITY_SHIFT, nominal_perf); 932 - max_freq = (nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT) * 1000; 919 + max_freq = div_u64((u64)highest_perf * nominal_freq, nominal_perf); 933 920 934 921 lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf); 935 - lowest_nonlinear_ratio = div_u64(lowest_nonlinear_perf << SCHED_CAPACITY_SHIFT, 936 - nominal_perf); 937 - lowest_nonlinear_freq = (nominal_freq * lowest_nonlinear_ratio >> SCHED_CAPACITY_SHIFT) * 1000; 938 - 939 - WRITE_ONCE(cpudata->min_freq, min_freq); 940 - WRITE_ONCE(cpudata->lowest_nonlinear_freq, lowest_nonlinear_freq); 941 - WRITE_ONCE(cpudata->nominal_freq, nominal_freq); 942 - WRITE_ONCE(cpudata->max_freq, max_freq); 922 + lowest_nonlinear_freq = div_u64((u64)nominal_freq * lowest_nonlinear_perf, nominal_perf); 923 + WRITE_ONCE(cpudata->min_freq, min_freq * 1000); 924 + WRITE_ONCE(cpudata->lowest_nonlinear_freq, lowest_nonlinear_freq * 1000); 925 + WRITE_ONCE(cpudata->nominal_freq, nominal_freq * 1000); 926 + WRITE_ONCE(cpudata->max_freq, max_freq * 1000); 943 927 944 928 /** 945 929 * Below values need to be initialized correctly, otherwise driver will fail to load ··· 945 937 */ 946 938 if (min_freq <= 0 || max_freq <= 0 || nominal_freq <= 0 || min_freq > max_freq) { 947 939 pr_err("min_freq(%d) or max_freq(%d) or nominal_freq(%d) value is incorrect\n", 948 - min_freq, max_freq, nominal_freq * 1000); 940 + min_freq, max_freq, nominal_freq); 949 941 return -EINVAL; 950 942 } 951 943 952 - if (lowest_nonlinear_freq <= min_freq || lowest_nonlinear_freq > nominal_freq * 1000) { 944 + if (lowest_nonlinear_freq <= min_freq || lowest_nonlinear_freq > nominal_freq) { 953 945 pr_err("lowest_nonlinear_freq(%d) value is out of range [min_freq(%d), nominal_freq(%d)]\n", 954 - lowest_nonlinear_freq, min_freq, nominal_freq * 1000); 946 + lowest_nonlinear_freq, min_freq, nominal_freq); 955 947 return -EINVAL; 956 948 } 957 949 ··· 1168 1160 static ssize_t store_energy_performance_preference( 1169 1161 struct cpufreq_policy *policy, const char *buf, size_t count) 1170 1162 { 1171 - struct amd_cpudata *cpudata = policy->driver_data; 1172 1163 char str_preference[21]; 1173 1164 ssize_t ret; 1174 1165 ··· 1179 1172 if (ret < 0) 1180 1173 return -EINVAL; 1181 1174 1182 - mutex_lock(&amd_pstate_limits_lock); 1183 - ret = amd_pstate_set_energy_pref_index(cpudata, ret); 1184 - mutex_unlock(&amd_pstate_limits_lock); 1175 + guard(mutex)(&amd_pstate_limits_lock); 1185 1176 1186 - return ret ?: count; 1177 + ret = amd_pstate_set_energy_pref_index(policy, ret); 1178 + 1179 + return ret ? ret : count; 1187 1180 } 1188 1181 1189 1182 static ssize_t show_energy_performance_preference( ··· 1192 1185 struct amd_cpudata *cpudata = policy->driver_data; 1193 1186 int preference; 1194 1187 1195 - preference = amd_pstate_get_energy_pref_index(cpudata); 1196 - if (preference < 0) 1197 - return preference; 1188 + switch (cpudata->epp_cached) { 1189 + case AMD_CPPC_EPP_PERFORMANCE: 1190 + preference = EPP_INDEX_PERFORMANCE; 1191 + break; 1192 + case AMD_CPPC_EPP_BALANCE_PERFORMANCE: 1193 + preference = EPP_INDEX_BALANCE_PERFORMANCE; 1194 + break; 1195 + case AMD_CPPC_EPP_BALANCE_POWERSAVE: 1196 + preference = EPP_INDEX_BALANCE_POWERSAVE; 1197 + break; 1198 + case AMD_CPPC_EPP_POWERSAVE: 1199 + preference = EPP_INDEX_POWERSAVE; 1200 + break; 1201 + default: 1202 + return -EINVAL; 1203 + } 1198 1204 1199 1205 return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]); 1200 1206 } ··· 1255 1235 amd_pstate_driver_cleanup(); 1256 1236 return ret; 1257 1237 } 1238 + 1239 + /* at least one CPU supports CPB */ 1240 + current_pstate_driver->boost_enabled = cpu_feature_enabled(X86_FEATURE_CPB); 1258 1241 1259 1242 ret = cpufreq_register_driver(current_pstate_driver); 1260 1243 if (ret) { ··· 1363 1340 static ssize_t status_show(struct device *dev, 1364 1341 struct device_attribute *attr, char *buf) 1365 1342 { 1366 - ssize_t ret; 1367 1343 1368 - mutex_lock(&amd_pstate_driver_lock); 1369 - ret = amd_pstate_show_status(buf); 1370 - mutex_unlock(&amd_pstate_driver_lock); 1344 + guard(mutex)(&amd_pstate_driver_lock); 1371 1345 1372 - return ret; 1346 + return amd_pstate_show_status(buf); 1373 1347 } 1374 1348 1375 1349 static ssize_t status_store(struct device *a, struct device_attribute *b, ··· 1375 1355 char *p = memchr(buf, '\n', count); 1376 1356 int ret; 1377 1357 1378 - mutex_lock(&amd_pstate_driver_lock); 1358 + guard(mutex)(&amd_pstate_driver_lock); 1379 1359 ret = amd_pstate_update_status(buf, p ? p - buf : count); 1380 - mutex_unlock(&amd_pstate_driver_lock); 1381 1360 1382 1361 return ret < 0 ? ret : count; 1383 1362 } ··· 1470 1451 return -ENOMEM; 1471 1452 1472 1453 cpudata->cpu = policy->cpu; 1473 - cpudata->epp_policy = 0; 1474 1454 1475 1455 ret = amd_pstate_init_perf(cpudata); 1476 1456 if (ret) ··· 1495 1477 1496 1478 policy->driver_data = cpudata; 1497 1479 1498 - cpudata->epp_cached = cpudata->epp_default = amd_pstate_get_epp(cpudata, 0); 1499 - 1500 1480 policy->min = policy->cpuinfo.min_freq; 1501 1481 policy->max = policy->cpuinfo.max_freq; 1502 1482 ··· 1505 1489 * the default cpufreq governor is neither powersave nor performance. 1506 1490 */ 1507 1491 if (amd_pstate_acpi_pm_profile_server() || 1508 - amd_pstate_acpi_pm_profile_undefined()) 1492 + amd_pstate_acpi_pm_profile_undefined()) { 1509 1493 policy->policy = CPUFREQ_POLICY_PERFORMANCE; 1510 - else 1494 + cpudata->epp_default = amd_pstate_get_epp(cpudata); 1495 + } else { 1511 1496 policy->policy = CPUFREQ_POLICY_POWERSAVE; 1497 + cpudata->epp_default = AMD_CPPC_EPP_BALANCE_PERFORMANCE; 1498 + } 1512 1499 1513 1500 if (cpu_feature_enabled(X86_FEATURE_CPPC)) { 1514 1501 ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value); ··· 1524 1505 return ret; 1525 1506 WRITE_ONCE(cpudata->cppc_cap1_cached, value); 1526 1507 } 1508 + ret = amd_pstate_set_epp(cpudata, cpudata->epp_default); 1509 + if (ret) 1510 + return ret; 1527 1511 1528 1512 current_pstate_driver->adjust_perf = NULL; 1529 1513 ··· 1552 1530 static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy) 1553 1531 { 1554 1532 struct amd_cpudata *cpudata = policy->driver_data; 1555 - u32 max_perf, min_perf; 1556 - u64 value; 1557 - s16 epp; 1533 + u32 epp; 1558 1534 1559 - max_perf = READ_ONCE(cpudata->highest_perf); 1560 - min_perf = READ_ONCE(cpudata->lowest_perf); 1561 1535 amd_pstate_update_min_max_limit(policy); 1562 - 1563 - max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_perf, 1564 - cpudata->max_limit_perf); 1565 - min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf, 1566 - cpudata->max_limit_perf); 1567 - value = READ_ONCE(cpudata->cppc_req_cached); 1568 - 1569 - if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) 1570 - min_perf = min(cpudata->nominal_perf, max_perf); 1571 - 1572 - /* Initial min/max values for CPPC Performance Controls Register */ 1573 - value &= ~AMD_CPPC_MIN_PERF(~0L); 1574 - value |= AMD_CPPC_MIN_PERF(min_perf); 1575 - 1576 - value &= ~AMD_CPPC_MAX_PERF(~0L); 1577 - value |= AMD_CPPC_MAX_PERF(max_perf); 1578 - 1579 - /* CPPC EPP feature require to set zero to the desire perf bit */ 1580 - value &= ~AMD_CPPC_DES_PERF(~0L); 1581 - value |= AMD_CPPC_DES_PERF(0); 1582 - 1583 - cpudata->epp_policy = cpudata->policy; 1584 - 1585 - /* Get BIOS pre-defined epp value */ 1586 - epp = amd_pstate_get_epp(cpudata, value); 1587 - if (epp < 0) { 1588 - /** 1589 - * This return value can only be negative for shared_memory 1590 - * systems where EPP register read/write not supported. 1591 - */ 1592 - return epp; 1593 - } 1594 1536 1595 1537 if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) 1596 1538 epp = 0; 1539 + else 1540 + epp = READ_ONCE(cpudata->epp_cached); 1597 1541 1598 - WRITE_ONCE(cpudata->cppc_req_cached, value); 1599 - return amd_pstate_set_epp(cpudata, epp); 1542 + if (trace_amd_pstate_epp_perf_enabled()) { 1543 + trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf, epp, 1544 + cpudata->min_limit_perf, 1545 + cpudata->max_limit_perf, 1546 + policy->boost_enabled); 1547 + } 1548 + 1549 + return amd_pstate_update_perf(cpudata, cpudata->min_limit_perf, 0U, 1550 + cpudata->max_limit_perf, epp, false); 1600 1551 } 1601 1552 1602 1553 static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy) ··· 1598 1603 return 0; 1599 1604 } 1600 1605 1601 - static void amd_pstate_epp_reenable(struct amd_cpudata *cpudata) 1606 + static int amd_pstate_epp_reenable(struct cpufreq_policy *policy) 1602 1607 { 1603 - struct cppc_perf_ctrls perf_ctrls; 1604 - u64 value, max_perf; 1608 + struct amd_cpudata *cpudata = policy->driver_data; 1609 + u64 max_perf; 1605 1610 int ret; 1606 1611 1607 1612 ret = amd_pstate_cppc_enable(true); 1608 1613 if (ret) 1609 1614 pr_err("failed to enable amd pstate during resume, return %d\n", ret); 1610 1615 1611 - value = READ_ONCE(cpudata->cppc_req_cached); 1612 1616 max_perf = READ_ONCE(cpudata->highest_perf); 1613 1617 1614 - if (cpu_feature_enabled(X86_FEATURE_CPPC)) { 1615 - wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value); 1616 - } else { 1617 - perf_ctrls.max_perf = max_perf; 1618 - cppc_set_perf(cpudata->cpu, &perf_ctrls); 1619 - perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(cpudata->epp_cached); 1620 - cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1); 1618 + if (trace_amd_pstate_epp_perf_enabled()) { 1619 + trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf, 1620 + cpudata->epp_cached, 1621 + FIELD_GET(AMD_CPPC_MIN_PERF_MASK, cpudata->cppc_req_cached), 1622 + max_perf, policy->boost_enabled); 1621 1623 } 1624 + 1625 + return amd_pstate_update_perf(cpudata, 0, 0, max_perf, cpudata->epp_cached, false); 1622 1626 } 1623 1627 1624 1628 static int amd_pstate_epp_cpu_online(struct cpufreq_policy *policy) 1625 1629 { 1626 1630 struct amd_cpudata *cpudata = policy->driver_data; 1631 + int ret; 1627 1632 1628 1633 pr_debug("AMD CPU Core %d going online\n", cpudata->cpu); 1629 1634 1630 - if (cppc_state == AMD_PSTATE_ACTIVE) { 1631 - amd_pstate_epp_reenable(cpudata); 1632 - cpudata->suspended = false; 1633 - } 1635 + ret = amd_pstate_epp_reenable(policy); 1636 + if (ret) 1637 + return ret; 1638 + cpudata->suspended = false; 1634 1639 1635 1640 return 0; 1636 - } 1637 - 1638 - static void amd_pstate_epp_offline(struct cpufreq_policy *policy) 1639 - { 1640 - struct amd_cpudata *cpudata = policy->driver_data; 1641 - struct cppc_perf_ctrls perf_ctrls; 1642 - int min_perf; 1643 - u64 value; 1644 - 1645 - min_perf = READ_ONCE(cpudata->lowest_perf); 1646 - value = READ_ONCE(cpudata->cppc_req_cached); 1647 - 1648 - mutex_lock(&amd_pstate_limits_lock); 1649 - if (cpu_feature_enabled(X86_FEATURE_CPPC)) { 1650 - cpudata->epp_policy = CPUFREQ_POLICY_UNKNOWN; 1651 - 1652 - /* Set max perf same as min perf */ 1653 - value &= ~AMD_CPPC_MAX_PERF(~0L); 1654 - value |= AMD_CPPC_MAX_PERF(min_perf); 1655 - value &= ~AMD_CPPC_MIN_PERF(~0L); 1656 - value |= AMD_CPPC_MIN_PERF(min_perf); 1657 - wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value); 1658 - } else { 1659 - perf_ctrls.desired_perf = 0; 1660 - perf_ctrls.min_perf = min_perf; 1661 - perf_ctrls.max_perf = min_perf; 1662 - cppc_set_perf(cpudata->cpu, &perf_ctrls); 1663 - perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(HWP_EPP_BALANCE_POWERSAVE); 1664 - cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1); 1665 - } 1666 - mutex_unlock(&amd_pstate_limits_lock); 1667 1641 } 1668 1642 1669 1643 static int amd_pstate_epp_cpu_offline(struct cpufreq_policy *policy) 1670 1644 { 1671 1645 struct amd_cpudata *cpudata = policy->driver_data; 1672 - 1673 - pr_debug("AMD CPU Core %d going offline\n", cpudata->cpu); 1646 + int min_perf; 1674 1647 1675 1648 if (cpudata->suspended) 1676 1649 return 0; 1677 1650 1678 - if (cppc_state == AMD_PSTATE_ACTIVE) 1679 - amd_pstate_epp_offline(policy); 1651 + min_perf = READ_ONCE(cpudata->lowest_perf); 1680 1652 1681 - return 0; 1653 + guard(mutex)(&amd_pstate_limits_lock); 1654 + 1655 + if (trace_amd_pstate_epp_perf_enabled()) { 1656 + trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf, 1657 + AMD_CPPC_EPP_BALANCE_POWERSAVE, 1658 + min_perf, min_perf, policy->boost_enabled); 1659 + } 1660 + 1661 + return amd_pstate_update_perf(cpudata, min_perf, 0, min_perf, 1662 + AMD_CPPC_EPP_BALANCE_POWERSAVE, false); 1682 1663 } 1683 1664 1684 1665 static int amd_pstate_epp_suspend(struct cpufreq_policy *policy) ··· 1682 1711 struct amd_cpudata *cpudata = policy->driver_data; 1683 1712 1684 1713 if (cpudata->suspended) { 1685 - mutex_lock(&amd_pstate_limits_lock); 1714 + guard(mutex)(&amd_pstate_limits_lock); 1686 1715 1687 1716 /* enable amd pstate from suspend state*/ 1688 - amd_pstate_epp_reenable(cpudata); 1689 - 1690 - mutex_unlock(&amd_pstate_limits_lock); 1717 + amd_pstate_epp_reenable(policy); 1691 1718 1692 1719 cpudata->suspended = false; 1693 1720 } ··· 1838 1869 static_call_update(amd_pstate_cppc_enable, shmem_cppc_enable); 1839 1870 static_call_update(amd_pstate_init_perf, shmem_init_perf); 1840 1871 static_call_update(amd_pstate_update_perf, shmem_update_perf); 1872 + static_call_update(amd_pstate_get_epp, shmem_get_epp); 1873 + static_call_update(amd_pstate_set_epp, shmem_set_epp); 1841 1874 } 1842 1875 1843 1876 if (amd_pstate_prefcore) {
-3
drivers/cpufreq/amd-pstate.h
··· 57 57 * @hw_prefcore: check whether HW supports preferred core featue. 58 58 * Only when hw_prefcore and early prefcore param are true, 59 59 * AMD P-State driver supports preferred core featue. 60 - * @epp_policy: Last saved policy used to set energy-performance preference 61 60 * @epp_cached: Cached CPPC energy-performance preference value 62 61 * @policy: Cpufreq policy value 63 62 * @cppc_cap1_cached Cached MSR_AMD_CPPC_CAP1 register value ··· 93 94 bool hw_prefcore; 94 95 95 96 /* EPP feature related attributes*/ 96 - s16 epp_policy; 97 97 s16 epp_cached; 98 98 u32 policy; 99 99 u64 cppc_cap1_cached; 100 100 bool suspended; 101 101 s16 epp_default; 102 - bool boost_state; 103 102 }; 104 103 105 104 /*
+45 -11
drivers/cpufreq/apple-soc-cpufreq.c
··· 22 22 #include <linux/pm_opp.h> 23 23 #include <linux/slab.h> 24 24 25 - #define APPLE_DVFS_CMD 0x20 26 - #define APPLE_DVFS_CMD_BUSY BIT(31) 27 - #define APPLE_DVFS_CMD_SET BIT(25) 28 - #define APPLE_DVFS_CMD_PS2 GENMASK(16, 12) 29 - #define APPLE_DVFS_CMD_PS1 GENMASK(4, 0) 25 + #define APPLE_DVFS_CMD 0x20 26 + #define APPLE_DVFS_CMD_BUSY BIT(31) 27 + #define APPLE_DVFS_CMD_SET BIT(25) 28 + #define APPLE_DVFS_CMD_PS1_S5L8960X GENMASK(24, 22) 29 + #define APPLE_DVFS_CMD_PS1_S5L8960X_SHIFT 22 30 + #define APPLE_DVFS_CMD_PS2 GENMASK(15, 12) 31 + #define APPLE_DVFS_CMD_PS1 GENMASK(4, 0) 32 + #define APPLE_DVFS_CMD_PS1_SHIFT 0 30 33 31 34 /* Same timebase as CPU counter (24MHz) */ 32 35 #define APPLE_DVFS_LAST_CHG_TIME 0x38 ··· 38 35 * Apple ran out of bits and had to shift this in T8112... 39 36 */ 40 37 #define APPLE_DVFS_STATUS 0x50 38 + #define APPLE_DVFS_STATUS_CUR_PS_S5L8960X GENMASK(5, 3) 39 + #define APPLE_DVFS_STATUS_CUR_PS_SHIFT_S5L8960X 3 40 + #define APPLE_DVFS_STATUS_TGT_PS_S5L8960X GENMASK(2, 0) 41 41 #define APPLE_DVFS_STATUS_CUR_PS_T8103 GENMASK(7, 4) 42 42 #define APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8103 4 43 43 #define APPLE_DVFS_STATUS_TGT_PS_T8103 GENMASK(3, 0) ··· 58 52 #define APPLE_DVFS_PLL_FACTOR_MULT GENMASK(31, 16) 59 53 #define APPLE_DVFS_PLL_FACTOR_DIV GENMASK(15, 0) 60 54 61 - #define APPLE_DVFS_TRANSITION_TIMEOUT 100 55 + #define APPLE_DVFS_TRANSITION_TIMEOUT 400 62 56 63 57 struct apple_soc_cpufreq_info { 58 + bool has_ps2; 64 59 u64 max_pstate; 65 60 u64 cur_pstate_mask; 66 61 u64 cur_pstate_shift; 62 + u64 ps1_mask; 63 + u64 ps1_shift; 67 64 }; 68 65 69 66 struct apple_cpu_priv { ··· 77 68 78 69 static struct cpufreq_driver apple_soc_cpufreq_driver; 79 70 71 + static const struct apple_soc_cpufreq_info soc_s5l8960x_info = { 72 + .has_ps2 = false, 73 + .max_pstate = 7, 74 + .cur_pstate_mask = APPLE_DVFS_STATUS_CUR_PS_S5L8960X, 75 + .cur_pstate_shift = APPLE_DVFS_STATUS_CUR_PS_SHIFT_S5L8960X, 76 + .ps1_mask = APPLE_DVFS_CMD_PS1_S5L8960X, 77 + .ps1_shift = APPLE_DVFS_CMD_PS1_S5L8960X_SHIFT, 78 + }; 79 + 80 80 static const struct apple_soc_cpufreq_info soc_t8103_info = { 81 + .has_ps2 = true, 81 82 .max_pstate = 15, 82 83 .cur_pstate_mask = APPLE_DVFS_STATUS_CUR_PS_T8103, 83 84 .cur_pstate_shift = APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8103, 85 + .ps1_mask = APPLE_DVFS_CMD_PS1, 86 + .ps1_shift = APPLE_DVFS_CMD_PS1_SHIFT, 84 87 }; 85 88 86 89 static const struct apple_soc_cpufreq_info soc_t8112_info = { 90 + .has_ps2 = false, 87 91 .max_pstate = 31, 88 92 .cur_pstate_mask = APPLE_DVFS_STATUS_CUR_PS_T8112, 89 93 .cur_pstate_shift = APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8112, 94 + .ps1_mask = APPLE_DVFS_CMD_PS1, 95 + .ps1_shift = APPLE_DVFS_CMD_PS1_SHIFT, 90 96 }; 91 97 92 98 static const struct apple_soc_cpufreq_info soc_default_info = { 99 + .has_ps2 = false, 93 100 .max_pstate = 15, 94 101 .cur_pstate_mask = 0, /* fallback */ 102 + .ps1_mask = APPLE_DVFS_CMD_PS1, 103 + .ps1_shift = APPLE_DVFS_CMD_PS1_SHIFT, 95 104 }; 96 105 97 106 static const struct of_device_id apple_soc_cpufreq_of_match[] __maybe_unused = { 107 + { 108 + .compatible = "apple,s5l8960x-cluster-cpufreq", 109 + .data = &soc_s5l8960x_info, 110 + }, 98 111 { 99 112 .compatible = "apple,t8103-cluster-cpufreq", 100 113 .data = &soc_t8103_info, ··· 140 109 unsigned int pstate; 141 110 142 111 if (priv->info->cur_pstate_mask) { 143 - u64 reg = readq_relaxed(priv->reg_base + APPLE_DVFS_STATUS); 112 + u32 reg = readl_relaxed(priv->reg_base + APPLE_DVFS_STATUS); 144 113 145 114 pstate = (reg & priv->info->cur_pstate_mask) >> priv->info->cur_pstate_shift; 146 115 } else { ··· 179 148 return -EIO; 180 149 } 181 150 182 - reg &= ~(APPLE_DVFS_CMD_PS1 | APPLE_DVFS_CMD_PS2); 183 - reg |= FIELD_PREP(APPLE_DVFS_CMD_PS1, pstate); 184 - reg |= FIELD_PREP(APPLE_DVFS_CMD_PS2, pstate); 151 + reg &= ~priv->info->ps1_mask; 152 + reg |= pstate << priv->info->ps1_shift; 153 + if (priv->info->has_ps2) { 154 + reg &= ~APPLE_DVFS_CMD_PS2; 155 + reg |= FIELD_PREP(APPLE_DVFS_CMD_PS2, pstate); 156 + } 185 157 reg |= APPLE_DVFS_CMD_SET; 186 158 187 159 writeq_relaxed(reg, priv->reg_base + APPLE_DVFS_CMD); ··· 309 275 310 276 transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev); 311 277 if (!transition_latency) 312 - transition_latency = CPUFREQ_ETERNAL; 278 + transition_latency = APPLE_DVFS_TRANSITION_TIMEOUT * NSEC_PER_USEC; 313 279 314 280 policy->cpuinfo.transition_latency = transition_latency; 315 281 policy->dvfs_possible_from_any_cpu = true;
+2 -2
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,en7581", }, 107 + 106 108 { .compatible = "allwinner,sun50i-a100" }, 107 109 { .compatible = "allwinner,sun50i-h6", }, 108 110 { .compatible = "allwinner,sun50i-h616", }, ··· 237 235 sizeof(struct cpufreq_dt_platform_data))); 238 236 } 239 237 core_initcall(cpufreq_dt_platdev_init); 240 - MODULE_DESCRIPTION("Generic DT based cpufreq platdev driver"); 241 - MODULE_LICENSE("GPL");
+5 -4
drivers/cpufreq/cpufreq.c
··· 25 25 #include <linux/mutex.h> 26 26 #include <linux/pm_qos.h> 27 27 #include <linux/slab.h> 28 + #include <linux/string_choices.h> 28 29 #include <linux/suspend.h> 29 30 #include <linux/syscore_ops.h> 30 31 #include <linux/tick.h> ··· 603 602 604 603 if (cpufreq_boost_trigger_state(enable)) { 605 604 pr_err("%s: Cannot %s BOOST!\n", 606 - __func__, enable ? "enable" : "disable"); 605 + __func__, str_enable_disable(enable)); 607 606 return -EINVAL; 608 607 } 609 608 610 609 pr_debug("%s: cpufreq BOOST %s\n", 611 - __func__, enable ? "enabled" : "disabled"); 610 + __func__, str_enabled_disabled(enable)); 612 611 613 612 return count; 614 613 } ··· 1539 1538 1540 1539 /* 1541 1540 * Register with the energy model before 1542 - * sugov_eas_rebuild_sd() is called, which will result 1541 + * em_rebuild_sched_domains() is called, which will result 1543 1542 * in rebuilding of the sched domains, which should only be done 1544 1543 * once the energy model is properly initialized for the policy 1545 1544 * first. ··· 2813 2812 write_unlock_irqrestore(&cpufreq_driver_lock, flags); 2814 2813 2815 2814 pr_err("%s: Cannot %s BOOST\n", 2816 - __func__, state ? "enable" : "disable"); 2815 + __func__, str_enable_disable(state)); 2817 2816 2818 2817 return ret; 2819 2818 }
+34 -26
drivers/cpufreq/intel_pstate.c
··· 28 28 #include <linux/pm_qos.h> 29 29 #include <linux/bitfield.h> 30 30 #include <trace/events/power.h> 31 + #include <linux/units.h> 31 32 32 33 #include <asm/cpu.h> 33 34 #include <asm/div64.h> ··· 303 302 304 303 static struct cpufreq_driver *intel_pstate_driver __read_mostly; 305 304 306 - #define HYBRID_SCALING_FACTOR 78741 305 + #define HYBRID_SCALING_FACTOR_ADL 78741 307 306 #define HYBRID_SCALING_FACTOR_MTL 80000 308 307 #define HYBRID_SCALING_FACTOR_LNL 86957 309 308 310 - static int hybrid_scaling_factor = HYBRID_SCALING_FACTOR; 309 + static int hybrid_scaling_factor; 311 310 312 311 static inline int core_get_scaling(void) 313 312 { ··· 415 414 static int intel_pstate_cppc_get_scaling(int cpu) 416 415 { 417 416 struct cppc_perf_caps cppc_perf; 418 - int ret; 419 - 420 - ret = cppc_get_perf_caps(cpu, &cppc_perf); 421 417 422 418 /* 423 - * If the nominal frequency and the nominal performance are not 424 - * zero and the ratio between them is not 100, return the hybrid 425 - * scaling factor. 419 + * Compute the perf-to-frequency scaling factor for the given CPU if 420 + * possible, unless it would be 0. 426 421 */ 427 - if (!ret && cppc_perf.nominal_perf && cppc_perf.nominal_freq && 428 - cppc_perf.nominal_perf * 100 != cppc_perf.nominal_freq) 429 - return hybrid_scaling_factor; 422 + if (!cppc_get_perf_caps(cpu, &cppc_perf) && 423 + cppc_perf.nominal_perf && cppc_perf.nominal_freq) 424 + return div_u64(cppc_perf.nominal_freq * KHZ_PER_MHZ, 425 + cppc_perf.nominal_perf); 430 426 431 427 return core_get_scaling(); 432 428 } ··· 2209 2211 2210 2212 static int hwp_get_cpu_scaling(int cpu) 2211 2213 { 2212 - u8 cpu_type = 0; 2214 + if (hybrid_scaling_factor) { 2215 + u8 cpu_type = 0; 2213 2216 2214 - smp_call_function_single(cpu, hybrid_get_type, &cpu_type, 1); 2215 - /* P-cores have a smaller perf level-to-freqency scaling factor. */ 2216 - if (cpu_type == 0x40) 2217 - return hybrid_scaling_factor; 2217 + smp_call_function_single(cpu, hybrid_get_type, &cpu_type, 1); 2218 2218 2219 - /* Use default core scaling for E-cores */ 2220 - if (cpu_type == 0x20) 2219 + /* 2220 + * Return the hybrid scaling factor for P-cores and use the 2221 + * default core scaling for E-cores. 2222 + */ 2223 + if (cpu_type == 0x40) 2224 + return hybrid_scaling_factor; 2225 + 2226 + if (cpu_type == 0x20) 2227 + return core_get_scaling(); 2228 + } 2229 + 2230 + /* Use core scaling on non-hybrid systems. */ 2231 + if (!cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) 2221 2232 return core_get_scaling(); 2222 2233 2223 2234 /* 2224 - * If reached here, this system is either non-hybrid (like Tiger 2225 - * Lake) or hybrid-capable (like Alder Lake or Raptor Lake) with 2226 - * no E cores (in which case CPUID for hybrid support is 0). 2227 - * 2228 - * The CPPC nominal_frequency field is 0 for non-hybrid systems, 2229 - * so the default core scaling will be used for them. 2235 + * The system is hybrid, but the hybrid scaling factor is not known or 2236 + * the CPU type is not one of the above, so use CPPC to compute the 2237 + * scaling factor for this CPU. 2230 2238 */ 2231 2239 return intel_pstate_cppc_get_scaling(cpu); 2232 2240 } ··· 2713 2709 } 2714 2710 2715 2711 cpu->epp_powersave = -EINVAL; 2716 - cpu->epp_policy = 0; 2712 + cpu->epp_policy = CPUFREQ_POLICY_UNKNOWN; 2717 2713 2718 2714 intel_pstate_get_cpu_pstates(cpu); 2719 2715 ··· 3669 3665 }; 3670 3666 3671 3667 static const struct x86_cpu_id intel_hybrid_scaling_factor[] = { 3668 + X86_MATCH_VFM(INTEL_ALDERLAKE, HYBRID_SCALING_FACTOR_ADL), 3669 + X86_MATCH_VFM(INTEL_ALDERLAKE_L, HYBRID_SCALING_FACTOR_ADL), 3670 + X86_MATCH_VFM(INTEL_RAPTORLAKE, HYBRID_SCALING_FACTOR_ADL), 3671 + X86_MATCH_VFM(INTEL_RAPTORLAKE_P, HYBRID_SCALING_FACTOR_ADL), 3672 + X86_MATCH_VFM(INTEL_RAPTORLAKE_S, HYBRID_SCALING_FACTOR_ADL), 3672 3673 X86_MATCH_VFM(INTEL_METEORLAKE_L, HYBRID_SCALING_FACTOR_MTL), 3673 - X86_MATCH_VFM(INTEL_ARROWLAKE, HYBRID_SCALING_FACTOR_MTL), 3674 3674 X86_MATCH_VFM(INTEL_LUNARLAKE_M, HYBRID_SCALING_FACTOR_LNL), 3675 3675 {} 3676 3676 };
+2 -1
drivers/cpufreq/powernv-cpufreq.c
··· 18 18 #include <linux/of.h> 19 19 #include <linux/reboot.h> 20 20 #include <linux/slab.h> 21 + #include <linux/string_choices.h> 21 22 #include <linux/cpu.h> 22 23 #include <linux/hashtable.h> 23 24 #include <trace/events/power.h> ··· 282 281 pr_info("cpufreq pstate min 0x%x nominal 0x%x max 0x%x\n", pstate_min, 283 282 pstate_nominal, pstate_max); 284 283 pr_info("Workload Optimized Frequency is %s in the platform\n", 285 - (powernv_pstate_info.wof_enabled) ? "enabled" : "disabled"); 284 + str_enabled_disabled(powernv_pstate_info.wof_enabled)); 286 285 287 286 pstate_ids = of_get_property(power_mgt, "ibm,pstate-ids", &len_ids); 288 287 if (!pstate_ids) {
+24 -10
drivers/cpufreq/qcom-cpufreq-hw.c
··· 143 143 } 144 144 145 145 /* Get the frequency requested by the cpufreq core for the CPU */ 146 - static unsigned int qcom_cpufreq_get_freq(unsigned int cpu) 146 + static unsigned int qcom_cpufreq_get_freq(struct cpufreq_policy *policy) 147 147 { 148 148 struct qcom_cpufreq_data *data; 149 149 const struct qcom_cpufreq_soc_data *soc_data; 150 - struct cpufreq_policy *policy; 151 150 unsigned int index; 152 151 153 - policy = cpufreq_cpu_get_raw(cpu); 154 152 if (!policy) 155 153 return 0; 156 154 ··· 161 163 return policy->freq_table[index].frequency; 162 164 } 163 165 164 - static unsigned int qcom_cpufreq_hw_get(unsigned int cpu) 166 + static unsigned int __qcom_cpufreq_hw_get(struct cpufreq_policy *policy) 165 167 { 166 168 struct qcom_cpufreq_data *data; 167 - struct cpufreq_policy *policy; 168 169 169 - policy = cpufreq_cpu_get_raw(cpu); 170 170 if (!policy) 171 171 return 0; 172 172 ··· 173 177 if (data->throttle_irq >= 0) 174 178 return qcom_lmh_get_throttle_freq(data) / HZ_PER_KHZ; 175 179 176 - return qcom_cpufreq_get_freq(cpu); 180 + return qcom_cpufreq_get_freq(policy); 181 + } 182 + 183 + static unsigned int qcom_cpufreq_hw_get(unsigned int cpu) 184 + { 185 + return __qcom_cpufreq_hw_get(cpufreq_cpu_get_raw(cpu)); 177 186 } 178 187 179 188 static unsigned int qcom_cpufreq_hw_fast_switch(struct cpufreq_policy *policy, ··· 364 363 * If h/w throttled frequency is higher than what cpufreq has requested 365 364 * for, then stop polling and switch back to interrupt mechanism. 366 365 */ 367 - if (throttled_freq >= qcom_cpufreq_get_freq(cpu)) 366 + if (throttled_freq >= qcom_cpufreq_get_freq(cpufreq_cpu_get_raw(cpu))) 368 367 enable_irq(data->throttle_irq); 369 368 else 370 369 mod_delayed_work(system_highpri_wq, &data->throttle_work, ··· 442 441 return data->throttle_irq; 443 442 444 443 data->cancel_throttle = false; 445 - data->policy = policy; 446 444 447 445 mutex_init(&data->throttle_lock); 448 446 INIT_DEFERRABLE_WORK(&data->throttle_work, qcom_lmh_dcvs_poll); ··· 552 552 553 553 policy->driver_data = data; 554 554 policy->dvfs_possible_from_any_cpu = true; 555 + data->policy = policy; 555 556 556 557 ret = qcom_cpufreq_hw_read_lut(cpu_dev, policy); 557 558 if (ret) { ··· 623 622 { 624 623 struct qcom_cpufreq_data *data = container_of(hw, struct qcom_cpufreq_data, cpu_clk); 625 624 626 - return qcom_lmh_get_throttle_freq(data); 625 + return __qcom_cpufreq_hw_get(data->policy) * HZ_PER_KHZ; 626 + } 627 + 628 + /* 629 + * Since we cannot determine the closest rate of the target rate, let's just 630 + * return the actual rate at which the clock is running at. This is needed to 631 + * make clk_set_rate() API work properly. 632 + */ 633 + static int qcom_cpufreq_hw_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) 634 + { 635 + req->rate = qcom_cpufreq_hw_recalc_rate(hw, 0); 636 + 637 + return 0; 627 638 } 628 639 629 640 static const struct clk_ops qcom_cpufreq_hw_clk_ops = { 630 641 .recalc_rate = qcom_cpufreq_hw_recalc_rate, 642 + .determine_rate = qcom_cpufreq_hw_determine_rate, 631 643 }; 632 644 633 645 static int qcom_cpufreq_hw_driver_probe(struct platform_device *pdev)
+45
drivers/cpufreq/scmi-cpufreq.c
··· 16 16 #include <linux/export.h> 17 17 #include <linux/module.h> 18 18 #include <linux/pm_opp.h> 19 + #include <linux/pm_qos.h> 19 20 #include <linux/slab.h> 20 21 #include <linux/scmi_protocol.h> 21 22 #include <linux/types.h> ··· 27 26 int nr_opp; 28 27 struct device *cpu_dev; 29 28 cpumask_var_t opp_shared_cpus; 29 + struct notifier_block limit_notify_nb; 30 + struct freq_qos_request limits_freq_req; 30 31 }; 31 32 32 33 static struct scmi_protocol_handle *ph; ··· 177 174 NULL, 178 175 }; 179 176 177 + static int scmi_limit_notify_cb(struct notifier_block *nb, unsigned long event, void *data) 178 + { 179 + struct scmi_data *priv = container_of(nb, struct scmi_data, limit_notify_nb); 180 + struct scmi_perf_limits_report *limit_notify = data; 181 + unsigned int limit_freq_khz; 182 + int ret; 183 + 184 + limit_freq_khz = limit_notify->range_max_freq / HZ_PER_KHZ; 185 + 186 + ret = freq_qos_update_request(&priv->limits_freq_req, limit_freq_khz); 187 + if (ret < 0) 188 + pr_warn("failed to update freq constraint: %d\n", ret); 189 + 190 + return NOTIFY_OK; 191 + } 192 + 180 193 static int scmi_cpufreq_init(struct cpufreq_policy *policy) 181 194 { 182 195 int ret, nr_opp, domain; ··· 200 181 struct device *cpu_dev; 201 182 struct scmi_data *priv; 202 183 struct cpufreq_frequency_table *freq_table; 184 + struct scmi_device *sdev = cpufreq_get_driver_data(); 203 185 204 186 cpu_dev = get_cpu_device(policy->cpu); 205 187 if (!cpu_dev) { ··· 314 294 } 315 295 } 316 296 297 + ret = freq_qos_add_request(&policy->constraints, &priv->limits_freq_req, FREQ_QOS_MAX, 298 + FREQ_QOS_MAX_DEFAULT_VALUE); 299 + if (ret < 0) { 300 + dev_err(cpu_dev, "failed to add qos limits request: %d\n", ret); 301 + goto out_free_table; 302 + } 303 + 304 + priv->limit_notify_nb.notifier_call = scmi_limit_notify_cb; 305 + ret = sdev->handle->notify_ops->event_notifier_register(sdev->handle, SCMI_PROTOCOL_PERF, 306 + SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED, 307 + &priv->domain_id, 308 + &priv->limit_notify_nb); 309 + if (ret) 310 + dev_warn(&sdev->dev, 311 + "failed to register for limits change notifier for domain %d\n", 312 + priv->domain_id); 313 + 317 314 return 0; 318 315 319 316 out_free_table: ··· 350 313 static void scmi_cpufreq_exit(struct cpufreq_policy *policy) 351 314 { 352 315 struct scmi_data *priv = policy->driver_data; 316 + struct scmi_device *sdev = cpufreq_get_driver_data(); 353 317 318 + sdev->handle->notify_ops->event_notifier_unregister(sdev->handle, SCMI_PROTOCOL_PERF, 319 + SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED, 320 + &priv->domain_id, 321 + &priv->limit_notify_nb); 322 + freq_qos_remove_request(&priv->limits_freq_req); 354 323 dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); 355 324 dev_pm_opp_remove_all_dynamic(priv->cpu_dev); 356 325 free_cpumask_var(priv->opp_shared_cpus); ··· 414 371 415 372 if (!handle) 416 373 return -ENODEV; 374 + 375 + scmi_cpufreq_driver.driver_data = sdev; 417 376 418 377 perf_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_PERF, &ph); 419 378 if (IS_ERR(perf_ops))
+1 -1
drivers/cpufreq/sparc-us2e-cpufreq.c
··· 323 323 impl = ((ver >> 32) & 0xffff); 324 324 325 325 if (manuf == 0x17 && impl == 0x13) { 326 - us2e_freq_table = kzalloc(NR_CPUS * sizeof(*us2e_freq_table), 326 + us2e_freq_table = kcalloc(NR_CPUS, sizeof(*us2e_freq_table), 327 327 GFP_KERNEL); 328 328 if (!us2e_freq_table) 329 329 return -ENOMEM;
+1 -1
drivers/cpufreq/sparc-us3-cpufreq.c
··· 171 171 impl == CHEETAH_PLUS_IMPL || 172 172 impl == JAGUAR_IMPL || 173 173 impl == PANTHER_IMPL)) { 174 - us3_freq_table = kzalloc(NR_CPUS * sizeof(*us3_freq_table), 174 + us3_freq_table = kcalloc(NR_CPUS, sizeof(*us3_freq_table), 175 175 GFP_KERNEL); 176 176 if (!us3_freq_table) 177 177 return -ENOMEM;
+2 -6
drivers/devfreq/devfreq-event.c
··· 244 244 edev = NULL; 245 245 out: 246 246 mutex_unlock(&devfreq_event_list_lock); 247 - 248 - if (!edev) { 249 - of_node_put(node); 250 - return ERR_PTR(-ENODEV); 251 - } 252 - 253 247 of_node_put(node); 248 + if (!edev) 249 + return ERR_PTR(-ENODEV); 254 250 255 251 return edev; 256 252 }
+2 -3
drivers/devfreq/exynos-bus.c
··· 236 236 return ret; 237 237 } 238 238 239 - static int exynos_bus_parse_of(struct device_node *np, 240 - struct exynos_bus *bus) 239 + static int exynos_bus_parse_of(struct exynos_bus *bus) 241 240 { 242 241 struct device *dev = bus->dev; 243 242 struct dev_pm_opp *opp; ··· 407 408 } 408 409 409 410 /* Parse the device-tree to get the resource information */ 410 - ret = exynos_bus_parse_of(np, bus); 411 + ret = exynos_bus_parse_of(bus); 411 412 if (ret < 0) 412 413 goto err_reg; 413 414
+1
drivers/idle/intel_idle.c
··· 1652 1652 X86_MATCH_VFM(INTEL_ATOM_TREMONT_D, &idle_cpu_snr), 1653 1653 X86_MATCH_VFM(INTEL_ATOM_CRESTMONT, &idle_cpu_grr), 1654 1654 X86_MATCH_VFM(INTEL_ATOM_CRESTMONT_X, &idle_cpu_srf), 1655 + X86_MATCH_VFM(INTEL_ATOM_DARKMONT_X, &idle_cpu_srf), 1655 1656 {} 1656 1657 }; 1657 1658
+12 -5
drivers/opp/core.c
··· 1528 1528 return ERR_PTR(ret); 1529 1529 } 1530 1530 1531 - void _get_opp_table_kref(struct opp_table *opp_table) 1532 - { 1533 - kref_get(&opp_table->kref); 1534 - } 1535 - 1536 1531 static struct opp_table *_update_opp_table_clk(struct device *dev, 1537 1532 struct opp_table *opp_table, 1538 1533 bool getclk) ··· 1688 1693 kfree(opp_table); 1689 1694 } 1690 1695 1696 + void _get_opp_table_kref(struct opp_table *opp_table) 1697 + { 1698 + kref_get(&opp_table->kref); 1699 + } 1700 + 1701 + void dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table) 1702 + { 1703 + _get_opp_table_kref(opp_table); 1704 + } 1705 + EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table_ref); 1706 + 1691 1707 void dev_pm_opp_put_opp_table(struct opp_table *opp_table) 1692 1708 { 1693 1709 kref_put_mutex(&opp_table->kref, _opp_table_kref_release, ··· 1733 1727 { 1734 1728 kref_get(&opp->kref); 1735 1729 } 1730 + EXPORT_SYMBOL_GPL(dev_pm_opp_get); 1736 1731 1737 1732 void dev_pm_opp_put(struct dev_pm_opp *opp) 1738 1733 {
+3 -1
drivers/opp/of.c
··· 926 926 927 927 ret = _of_opp_alloc_required_opps(opp_table, new_opp); 928 928 if (ret) 929 - goto free_opp; 929 + goto put_node; 930 930 931 931 if (!of_property_read_u32(np, "clock-latency-ns", &val)) 932 932 new_opp->clock_latency_ns = val; ··· 976 976 977 977 free_required_opps: 978 978 _of_opp_free_required_opps(opp_table, new_opp); 979 + put_node: 980 + of_node_put(np); 979 981 free_opp: 980 982 _opp_free(new_opp); 981 983
-1
drivers/opp/opp.h
··· 250 250 }; 251 251 252 252 /* Routines internal to opp core */ 253 - void dev_pm_opp_get(struct dev_pm_opp *opp); 254 253 bool _opp_remove_all_static(struct opp_table *opp_table); 255 254 void _get_opp_table_kref(struct opp_table *opp_table); 256 255 int _get_opp_count(struct opp_table *opp_table);
+2
include/linux/energy_model.h
··· 179 179 int em_dev_update_chip_binning(struct device *dev); 180 180 int em_update_performance_limits(struct em_perf_domain *pd, 181 181 unsigned long freq_min_khz, unsigned long freq_max_khz); 182 + void em_rebuild_sched_domains(void); 182 183 183 184 /** 184 185 * em_pd_get_efficient_state() - Get an efficient performance state from the EM ··· 405 404 { 406 405 return -EINVAL; 407 406 } 407 + static inline void em_rebuild_sched_domains(void) {} 408 408 #endif 409 409 410 410 #endif
+6
include/linux/pm_opp.h
··· 100 100 #if defined(CONFIG_PM_OPP) 101 101 102 102 struct opp_table *dev_pm_opp_get_opp_table(struct device *dev); 103 + void dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table); 103 104 void dev_pm_opp_put_opp_table(struct opp_table *opp_table); 104 105 105 106 unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, bool peak, int index); ··· 161 160 struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev, 162 161 unsigned int *bw, int index); 163 162 163 + void dev_pm_opp_get(struct dev_pm_opp *opp); 164 164 void dev_pm_opp_put(struct dev_pm_opp *opp); 165 165 166 166 int dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *opp); ··· 206 204 { 207 205 return ERR_PTR(-EOPNOTSUPP); 208 206 } 207 + 208 + static inline void dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table) {} 209 209 210 210 static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {} 211 211 ··· 344 340 { 345 341 return ERR_PTR(-EOPNOTSUPP); 346 342 } 343 + 344 + static inline void dev_pm_opp_get(struct dev_pm_opp *opp) {} 347 345 348 346 static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {} 349 347
+6
include/linux/pm_wakeirq.h
··· 10 10 extern int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq); 11 11 extern int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq); 12 12 extern void dev_pm_clear_wake_irq(struct device *dev); 13 + extern int devm_pm_set_wake_irq(struct device *dev, int irq); 13 14 14 15 #else /* !CONFIG_PM */ 15 16 ··· 31 30 32 31 static inline void dev_pm_clear_wake_irq(struct device *dev) 33 32 { 33 + } 34 + 35 + static inline int devm_pm_set_wake_irq(struct device *dev, int irq) 36 + { 37 + return 0; 34 38 } 35 39 36 40 #endif /* CONFIG_PM */
+17
include/linux/pm_wakeup.h
··· 240 240 return 0; 241 241 } 242 242 243 + static void device_disable_wakeup(void *dev) 244 + { 245 + device_init_wakeup(dev, false); 246 + } 247 + 248 + /** 249 + * devm_device_init_wakeup - Resource managed device wakeup initialization. 250 + * @dev: Device to handle. 251 + * 252 + * This function is the devm managed version of device_init_wakeup(dev, true). 253 + */ 254 + static inline int devm_device_init_wakeup(struct device *dev) 255 + { 256 + device_init_wakeup(dev, true); 257 + return devm_add_action_or_reset(dev, device_disable_wakeup, dev); 258 + } 259 + 243 260 #endif /* _LINUX_PM_WAKEUP_H */
+20 -1
kernel/power/Kconfig
··· 257 257 boot session. 258 258 259 259 config DPM_WATCHDOG_TIMEOUT 260 - int "Watchdog timeout in seconds" 260 + int "Watchdog timeout to panic in seconds" 261 261 range 1 120 262 262 default 120 263 263 depends on DPM_WATCHDOG 264 + 265 + config DPM_WATCHDOG_WARNING_TIMEOUT 266 + int "Watchdog timeout to warn in seconds" 267 + range 1 DPM_WATCHDOG_TIMEOUT 268 + default DPM_WATCHDOG_TIMEOUT 269 + depends on DPM_WATCHDOG 270 + help 271 + If the DPM watchdog warning timeout and main timeout are 272 + different then a non-fatal warning (with a stack trace of 273 + the stuck suspend routine) will be printed when the warning 274 + timeout expires. If the suspend routine gets un-stuck 275 + before the main timeout expires then no other action is 276 + taken. If the routine continues to be stuck and the main 277 + timeout expires then an emergency-level message and stack 278 + trace will be printed and the system will panic. 279 + 280 + If the warning timeout is equal to the main timeout (the 281 + default) then the warning will never happen and the system 282 + will jump straight to panic when the main timeout expires. 264 283 265 284 config PM_TRACE 266 285 bool
-1
kernel/power/autosleep.c
··· 9 9 10 10 #include <linux/device.h> 11 11 #include <linux/mutex.h> 12 - #include <linux/pm_wakeup.h> 13 12 14 13 #include "power.h" 15 14
+17
kernel/power/energy_model.c
··· 908 908 return 0; 909 909 } 910 910 EXPORT_SYMBOL_GPL(em_update_performance_limits); 911 + 912 + static void rebuild_sd_workfn(struct work_struct *work) 913 + { 914 + rebuild_sched_domains_energy(); 915 + } 916 + 917 + void em_rebuild_sched_domains(void) 918 + { 919 + static DECLARE_WORK(rebuild_sd_work, rebuild_sd_workfn); 920 + 921 + /* 922 + * When called from the cpufreq_register_driver() path, the 923 + * cpu_hotplug_lock is already held, so use a work item to 924 + * avoid nested locking in rebuild_sched_domains(). 925 + */ 926 + schedule_work(&rebuild_sd_work); 927 + }
+1 -1
kernel/power/power.h
··· 110 110 111 111 extern void clear_or_poison_free_pages(void); 112 112 113 - /** 113 + /* 114 114 * Auxiliary structure used for reading the snapshot image data and 115 115 * metadata from and writing them to the list of page backup entries 116 116 * (PBEs) which is the main data structure of swsusp.
+8 -29
kernel/sched/cpufreq_schedutil.c
··· 83 83 84 84 if (unlikely(sg_policy->limits_changed)) { 85 85 sg_policy->limits_changed = false; 86 - sg_policy->need_freq_update = true; 86 + sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS); 87 87 return true; 88 88 } 89 89 ··· 96 96 unsigned int next_freq) 97 97 { 98 98 if (sg_policy->need_freq_update) 99 - sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS); 99 + sg_policy->need_freq_update = false; 100 100 else if (sg_policy->next_freq == next_freq) 101 101 return false; 102 102 ··· 604 604 605 605 /********************** cpufreq governor interface *********************/ 606 606 607 - #ifdef CONFIG_ENERGY_MODEL 608 - static void rebuild_sd_workfn(struct work_struct *work) 609 - { 610 - rebuild_sched_domains_energy(); 611 - } 612 - 613 - static DECLARE_WORK(rebuild_sd_work, rebuild_sd_workfn); 614 - 615 - /* 616 - * EAS shouldn't be attempted without sugov, so rebuild the sched_domains 617 - * on governor changes to make sure the scheduler knows about it. 618 - */ 619 - static void sugov_eas_rebuild_sd(void) 620 - { 621 - /* 622 - * When called from the cpufreq_register_driver() path, the 623 - * cpu_hotplug_lock is already held, so use a work item to 624 - * avoid nested locking in rebuild_sched_domains(). 625 - */ 626 - schedule_work(&rebuild_sd_work); 627 - } 628 - #else 629 - static inline void sugov_eas_rebuild_sd(void) { }; 630 - #endif 631 - 632 607 struct cpufreq_governor schedutil_gov; 633 608 634 609 static struct sugov_policy *sugov_policy_alloc(struct cpufreq_policy *policy) ··· 759 784 goto fail; 760 785 761 786 out: 762 - sugov_eas_rebuild_sd(); 787 + /* 788 + * Schedutil is the preferred governor for EAS, so rebuild sched domains 789 + * on governor changes to make sure the scheduler knows about them. 790 + */ 791 + em_rebuild_sched_domains(); 763 792 mutex_unlock(&global_tunables_lock); 764 793 return 0; 765 794 ··· 805 826 sugov_policy_free(sg_policy); 806 827 cpufreq_disable_fast_switch(policy); 807 828 808 - sugov_eas_rebuild_sd(); 829 + em_rebuild_sched_domains(); 809 830 } 810 831 811 832 static int sugov_start(struct cpufreq_policy *policy)
+8
tools/power/cpupower/Makefile
··· 87 87 # to something more interesting, like "arm-linux-". If you want 88 88 # to compile vs uClibc, that can be done here as well. 89 89 CROSS ?= #/usr/i386-linux-uclibc/usr/bin/i386-uclibc- 90 + ifneq ($(CROSS), ) 91 + CC = $(CROSS)gcc 92 + LD = $(CROSS)gcc 93 + AR = $(CROSS)ar 94 + STRIP = $(CROSS)strip 95 + RANLIB = $(CROSS)ranlib 96 + else 90 97 CC ?= $(CROSS)gcc 91 98 LD ?= $(CROSS)gcc 92 99 AR ?= $(CROSS)ar 93 100 STRIP ?= $(CROSS)strip 94 101 RANLIB ?= $(CROSS)ranlib 102 + endif 95 103 HOSTCC = gcc 96 104 MKDIR = mkdir 97 105
+10
tools/power/cpupower/bindings/python/Makefile
··· 11 11 LIB_DIR := ../../lib 12 12 PY_INCLUDE = $(firstword $(shell python-config --includes)) 13 13 OBJECTS_LIB = $(wildcard $(LIB_DIR)/*.o) 14 + INSTALL_DIR = $(shell python3 -c "import site; print(site.getsitepackages()[0])") 14 15 15 16 all: _raw_pylibcpupower.so 16 17 ··· 28 27 $(error "python-config was not found. Make sure you have it installed and in the PATH to generate the bindings.") 29 28 endif 30 29 swig -python raw_pylibcpupower.swg 30 + 31 + # Only installs the Python bindings 32 + install: _raw_pylibcpupower.so 33 + install -D _raw_pylibcpupower.so $(INSTALL_DIR)/_raw_pylibcpupower.so 34 + install -D raw_pylibcpupower.py $(INSTALL_DIR)/raw_pylibcpupower.py 35 + 36 + uninstall: 37 + rm -f $(INSTALL_DIR)/_raw_pylibcpupower.so 38 + rm -f $(INSTALL_DIR)/raw_pylibcpupower.py 31 39 32 40 # Will only clean the bindings folder; will not clean the actual cpupower folder 33 41 clean:
+25
tools/power/cpupower/bindings/python/README
··· 48 48 $ python test_raw_pylibcpupower.py 49 49 50 50 51 + developing/using the bindings directly 52 + -------------------------------------- 53 + 54 + You need to add the Python bindings directory to your $PYTHONPATH. 55 + 56 + You would set the path in the Bash terminal or in the Bash profile: 57 + 58 + PYTHONPATH=~/linux/tools/power/cpupower/bindings/python:$PYTHONPATH 59 + 60 + This allows you to set a specific repo of the bindings to use. 61 + 62 + 63 + installing/uninstalling 64 + ----------------------- 65 + 66 + Python uses a system specific site-packages folder to look up modules to import 67 + by default. You do not need to install cpupower to use the SWIG bindings. 68 + 69 + You can install and uninstall the bindings to the site-packages with: 70 + 71 + sudo make install 72 + 73 + sudo make uninstall 74 + 75 + 51 76 credits 52 77 ------- 53 78
+5
tools/power/cpupower/bindings/python/raw_pylibcpupower.swg
··· 134 134 135 135 unsigned long cpufreq_get_transitions(unsigned int cpu); 136 136 137 + char *cpufreq_get_energy_performance_preference(unsigned int cpu); 138 + void cpufreq_put_energy_performance_preference(char *ptr); 139 + 137 140 int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy); 138 141 139 142 int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq); ··· 162 159 int cpuidle_state_disable(unsigned int cpu, unsigned int idlestate, 163 160 unsigned int disable); 164 161 unsigned long cpuidle_state_latency(unsigned int cpu, 162 + unsigned int idlestate); 163 + unsigned long cpuidle_state_residency(unsigned int cpu, 165 164 unsigned int idlestate); 166 165 unsigned long cpuidle_state_usage(unsigned int cpu, 167 166 unsigned int idlestate);
+18
tools/power/cpupower/lib/cpufreq.c
··· 102 102 if (len == 0) 103 103 return 0; 104 104 105 + if (!strcmp(linebuf, "enabled\n")) 106 + return 1; 107 + if (!strcmp(linebuf, "disabled\n")) 108 + return 0; 105 109 value = strtoul(linebuf, &endp, 0); 106 110 107 111 if (endp == linebuf || errno == ERANGE) ··· 127 123 enum cpufreq_string { 128 124 SCALING_DRIVER, 129 125 SCALING_GOVERNOR, 126 + ENERGY_PERFORMANCE_PREFERENCE, 130 127 MAX_CPUFREQ_STRING_FILES 131 128 }; 132 129 133 130 static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = { 134 131 [SCALING_DRIVER] = "scaling_driver", 135 132 [SCALING_GOVERNOR] = "scaling_governor", 133 + [ENERGY_PERFORMANCE_PREFERENCE] = "energy_performance_preference", 136 134 }; 137 135 138 136 ··· 207 201 unsigned long cpufreq_get_transition_latency(unsigned int cpu) 208 202 { 209 203 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY); 204 + } 205 + 206 + char *cpufreq_get_energy_performance_preference(unsigned int cpu) 207 + { 208 + return sysfs_cpufreq_get_one_string(cpu, ENERGY_PERFORMANCE_PREFERENCE); 209 + } 210 + 211 + void cpufreq_put_energy_performance_preference(char *ptr) 212 + { 213 + if (!ptr) 214 + return; 215 + free(ptr); 210 216 } 211 217 212 218 int cpufreq_get_hardware_limits(unsigned int cpu,
+8
tools/power/cpupower/lib/cpufreq.h
··· 68 68 unsigned long cpufreq_get_transition_latency(unsigned int cpu); 69 69 70 70 71 + /* determine energy performance preference 72 + * 73 + * returns NULL on failure, else the string that represents the energy performance 74 + * preference requested. 75 + */ 76 + char *cpufreq_get_energy_performance_preference(unsigned int cpu); 77 + void cpufreq_put_energy_performance_preference(char *ptr); 78 + 71 79 /* determine hardware CPU frequency limits 72 80 * 73 81 * These may be limited further by thermal, energy or other
+33 -3
tools/power/cpupower/utils/cpufreq-info.c
··· 120 120 } else 121 121 printf("%lu ns", duration); 122 122 } 123 - return; 124 123 } 125 124 126 125 static int get_boost_mode_x86(unsigned int cpu) ··· 254 255 255 256 static int get_freq_hardware(unsigned int cpu, unsigned int human) 256 257 { 257 - unsigned long freq = cpufreq_get_freq_hardware(cpu); 258 + unsigned long freq; 259 + 260 + if (cpupower_cpu_info.caps & CPUPOWER_CAP_APERF) 261 + return -EINVAL; 262 + 263 + freq = cpufreq_get_freq_hardware(cpu); 258 264 printf(_(" current CPU frequency: ")); 259 265 if (!freq) { 260 266 printf("Unable to call hardware\n"); ··· 422 418 return 0; 423 419 } 424 420 421 + /* --epp / -z */ 422 + 423 + static int get_epp(unsigned int cpu, bool interactive) 424 + { 425 + char *epp; 426 + 427 + epp = cpufreq_get_energy_performance_preference(cpu); 428 + if (!epp) 429 + return -EINVAL; 430 + if (interactive) 431 + printf(_(" energy performance preference: %s\n"), epp); 432 + 433 + cpufreq_put_energy_performance_preference(epp); 434 + 435 + return 0; 436 + } 437 + 425 438 /* --latency / -y */ 426 439 427 440 static int get_latency(unsigned int cpu, unsigned int human) 428 441 { 429 442 unsigned long latency = cpufreq_get_transition_latency(cpu); 443 + 444 + if (!get_epp(cpu, false)) 445 + return -EINVAL; 430 446 431 447 printf(_(" maximum transition latency: ")); 432 448 if (!latency || latency == UINT_MAX) { ··· 481 457 get_related_cpus(cpu); 482 458 get_affected_cpus(cpu); 483 459 get_latency(cpu, 1); 460 + get_epp(cpu, true); 484 461 get_hardware_limits(cpu, 1); 485 462 486 463 freqs = cpufreq_get_available_frequencies(cpu); ··· 522 497 {"human", no_argument, NULL, 'm'}, 523 498 {"no-rounding", no_argument, NULL, 'n'}, 524 499 {"performance", no_argument, NULL, 'c'}, 500 + {"epp", no_argument, NULL, 'z'}, 525 501 { }, 526 502 }; 527 503 ··· 536 510 int output_param = 0; 537 511 538 512 do { 539 - ret = getopt_long(argc, argv, "oefwldpgrasmybnc", info_opts, 513 + ret = getopt_long(argc, argv, "oefwldpgrasmybncz", info_opts, 540 514 NULL); 541 515 switch (ret) { 542 516 case '?': ··· 560 534 case 's': 561 535 case 'y': 562 536 case 'c': 537 + case 'z': 563 538 if (output_param) { 564 539 output_param = -1; 565 540 cont = 0; ··· 669 642 break; 670 643 case 'c': 671 644 ret = get_perf_cap(cpu); 645 + break; 646 + case 'z': 647 + ret = get_epp(cpu, true); 672 648 break; 673 649 } 674 650 if (ret)
+14 -4
tools/power/cpupower/utils/helpers/amd.c
··· 177 177 AMD_PSTATE_HIGHEST_PERF, 178 178 AMD_PSTATE_MAX_FREQ, 179 179 AMD_PSTATE_LOWEST_NONLINEAR_FREQ, 180 + AMD_PSTATE_HW_PREFCORE, 181 + AMD_PSTATE_PREFCORE_RANKING, 180 182 MAX_AMD_PSTATE_VALUE_READ_FILES, 181 183 }; 182 184 ··· 186 184 [AMD_PSTATE_HIGHEST_PERF] = "amd_pstate_highest_perf", 187 185 [AMD_PSTATE_MAX_FREQ] = "amd_pstate_max_freq", 188 186 [AMD_PSTATE_LOWEST_NONLINEAR_FREQ] = "amd_pstate_lowest_nonlinear_freq", 187 + [AMD_PSTATE_HW_PREFCORE] = "amd_pstate_hw_prefcore", 188 + [AMD_PSTATE_PREFCORE_RANKING] = "amd_pstate_prefcore_ranking", 189 189 }; 190 190 191 191 static unsigned long amd_pstate_get_data(unsigned int cpu, ··· 219 215 220 216 void amd_pstate_show_perf_and_freq(unsigned int cpu, int no_rounding) 221 217 { 222 - printf(_(" AMD PSTATE Highest Performance: %lu. Maximum Frequency: "), 218 + 219 + printf(_(" amd-pstate limits:\n")); 220 + printf(_(" Highest Performance: %lu. Maximum Frequency: "), 223 221 amd_pstate_get_data(cpu, AMD_PSTATE_HIGHEST_PERF)); 224 222 /* 225 223 * If boost isn't active, the cpuinfo_max doesn't indicate real max ··· 230 224 print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_MAX_FREQ), no_rounding); 231 225 printf(".\n"); 232 226 233 - printf(_(" AMD PSTATE Nominal Performance: %lu. Nominal Frequency: "), 227 + printf(_(" Nominal Performance: %lu. Nominal Frequency: "), 234 228 acpi_cppc_get_data(cpu, NOMINAL_PERF)); 235 229 print_speed(acpi_cppc_get_data(cpu, NOMINAL_FREQ) * 1000, 236 230 no_rounding); 237 231 printf(".\n"); 238 232 239 - printf(_(" AMD PSTATE Lowest Non-linear Performance: %lu. Lowest Non-linear Frequency: "), 233 + printf(_(" Lowest Non-linear Performance: %lu. Lowest Non-linear Frequency: "), 240 234 acpi_cppc_get_data(cpu, LOWEST_NONLINEAR_PERF)); 241 235 print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_LOWEST_NONLINEAR_FREQ), 242 236 no_rounding); 243 237 printf(".\n"); 244 238 245 - printf(_(" AMD PSTATE Lowest Performance: %lu. Lowest Frequency: "), 239 + printf(_(" Lowest Performance: %lu. Lowest Frequency: "), 246 240 acpi_cppc_get_data(cpu, LOWEST_PERF)); 247 241 print_speed(acpi_cppc_get_data(cpu, LOWEST_FREQ) * 1000, no_rounding); 248 242 printf(".\n"); 243 + 244 + printf(_(" Preferred Core Support: %lu. Preferred Core Ranking: %lu.\n"), 245 + amd_pstate_get_data(cpu, AMD_PSTATE_HW_PREFCORE), 246 + amd_pstate_get_data(cpu, AMD_PSTATE_PREFCORE_RANKING)); 249 247 } 250 248 251 249 /* AMD P-State Helper Functions ************************************/
+2 -2
tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c
··· 117 117 118 118 for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) { 119 119 for (cpu = 0; cpu < cpu_count; cpu++) { 120 - hsw_ext_get_count(num, &val, cpu); 120 + is_valid[cpu] = !hsw_ext_get_count(num, &val, cpu); 121 121 previous_count[num][cpu] = val; 122 122 } 123 123 } ··· 134 134 135 135 for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) { 136 136 for (cpu = 0; cpu < cpu_count; cpu++) { 137 - is_valid[cpu] = !hsw_ext_get_count(num, &val, cpu); 137 + is_valid[cpu] |= !hsw_ext_get_count(num, &val, cpu); 138 138 current_count[num][cpu] = val; 139 139 } 140 140 }
+10 -7
tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
··· 33 33 unsigned int cpu); 34 34 static int mperf_get_count_freq(unsigned int id, unsigned long long *count, 35 35 unsigned int cpu); 36 - static struct timespec time_start, time_end; 36 + static struct timespec *time_start, *time_end; 37 37 38 38 static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = { 39 39 { ··· 148 148 ret = get_aperf_mperf(cpu, &aval, &mval); 149 149 aperf_current_count[cpu] = aval; 150 150 mperf_current_count[cpu] = mval; 151 - is_valid[cpu] = !ret; 151 + is_valid[cpu] |= !ret; 152 152 153 153 return 0; 154 154 } ··· 174 174 dprint("%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n", 175 175 mperf_cstates[id].name, mperf_diff, tsc_diff); 176 176 } else if (max_freq_mode == MAX_FREQ_SYSFS) { 177 - timediff = max_frequency * timespec_diff_us(time_start, time_end); 177 + timediff = max_frequency * timespec_diff_us(time_start[cpu], time_end[cpu]); 178 178 *percent = 100.0 * mperf_diff / timediff; 179 179 dprint("%s: MAXFREQ - mperf_diff: %llu, time_diff: %llu\n", 180 180 mperf_cstates[id].name, mperf_diff, timediff); ··· 207 207 if (max_freq_mode == MAX_FREQ_TSC_REF) { 208 208 /* Calculate max_freq from TSC count */ 209 209 tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu]; 210 - time_diff = timespec_diff_us(time_start, time_end); 210 + time_diff = timespec_diff_us(time_start[cpu], time_end[cpu]); 211 211 max_frequency = tsc_diff / time_diff; 212 212 } 213 213 ··· 226 226 { 227 227 int cpu; 228 228 229 - clock_gettime(CLOCK_REALTIME, &time_start); 230 - 231 229 for (cpu = 0; cpu < cpu_count; cpu++) { 230 + clock_gettime(CLOCK_REALTIME, &time_start[cpu]); 232 231 mperf_get_tsc(&tsc_at_measure_start[cpu]); 233 232 mperf_init_stats(cpu); 234 233 } ··· 242 243 for (cpu = 0; cpu < cpu_count; cpu++) { 243 244 mperf_measure_stats(cpu); 244 245 mperf_get_tsc(&tsc_at_measure_end[cpu]); 246 + clock_gettime(CLOCK_REALTIME, &time_end[cpu]); 245 247 } 246 248 247 - clock_gettime(CLOCK_REALTIME, &time_end); 248 249 return 0; 249 250 } 250 251 ··· 348 349 aperf_current_count = calloc(cpu_count, sizeof(unsigned long long)); 349 350 tsc_at_measure_start = calloc(cpu_count, sizeof(unsigned long long)); 350 351 tsc_at_measure_end = calloc(cpu_count, sizeof(unsigned long long)); 352 + time_start = calloc(cpu_count, sizeof(struct timespec)); 353 + time_end = calloc(cpu_count, sizeof(struct timespec)); 351 354 mperf_monitor.name_len = strlen(mperf_monitor.name); 352 355 return &mperf_monitor; 353 356 } ··· 362 361 free(aperf_current_count); 363 362 free(tsc_at_measure_start); 364 363 free(tsc_at_measure_end); 364 + free(time_start); 365 + free(time_end); 365 366 free(is_valid); 366 367 } 367 368
+1 -1
tools/power/cpupower/utils/idle_monitor/nhm_idle.c
··· 151 151 152 152 for (num = 0; num < NHM_CSTATE_COUNT; num++) { 153 153 for (cpu = 0; cpu < cpu_count; cpu++) { 154 - is_valid[cpu] = !nhm_get_count(num, &val, cpu); 154 + is_valid[cpu] |= !nhm_get_count(num, &val, cpu); 155 155 current_count[num][cpu] = val; 156 156 } 157 157 }
+2 -2
tools/power/cpupower/utils/idle_monitor/snb_idle.c
··· 115 115 116 116 for (num = 0; num < SNB_CSTATE_COUNT; num++) { 117 117 for (cpu = 0; cpu < cpu_count; cpu++) { 118 - snb_get_count(num, &val, cpu); 118 + is_valid[cpu] = !snb_get_count(num, &val, cpu); 119 119 previous_count[num][cpu] = val; 120 120 } 121 121 } ··· 132 132 133 133 for (num = 0; num < SNB_CSTATE_COUNT; num++) { 134 134 for (cpu = 0; cpu < cpu_count; cpu++) { 135 - is_valid[cpu] = !snb_get_count(num, &val, cpu); 135 + is_valid[cpu] |= !snb_get_count(num, &val, cpu); 136 136 current_count[num][cpu] = val; 137 137 } 138 138 }
+2
tools/testing/selftests/cpufreq/.gitignore
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + cpufreq_selftest.*
+1
tools/testing/selftests/cpufreq/Makefile
··· 3 3 4 4 TEST_PROGS := main.sh 5 5 TEST_FILES := cpu.sh cpufreq.sh governor.sh module.sh special-tests.sh 6 + EXTRA_CLEAN := cpufreq_selftest.dmesg_cpufreq.txt cpufreq_selftest.dmesg_full.txt cpufreq_selftest.txt 6 7 7 8 include ../lib.mk 8 9