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

Pull more power management updates from Rafael Wysocki:
"These add support for new hardware (ap807 and AM62A7), fix several
issues in cpufreq drivers and in the operating performance points
(OPP) framework, fix up intel_idle after recent changes and add
documentation.

Specifics:

- Add missing __init annotation to one function in the intel_idle
drvier (Rafael Wysocki)

- Make intel_pstate use a correct scaling factor when mapping HWP
performance levels to frequency values on hybrid-capable systems
with disabled E-cores (Srinivas Pandruvada)

- Fix Kconfig dependencies of the cpufreq-dt-platform driver (Viresh
Kumar)

- Add support to build cpufreq-dt-platdev as a module (Zhipeng Wang)

- Don't allocate Sparc's cpufreq_driver dynamically (Viresh Kumar)

- Add support for TI's AM62A7 platform (Vibhore Vardhan)

- Add support for Armada's ap807 platform (Russell King (Oracle))

- Add support for StarFive JH7110 SoC (Mason Huo)

- Fix voltage selection for Mediatek Socs (Daniel Golle)

- Fix error handling in Tegra's cpufreq driver (Christophe JAILLET)

- Document Qualcomm's IPQ8074 in DT bindings (Robert Marko)

- Don't warn for disabling a non-existing frequency for imx6q cpufreq
driver (Christoph Niedermaier)

- Use dev_err_probe() in Qualcomm's cpufreq driver (Andrew Halaney)

- Simplify performance state related logic in the OPP core (Viresh
Kumar)

- Fix use-after-free and improve locking around lazy_opp_tables
(Viresh Kumar, Stephan Gerhold)

- Minor cleanups - using dev_err_probe() and rate-limiting debug
messages (Andrew Halaney, Adrián Larumbe)"

* tag 'pm-6.5-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (23 commits)
cpufreq: intel_pstate: Fix scaling for hybrid-capable systems with disabled E-cores
cpufreq: Make CONFIG_CPUFREQ_DT_PLATDEV depend on OF
intel_idle: Add __init annotation to matchup_vm_state_with_baremetal()
OPP: Properly propagate error along when failing to get icc_path
OPP: Use dev_err_probe() when failing to get icc_path
cpufreq: qcom-cpufreq-hw: Use dev_err_probe() when failing to get icc paths
cpufreq: mediatek: correct voltages for MT7622 and MT7623
cpufreq: armada-8k: add ap807 support
OPP: Simplify the over-designed pstate <-> level dance
OPP: pstate is only valid for genpd OPP tables
OPP: don't drop performance constraint on OPP table removal
OPP: Protect `lazy_opp_tables` list with `opp_table_lock`
OPP: Staticize `lazy_opp_tables` in of.c
cpufreq: dt-platdev: Support building as module
opp: Fix use-after-free in lazy_opp_tables after probe deferral
dt-bindings: cpufreq: qcom-cpufreq-nvmem: document IPQ8074
cpufreq: dt-platdev: Blacklist ti,am62a7 SoC
cpufreq: ti-cpufreq: Add support for AM62A7
OPP: rate-limit debug messages when no change in OPP is required
cpufreq: imx6q: don't warn for disabling a non-existing frequency
...

+180 -164
+1
Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml
··· 28 28 - qcom,apq8064 29 29 - qcom,apq8096 30 30 - qcom,ipq8064 31 + - qcom,ipq8074 31 32 - qcom,msm8939 32 33 - qcom,msm8960 33 34 - qcom,msm8974
+2 -1
drivers/cpufreq/Kconfig
··· 218 218 If in doubt, say N. 219 219 220 220 config CPUFREQ_DT_PLATDEV 221 - bool 221 + tristate "Generic DT based cpufreq platdev driver" 222 + depends on OF 222 223 help 223 224 This adds a generic DT based cpufreq platdev driver for frequency 224 225 management. This creates a 'cpufreq-dt' platform device, on the
+9 -7
drivers/cpufreq/armada-8k-cpufreq.c
··· 21 21 #include <linux/pm_opp.h> 22 22 #include <linux/slab.h> 23 23 24 + static const struct of_device_id __maybe_unused armada_8k_cpufreq_of_match[] = { 25 + { .compatible = "marvell,ap806-cpu-clock" }, 26 + { .compatible = "marvell,ap807-cpu-clock" }, 27 + { }, 28 + }; 29 + MODULE_DEVICE_TABLE(of, armada_8k_cpufreq_of_match); 30 + 24 31 /* 25 32 * Setup the opps list with the divider for the max frequency, that 26 33 * will be filled at runtime. ··· 134 127 struct device_node *node; 135 128 struct cpumask cpus; 136 129 137 - node = of_find_compatible_node(NULL, NULL, "marvell,ap806-cpu-clock"); 130 + node = of_find_matching_node_and_match(NULL, armada_8k_cpufreq_of_match, 131 + NULL); 138 132 if (!node || !of_device_is_available(node)) { 139 133 of_node_put(node); 140 134 return -ENODEV; ··· 211 203 armada_8k_cpufreq_free_table(freq_tables); 212 204 } 213 205 module_exit(armada_8k_cpufreq_exit); 214 - 215 - static const struct of_device_id __maybe_unused armada_8k_cpufreq_of_match[] = { 216 - { .compatible = "marvell,ap806-cpu-clock" }, 217 - { }, 218 - }; 219 - MODULE_DEVICE_TABLE(of, armada_8k_cpufreq_of_match); 220 206 221 207 MODULE_AUTHOR("Gregory Clement <gregory.clement@bootlin.com>"); 222 208 MODULE_DESCRIPTION("Armada 8K cpufreq driver");
+5
drivers/cpufreq/cpufreq-dt-platdev.c
··· 5 5 */ 6 6 7 7 #include <linux/err.h> 8 + #include <linux/module.h> 8 9 #include <linux/of.h> 9 10 #include <linux/platform_device.h> 10 11 ··· 85 84 { .compatible = "st-ericsson,u8540", }, 86 85 { .compatible = "st-ericsson,u9500", }, 87 86 { .compatible = "st-ericsson,u9540", }, 87 + 88 + { .compatible = "starfive,jh7110", }, 88 89 89 90 { .compatible = "ti,omap2", }, 90 91 { .compatible = "ti,omap4", }, ··· 168 165 { .compatible = "ti,dra7", }, 169 166 { .compatible = "ti,omap3", }, 170 167 { .compatible = "ti,am625", }, 168 + { .compatible = "ti,am62a7", }, 171 169 172 170 { .compatible = "qcom,ipq8064", }, 173 171 { .compatible = "qcom,apq8064", }, ··· 218 214 sizeof(struct cpufreq_dt_platform_data))); 219 215 } 220 216 core_initcall(cpufreq_dt_platdev_init); 217 + MODULE_LICENSE("GPL");
+16 -14
drivers/cpufreq/imx6q-cpufreq.c
··· 209 209 .suspend = cpufreq_generic_suspend, 210 210 }; 211 211 212 + static void imx6x_disable_freq_in_opp(struct device *dev, unsigned long freq) 213 + { 214 + int ret = dev_pm_opp_disable(dev, freq); 215 + 216 + if (ret < 0 && ret != -ENODEV) 217 + dev_warn(dev, "failed to disable %ldMHz OPP\n", freq / 1000000); 218 + } 219 + 212 220 #define OCOTP_CFG3 0x440 213 221 #define OCOTP_CFG3_SPEED_SHIFT 16 214 222 #define OCOTP_CFG3_SPEED_1P2GHZ 0x3 ··· 262 254 val &= 0x3; 263 255 264 256 if (val < OCOTP_CFG3_SPEED_996MHZ) 265 - if (dev_pm_opp_disable(dev, 996000000)) 266 - dev_warn(dev, "failed to disable 996MHz OPP\n"); 257 + imx6x_disable_freq_in_opp(dev, 996000000); 267 258 268 259 if (of_machine_is_compatible("fsl,imx6q") || 269 260 of_machine_is_compatible("fsl,imx6qp")) { 270 261 if (val != OCOTP_CFG3_SPEED_852MHZ) 271 - if (dev_pm_opp_disable(dev, 852000000)) 272 - dev_warn(dev, "failed to disable 852MHz OPP\n"); 262 + imx6x_disable_freq_in_opp(dev, 852000000); 263 + 273 264 if (val != OCOTP_CFG3_SPEED_1P2GHZ) 274 - if (dev_pm_opp_disable(dev, 1200000000)) 275 - dev_warn(dev, "failed to disable 1.2GHz OPP\n"); 265 + imx6x_disable_freq_in_opp(dev, 1200000000); 276 266 } 277 267 278 268 return 0; ··· 322 316 val >>= OCOTP_CFG3_SPEED_SHIFT; 323 317 val &= 0x3; 324 318 325 - if (of_machine_is_compatible("fsl,imx6ul")) { 319 + if (of_machine_is_compatible("fsl,imx6ul")) 326 320 if (val != OCOTP_CFG3_6UL_SPEED_696MHZ) 327 - if (dev_pm_opp_disable(dev, 696000000)) 328 - dev_warn(dev, "failed to disable 696MHz OPP\n"); 329 - } 321 + imx6x_disable_freq_in_opp(dev, 696000000); 330 322 331 323 if (of_machine_is_compatible("fsl,imx6ull")) { 332 324 if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ) 333 - if (dev_pm_opp_disable(dev, 792000000)) 334 - dev_warn(dev, "failed to disable 792MHz OPP\n"); 325 + imx6x_disable_freq_in_opp(dev, 792000000); 335 326 336 327 if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ) 337 - if (dev_pm_opp_disable(dev, 900000000)) 338 - dev_warn(dev, "failed to disable 900MHz OPP\n"); 328 + imx6x_disable_freq_in_opp(dev, 900000000); 339 329 } 340 330 341 331 return ret;
+48 -10
drivers/cpufreq/intel_pstate.c
··· 302 302 303 303 static struct cpufreq_driver *intel_pstate_driver __read_mostly; 304 304 305 + #define HYBRID_SCALING_FACTOR 78741 306 + 307 + static inline int core_get_scaling(void) 308 + { 309 + return 100000; 310 + } 311 + 305 312 #ifdef CONFIG_ACPI 306 313 static bool acpi_ppc; 307 314 #endif ··· 407 400 408 401 return cppc_perf.nominal_perf; 409 402 } 403 + 404 + static int intel_pstate_cppc_get_scaling(int cpu) 405 + { 406 + struct cppc_perf_caps cppc_perf; 407 + int ret; 408 + 409 + ret = cppc_get_perf_caps(cpu, &cppc_perf); 410 + 411 + /* 412 + * If the nominal frequency and the nominal performance are not 413 + * zero and the ratio between them is not 100, return the hybrid 414 + * scaling factor. 415 + */ 416 + if (!ret && cppc_perf.nominal_perf && cppc_perf.nominal_freq && 417 + cppc_perf.nominal_perf * 100 != cppc_perf.nominal_freq) 418 + return HYBRID_SCALING_FACTOR; 419 + 420 + return core_get_scaling(); 421 + } 422 + 410 423 #else /* CONFIG_ACPI_CPPC_LIB */ 411 424 static inline void intel_pstate_set_itmt_prio(int cpu) 412 425 { ··· 518 491 static inline int intel_pstate_get_cppc_guaranteed(int cpu) 519 492 { 520 493 return -ENOTSUPP; 494 + } 495 + 496 + static int intel_pstate_cppc_get_scaling(int cpu) 497 + { 498 + return core_get_scaling(); 521 499 } 522 500 #endif /* CONFIG_ACPI_CPPC_LIB */ 523 501 ··· 1929 1897 return ret; 1930 1898 } 1931 1899 1932 - static inline int core_get_scaling(void) 1933 - { 1934 - return 100000; 1935 - } 1936 - 1937 1900 static u64 core_get_val(struct cpudata *cpudata, int pstate) 1938 1901 { 1939 1902 u64 val; ··· 1965 1938 *cpu_type = get_this_hybrid_cpu_type(); 1966 1939 } 1967 1940 1968 - static int hybrid_get_cpu_scaling(int cpu) 1941 + static int hwp_get_cpu_scaling(int cpu) 1969 1942 { 1970 1943 u8 cpu_type = 0; 1971 1944 1972 1945 smp_call_function_single(cpu, hybrid_get_type, &cpu_type, 1); 1973 1946 /* P-cores have a smaller perf level-to-freqency scaling factor. */ 1974 1947 if (cpu_type == 0x40) 1975 - return 78741; 1948 + return HYBRID_SCALING_FACTOR; 1976 1949 1977 - return core_get_scaling(); 1950 + /* Use default core scaling for E-cores */ 1951 + if (cpu_type == 0x20) 1952 + return core_get_scaling(); 1953 + 1954 + /* 1955 + * If reached here, this system is either non-hybrid (like Tiger 1956 + * Lake) or hybrid-capable (like Alder Lake or Raptor Lake) with 1957 + * no E cores (in which case CPUID for hybrid support is 0). 1958 + * 1959 + * The CPPC nominal_frequency field is 0 for non-hybrid systems, 1960 + * so the default core scaling will be used for them. 1961 + */ 1962 + return intel_pstate_cppc_get_scaling(cpu); 1978 1963 } 1979 1964 1980 1965 static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) ··· 3434 3395 if (!default_driver) 3435 3396 default_driver = &intel_pstate; 3436 3397 3437 - if (boot_cpu_has(X86_FEATURE_HYBRID_CPU)) 3438 - pstate_funcs.get_cpu_scaling = hybrid_get_cpu_scaling; 3398 + pstate_funcs.get_cpu_scaling = hwp_get_cpu_scaling; 3439 3399 3440 3400 goto hwp_cpu_matched; 3441 3401 }
+10 -3
drivers/cpufreq/mediatek-cpufreq.c
··· 696 696 static const struct mtk_cpufreq_platform_data mt7622_platform_data = { 697 697 .min_volt_shift = 100000, 698 698 .max_volt_shift = 200000, 699 - .proc_max_volt = 1360000, 699 + .proc_max_volt = 1350000, 700 700 .sram_min_volt = 0, 701 - .sram_max_volt = 1360000, 701 + .sram_max_volt = 1350000, 702 + .ccifreq_supported = false, 703 + }; 704 + 705 + static const struct mtk_cpufreq_platform_data mt7623_platform_data = { 706 + .min_volt_shift = 100000, 707 + .max_volt_shift = 200000, 708 + .proc_max_volt = 1300000, 702 709 .ccifreq_supported = false, 703 710 }; 704 711 ··· 741 734 { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, 742 735 { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, 743 736 { .compatible = "mediatek,mt7622", .data = &mt7622_platform_data }, 744 - { .compatible = "mediatek,mt7623", .data = &mt7622_platform_data }, 737 + { .compatible = "mediatek,mt7623", .data = &mt7623_platform_data }, 745 738 { .compatible = "mediatek,mt8167", .data = &mt8516_platform_data }, 746 739 { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, 747 740 { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
+1 -1
drivers/cpufreq/qcom-cpufreq-hw.c
··· 661 661 662 662 ret = dev_pm_opp_of_find_icc_paths(cpu_dev, NULL); 663 663 if (ret) 664 - return ret; 664 + return dev_err_probe(dev, ret, "Failed to find icc paths\n"); 665 665 666 666 for (num_domains = 0; num_domains < MAX_FREQ_DOMAINS; num_domains++) 667 667 if (!platform_get_resource(pdev, IORESOURCE_MEM, num_domains))
+17 -41
drivers/cpufreq/sparc-us2e-cpufreq.c
··· 20 20 #include <asm/asi.h> 21 21 #include <asm/timer.h> 22 22 23 - static struct cpufreq_driver *cpufreq_us2e_driver; 24 - 25 23 struct us2e_freq_percpu_info { 26 24 struct cpufreq_frequency_table table[6]; 27 25 }; ··· 298 300 299 301 static int us2e_freq_cpu_exit(struct cpufreq_policy *policy) 300 302 { 301 - if (cpufreq_us2e_driver) 302 - us2e_freq_target(policy, 0); 303 - 303 + us2e_freq_target(policy, 0); 304 304 return 0; 305 305 } 306 + 307 + static struct cpufreq_driver cpufreq_us2e_driver = { 308 + .name = "UltraSPARC-IIe", 309 + .init = us2e_freq_cpu_init, 310 + .verify = cpufreq_generic_frequency_table_verify, 311 + .target_index = us2e_freq_target, 312 + .get = us2e_freq_get, 313 + .exit = us2e_freq_cpu_exit, 314 + }; 306 315 307 316 static int __init us2e_freq_init(void) 308 317 { ··· 324 319 impl = ((ver >> 32) & 0xffff); 325 320 326 321 if (manuf == 0x17 && impl == 0x13) { 327 - struct cpufreq_driver *driver; 328 - 329 - ret = -ENOMEM; 330 - driver = kzalloc(sizeof(*driver), GFP_KERNEL); 331 - if (!driver) 332 - goto err_out; 333 - 334 - us2e_freq_table = kzalloc((NR_CPUS * sizeof(*us2e_freq_table)), 335 - GFP_KERNEL); 322 + us2e_freq_table = kzalloc(NR_CPUS * sizeof(*us2e_freq_table), 323 + GFP_KERNEL); 336 324 if (!us2e_freq_table) 337 - goto err_out; 325 + return -ENOMEM; 338 326 339 - driver->init = us2e_freq_cpu_init; 340 - driver->verify = cpufreq_generic_frequency_table_verify; 341 - driver->target_index = us2e_freq_target; 342 - driver->get = us2e_freq_get; 343 - driver->exit = us2e_freq_cpu_exit; 344 - strcpy(driver->name, "UltraSPARC-IIe"); 345 - 346 - cpufreq_us2e_driver = driver; 347 - ret = cpufreq_register_driver(driver); 327 + ret = cpufreq_register_driver(&cpufreq_us2e_driver); 348 328 if (ret) 349 - goto err_out; 329 + kfree(us2e_freq_table); 350 330 351 - return 0; 352 - 353 - err_out: 354 - if (driver) { 355 - kfree(driver); 356 - cpufreq_us2e_driver = NULL; 357 - } 358 - kfree(us2e_freq_table); 359 - us2e_freq_table = NULL; 360 331 return ret; 361 332 } 362 333 ··· 341 360 342 361 static void __exit us2e_freq_exit(void) 343 362 { 344 - if (cpufreq_us2e_driver) { 345 - cpufreq_unregister_driver(cpufreq_us2e_driver); 346 - kfree(cpufreq_us2e_driver); 347 - cpufreq_us2e_driver = NULL; 348 - kfree(us2e_freq_table); 349 - us2e_freq_table = NULL; 350 - } 363 + cpufreq_unregister_driver(&cpufreq_us2e_driver); 364 + kfree(us2e_freq_table); 351 365 } 352 366 353 367 MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+17 -41
drivers/cpufreq/sparc-us3-cpufreq.c
··· 19 19 #include <asm/head.h> 20 20 #include <asm/timer.h> 21 21 22 - static struct cpufreq_driver *cpufreq_us3_driver; 23 - 24 22 struct us3_freq_percpu_info { 25 23 struct cpufreq_frequency_table table[4]; 26 24 }; ··· 142 144 143 145 static int us3_freq_cpu_exit(struct cpufreq_policy *policy) 144 146 { 145 - if (cpufreq_us3_driver) 146 - us3_freq_target(policy, 0); 147 - 147 + us3_freq_target(policy, 0); 148 148 return 0; 149 149 } 150 + 151 + static struct cpufreq_driver cpufreq_us3_driver = { 152 + .name = "UltraSPARC-III", 153 + .init = us3_freq_cpu_init, 154 + .verify = cpufreq_generic_frequency_table_verify, 155 + .target_index = us3_freq_target, 156 + .get = us3_freq_get, 157 + .exit = us3_freq_cpu_exit, 158 + }; 150 159 151 160 static int __init us3_freq_init(void) 152 161 { ··· 172 167 impl == CHEETAH_PLUS_IMPL || 173 168 impl == JAGUAR_IMPL || 174 169 impl == PANTHER_IMPL)) { 175 - struct cpufreq_driver *driver; 176 - 177 - ret = -ENOMEM; 178 - driver = kzalloc(sizeof(*driver), GFP_KERNEL); 179 - if (!driver) 180 - goto err_out; 181 - 182 - us3_freq_table = kzalloc((NR_CPUS * sizeof(*us3_freq_table)), 183 - GFP_KERNEL); 170 + us3_freq_table = kzalloc(NR_CPUS * sizeof(*us3_freq_table), 171 + GFP_KERNEL); 184 172 if (!us3_freq_table) 185 - goto err_out; 173 + return -ENOMEM; 186 174 187 - driver->init = us3_freq_cpu_init; 188 - driver->verify = cpufreq_generic_frequency_table_verify; 189 - driver->target_index = us3_freq_target; 190 - driver->get = us3_freq_get; 191 - driver->exit = us3_freq_cpu_exit; 192 - strcpy(driver->name, "UltraSPARC-III"); 193 - 194 - cpufreq_us3_driver = driver; 195 - ret = cpufreq_register_driver(driver); 175 + ret = cpufreq_register_driver(&cpufreq_us3_driver); 196 176 if (ret) 197 - goto err_out; 177 + kfree(us3_freq_table); 198 178 199 - return 0; 200 - 201 - err_out: 202 - if (driver) { 203 - kfree(driver); 204 - cpufreq_us3_driver = NULL; 205 - } 206 - kfree(us3_freq_table); 207 - us3_freq_table = NULL; 208 179 return ret; 209 180 } 210 181 ··· 189 208 190 209 static void __exit us3_freq_exit(void) 191 210 { 192 - if (cpufreq_us3_driver) { 193 - cpufreq_unregister_driver(cpufreq_us3_driver); 194 - kfree(cpufreq_us3_driver); 195 - cpufreq_us3_driver = NULL; 196 - kfree(us3_freq_table); 197 - us3_freq_table = NULL; 198 - } 211 + cpufreq_unregister_driver(&cpufreq_us3_driver); 212 + kfree(us3_freq_table); 199 213 } 200 214 201 215 MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+4 -2
drivers/cpufreq/tegra194-cpufreq.c
··· 686 686 687 687 /* Check for optional OPPv2 and interconnect paths on CPU0 to enable ICC scaling */ 688 688 cpu_dev = get_cpu_device(0); 689 - if (!cpu_dev) 690 - return -EPROBE_DEFER; 689 + if (!cpu_dev) { 690 + err = -EPROBE_DEFER; 691 + goto err_free_res; 692 + } 691 693 692 694 if (dev_pm_opp_of_get_opp_desc_node(cpu_dev)) { 693 695 err = dev_pm_opp_of_find_icc_paths(cpu_dev, NULL);
+1
drivers/cpufreq/ti-cpufreq.c
··· 337 337 { .compatible = "ti,omap34xx", .data = &omap34xx_soc_data, }, 338 338 { .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, }, 339 339 { .compatible = "ti,am625", .data = &am625_soc_data, }, 340 + { .compatible = "ti,am62a7", .data = &am625_soc_data, }, 340 341 /* legacy */ 341 342 { .compatible = "ti,omap3430", .data = &omap34xx_soc_data, }, 342 343 { .compatible = "ti,omap3630", .data = &omap36xx_soc_data, },
+1 -1
drivers/idle/intel_idle.c
··· 2147 2147 * All our short idle states are dominated by vmexit/vmenter latencies, 2148 2148 * not the underlying hardware latencies so we keep our values for these. 2149 2149 */ 2150 - static void matchup_vm_state_with_baremetal(void) 2150 + static void __init matchup_vm_state_with_baremetal(void) 2151 2151 { 2152 2152 int cstate; 2153 2153
+25 -19
drivers/opp/core.c
··· 29 29 */ 30 30 LIST_HEAD(opp_tables); 31 31 32 - /* OPP tables with uninitialized required OPPs */ 33 - LIST_HEAD(lazy_opp_tables); 34 - 35 32 /* Lock to allow exclusive modification to the device and opp lists */ 36 33 DEFINE_MUTEX(opp_table_lock); 37 34 /* Flag indicating that opp_tables list is being updated at the moment */ ··· 227 230 unsigned int dev_pm_opp_get_required_pstate(struct dev_pm_opp *opp, 228 231 unsigned int index) 229 232 { 233 + struct opp_table *opp_table = opp->opp_table; 234 + 230 235 if (IS_ERR_OR_NULL(opp) || !opp->available || 231 - index >= opp->opp_table->required_opp_count) { 236 + index >= opp_table->required_opp_count) { 232 237 pr_err("%s: Invalid parameters\n", __func__); 233 238 return 0; 234 239 } 235 240 236 241 /* required-opps not fully initialized yet */ 237 - if (lazy_linking_pending(opp->opp_table)) 242 + if (lazy_linking_pending(opp_table)) 238 243 return 0; 239 244 240 - return opp->required_opps[index]->pstate; 245 + /* The required OPP table must belong to a genpd */ 246 + if (unlikely(!opp_table->required_opp_tables[index]->is_genpd)) { 247 + pr_err("%s: Performance state is only valid for genpds.\n", __func__); 248 + return 0; 249 + } 250 + 251 + return opp->required_opps[index]->level; 241 252 } 242 253 EXPORT_SYMBOL_GPL(dev_pm_opp_get_required_pstate); 243 254 ··· 943 938 static int _set_performance_state(struct device *dev, struct device *pd_dev, 944 939 struct dev_pm_opp *opp, int i) 945 940 { 946 - unsigned int pstate = likely(opp) ? opp->required_opps[i]->pstate : 0; 941 + unsigned int pstate = likely(opp) ? opp->required_opps[i]->level: 0; 947 942 int ret; 948 943 949 944 if (!pd_dev) ··· 1096 1091 1097 1092 /* Return early if nothing to do */ 1098 1093 if (!forced && old_opp == opp && opp_table->enabled) { 1099 - dev_dbg(dev, "%s: OPPs are same, nothing to do\n", __func__); 1094 + dev_dbg_ratelimited(dev, "%s: OPPs are same, nothing to do\n", __func__); 1100 1095 return 0; 1101 1096 } 1102 1097 ··· 1363 1358 return opp_table; 1364 1359 1365 1360 remove_opp_dev: 1361 + _of_clear_opp_table(opp_table); 1366 1362 _remove_opp_dev(opp_dev, opp_table); 1363 + mutex_destroy(&opp_table->genpd_virt_dev_lock); 1364 + mutex_destroy(&opp_table->lock); 1367 1365 err: 1368 1366 kfree(opp_table); 1369 1367 return ERR_PTR(ret); ··· 1530 1522 1531 1523 WARN_ON(!list_empty(&opp_table->opp_list)); 1532 1524 1533 - list_for_each_entry_safe(opp_dev, temp, &opp_table->dev_list, node) { 1534 - /* 1535 - * The OPP table is getting removed, drop the performance state 1536 - * constraints. 1537 - */ 1538 - if (opp_table->genpd_performance_state) 1539 - dev_pm_genpd_set_performance_state((struct device *)(opp_dev->dev), 0); 1540 - 1525 + list_for_each_entry_safe(opp_dev, temp, &opp_table->dev_list, node) 1541 1526 _remove_opp_dev(opp_dev, opp_table); 1542 - } 1543 1527 1544 1528 mutex_destroy(&opp_table->genpd_virt_dev_lock); 1545 1529 mutex_destroy(&opp_table->lock); ··· 2704 2704 if (!src_table || !src_table->required_opp_count) 2705 2705 return pstate; 2706 2706 2707 + /* Both OPP tables must belong to genpds */ 2708 + if (unlikely(!src_table->is_genpd || !dst_table->is_genpd)) { 2709 + pr_err("%s: Performance state is only valid for genpds.\n", __func__); 2710 + return -EINVAL; 2711 + } 2712 + 2707 2713 /* required-opps not fully initialized yet */ 2708 2714 if (lazy_linking_pending(src_table)) 2709 2715 return -EBUSY; ··· 2728 2722 mutex_lock(&src_table->lock); 2729 2723 2730 2724 list_for_each_entry(opp, &src_table->opp_list, node) { 2731 - if (opp->pstate == pstate) { 2732 - dest_pstate = opp->required_opps[i]->pstate; 2725 + if (opp->level == pstate) { 2726 + dest_pstate = opp->required_opps[i]->level; 2733 2727 goto unlock; 2734 2728 } 2735 2729 }
-1
drivers/opp/debugfs.c
··· 152 152 debugfs_create_bool("dynamic", S_IRUGO, d, &opp->dynamic); 153 153 debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo); 154 154 debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend); 155 - debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate); 156 155 debugfs_create_u32("level", S_IRUGO, d, &opp->level); 157 156 debugfs_create_ulong("clock_latency_ns", S_IRUGO, d, 158 157 &opp->clock_latency_ns);
+22 -18
drivers/opp/of.c
··· 21 21 22 22 #include "opp.h" 23 23 24 + /* OPP tables with uninitialized required OPPs, protected by opp_table_lock */ 25 + static LIST_HEAD(lazy_opp_tables); 26 + 24 27 /* 25 28 * Returns opp descriptor node for a device node, caller must 26 29 * do of_node_put(). ··· 148 145 149 146 opp_table->required_opp_count = 0; 150 147 opp_table->required_opp_tables = NULL; 148 + 149 + mutex_lock(&opp_table_lock); 151 150 list_del(&opp_table->lazy); 151 + mutex_unlock(&opp_table_lock); 152 152 } 153 153 154 154 /* ··· 200 194 } 201 195 202 196 /* Let's do the linking later on */ 203 - if (lazy) 197 + if (lazy) { 198 + /* 199 + * The OPP table is not held while allocating the table, take it 200 + * now to avoid corruption to the lazy_opp_tables list. 201 + */ 202 + mutex_lock(&opp_table_lock); 204 203 list_add(&opp_table->lazy, &lazy_opp_tables); 204 + mutex_unlock(&opp_table_lock); 205 + } 205 206 else 206 207 _update_set_required_opps(opp_table); 207 208 ··· 513 500 for (i = 0; i < num_paths; i++) { 514 501 paths[i] = of_icc_get_by_index(dev, i); 515 502 if (IS_ERR(paths[i])) { 516 - ret = PTR_ERR(paths[i]); 517 - if (ret != -EPROBE_DEFER) { 518 - dev_err(dev, "%s: Unable to get path%d: %d\n", 519 - __func__, i, ret); 520 - } 503 + ret = dev_err_probe(dev, PTR_ERR(paths[i]), "%s: Unable to get path%d\n", __func__, i); 521 504 goto err; 522 505 } 523 506 } ··· 941 932 if (ret) 942 933 goto free_required_opps; 943 934 944 - if (opp_table->is_genpd) 945 - new_opp->pstate = pm_genpd_opp_to_performance_state(dev, new_opp); 946 - 947 935 ret = _opp_add(dev, new_opp, opp_table); 948 936 if (ret) { 949 937 /* Don't return error for duplicate OPPs */ ··· 1025 1019 dev_err(dev, "%s: no supported OPPs", __func__); 1026 1020 ret = -ENOENT; 1027 1021 goto remove_static_opp; 1028 - } 1029 - 1030 - list_for_each_entry(opp, &opp_table->opp_list, node) { 1031 - /* Any non-zero performance state would enable the feature */ 1032 - if (opp->pstate) { 1033 - opp_table->genpd_performance_state = true; 1034 - break; 1035 - } 1036 1022 } 1037 1023 1038 1024 lazy_link_required_opp_table(opp_table); ··· 1385 1387 goto put_required_np; 1386 1388 } 1387 1389 1390 + /* The OPP tables must belong to a genpd */ 1391 + if (unlikely(!opp_table->is_genpd)) { 1392 + pr_err("%s: Performance state is only valid for genpds.\n", __func__); 1393 + goto put_required_np; 1394 + } 1395 + 1388 1396 opp = _find_opp_of_np(opp_table, required_np); 1389 1397 if (opp) { 1390 - pstate = opp->pstate; 1398 + pstate = opp->level; 1391 1399 dev_pm_opp_put(opp); 1392 1400 } 1393 1401
+1 -5
drivers/opp/opp.h
··· 26 26 /* Lock to allow exclusive modification to the device and opp lists */ 27 27 extern struct mutex opp_table_lock; 28 28 29 - extern struct list_head opp_tables, lazy_opp_tables; 29 + extern struct list_head opp_tables; 30 30 31 31 /* OPP Config flags */ 32 32 #define OPP_CONFIG_CLK BIT(0) ··· 78 78 * @turbo: true if turbo (boost) OPP 79 79 * @suspend: true if suspend OPP 80 80 * @removed: flag indicating that OPP's reference is dropped by OPP core. 81 - * @pstate: Device's power domain's performance state. 82 81 * @rates: Frequencies in hertz 83 82 * @level: Performance level 84 83 * @supplies: Power supplies voltage/current values ··· 100 101 bool turbo; 101 102 bool suspend; 102 103 bool removed; 103 - unsigned int pstate; 104 104 unsigned long *rates; 105 105 unsigned int level; 106 106 ··· 180 182 * @paths: Interconnect path handles 181 183 * @path_count: Number of interconnect paths 182 184 * @enabled: Set to true if the device's resources are enabled/configured. 183 - * @genpd_performance_state: Device's power domain support performance state. 184 185 * @is_genpd: Marks if the OPP table belongs to a genpd. 185 186 * @set_required_opps: Helper responsible to set required OPPs. 186 187 * @dentry: debugfs dentry pointer of the real device directory (not links). ··· 230 233 struct icc_path **paths; 231 234 unsigned int path_count; 232 235 bool enabled; 233 - bool genpd_performance_state; 234 236 bool is_genpd; 235 237 int (*set_required_opps)(struct device *dev, 236 238 struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down);