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

Merge tag 'pm-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management updates from Rafael Wysocki:
"These rework cpuidle governors to call tick_nohz_get_sleep_length()
less often and fix one of them, rework hibernation to avoid storing
pages filled with zeros in hibernation images, switch over some
cpufreq drivers to use void remove callbacks, fix and clean up
multiple cpufreq drivers, fix the devfreq core, update the cpupower
utility and make other assorted improvements.

Specifics:

- Rework the menu and teo cpuidle governors to avoid calling
tick_nohz_get_sleep_length(), which is likely to become quite
expensive going forward, too often and improve making decisions
regarding whether or not to stop the scheduler tick in the teo
governor (Rafael Wysocki)

- Improve the performance of cpufreq_stats_create_table() in some
cases (Liao Chang)

- Fix two issues in the amd-pstate-ut cpufreq driver (Swapnil Sapkal)

- Use clamp() helper macro to improve the code readability in
cpufreq_verify_within_limits() (Liao Chang)

- Set stale CPU frequency to minimum in intel_pstate (Doug Smythies)

- Migrate cpufreq drivers for various platforms to use void remove
callback (Yangtao Li)

- Add online/offline/exit hooks for Tegra driver (Sumit Gupta)

- Explicitly include correct DT includes in cpufreq (Rob Herring)

- Frequency domain updates for qcom-hw driver (Neil Armstrong)

- Modify AMD pstate driver return the highest_perf value (Meng Li)

- Generic cleanups for cppc, mediatek and powernow driver (Liao
Chang, Konrad Dybcio)

- Add more platforms to cpufreq-arm driver's blocklist
(AngeloGioacchino Del Regno and Konrad Dybcio)

- brcmstb-avs-cpufreq: Fix -Warray-bounds bug (Gustavo A. R. Silva)

- Add device PM helpers to allow a device to remain powered-on during
system-wide transitions (Ulf Hansson)

- Rework hibernation memory snapshotting to avoid storing pages
filled with zeros in hibernation image files (Brian Geffon)

- Add check to make sure that CPU latency QoS constraints do not use
negative values (Clive Lin)

- Optimize rp->domains memory allocation in the Intel RAPL power
capping driver (xiongxin)

- Remove recursion while parsing zones in the arm_scmi power capping
driver (Cristian Marussi)

- Fix memory leak in devfreq_dev_release() (Boris Brezillon)

- Rewrite devfreq_monitor_start() kerneldoc comment (Manivannan
Sadhasivam)

- Explicitly include correct DT includes in devfreq (Rob Herring)

- Remove unsued pm_runtime_update_max_time_suspended() extern
declaration (YueHaibing)

- Add turbo-boost support to cpupower (Wyes Karny)

- Add support for amd_pstate mode change to cpupower (Wyes Karny)

- Fix 'cpupower idle_set' command to accept only numeric values of
arguments (Likhitha Korrapati)

- Clean up OPP code and add new frequency related APIs to it (Viresh
Kumar, Manivannan Sadhasivam)

- Convert ti cpufreq/opp bindings to json schema (Nishanth Menon)"

* tag 'pm-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (74 commits)
cpufreq: tegra194: remove opp table in exit hook
cpufreq: powernow-k8: Use related_cpus instead of cpus in driver.exit()
cpufreq: tegra194: add online/offline hooks
cpuidle: teo: Avoid unnecessary variable assignments
cpufreq: qcom-cpufreq-hw: add support for 4 freq domains
dt-bindings: cpufreq: qcom-hw: add a 4th frequency domain
cpufreq: amd-pstate-ut: Fix kernel panic when loading the driver
cpufreq: amd-pstate-ut: Remove module parameter access
cpufreq: Use clamp() helper macro to improve the code readability
PM: sleep: Add helpers to allow a device to remain powered-on
PM: QoS: Add check to make sure CPU latency is non-negative
PM: runtime: Remove unsued extern declaration of pm_runtime_update_max_time_suspended()
cpufreq: intel_pstate: set stale CPU frequency to minimum
cpufreq: stats: Improve the performance of cpufreq_stats_create_table()
dt-bindings: cpufreq: Convert ti-cpufreq to json schema
dt-bindings: opp: Convert ti-omap5-opp-supply to json schema
OPP: Fix argument name in doc comment
cpuidle: menu: Skip tick_nohz_get_sleep_length() call in some cases
cpufreq: cppc: Set fie_disabled to FIE_DISABLED if fails to create kworker_fie
cpufreq: cppc: cppc_cpufreq_get_rate() returns zero in all error cases.
...

+1103 -619
+4 -1
Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
··· 49 49 - description: Frequency domain 0 register region 50 50 - description: Frequency domain 1 register region 51 51 - description: Frequency domain 2 register region 52 + - description: Frequency domain 3 register region 52 53 53 54 reg-names: 54 55 minItems: 1 ··· 57 56 - const: freq-domain0 58 57 - const: freq-domain1 59 58 - const: freq-domain2 59 + - const: freq-domain3 60 60 61 61 clocks: 62 62 items: ··· 71 69 72 70 interrupts: 73 71 minItems: 1 74 - maxItems: 3 72 + maxItems: 4 75 73 76 74 interrupt-names: 77 75 minItems: 1 ··· 79 77 - const: dcvsh-irq-0 80 78 - const: dcvsh-irq-1 81 79 - const: dcvsh-irq-2 80 + - const: dcvsh-irq-3 82 81 83 82 '#freq-domain-cells': 84 83 const: 1
-132
Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt
··· 1 - TI CPUFreq and OPP bindings 2 - ================================ 3 - 4 - Certain TI SoCs, like those in the am335x, am437x, am57xx, and dra7xx 5 - families support different OPPs depending on the silicon variant in use. 6 - The ti-cpufreq driver can use revision and an efuse value from the SoC to 7 - provide the OPP framework with supported hardware information. This is 8 - used to determine which OPPs from the operating-points-v2 table get enabled 9 - when it is parsed by the OPP framework. 10 - 11 - Required properties: 12 - -------------------- 13 - In 'cpus' nodes: 14 - - operating-points-v2: Phandle to the operating-points-v2 table to use. 15 - 16 - In 'operating-points-v2' table: 17 - - compatible: Should be 18 - - 'operating-points-v2-ti-cpu' for am335x, am43xx, and dra7xx/am57xx, 19 - omap34xx, omap36xx and am3517 SoCs 20 - - syscon: A phandle pointing to a syscon node representing the control module 21 - register space of the SoC. 22 - 23 - Optional properties: 24 - -------------------- 25 - - "vdd-supply", "vbb-supply": to define two regulators for dra7xx 26 - - "cpu0-supply", "vbb-supply": to define two regulators for omap36xx 27 - 28 - For each opp entry in 'operating-points-v2' table: 29 - - opp-supported-hw: Two bitfields indicating: 30 - 1. Which revision of the SoC the OPP is supported by 31 - 2. Which eFuse bits indicate this OPP is available 32 - 33 - A bitwise AND is performed against these values and if any bit 34 - matches, the OPP gets enabled. 35 - 36 - Example: 37 - -------- 38 - 39 - /* From arch/arm/boot/dts/am33xx.dtsi */ 40 - cpus { 41 - #address-cells = <1>; 42 - #size-cells = <0>; 43 - cpu@0 { 44 - compatible = "arm,cortex-a8"; 45 - device_type = "cpu"; 46 - reg = <0>; 47 - 48 - operating-points-v2 = <&cpu0_opp_table>; 49 - 50 - clocks = <&dpll_mpu_ck>; 51 - clock-names = "cpu"; 52 - 53 - clock-latency = <300000>; /* From omap-cpufreq driver */ 54 - }; 55 - }; 56 - 57 - /* 58 - * cpu0 has different OPPs depending on SoC revision and some on revisions 59 - * 0x2 and 0x4 have eFuse bits that indicate if they are available or not 60 - */ 61 - cpu0_opp_table: opp-table { 62 - compatible = "operating-points-v2-ti-cpu"; 63 - syscon = <&scm_conf>; 64 - 65 - /* 66 - * The three following nodes are marked with opp-suspend 67 - * because they can not be enabled simultaneously on a 68 - * single SoC. 69 - */ 70 - opp50-300000000 { 71 - opp-hz = /bits/ 64 <300000000>; 72 - opp-microvolt = <950000 931000 969000>; 73 - opp-supported-hw = <0x06 0x0010>; 74 - opp-suspend; 75 - }; 76 - 77 - opp100-275000000 { 78 - opp-hz = /bits/ 64 <275000000>; 79 - opp-microvolt = <1100000 1078000 1122000>; 80 - opp-supported-hw = <0x01 0x00FF>; 81 - opp-suspend; 82 - }; 83 - 84 - opp100-300000000 { 85 - opp-hz = /bits/ 64 <300000000>; 86 - opp-microvolt = <1100000 1078000 1122000>; 87 - opp-supported-hw = <0x06 0x0020>; 88 - opp-suspend; 89 - }; 90 - 91 - opp100-500000000 { 92 - opp-hz = /bits/ 64 <500000000>; 93 - opp-microvolt = <1100000 1078000 1122000>; 94 - opp-supported-hw = <0x01 0xFFFF>; 95 - }; 96 - 97 - opp100-600000000 { 98 - opp-hz = /bits/ 64 <600000000>; 99 - opp-microvolt = <1100000 1078000 1122000>; 100 - opp-supported-hw = <0x06 0x0040>; 101 - }; 102 - 103 - opp120-600000000 { 104 - opp-hz = /bits/ 64 <600000000>; 105 - opp-microvolt = <1200000 1176000 1224000>; 106 - opp-supported-hw = <0x01 0xFFFF>; 107 - }; 108 - 109 - opp120-720000000 { 110 - opp-hz = /bits/ 64 <720000000>; 111 - opp-microvolt = <1200000 1176000 1224000>; 112 - opp-supported-hw = <0x06 0x0080>; 113 - }; 114 - 115 - oppturbo-720000000 { 116 - opp-hz = /bits/ 64 <720000000>; 117 - opp-microvolt = <1260000 1234800 1285200>; 118 - opp-supported-hw = <0x01 0xFFFF>; 119 - }; 120 - 121 - oppturbo-800000000 { 122 - opp-hz = /bits/ 64 <800000000>; 123 - opp-microvolt = <1260000 1234800 1285200>; 124 - opp-supported-hw = <0x06 0x0100>; 125 - }; 126 - 127 - oppnitro-1000000000 { 128 - opp-hz = /bits/ 64 <1000000000>; 129 - opp-microvolt = <1325000 1298500 1351500>; 130 - opp-supported-hw = <0x04 0x0200>; 131 - }; 132 - };
+92
Documentation/devicetree/bindings/opp/operating-points-v2-ti-cpu.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/opp/operating-points-v2-ti-cpu.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: TI CPU OPP (Operating Performance Points) 8 + 9 + description: 10 + TI SoCs, like those in the AM335x, AM437x, AM57xx, AM62x, and DRA7xx 11 + families, the CPU frequencies subset and the voltage value of each 12 + OPP vary based on the silicon variant used. The data sheet sections 13 + corresponding to "Operating Performance Points" describe the frequency 14 + and voltage values based on device type and speed bin information 15 + blown in corresponding eFuse bits as referred to by the Technical 16 + Reference Manual. 17 + 18 + This document extends the operating-points-v2 binding by providing 19 + the hardware description for the scheme mentioned above. 20 + 21 + maintainers: 22 + - Nishanth Menon <nm@ti.com> 23 + 24 + allOf: 25 + - $ref: opp-v2-base.yaml# 26 + 27 + properties: 28 + compatible: 29 + const: operating-points-v2-ti-cpu 30 + 31 + syscon: 32 + $ref: /schemas/types.yaml#/definitions/phandle 33 + description: | 34 + points to syscon node representing the control module 35 + register space of the SoC. 36 + 37 + opp-shared: true 38 + 39 + patternProperties: 40 + '^opp(-?[0-9]+)*$': 41 + type: object 42 + additionalProperties: false 43 + 44 + properties: 45 + clock-latency-ns: true 46 + opp-hz: true 47 + opp-microvolt: true 48 + opp-supported-hw: true 49 + opp-suspend: true 50 + turbo-mode: true 51 + 52 + required: 53 + - opp-hz 54 + - opp-supported-hw 55 + 56 + required: 57 + - compatible 58 + - syscon 59 + 60 + additionalProperties: false 61 + 62 + examples: 63 + - | 64 + opp-table { 65 + compatible = "operating-points-v2-ti-cpu"; 66 + syscon = <&scm_conf>; 67 + 68 + opp-300000000 { 69 + opp-hz = /bits/ 64 <300000000>; 70 + opp-microvolt = <1100000 1078000 1122000>; 71 + opp-supported-hw = <0x06 0x0020>; 72 + opp-suspend; 73 + }; 74 + 75 + opp-500000000 { 76 + opp-hz = /bits/ 64 <500000000>; 77 + opp-microvolt = <1100000 1078000 1122000>; 78 + opp-supported-hw = <0x01 0xFFFF>; 79 + }; 80 + 81 + opp-600000000 { 82 + opp-hz = /bits/ 64 <600000000>; 83 + opp-microvolt = <1100000 1078000 1122000>; 84 + opp-supported-hw = <0x06 0x0040>; 85 + }; 86 + 87 + opp-1000000000 { 88 + opp-hz = /bits/ 64 <1000000000>; 89 + opp-microvolt = <1325000 1298500 1351500>; 90 + opp-supported-hw = <0x04 0x0200>; 91 + }; 92 + };
+1 -1
Documentation/devicetree/bindings/opp/opp-v2-base.yaml
··· 56 56 need to be configured and that is left for the implementation 57 57 specific binding. 58 58 minItems: 1 59 - maxItems: 16 59 + maxItems: 32 60 60 items: 61 61 maxItems: 1 62 62
+101
Documentation/devicetree/bindings/opp/ti,omap-opp-supply.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/opp/ti,omap-opp-supply.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Texas Instruments OMAP compatible OPP supply 8 + 9 + description: 10 + OMAP5, DRA7, and AM57 families of SoCs have Class 0 AVS eFuse 11 + registers, which contain OPP-specific voltage information tailored 12 + for the specific device. This binding provides the information 13 + needed to describe such a hardware values and relate them to program 14 + the primary regulator during an OPP transition. 15 + 16 + Also, some supplies may have an associated vbb-supply, an Adaptive 17 + Body Bias regulator, which must transition in a specific sequence 18 + w.r.t the vdd-supply and clk when making an OPP transition. By 19 + supplying two regulators to the device that will undergo OPP 20 + transitions, we can use the multi-regulator support implemented by 21 + the OPP core to describe both regulators the platform needs. The 22 + OPP core binding Documentation/devicetree/bindings/opp/opp-v2.yaml 23 + provides further information (refer to Example 4 Handling multiple 24 + regulators). 25 + 26 + maintainers: 27 + - Nishanth Menon <nm@ti.com> 28 + 29 + properties: 30 + $nodename: 31 + pattern: '^opp-supply(@[0-9a-f]+)?$' 32 + 33 + compatible: 34 + oneOf: 35 + - description: Basic OPP supply controlling VDD and VBB 36 + const: ti,omap-opp-supply 37 + - description: OMAP5+ optimized voltages in efuse(Class 0) VDD along with 38 + VBB. 39 + const: ti,omap5-opp-supply 40 + - description: OMAP5+ optimized voltages in efuse(class0) VDD but no VBB 41 + const: ti,omap5-core-opp-supply 42 + 43 + reg: 44 + maxItems: 1 45 + 46 + ti,absolute-max-voltage-uv: 47 + $ref: /schemas/types.yaml#/definitions/uint32 48 + description: Absolute maximum voltage for the OPP supply in micro-volts. 49 + minimum: 750000 50 + maximum: 1500000 51 + 52 + ti,efuse-settings: 53 + description: An array of u32 tuple items providing information about 54 + optimized efuse configuration. 55 + minItems: 1 56 + $ref: /schemas/types.yaml#/definitions/uint32-matrix 57 + items: 58 + items: 59 + - description: Reference voltage in micro-volts (OPP Voltage) 60 + minimum: 750000 61 + maximum: 1500000 62 + multipleOf: 10000 63 + - description: efuse offset where the optimized voltage is located 64 + multipleOf: 4 65 + maximum: 256 66 + 67 + required: 68 + - compatible 69 + - ti,absolute-max-voltage-uv 70 + 71 + allOf: 72 + - if: 73 + not: 74 + properties: 75 + compatible: 76 + contains: 77 + const: ti,omap-opp-supply 78 + then: 79 + required: 80 + - reg 81 + - ti,efuse-settings 82 + 83 + additionalProperties: false 84 + 85 + examples: 86 + - | 87 + opp-supply { 88 + compatible = "ti,omap-opp-supply"; 89 + ti,absolute-max-voltage-uv = <1375000>; 90 + }; 91 + - | 92 + opp-supply@4a003b20 { 93 + compatible = "ti,omap5-opp-supply"; 94 + reg = <0x4a003b20 0x8>; 95 + ti,efuse-settings = 96 + /* uV offset */ 97 + <1060000 0x0>, 98 + <1160000 0x4>, 99 + <1210000 0x8>; 100 + ti,absolute-max-voltage-uv = <1500000>; 101 + };
-63
Documentation/devicetree/bindings/opp/ti-omap5-opp-supply.txt
··· 1 - Texas Instruments OMAP compatible OPP supply description 2 - 3 - OMAP5, DRA7, and AM57 family of SoCs have Class0 AVS eFuse registers which 4 - contain data that can be used to adjust voltages programmed for some of their 5 - supplies for more efficient operation. This binding provides the information 6 - needed to read these values and use them to program the main regulator during 7 - an OPP transitions. 8 - 9 - Also, some supplies may have an associated vbb-supply which is an Adaptive Body 10 - Bias regulator which much be transitioned in a specific sequence with regards 11 - to the vdd-supply and clk when making an OPP transition. By supplying two 12 - regulators to the device that will undergo OPP transitions we can make use 13 - of the multi regulator binding that is part of the OPP core described here [1] 14 - to describe both regulators needed by the platform. 15 - 16 - [1] Documentation/devicetree/bindings/opp/opp-v2.yaml 17 - 18 - Required Properties for Device Node: 19 - - vdd-supply: phandle to regulator controlling VDD supply 20 - - vbb-supply: phandle to regulator controlling Body Bias supply 21 - (Usually Adaptive Body Bias regulator) 22 - 23 - Required Properties for opp-supply node: 24 - - compatible: Should be one of: 25 - "ti,omap-opp-supply" - basic OPP supply controlling VDD and VBB 26 - "ti,omap5-opp-supply" - OMAP5+ optimized voltages in efuse(class0)VDD 27 - along with VBB 28 - "ti,omap5-core-opp-supply" - OMAP5+ optimized voltages in efuse(class0) VDD 29 - but no VBB. 30 - - reg: Address and length of the efuse register set for the device (mandatory 31 - only for "ti,omap5-opp-supply") 32 - - ti,efuse-settings: An array of u32 tuple items providing information about 33 - optimized efuse configuration. Each item consists of the following: 34 - volt: voltage in uV - reference voltage (OPP voltage) 35 - efuse_offseet: efuse offset from reg where the optimized voltage is stored. 36 - - ti,absolute-max-voltage-uv: absolute maximum voltage for the OPP supply. 37 - 38 - Example: 39 - 40 - /* Device Node (CPU) */ 41 - cpus { 42 - cpu0: cpu@0 { 43 - device_type = "cpu"; 44 - 45 - ... 46 - 47 - vdd-supply = <&vcc>; 48 - vbb-supply = <&abb_mpu>; 49 - }; 50 - }; 51 - 52 - /* OMAP OPP Supply with Class0 registers */ 53 - opp_supply_mpu: opp_supply@4a003b20 { 54 - compatible = "ti,omap5-opp-supply"; 55 - reg = <0x4a003b20 0x8>; 56 - ti,efuse-settings = < 57 - /* uV offset */ 58 - 1060000 0x0 59 - 1160000 0x4 60 - 1210000 0x8 61 - >; 62 - ti,absolute-max-voltage-uv = <1500000>; 63 - };
+2 -4
drivers/cpufreq/acpi-cpufreq.c
··· 1011 1011 return ret; 1012 1012 } 1013 1013 1014 - static int acpi_cpufreq_remove(struct platform_device *pdev) 1014 + static void acpi_cpufreq_remove(struct platform_device *pdev) 1015 1015 { 1016 1016 pr_debug("%s\n", __func__); 1017 1017 1018 1018 cpufreq_unregister_driver(&acpi_cpufreq_driver); 1019 1019 1020 1020 free_acpi_perf_data(); 1021 - 1022 - return 0; 1023 1021 } 1024 1022 1025 1023 static struct platform_driver acpi_cpufreq_platdrv = { 1026 1024 .driver = { 1027 1025 .name = "acpi-cpufreq", 1028 1026 }, 1029 - .remove = acpi_cpufreq_remove, 1027 + .remove_new = acpi_cpufreq_remove, 1030 1028 }; 1031 1029 1032 1030 static int __init acpi_cpufreq_init(void)
+20 -30
drivers/cpufreq/amd-pstate-ut.c
··· 64 64 static bool get_shared_mem(void) 65 65 { 66 66 bool result = false; 67 - char path[] = "/sys/module/amd_pstate/parameters/shared_mem"; 68 - char buf[5] = {0}; 69 - struct file *filp = NULL; 70 - loff_t pos = 0; 71 - ssize_t ret; 72 67 73 - if (!boot_cpu_has(X86_FEATURE_CPPC)) { 74 - filp = filp_open(path, O_RDONLY, 0); 75 - if (IS_ERR(filp)) 76 - pr_err("%s unable to open %s file!\n", __func__, path); 77 - else { 78 - ret = kernel_read(filp, &buf, sizeof(buf), &pos); 79 - if (ret < 0) 80 - pr_err("%s read %s file fail ret=%ld!\n", 81 - __func__, path, (long)ret); 82 - filp_close(filp, NULL); 83 - } 84 - 85 - if ('Y' == *buf) 86 - result = true; 87 - } 68 + if (!boot_cpu_has(X86_FEATURE_CPPC)) 69 + result = true; 88 70 89 71 return result; 90 72 } ··· 127 145 struct cpufreq_policy *policy = NULL; 128 146 struct amd_cpudata *cpudata = NULL; 129 147 130 - highest_perf = amd_get_highest_perf(); 131 - 132 148 for_each_possible_cpu(cpu) { 133 149 policy = cpufreq_cpu_get(cpu); 134 150 if (!policy) ··· 138 158 if (ret) { 139 159 amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL; 140 160 pr_err("%s cppc_get_perf_caps ret=%d error!\n", __func__, ret); 141 - return; 161 + goto skip_test; 142 162 } 143 163 164 + highest_perf = cppc_perf.highest_perf; 144 165 nominal_perf = cppc_perf.nominal_perf; 145 166 lowest_nonlinear_perf = cppc_perf.lowest_nonlinear_perf; 146 167 lowest_perf = cppc_perf.lowest_perf; ··· 150 169 if (ret) { 151 170 amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL; 152 171 pr_err("%s read CPPC_CAP1 ret=%d error!\n", __func__, ret); 153 - return; 172 + goto skip_test; 154 173 } 155 174 175 + highest_perf = AMD_CPPC_HIGHEST_PERF(cap1); 156 176 nominal_perf = AMD_CPPC_NOMINAL_PERF(cap1); 157 177 lowest_nonlinear_perf = AMD_CPPC_LOWNONLIN_PERF(cap1); 158 178 lowest_perf = AMD_CPPC_LOWEST_PERF(cap1); ··· 169 187 nominal_perf, cpudata->nominal_perf, 170 188 lowest_nonlinear_perf, cpudata->lowest_nonlinear_perf, 171 189 lowest_perf, cpudata->lowest_perf); 172 - return; 190 + goto skip_test; 173 191 } 174 192 175 193 if (!((highest_perf >= nominal_perf) && ··· 180 198 pr_err("%s cpu%d highest=%d >= nominal=%d > lowest_nonlinear=%d > lowest=%d > 0, the formula is incorrect!\n", 181 199 __func__, cpu, highest_perf, nominal_perf, 182 200 lowest_nonlinear_perf, lowest_perf); 183 - return; 201 + goto skip_test; 184 202 } 203 + cpufreq_cpu_put(policy); 185 204 } 186 205 187 206 amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS; 207 + return; 208 + skip_test: 209 + cpufreq_cpu_put(policy); 188 210 } 189 211 190 212 /* ··· 216 230 pr_err("%s cpu%d max=%d >= nominal=%d > lowest_nonlinear=%d > min=%d > 0, the formula is incorrect!\n", 217 231 __func__, cpu, cpudata->max_freq, cpudata->nominal_freq, 218 232 cpudata->lowest_nonlinear_freq, cpudata->min_freq); 219 - return; 233 + goto skip_test; 220 234 } 221 235 222 236 if (cpudata->min_freq != policy->min) { 223 237 amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL; 224 238 pr_err("%s cpu%d cpudata_min_freq=%d policy_min=%d, they should be equal!\n", 225 239 __func__, cpu, cpudata->min_freq, policy->min); 226 - return; 240 + goto skip_test; 227 241 } 228 242 229 243 if (cpudata->boost_supported) { ··· 235 249 pr_err("%s cpu%d policy_max=%d should be equal cpu_max=%d or cpu_nominal=%d !\n", 236 250 __func__, cpu, policy->max, cpudata->max_freq, 237 251 cpudata->nominal_freq); 238 - return; 252 + goto skip_test; 239 253 } 240 254 } else { 241 255 amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL; 242 256 pr_err("%s cpu%d must support boost!\n", __func__, cpu); 243 - return; 257 + goto skip_test; 244 258 } 259 + cpufreq_cpu_put(policy); 245 260 } 246 261 247 262 amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS; 263 + return; 264 + skip_test: 265 + cpufreq_cpu_put(policy); 248 266 } 249 267 250 268 static int __init amd_pstate_ut_init(void)
+1 -3
drivers/cpufreq/armada-37xx-cpufreq.c
··· 14 14 #include <linux/interrupt.h> 15 15 #include <linux/io.h> 16 16 #include <linux/mfd/syscon.h> 17 + #include <linux/mod_devicetable.h> 17 18 #include <linux/module.h> 18 - #include <linux/of_address.h> 19 - #include <linux/of_device.h> 20 - #include <linux/of_irq.h> 21 19 #include <linux/platform_device.h> 22 20 #include <linux/pm_opp.h> 23 21 #include <linux/regmap.h>
+7 -5
drivers/cpufreq/brcmstb-avs-cpufreq.c
··· 434 434 if (ret) 435 435 return ERR_PTR(ret); 436 436 437 - table = devm_kcalloc(dev, AVS_PSTATE_MAX + 1, sizeof(*table), 437 + /* 438 + * We allocate space for the 5 different P-STATES AVS, 439 + * plus extra space for a terminating element. 440 + */ 441 + table = devm_kcalloc(dev, AVS_PSTATE_MAX + 1 + 1, sizeof(*table), 438 442 GFP_KERNEL); 439 443 if (!table) 440 444 return ERR_PTR(-ENOMEM); ··· 753 749 return ret; 754 750 } 755 751 756 - static int brcm_avs_cpufreq_remove(struct platform_device *pdev) 752 + static void brcm_avs_cpufreq_remove(struct platform_device *pdev) 757 753 { 758 754 cpufreq_unregister_driver(&brcm_avs_driver); 759 755 760 756 brcm_avs_prepare_uninit(pdev); 761 - 762 - return 0; 763 757 } 764 758 765 759 static const struct of_device_id brcm_avs_cpufreq_match[] = { ··· 772 770 .of_match_table = brcm_avs_cpufreq_match, 773 771 }, 774 772 .probe = brcm_avs_cpufreq_probe, 775 - .remove = brcm_avs_cpufreq_remove, 773 + .remove_new = brcm_avs_cpufreq_remove, 776 774 }; 777 775 module_platform_driver(brcm_avs_cpufreq_platdrv); 778 776
+8 -5
drivers/cpufreq/cppc_cpufreq.c
··· 249 249 return; 250 250 251 251 kworker_fie = kthread_create_worker(0, "cppc_fie"); 252 - if (IS_ERR(kworker_fie)) 252 + if (IS_ERR(kworker_fie)) { 253 + pr_warn("%s: failed to create kworker_fie: %ld\n", __func__, 254 + PTR_ERR(kworker_fie)); 255 + fie_disabled = FIE_DISABLED; 253 256 return; 257 + } 254 258 255 259 ret = sched_setattr_nocheck(kworker_fie->task, &attr); 256 260 if (ret) { 257 261 pr_warn("%s: failed to set SCHED_DEADLINE: %d\n", __func__, 258 262 ret); 259 263 kthread_destroy_worker(kworker_fie); 260 - return; 264 + fie_disabled = FIE_DISABLED; 261 265 } 262 266 } 263 267 ··· 271 267 return; 272 268 273 269 kthread_destroy_worker(kworker_fie); 274 - kworker_fie = NULL; 275 270 } 276 271 277 272 #else ··· 852 849 853 850 ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0); 854 851 if (ret) 855 - return ret; 852 + return 0; 856 853 857 854 udelay(2); /* 2usec delay between sampling */ 858 855 859 856 ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t1); 860 857 if (ret) 861 - return ret; 858 + return 0; 862 859 863 860 delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0, 864 861 &fb_ctrs_t1);
+7
drivers/cpufreq/cpufreq-dt-platdev.c
··· 143 143 144 144 { .compatible = "qcom,apq8096", }, 145 145 { .compatible = "qcom,msm8996", }, 146 + { .compatible = "qcom,msm8998", }, 147 + { .compatible = "qcom,qcm2290", }, 146 148 { .compatible = "qcom,qcs404", }, 149 + { .compatible = "qcom,qdu1000", }, 147 150 { .compatible = "qcom,sa8155p" }, 148 151 { .compatible = "qcom,sa8540p" }, 152 + { .compatible = "qcom,sa8775p" }, 149 153 { .compatible = "qcom,sc7180", }, 150 154 { .compatible = "qcom,sc7280", }, 151 155 { .compatible = "qcom,sc8180x", }, 152 156 { .compatible = "qcom,sc8280xp", }, 153 157 { .compatible = "qcom,sdm845", }, 158 + { .compatible = "qcom,sdx75", }, 154 159 { .compatible = "qcom,sm6115", }, 155 160 { .compatible = "qcom,sm6350", }, 156 161 { .compatible = "qcom,sm6375", }, ··· 163 158 { .compatible = "qcom,sm8150", }, 164 159 { .compatible = "qcom,sm8250", }, 165 160 { .compatible = "qcom,sm8350", }, 161 + { .compatible = "qcom,sm8450", }, 162 + { .compatible = "qcom,sm8550", }, 166 163 167 164 { .compatible = "st,stih407", }, 168 165 { .compatible = "st,stih410", },
+2 -3
drivers/cpufreq/cpufreq-dt.c
··· 349 349 return ret; 350 350 } 351 351 352 - static int dt_cpufreq_remove(struct platform_device *pdev) 352 + static void dt_cpufreq_remove(struct platform_device *pdev) 353 353 { 354 354 cpufreq_unregister_driver(&dt_cpufreq_driver); 355 355 dt_cpufreq_release(); 356 - return 0; 357 356 } 358 357 359 358 static struct platform_driver dt_cpufreq_platdrv = { ··· 360 361 .name = "cpufreq-dt", 361 362 }, 362 363 .probe = dt_cpufreq_probe, 363 - .remove = dt_cpufreq_remove, 364 + .remove_new = dt_cpufreq_remove, 364 365 }; 365 366 module_platform_driver(dt_cpufreq_platdrv); 366 367
+4 -4
drivers/cpufreq/cpufreq.c
··· 1234 1234 ret = freq_qos_add_notifier(&policy->constraints, FREQ_QOS_MIN, 1235 1235 &policy->nb_min); 1236 1236 if (ret) { 1237 - dev_err(dev, "Failed to register MIN QoS notifier: %d (%*pbl)\n", 1238 - ret, cpumask_pr_args(policy->cpus)); 1237 + dev_err(dev, "Failed to register MIN QoS notifier: %d (CPU%u)\n", 1238 + ret, cpu); 1239 1239 goto err_kobj_remove; 1240 1240 } 1241 1241 1242 1242 ret = freq_qos_add_notifier(&policy->constraints, FREQ_QOS_MAX, 1243 1243 &policy->nb_max); 1244 1244 if (ret) { 1245 - dev_err(dev, "Failed to register MAX QoS notifier: %d (%*pbl)\n", 1246 - ret, cpumask_pr_args(policy->cpus)); 1245 + dev_err(dev, "Failed to register MAX QoS notifier: %d (CPU%u)\n", 1246 + ret, cpu); 1247 1247 goto err_min_qos_notifier; 1248 1248 } 1249 1249
+2 -1
drivers/cpufreq/cpufreq_stats.c
··· 243 243 244 244 /* Find valid-unique entries */ 245 245 cpufreq_for_each_valid_entry(pos, policy->freq_table) 246 - if (freq_table_get_index(stats, pos->frequency) == -1) 246 + if (policy->freq_table_sorted != CPUFREQ_TABLE_UNSORTED || 247 + freq_table_get_index(stats, pos->frequency) == -1) 247 248 stats->freq_table[i++] = pos->frequency; 248 249 249 250 stats->state_num = i;
+2 -4
drivers/cpufreq/davinci-cpufreq.c
··· 131 131 return cpufreq_register_driver(&davinci_driver); 132 132 } 133 133 134 - static int __exit davinci_cpufreq_remove(struct platform_device *pdev) 134 + static void __exit davinci_cpufreq_remove(struct platform_device *pdev) 135 135 { 136 136 cpufreq_unregister_driver(&davinci_driver); 137 137 ··· 139 139 140 140 if (cpufreq.asyncclk) 141 141 clk_put(cpufreq.asyncclk); 142 - 143 - return 0; 144 142 } 145 143 146 144 static struct platform_driver davinci_cpufreq_driver = { 147 145 .driver = { 148 146 .name = "cpufreq-davinci", 149 147 }, 150 - .remove = __exit_p(davinci_cpufreq_remove), 148 + .remove_new = __exit_p(davinci_cpufreq_remove), 151 149 }; 152 150 153 151 int __init davinci_cpufreq_init(void)
+2 -4
drivers/cpufreq/imx-cpufreq-dt.c
··· 172 172 return 0; 173 173 } 174 174 175 - static int imx_cpufreq_dt_remove(struct platform_device *pdev) 175 + static void imx_cpufreq_dt_remove(struct platform_device *pdev) 176 176 { 177 177 platform_device_unregister(cpufreq_dt_pdev); 178 178 if (!of_machine_is_compatible("fsl,imx7ulp")) 179 179 dev_pm_opp_put_supported_hw(cpufreq_opp_token); 180 180 else 181 181 clk_bulk_put(ARRAY_SIZE(imx7ulp_clks), imx7ulp_clks); 182 - 183 - return 0; 184 182 } 185 183 186 184 static struct platform_driver imx_cpufreq_dt_driver = { 187 185 .probe = imx_cpufreq_dt_probe, 188 - .remove = imx_cpufreq_dt_remove, 186 + .remove_new = imx_cpufreq_dt_remove, 189 187 .driver = { 190 188 .name = "imx-cpufreq-dt", 191 189 },
+2 -4
drivers/cpufreq/imx6q-cpufreq.c
··· 519 519 return ret; 520 520 } 521 521 522 - static int imx6q_cpufreq_remove(struct platform_device *pdev) 522 + static void imx6q_cpufreq_remove(struct platform_device *pdev) 523 523 { 524 524 cpufreq_unregister_driver(&imx6q_cpufreq_driver); 525 525 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); ··· 530 530 regulator_put(soc_reg); 531 531 532 532 clk_bulk_put(num_clks, clks); 533 - 534 - return 0; 535 533 } 536 534 537 535 static struct platform_driver imx6q_cpufreq_platdrv = { ··· 537 539 .name = "imx6q-cpufreq", 538 540 }, 539 541 .probe = imx6q_cpufreq_probe, 540 - .remove = imx6q_cpufreq_remove, 542 + .remove_new = imx6q_cpufreq_remove, 541 543 }; 542 544 module_platform_driver(imx6q_cpufreq_platdrv); 543 545
+5
drivers/cpufreq/intel_pstate.c
··· 2609 2609 intel_pstate_clear_update_util_hook(policy->cpu); 2610 2610 intel_pstate_hwp_set(policy->cpu); 2611 2611 } 2612 + /* 2613 + * policy->cur is never updated with the intel_pstate driver, but it 2614 + * is used as a stale frequency value. So, keep it within limits. 2615 + */ 2616 + policy->cur = policy->min; 2612 2617 2613 2618 mutex_unlock(&intel_pstate_limits_lock); 2614 2619
+2 -4
drivers/cpufreq/kirkwood-cpufreq.c
··· 178 178 return err; 179 179 } 180 180 181 - static int kirkwood_cpufreq_remove(struct platform_device *pdev) 181 + static void kirkwood_cpufreq_remove(struct platform_device *pdev) 182 182 { 183 183 cpufreq_unregister_driver(&kirkwood_cpufreq_driver); 184 184 185 185 clk_disable_unprepare(priv.powersave_clk); 186 186 clk_disable_unprepare(priv.ddr_clk); 187 187 clk_disable_unprepare(priv.cpu_clk); 188 - 189 - return 0; 190 188 } 191 189 192 190 static struct platform_driver kirkwood_cpufreq_platform_driver = { 193 191 .probe = kirkwood_cpufreq_probe, 194 - .remove = kirkwood_cpufreq_remove, 192 + .remove_new = kirkwood_cpufreq_remove, 195 193 .driver = { 196 194 .name = "kirkwood-cpufreq", 197 195 },
+4 -5
drivers/cpufreq/mediatek-cpufreq-hw.c
··· 10 10 #include <linux/iopoll.h> 11 11 #include <linux/kernel.h> 12 12 #include <linux/module.h> 13 - #include <linux/of_address.h> 13 + #include <linux/of.h> 14 14 #include <linux/of_platform.h> 15 + #include <linux/platform_device.h> 15 16 #include <linux/slab.h> 16 17 17 18 #define LUT_MAX_ENTRIES 32U ··· 316 315 return ret; 317 316 } 318 317 319 - static int mtk_cpufreq_hw_driver_remove(struct platform_device *pdev) 318 + static void mtk_cpufreq_hw_driver_remove(struct platform_device *pdev) 320 319 { 321 320 cpufreq_unregister_driver(&cpufreq_mtk_hw_driver); 322 - 323 - return 0; 324 321 } 325 322 326 323 static const struct of_device_id mtk_cpufreq_hw_match[] = { ··· 329 330 330 331 static struct platform_driver mtk_cpufreq_hw_driver = { 331 332 .probe = mtk_cpufreq_hw_driver_probe, 332 - .remove = mtk_cpufreq_hw_driver_remove, 333 + .remove_new = mtk_cpufreq_hw_driver_remove, 333 334 .driver = { 334 335 .name = "mtk-cpufreq-hw", 335 336 .of_match_table = mtk_cpufreq_hw_match,
-2
drivers/cpufreq/mediatek-cpufreq.c
··· 313 313 return ret; 314 314 } 315 315 316 - #define DYNAMIC_POWER "dynamic-power-coefficient" 317 - 318 316 static int mtk_cpufreq_opp_notifier(struct notifier_block *nb, 319 317 unsigned long event, void *data) 320 318 {
+2 -4
drivers/cpufreq/omap-cpufreq.c
··· 182 182 return cpufreq_register_driver(&omap_driver); 183 183 } 184 184 185 - static int omap_cpufreq_remove(struct platform_device *pdev) 185 + static void omap_cpufreq_remove(struct platform_device *pdev) 186 186 { 187 187 cpufreq_unregister_driver(&omap_driver); 188 - 189 - return 0; 190 188 } 191 189 192 190 static struct platform_driver omap_cpufreq_platdrv = { ··· 192 194 .name = "omap-cpufreq", 193 195 }, 194 196 .probe = omap_cpufreq_probe, 195 - .remove = omap_cpufreq_remove, 197 + .remove_new = omap_cpufreq_remove, 196 198 }; 197 199 module_platform_driver(omap_cpufreq_platdrv); 198 200
+2 -4
drivers/cpufreq/pcc-cpufreq.c
··· 608 608 return ret; 609 609 } 610 610 611 - static int pcc_cpufreq_remove(struct platform_device *pdev) 611 + static void pcc_cpufreq_remove(struct platform_device *pdev) 612 612 { 613 613 cpufreq_unregister_driver(&pcc_cpufreq_driver); 614 614 615 615 pcc_clear_mapping(); 616 616 617 617 free_percpu(pcc_cpu_info); 618 - 619 - return 0; 620 618 } 621 619 622 620 static struct platform_driver pcc_cpufreq_platdrv = { 623 621 .driver = { 624 622 .name = "pcc-cpufreq", 625 623 }, 626 - .remove = pcc_cpufreq_remove, 624 + .remove_new = pcc_cpufreq_remove, 627 625 }; 628 626 629 627 static int __init pcc_cpufreq_init(void)
+2 -1
drivers/cpufreq/powernow-k8.c
··· 1101 1101 1102 1102 kfree(data->powernow_table); 1103 1103 kfree(data); 1104 - for_each_cpu(cpu, pol->cpus) 1104 + /* pol->cpus will be empty here, use related_cpus instead. */ 1105 + for_each_cpu(cpu, pol->related_cpus) 1105 1106 per_cpu(powernow_data, cpu) = NULL; 1106 1107 1107 1108 return 0;
+1 -1
drivers/cpufreq/ppc_cbe_cpufreq.c
··· 9 9 10 10 #include <linux/cpufreq.h> 11 11 #include <linux/module.h> 12 - #include <linux/of_platform.h> 12 + #include <linux/of.h> 13 13 14 14 #include <asm/machdep.h> 15 15 #include <asm/cell-regs.h>
-1
drivers/cpufreq/ppc_cbe_cpufreq_pmi.c
··· 11 11 #include <linux/types.h> 12 12 #include <linux/timer.h> 13 13 #include <linux/init.h> 14 - #include <linux/of_platform.h> 15 14 #include <linux/pm_qos.h> 16 15 #include <linux/slab.h> 17 16
+3 -5
drivers/cpufreq/qcom-cpufreq-hw.c
··· 28 28 29 29 #define GT_IRQ_STATUS BIT(2) 30 30 31 - #define MAX_FREQ_DOMAINS 3 31 + #define MAX_FREQ_DOMAINS 4 32 32 33 33 struct qcom_cpufreq_soc_data { 34 34 u32 reg_enable; ··· 730 730 return ret; 731 731 } 732 732 733 - static int qcom_cpufreq_hw_driver_remove(struct platform_device *pdev) 733 + static void qcom_cpufreq_hw_driver_remove(struct platform_device *pdev) 734 734 { 735 735 cpufreq_unregister_driver(&cpufreq_qcom_hw_driver); 736 - 737 - return 0; 738 736 } 739 737 740 738 static struct platform_driver qcom_cpufreq_hw_driver = { 741 739 .probe = qcom_cpufreq_hw_driver_probe, 742 - .remove = qcom_cpufreq_hw_driver_remove, 740 + .remove_new = qcom_cpufreq_hw_driver_remove, 743 741 .driver = { 744 742 .name = "qcom-cpufreq-hw", 745 743 .of_match_table = qcom_cpufreq_hw_match,
+2 -5
drivers/cpufreq/qcom-cpufreq-nvmem.c
··· 22 22 #include <linux/module.h> 23 23 #include <linux/nvmem-consumer.h> 24 24 #include <linux/of.h> 25 - #include <linux/of_device.h> 26 25 #include <linux/platform_device.h> 27 26 #include <linux/pm_domain.h> 28 27 #include <linux/pm_opp.h> ··· 333 334 return ret; 334 335 } 335 336 336 - static int qcom_cpufreq_remove(struct platform_device *pdev) 337 + static void qcom_cpufreq_remove(struct platform_device *pdev) 337 338 { 338 339 struct qcom_cpufreq_drv *drv = platform_get_drvdata(pdev); 339 340 unsigned int cpu; ··· 345 346 346 347 kfree(drv->opp_tokens); 347 348 kfree(drv); 348 - 349 - return 0; 350 349 } 351 350 352 351 static struct platform_driver qcom_cpufreq_driver = { 353 352 .probe = qcom_cpufreq_probe, 354 - .remove = qcom_cpufreq_remove, 353 + .remove_new = qcom_cpufreq_remove, 355 354 .driver = { 356 355 .name = "qcom-cpufreq-nvmem", 357 356 },
+2 -4
drivers/cpufreq/qoriq-cpufreq.c
··· 288 288 return 0; 289 289 } 290 290 291 - static int qoriq_cpufreq_remove(struct platform_device *pdev) 291 + static void qoriq_cpufreq_remove(struct platform_device *pdev) 292 292 { 293 293 cpufreq_unregister_driver(&qoriq_cpufreq_driver); 294 - 295 - return 0; 296 294 } 297 295 298 296 static struct platform_driver qoriq_cpufreq_platform_driver = { ··· 298 300 .name = "qoriq-cpufreq", 299 301 }, 300 302 .probe = qoriq_cpufreq_probe, 301 - .remove = qoriq_cpufreq_remove, 303 + .remove_new = qoriq_cpufreq_remove, 302 304 }; 303 305 module_platform_driver(qoriq_cpufreq_platform_driver); 304 306
+2 -4
drivers/cpufreq/raspberrypi-cpufreq.c
··· 65 65 return ret; 66 66 } 67 67 68 - static int raspberrypi_cpufreq_remove(struct platform_device *pdev) 68 + static void raspberrypi_cpufreq_remove(struct platform_device *pdev) 69 69 { 70 70 struct device *cpu_dev; 71 71 ··· 74 74 dev_pm_opp_remove_all_dynamic(cpu_dev); 75 75 76 76 platform_device_unregister(cpufreq_dt); 77 - 78 - return 0; 79 77 } 80 78 81 79 /* ··· 85 87 .name = "raspberrypi-cpufreq", 86 88 }, 87 89 .probe = raspberrypi_cpufreq_probe, 88 - .remove = raspberrypi_cpufreq_remove, 90 + .remove_new = raspberrypi_cpufreq_remove, 89 91 }; 90 92 module_platform_driver(raspberrypi_cpufreq_driver); 91 93
+3 -4
drivers/cpufreq/scpi-cpufreq.c
··· 14 14 #include <linux/cpumask.h> 15 15 #include <linux/export.h> 16 16 #include <linux/module.h> 17 - #include <linux/of_platform.h> 17 + #include <linux/platform_device.h> 18 18 #include <linux/pm_opp.h> 19 19 #include <linux/scpi_protocol.h> 20 20 #include <linux/slab.h> ··· 208 208 return ret; 209 209 } 210 210 211 - static int scpi_cpufreq_remove(struct platform_device *pdev) 211 + static void scpi_cpufreq_remove(struct platform_device *pdev) 212 212 { 213 213 cpufreq_unregister_driver(&scpi_cpufreq_driver); 214 214 scpi_ops = NULL; 215 - return 0; 216 215 } 217 216 218 217 static struct platform_driver scpi_cpufreq_platdrv = { ··· 219 220 .name = "scpi-cpufreq", 220 221 }, 221 222 .probe = scpi_cpufreq_probe, 222 - .remove = scpi_cpufreq_remove, 223 + .remove_new = scpi_cpufreq_remove, 223 224 }; 224 225 module_platform_driver(scpi_cpufreq_platdrv); 225 226
+1 -1
drivers/cpufreq/sti-cpufreq.c
··· 13 13 #include <linux/mfd/syscon.h> 14 14 #include <linux/module.h> 15 15 #include <linux/of.h> 16 - #include <linux/of_platform.h> 16 + #include <linux/platform_device.h> 17 17 #include <linux/pm_opp.h> 18 18 #include <linux/regmap.h> 19 19
+2 -4
drivers/cpufreq/sun50i-cpufreq-nvmem.c
··· 137 137 return ret; 138 138 } 139 139 140 - static int sun50i_cpufreq_nvmem_remove(struct platform_device *pdev) 140 + static void sun50i_cpufreq_nvmem_remove(struct platform_device *pdev) 141 141 { 142 142 int *opp_tokens = platform_get_drvdata(pdev); 143 143 unsigned int cpu; ··· 148 148 dev_pm_opp_put_prop_name(opp_tokens[cpu]); 149 149 150 150 kfree(opp_tokens); 151 - 152 - return 0; 153 151 } 154 152 155 153 static struct platform_driver sun50i_cpufreq_driver = { 156 154 .probe = sun50i_cpufreq_nvmem_probe, 157 - .remove = sun50i_cpufreq_nvmem_remove, 155 + .remove_new = sun50i_cpufreq_nvmem_remove, 158 156 .driver = { 159 157 .name = "sun50i-cpufreq-nvmem", 160 158 },
+2 -4
drivers/cpufreq/tegra186-cpufreq.c
··· 259 259 return err; 260 260 } 261 261 262 - static int tegra186_cpufreq_remove(struct platform_device *pdev) 262 + static void tegra186_cpufreq_remove(struct platform_device *pdev) 263 263 { 264 264 cpufreq_unregister_driver(&tegra186_cpufreq_driver); 265 - 266 - return 0; 267 265 } 268 266 269 267 static const struct of_device_id tegra186_cpufreq_of_match[] = { ··· 276 278 .of_match_table = tegra186_cpufreq_of_match, 277 279 }, 278 280 .probe = tegra186_cpufreq_probe, 279 - .remove = tegra186_cpufreq_remove, 281 + .remove_new = tegra186_cpufreq_remove, 280 282 }; 281 283 module_platform_driver(tegra186_cpufreq_platform_driver); 282 284
+31 -4
drivers/cpufreq/tegra194-cpufreq.c
··· 508 508 return 0; 509 509 } 510 510 511 + static int tegra194_cpufreq_online(struct cpufreq_policy *policy) 512 + { 513 + /* We did light-weight tear down earlier, nothing to do here */ 514 + return 0; 515 + } 516 + 517 + static int tegra194_cpufreq_offline(struct cpufreq_policy *policy) 518 + { 519 + /* 520 + * Preserve policy->driver_data and don't free resources on light-weight 521 + * tear down. 522 + */ 523 + 524 + return 0; 525 + } 526 + 527 + static int tegra194_cpufreq_exit(struct cpufreq_policy *policy) 528 + { 529 + struct device *cpu_dev = get_cpu_device(policy->cpu); 530 + 531 + dev_pm_opp_remove_all_dynamic(cpu_dev); 532 + dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); 533 + 534 + return 0; 535 + } 536 + 511 537 static int tegra194_cpufreq_set_target(struct cpufreq_policy *policy, 512 538 unsigned int index) 513 539 { ··· 561 535 .target_index = tegra194_cpufreq_set_target, 562 536 .get = tegra194_get_speed, 563 537 .init = tegra194_cpufreq_init, 538 + .exit = tegra194_cpufreq_exit, 539 + .online = tegra194_cpufreq_online, 540 + .offline = tegra194_cpufreq_offline, 564 541 .attr = cpufreq_generic_attr, 565 542 }; 566 543 ··· 737 708 return err; 738 709 } 739 710 740 - static int tegra194_cpufreq_remove(struct platform_device *pdev) 711 + static void tegra194_cpufreq_remove(struct platform_device *pdev) 741 712 { 742 713 cpufreq_unregister_driver(&tegra194_cpufreq_driver); 743 714 tegra194_cpufreq_free_resources(); 744 - 745 - return 0; 746 715 } 747 716 748 717 static const struct of_device_id tegra194_cpufreq_of_match[] = { ··· 757 730 .of_match_table = tegra194_cpufreq_of_match, 758 731 }, 759 732 .probe = tegra194_cpufreq_probe, 760 - .remove = tegra194_cpufreq_remove, 733 + .remove_new = tegra194_cpufreq_remove, 761 734 }; 762 735 module_platform_driver(tegra194_ccplex_driver); 763 736
+1 -1
drivers/cpufreq/ti-cpufreq.c
··· 12 12 #include <linux/module.h> 13 13 #include <linux/init.h> 14 14 #include <linux/of.h> 15 - #include <linux/of_platform.h> 15 + #include <linux/platform_device.h> 16 16 #include <linux/pm_opp.h> 17 17 #include <linux/regmap.h> 18 18 #include <linux/slab.h>
+2 -4
drivers/cpufreq/vexpress-spc-cpufreq.c
··· 18 18 #include <linux/device.h> 19 19 #include <linux/module.h> 20 20 #include <linux/mutex.h> 21 - #include <linux/of_platform.h> 22 21 #include <linux/platform_device.h> 23 22 #include <linux/pm_opp.h> 24 23 #include <linux/slab.h> ··· 551 552 return ret; 552 553 } 553 554 554 - static int ve_spc_cpufreq_remove(struct platform_device *pdev) 555 + static void ve_spc_cpufreq_remove(struct platform_device *pdev) 555 556 { 556 557 bL_switcher_get_enabled(); 557 558 __bLs_unregister_notifier(); ··· 559 560 bL_switcher_put_enabled(); 560 561 pr_info("%s: Un-registered platform driver: %s\n", __func__, 561 562 ve_spc_cpufreq_driver.name); 562 - return 0; 563 563 } 564 564 565 565 static struct platform_driver ve_spc_cpufreq_platdrv = { ··· 566 568 .name = "vexpress-spc-cpufreq", 567 569 }, 568 570 .probe = ve_spc_cpufreq_probe, 569 - .remove = ve_spc_cpufreq_remove, 571 + .remove_new = ve_spc_cpufreq_remove, 570 572 }; 571 573 module_platform_driver(ve_spc_cpufreq_platdrv); 572 574
+14
drivers/cpuidle/governors/gov.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + /* Common definitions for cpuidle governors. */ 4 + 5 + #ifndef __CPUIDLE_GOVERNOR_H 6 + #define __CPUIDLE_GOVERNOR_H 7 + 8 + /* 9 + * Idle state target residency threshold used for deciding whether or not to 10 + * check the time till the closest expected timer event. 11 + */ 12 + #define RESIDENCY_THRESHOLD_NS (15 * NSEC_PER_USEC) 13 + 14 + #endif /* __CPUIDLE_GOVERNOR_H */
+38 -27
drivers/cpuidle/governors/menu.c
··· 19 19 #include <linux/sched/stat.h> 20 20 #include <linux/math64.h> 21 21 22 + #include "gov.h" 23 + 22 24 #define BUCKETS 12 23 25 #define INTERVAL_SHIFT 3 24 26 #define INTERVALS (1UL << INTERVAL_SHIFT) ··· 168 166 * of points is below a threshold. If it is... then use the 169 167 * average of these 8 points as the estimated value. 170 168 */ 171 - static unsigned int get_typical_interval(struct menu_device *data, 172 - unsigned int predicted_us) 169 + static unsigned int get_typical_interval(struct menu_device *data) 173 170 { 174 171 int i, divisor; 175 172 unsigned int min, max, thresh, avg; ··· 196 195 } 197 196 } 198 197 199 - /* 200 - * If the result of the computation is going to be discarded anyway, 201 - * avoid the computation altogether. 202 - */ 203 - if (min >= predicted_us) 198 + if (!max) 204 199 return UINT_MAX; 205 200 206 201 if (divisor == INTERVALS) ··· 264 267 { 265 268 struct menu_device *data = this_cpu_ptr(&menu_devices); 266 269 s64 latency_req = cpuidle_governor_latency_req(dev->cpu); 267 - unsigned int predicted_us; 268 270 u64 predicted_ns; 269 271 u64 interactivity_req; 270 272 unsigned int nr_iowaiters; ··· 275 279 data->needs_update = 0; 276 280 } 277 281 278 - /* determine the expected residency time, round up */ 279 - delta = tick_nohz_get_sleep_length(&delta_tick); 280 - if (unlikely(delta < 0)) { 281 - delta = 0; 282 - delta_tick = 0; 283 - } 284 - data->next_timer_ns = delta; 285 - 286 282 nr_iowaiters = nr_iowait_cpu(dev->cpu); 287 - data->bucket = which_bucket(data->next_timer_ns, nr_iowaiters); 283 + 284 + /* Find the shortest expected idle interval. */ 285 + predicted_ns = get_typical_interval(data) * NSEC_PER_USEC; 286 + if (predicted_ns > RESIDENCY_THRESHOLD_NS) { 287 + unsigned int timer_us; 288 + 289 + /* Determine the time till the closest timer. */ 290 + delta = tick_nohz_get_sleep_length(&delta_tick); 291 + if (unlikely(delta < 0)) { 292 + delta = 0; 293 + delta_tick = 0; 294 + } 295 + 296 + data->next_timer_ns = delta; 297 + data->bucket = which_bucket(data->next_timer_ns, nr_iowaiters); 298 + 299 + /* Round up the result for half microseconds. */ 300 + timer_us = div_u64((RESOLUTION * DECAY * NSEC_PER_USEC) / 2 + 301 + data->next_timer_ns * 302 + data->correction_factor[data->bucket], 303 + RESOLUTION * DECAY * NSEC_PER_USEC); 304 + /* Use the lowest expected idle interval to pick the idle state. */ 305 + predicted_ns = min((u64)timer_us * NSEC_PER_USEC, predicted_ns); 306 + } else { 307 + /* 308 + * Because the next timer event is not going to be determined 309 + * in this case, assume that without the tick the closest timer 310 + * will be in distant future and that the closest tick will occur 311 + * after 1/2 of the tick period. 312 + */ 313 + data->next_timer_ns = KTIME_MAX; 314 + delta_tick = TICK_NSEC / 2; 315 + data->bucket = which_bucket(KTIME_MAX, nr_iowaiters); 316 + } 288 317 289 318 if (unlikely(drv->state_count <= 1 || latency_req == 0) || 290 319 ((data->next_timer_ns < drv->states[1].target_residency_ns || ··· 323 302 *stop_tick = !(drv->states[0].flags & CPUIDLE_FLAG_POLLING); 324 303 return 0; 325 304 } 326 - 327 - /* Round up the result for half microseconds. */ 328 - predicted_us = div_u64(data->next_timer_ns * 329 - data->correction_factor[data->bucket] + 330 - (RESOLUTION * DECAY * NSEC_PER_USEC) / 2, 331 - RESOLUTION * DECAY * NSEC_PER_USEC); 332 - /* Use the lowest expected idle interval to pick the idle state. */ 333 - predicted_ns = (u64)min(predicted_us, 334 - get_typical_interval(data, predicted_us)) * 335 - NSEC_PER_USEC; 336 305 337 306 if (tick_nohz_tick_stopped()) { 338 307 /*
+152 -85
drivers/cpuidle/governors/teo.c
··· 140 140 #include <linux/sched/topology.h> 141 141 #include <linux/tick.h> 142 142 143 + #include "gov.h" 144 + 143 145 /* 144 146 * The number of bits to shift the CPU's capacity by in order to determine 145 147 * the utilized threshold. ··· 153 151 * noise and low enough to react quickly when activity starts to ramp up. 154 152 */ 155 153 #define UTIL_THRESHOLD_SHIFT 6 156 - 157 154 158 155 /* 159 156 * The PULSE value is added to metrics when they grow and the DECAY_SHIFT value ··· 187 186 * @total: Grand total of the "intercepts" and "hits" metrics for all bins. 188 187 * @next_recent_idx: Index of the next @recent_idx entry to update. 189 188 * @recent_idx: Indices of bins corresponding to recent "intercepts". 189 + * @tick_hits: Number of "hits" after TICK_NSEC. 190 190 * @util_threshold: Threshold above which the CPU is considered utilized 191 - * @utilized: Whether the last sleep on the CPU happened while utilized 192 191 */ 193 192 struct teo_cpu { 194 193 s64 time_span_ns; ··· 197 196 unsigned int total; 198 197 int next_recent_idx; 199 198 int recent_idx[NR_RECENT]; 199 + unsigned int tick_hits; 200 200 unsigned long util_threshold; 201 - bool utilized; 202 201 }; 203 202 204 203 static DEFINE_PER_CPU(struct teo_cpu, teo_cpus); ··· 229 228 { 230 229 struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu); 231 230 int i, idx_timer = 0, idx_duration = 0; 231 + s64 target_residency_ns; 232 232 u64 measured_ns; 233 233 234 234 if (cpu_data->time_span_ns >= cpu_data->sleep_length_ns) { ··· 270 268 * fall into. 271 269 */ 272 270 for (i = 0; i < drv->state_count; i++) { 273 - s64 target_residency_ns = drv->states[i].target_residency_ns; 274 271 struct teo_bin *bin = &cpu_data->state_bins[i]; 275 272 276 273 bin->hits -= bin->hits >> DECAY_SHIFT; 277 274 bin->intercepts -= bin->intercepts >> DECAY_SHIFT; 278 275 279 276 cpu_data->total += bin->hits + bin->intercepts; 277 + 278 + target_residency_ns = drv->states[i].target_residency_ns; 280 279 281 280 if (target_residency_ns <= cpu_data->sleep_length_ns) { 282 281 idx_timer = i; ··· 294 291 cpu_data->state_bins[cpu_data->recent_idx[i]].recent--; 295 292 296 293 /* 294 + * If the deepest state's target residency is below the tick length, 295 + * make a record of it to help teo_select() decide whether or not 296 + * to stop the tick. This effectively adds an extra hits-only bin 297 + * beyond the last state-related one. 298 + */ 299 + if (target_residency_ns < TICK_NSEC) { 300 + cpu_data->tick_hits -= cpu_data->tick_hits >> DECAY_SHIFT; 301 + 302 + cpu_data->total += cpu_data->tick_hits; 303 + 304 + if (TICK_NSEC <= cpu_data->sleep_length_ns) { 305 + idx_timer = drv->state_count; 306 + if (TICK_NSEC <= measured_ns) { 307 + cpu_data->tick_hits += PULSE; 308 + goto end; 309 + } 310 + } 311 + } 312 + 313 + /* 297 314 * If the measured idle duration falls into the same bin as the sleep 298 315 * length, this is a "hit", so update the "hits" metric for that bin. 299 316 * Otherwise, update the "intercepts" metric for the bin fallen into by ··· 328 305 cpu_data->recent_idx[i] = idx_duration; 329 306 } 330 307 308 + end: 331 309 cpu_data->total += PULSE; 332 310 } 333 311 334 - static bool teo_time_ok(u64 interval_ns) 312 + static bool teo_state_ok(int i, struct cpuidle_driver *drv) 335 313 { 336 - return !tick_nohz_tick_stopped() || interval_ns >= TICK_NSEC; 337 - } 338 - 339 - static s64 teo_middle_of_bin(int idx, struct cpuidle_driver *drv) 340 - { 341 - return (drv->states[idx].target_residency_ns + 342 - drv->states[idx+1].target_residency_ns) / 2; 314 + return !tick_nohz_tick_stopped() || 315 + drv->states[i].target_residency_ns >= TICK_NSEC; 343 316 } 344 317 345 318 /** ··· 375 356 { 376 357 struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu); 377 358 s64 latency_req = cpuidle_governor_latency_req(dev->cpu); 359 + ktime_t delta_tick = TICK_NSEC / 2; 360 + unsigned int tick_intercept_sum = 0; 378 361 unsigned int idx_intercept_sum = 0; 379 362 unsigned int intercept_sum = 0; 380 363 unsigned int idx_recent_sum = 0; ··· 386 365 int constraint_idx = 0; 387 366 int idx0 = 0, idx = -1; 388 367 bool alt_intercepts, alt_recent; 389 - ktime_t delta_tick; 368 + bool cpu_utilized; 390 369 s64 duration_ns; 391 370 int i; 392 371 ··· 396 375 } 397 376 398 377 cpu_data->time_span_ns = local_clock(); 399 - 400 - duration_ns = tick_nohz_get_sleep_length(&delta_tick); 401 - cpu_data->sleep_length_ns = duration_ns; 378 + /* 379 + * Set the expected sleep length to infinity in case of an early 380 + * return. 381 + */ 382 + cpu_data->sleep_length_ns = KTIME_MAX; 402 383 403 384 /* Check if there is any choice in the first place. */ 404 385 if (drv->state_count < 2) { 405 386 idx = 0; 406 - goto end; 407 - } 408 - if (!dev->states_usage[0].disable) { 409 - idx = 0; 410 - if (drv->states[1].target_residency_ns > duration_ns) 411 - goto end; 387 + goto out_tick; 412 388 } 413 389 414 - cpu_data->utilized = teo_cpu_is_utilized(dev->cpu, cpu_data); 390 + if (!dev->states_usage[0].disable) 391 + idx = 0; 392 + 393 + cpu_utilized = teo_cpu_is_utilized(dev->cpu, cpu_data); 415 394 /* 416 395 * If the CPU is being utilized over the threshold and there are only 2 417 396 * states to choose from, the metrics need not be considered, so choose 418 397 * the shallowest non-polling state and exit. 419 398 */ 420 - if (drv->state_count < 3 && cpu_data->utilized) { 421 - for (i = 0; i < drv->state_count; ++i) { 422 - if (!dev->states_usage[i].disable && 423 - !(drv->states[i].flags & CPUIDLE_FLAG_POLLING)) { 424 - idx = i; 425 - goto end; 426 - } 399 + if (drv->state_count < 3 && cpu_utilized) { 400 + /* 401 + * If state 0 is enabled and it is not a polling one, select it 402 + * right away unless the scheduler tick has been stopped, in 403 + * which case care needs to be taken to leave the CPU in a deep 404 + * enough state in case it is not woken up any time soon after 405 + * all. If state 1 is disabled, though, state 0 must be used 406 + * anyway. 407 + */ 408 + if ((!idx && !(drv->states[0].flags & CPUIDLE_FLAG_POLLING) && 409 + teo_state_ok(0, drv)) || dev->states_usage[1].disable) { 410 + idx = 0; 411 + goto out_tick; 427 412 } 413 + /* Assume that state 1 is not a polling one and use it. */ 414 + idx = 1; 415 + duration_ns = drv->states[1].target_residency_ns; 416 + goto end; 428 417 } 429 418 430 - /* 431 - * Find the deepest idle state whose target residency does not exceed 432 - * the current sleep length and the deepest idle state not deeper than 433 - * the former whose exit latency does not exceed the current latency 434 - * constraint. Compute the sums of metrics for early wakeup pattern 435 - * detection. 436 - */ 419 + /* Compute the sums of metrics for early wakeup pattern detection. */ 437 420 for (i = 1; i < drv->state_count; i++) { 438 421 struct teo_bin *prev_bin = &cpu_data->state_bins[i-1]; 439 422 struct cpuidle_state *s = &drv->states[i]; ··· 453 428 if (dev->states_usage[i].disable) 454 429 continue; 455 430 456 - if (idx < 0) { 457 - idx = i; /* first enabled state */ 458 - idx0 = i; 459 - } 460 - 461 - if (s->target_residency_ns > duration_ns) 462 - break; 431 + if (idx < 0) 432 + idx0 = i; /* first enabled state */ 463 433 464 434 idx = i; 465 435 466 436 if (s->exit_latency_ns <= latency_req) 467 437 constraint_idx = i; 468 438 439 + /* Save the sums for the current state. */ 469 440 idx_intercept_sum = intercept_sum; 470 441 idx_hit_sum = hit_sum; 471 442 idx_recent_sum = recent_sum; ··· 470 449 /* Avoid unnecessary overhead. */ 471 450 if (idx < 0) { 472 451 idx = 0; /* No states enabled, must use 0. */ 473 - goto end; 474 - } else if (idx == idx0) { 452 + goto out_tick; 453 + } 454 + 455 + if (idx == idx0) { 456 + /* 457 + * Only one idle state is enabled, so use it, but do not 458 + * allow the tick to be stopped it is shallow enough. 459 + */ 460 + duration_ns = drv->states[idx].target_residency_ns; 475 461 goto end; 476 462 } 463 + 464 + tick_intercept_sum = intercept_sum + 465 + cpu_data->state_bins[drv->state_count-1].intercepts; 477 466 478 467 /* 479 468 * If the sum of the intercepts metric for all of the idle states ··· 492 461 * all of the deeper states, or the sum of the numbers of recent 493 462 * intercepts over all of the states shallower than the candidate one 494 463 * is greater than a half of the number of recent events taken into 495 - * account, the CPU is likely to wake up early, so find an alternative 496 - * idle state to select. 464 + * account, a shallower idle state is likely to be a better choice. 497 465 */ 498 466 alt_intercepts = 2 * idx_intercept_sum > cpu_data->total - idx_hit_sum; 499 467 alt_recent = idx_recent_sum > NR_RECENT / 2; 500 468 if (alt_recent || alt_intercepts) { 501 - s64 first_suitable_span_ns = duration_ns; 502 469 int first_suitable_idx = idx; 503 470 504 471 /* ··· 505 476 * cases (both with respect to intercepts overall and with 506 477 * respect to the recent intercepts only) in the past. 507 478 * 508 - * Take the possible latency constraint and duration limitation 509 - * present if the tick has been stopped already into account. 479 + * Take the possible duration limitation present if the tick 480 + * has been stopped already into account. 510 481 */ 511 482 intercept_sum = 0; 512 483 recent_sum = 0; 513 484 514 485 for (i = idx - 1; i >= 0; i--) { 515 486 struct teo_bin *bin = &cpu_data->state_bins[i]; 516 - s64 span_ns; 517 487 518 488 intercept_sum += bin->intercepts; 519 489 recent_sum += bin->recent; 520 490 521 - span_ns = teo_middle_of_bin(i, drv); 522 - 523 491 if ((!alt_recent || 2 * recent_sum > idx_recent_sum) && 524 492 (!alt_intercepts || 525 493 2 * intercept_sum > idx_intercept_sum)) { 526 - if (teo_time_ok(span_ns) && 527 - !dev->states_usage[i].disable) { 494 + /* 495 + * Use the current state unless it is too 496 + * shallow or disabled, in which case take the 497 + * first enabled state that is deep enough. 498 + */ 499 + if (teo_state_ok(i, drv) && 500 + !dev->states_usage[i].disable) 528 501 idx = i; 529 - duration_ns = span_ns; 530 - } else { 531 - /* 532 - * The current state is too shallow or 533 - * disabled, so take the first enabled 534 - * deeper state with suitable time span. 535 - */ 502 + else 536 503 idx = first_suitable_idx; 537 - duration_ns = first_suitable_span_ns; 538 - } 504 + 539 505 break; 540 506 } 541 507 542 508 if (dev->states_usage[i].disable) 543 509 continue; 544 510 545 - if (!teo_time_ok(span_ns)) { 511 + if (!teo_state_ok(i, drv)) { 546 512 /* 547 513 * The current state is too shallow, but if an 548 514 * alternative candidate state has been found, ··· 549 525 break; 550 526 } 551 527 552 - first_suitable_span_ns = span_ns; 553 528 first_suitable_idx = i; 554 529 } 555 530 } ··· 562 539 563 540 /* 564 541 * If the CPU is being utilized over the threshold, choose a shallower 565 - * non-polling state to improve latency 542 + * non-polling state to improve latency, unless the scheduler tick has 543 + * been stopped already and the shallower state's target residency is 544 + * not sufficiently large. 566 545 */ 567 - if (cpu_data->utilized) 568 - idx = teo_find_shallower_state(drv, dev, idx, duration_ns, true); 546 + if (cpu_utilized) { 547 + i = teo_find_shallower_state(drv, dev, idx, KTIME_MAX, true); 548 + if (teo_state_ok(i, drv)) 549 + idx = i; 550 + } 551 + 552 + /* 553 + * Skip the timers check if state 0 is the current candidate one, 554 + * because an immediate non-timer wakeup is expected in that case. 555 + */ 556 + if (!idx) 557 + goto out_tick; 558 + 559 + /* 560 + * If state 0 is a polling one, check if the target residency of 561 + * the current candidate state is low enough and skip the timers 562 + * check in that case too. 563 + */ 564 + if ((drv->states[0].flags & CPUIDLE_FLAG_POLLING) && 565 + drv->states[idx].target_residency_ns < RESIDENCY_THRESHOLD_NS) 566 + goto out_tick; 567 + 568 + duration_ns = tick_nohz_get_sleep_length(&delta_tick); 569 + cpu_data->sleep_length_ns = duration_ns; 570 + 571 + /* 572 + * If the closest expected timer is before the terget residency of the 573 + * candidate state, a shallower one needs to be found. 574 + */ 575 + if (drv->states[idx].target_residency_ns > duration_ns) { 576 + i = teo_find_shallower_state(drv, dev, idx, duration_ns, false); 577 + if (teo_state_ok(i, drv)) 578 + idx = i; 579 + } 580 + 581 + /* 582 + * If the selected state's target residency is below the tick length 583 + * and intercepts occurring before the tick length are the majority of 584 + * total wakeup events, do not stop the tick. 585 + */ 586 + if (drv->states[idx].target_residency_ns < TICK_NSEC && 587 + tick_intercept_sum > cpu_data->total / 2 + cpu_data->total / 8) 588 + duration_ns = TICK_NSEC / 2; 569 589 570 590 end: 571 591 /* 572 - * Don't stop the tick if the selected state is a polling one or if the 573 - * expected idle duration is shorter than the tick period length. 592 + * Allow the tick to be stopped unless the selected state is a polling 593 + * one or the expected idle duration is shorter than the tick period 594 + * length. 574 595 */ 575 - if (((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) || 576 - duration_ns < TICK_NSEC) && !tick_nohz_tick_stopped()) { 577 - *stop_tick = false; 596 + if ((!(drv->states[idx].flags & CPUIDLE_FLAG_POLLING) && 597 + duration_ns >= TICK_NSEC) || tick_nohz_tick_stopped()) 598 + return idx; 578 599 579 - /* 580 - * The tick is not going to be stopped, so if the target 581 - * residency of the state to be returned is not within the time 582 - * till the closest timer including the tick, try to correct 583 - * that. 584 - */ 585 - if (idx > idx0 && 586 - drv->states[idx].target_residency_ns > delta_tick) 587 - idx = teo_find_shallower_state(drv, dev, idx, delta_tick, false); 588 - } 600 + /* 601 + * The tick is not going to be stopped, so if the target residency of 602 + * the state to be returned is not within the time till the closest 603 + * timer including the tick, try to correct that. 604 + */ 605 + if (idx > idx0 && 606 + drv->states[idx].target_residency_ns > delta_tick) 607 + idx = teo_find_shallower_state(drv, dev, idx, delta_tick, false); 589 608 609 + out_tick: 610 + *stop_tick = false; 590 611 return idx; 591 612 } 592 613
+6 -4
drivers/devfreq/devfreq.c
··· 472 472 * devfreq_monitor_start() - Start load monitoring of devfreq instance 473 473 * @devfreq: the devfreq instance. 474 474 * 475 - * Helper function for starting devfreq device load monitoring. By 476 - * default delayed work based monitoring is supported. Function 477 - * to be called from governor in response to DEVFREQ_GOV_START 478 - * event when device is added to devfreq framework. 475 + * Helper function for starting devfreq device load monitoring. By default, 476 + * deferrable timer is used for load monitoring. But the users can change this 477 + * behavior using the "timer" type in devfreq_dev_profile. This function will be 478 + * called by devfreq governor in response to the DEVFREQ_GOV_START event 479 + * generated while adding a device to the devfreq framework. 479 480 */ 480 481 void devfreq_monitor_start(struct devfreq *devfreq) 481 482 { ··· 764 763 dev_pm_opp_put_opp_table(devfreq->opp_table); 765 764 766 765 mutex_destroy(&devfreq->lock); 766 + srcu_cleanup_notifier_head(&devfreq->transition_notifier_list); 767 767 kfree(devfreq); 768 768 } 769 769
+1 -1
drivers/devfreq/imx-bus.c
··· 7 7 #include <linux/devfreq.h> 8 8 #include <linux/device.h> 9 9 #include <linux/module.h> 10 - #include <linux/of_device.h> 10 + #include <linux/of.h> 11 11 #include <linux/pm_opp.h> 12 12 #include <linux/platform_device.h> 13 13 #include <linux/slab.h>
+1 -1
drivers/devfreq/imx8m-ddrc.c
··· 3 3 * Copyright 2019 NXP 4 4 */ 5 5 6 + #include <linux/mod_devicetable.h> 6 7 #include <linux/module.h> 7 8 #include <linux/device.h> 8 - #include <linux/of_device.h> 9 9 #include <linux/platform_device.h> 10 10 #include <linux/devfreq.h> 11 11 #include <linux/pm_opp.h>
-1
drivers/devfreq/mtk-cci-devfreq.c
··· 8 8 #include <linux/minmax.h> 9 9 #include <linux/module.h> 10 10 #include <linux/of.h> 11 - #include <linux/of_device.h> 12 11 #include <linux/platform_device.h> 13 12 #include <linux/pm_opp.h> 14 13 #include <linux/regulator/consumer.h>
+1 -1
drivers/devfreq/tegra30-devfreq.c
··· 13 13 #include <linux/io.h> 14 14 #include <linux/irq.h> 15 15 #include <linux/module.h> 16 - #include <linux/of_device.h> 16 + #include <linux/of.h> 17 17 #include <linux/platform_device.h> 18 18 #include <linux/pm_opp.h> 19 19 #include <linux/reset.h>
+99 -18
drivers/opp/core.c
··· 177 177 EXPORT_SYMBOL_GPL(dev_pm_opp_get_power); 178 178 179 179 /** 180 - * dev_pm_opp_get_freq() - Gets the frequency corresponding to an available opp 181 - * @opp: opp for which frequency has to be returned for 180 + * dev_pm_opp_get_freq_indexed() - Gets the frequency corresponding to an 181 + * available opp with specified index 182 + * @opp: opp for which frequency has to be returned for 183 + * @index: index of the frequency within the required opp 182 184 * 183 - * Return: frequency in hertz corresponding to the opp, else 184 - * return 0 185 + * Return: frequency in hertz corresponding to the opp with specified index, 186 + * else return 0 185 187 */ 186 - unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp) 188 + unsigned long dev_pm_opp_get_freq_indexed(struct dev_pm_opp *opp, u32 index) 187 189 { 188 - if (IS_ERR_OR_NULL(opp)) { 190 + if (IS_ERR_OR_NULL(opp) || index >= opp->opp_table->clk_count) { 189 191 pr_err("%s: Invalid parameters\n", __func__); 190 192 return 0; 191 193 } 192 194 193 - if (!assert_single_clk(opp->opp_table)) 194 - return 0; 195 - 196 - return opp->rates[0]; 195 + return opp->rates[index]; 197 196 } 198 - EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq); 197 + EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq_indexed); 199 198 200 199 /** 201 200 * dev_pm_opp_get_level() - Gets the level corresponding to an available opp ··· 226 227 unsigned int dev_pm_opp_get_required_pstate(struct dev_pm_opp *opp, 227 228 unsigned int index) 228 229 { 229 - struct opp_table *opp_table = opp->opp_table; 230 - 231 230 if (IS_ERR_OR_NULL(opp) || !opp->available || 232 - index >= opp_table->required_opp_count) { 231 + index >= opp->opp_table->required_opp_count) { 233 232 pr_err("%s: Invalid parameters\n", __func__); 234 233 return 0; 235 234 } 236 235 237 236 /* required-opps not fully initialized yet */ 238 - if (lazy_linking_pending(opp_table)) 237 + if (lazy_linking_pending(opp->opp_table)) 239 238 return 0; 240 239 241 240 /* The required OPP table must belong to a genpd */ 242 - if (unlikely(!opp_table->required_opp_tables[index]->is_genpd)) { 241 + if (unlikely(!opp->opp_table->required_opp_tables[index]->is_genpd)) { 243 242 pr_err("%s: Performance state is only valid for genpds.\n", __func__); 244 243 return 0; 245 244 } ··· 447 450 /* Helpers to read keys */ 448 451 static unsigned long _read_freq(struct dev_pm_opp *opp, int index) 449 452 { 450 - return opp->rates[0]; 453 + return opp->rates[index]; 451 454 } 452 455 453 456 static unsigned long _read_level(struct dev_pm_opp *opp, int index) ··· 623 626 } 624 627 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact); 625 628 629 + /** 630 + * dev_pm_opp_find_freq_exact_indexed() - Search for an exact freq for the 631 + * clock corresponding to the index 632 + * @dev: Device for which we do this operation 633 + * @freq: frequency to search for 634 + * @index: Clock index 635 + * @available: true/false - match for available opp 636 + * 637 + * Search for the matching exact OPP for the clock corresponding to the 638 + * specified index from a starting freq for a device. 639 + * 640 + * Return: matching *opp , else returns ERR_PTR in case of error and should be 641 + * handled using IS_ERR. Error return values can be: 642 + * EINVAL: for bad pointer 643 + * ERANGE: no match found for search 644 + * ENODEV: if device not found in list of registered devices 645 + * 646 + * The callers are required to call dev_pm_opp_put() for the returned OPP after 647 + * use. 648 + */ 649 + struct dev_pm_opp * 650 + dev_pm_opp_find_freq_exact_indexed(struct device *dev, unsigned long freq, 651 + u32 index, bool available) 652 + { 653 + return _find_key_exact(dev, freq, index, available, _read_freq, NULL); 654 + } 655 + EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact_indexed); 656 + 626 657 static noinline struct dev_pm_opp *_find_freq_ceil(struct opp_table *opp_table, 627 658 unsigned long *freq) 628 659 { ··· 684 659 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil); 685 660 686 661 /** 662 + * dev_pm_opp_find_freq_ceil_indexed() - Search for a rounded ceil freq for the 663 + * clock corresponding to the index 664 + * @dev: Device for which we do this operation 665 + * @freq: Start frequency 666 + * @index: Clock index 667 + * 668 + * Search for the matching ceil *available* OPP for the clock corresponding to 669 + * the specified index from a starting freq for a device. 670 + * 671 + * Return: matching *opp and refreshes *freq accordingly, else returns 672 + * ERR_PTR in case of error and should be handled using IS_ERR. Error return 673 + * values can be: 674 + * EINVAL: for bad pointer 675 + * ERANGE: no match found for search 676 + * ENODEV: if device not found in list of registered devices 677 + * 678 + * The callers are required to call dev_pm_opp_put() for the returned OPP after 679 + * use. 680 + */ 681 + struct dev_pm_opp * 682 + dev_pm_opp_find_freq_ceil_indexed(struct device *dev, unsigned long *freq, 683 + u32 index) 684 + { 685 + return _find_key_ceil(dev, freq, index, true, _read_freq, NULL); 686 + } 687 + EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil_indexed); 688 + 689 + /** 687 690 * dev_pm_opp_find_freq_floor() - Search for a rounded floor freq 688 691 * @dev: device for which we do this operation 689 692 * @freq: Start frequency ··· 735 682 return _find_key_floor(dev, freq, 0, true, _read_freq, assert_single_clk); 736 683 } 737 684 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor); 685 + 686 + /** 687 + * dev_pm_opp_find_freq_floor_indexed() - Search for a rounded floor freq for the 688 + * clock corresponding to the index 689 + * @dev: Device for which we do this operation 690 + * @freq: Start frequency 691 + * @index: Clock index 692 + * 693 + * Search for the matching floor *available* OPP for the clock corresponding to 694 + * the specified index from a starting freq for a device. 695 + * 696 + * Return: matching *opp and refreshes *freq accordingly, else returns 697 + * ERR_PTR in case of error and should be handled using IS_ERR. Error return 698 + * values can be: 699 + * EINVAL: for bad pointer 700 + * ERANGE: no match found for search 701 + * ENODEV: if device not found in list of registered devices 702 + * 703 + * The callers are required to call dev_pm_opp_put() for the returned OPP after 704 + * use. 705 + */ 706 + struct dev_pm_opp * 707 + dev_pm_opp_find_freq_floor_indexed(struct device *dev, unsigned long *freq, 708 + u32 index) 709 + { 710 + return _find_key_floor(dev, freq, index, true, _read_freq, NULL); 711 + } 712 + EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor_indexed); 738 713 739 714 /** 740 715 * dev_pm_opp_find_level_exact() - search for an exact level ··· 2460 2379 2461 2380 virt_dev = dev_pm_domain_attach_by_name(dev, *name); 2462 2381 if (IS_ERR_OR_NULL(virt_dev)) { 2463 - ret = PTR_ERR(virt_dev) ? : -ENODEV; 2382 + ret = virt_dev ? PTR_ERR(virt_dev) : -ENODEV; 2464 2383 dev_err(dev, "Couldn't attach to pm_domain: %d\n", ret); 2465 2384 goto err; 2466 2385 }
+2 -2
drivers/opp/cpu.c
··· 24 24 /** 25 25 * dev_pm_opp_init_cpufreq_table() - create a cpufreq table for a device 26 26 * @dev: device for which we do this operation 27 - * @table: Cpufreq table returned back to caller 27 + * @opp_table: Cpufreq table returned back to caller 28 28 * 29 29 * Generate a cpufreq table for a provided device- this assumes that the 30 30 * opp table is already initialized and ready for usage. ··· 89 89 /** 90 90 * dev_pm_opp_free_cpufreq_table() - free the cpufreq table 91 91 * @dev: device for which we do this operation 92 - * @table: table to free 92 + * @opp_table: table to free 93 93 * 94 94 * Free up the table allocated by dev_pm_opp_init_cpufreq_table 95 95 */
+92 -67
drivers/powercap/arm_scmi_powercap.c
··· 12 12 #include <linux/module.h> 13 13 #include <linux/powercap.h> 14 14 #include <linux/scmi_protocol.h> 15 + #include <linux/slab.h> 15 16 16 17 #define to_scmi_powercap_zone(z) \ 17 18 container_of(z, struct scmi_powercap_zone, zone) ··· 20 19 static const struct scmi_powercap_proto_ops *powercap_ops; 21 20 22 21 struct scmi_powercap_zone { 22 + bool registered; 23 + bool invalid; 23 24 unsigned int height; 24 25 struct device *dev; 25 26 struct scmi_protocol_handle *ph; ··· 35 32 unsigned int num_zones; 36 33 struct scmi_powercap_zone *spzones; 37 34 struct list_head *registered_zones; 35 + struct list_head scmi_zones; 38 36 }; 39 37 40 38 static struct powercap_control_type *scmi_top_pcntrl; ··· 275 271 } 276 272 } 277 273 278 - static inline bool 279 - scmi_powercap_is_zone_registered(struct scmi_powercap_zone *spz) 280 - { 281 - return !list_empty(&spz->node); 282 - } 283 - 284 274 static inline unsigned int 285 275 scmi_powercap_get_zone_height(struct scmi_powercap_zone *spz) 286 276 { ··· 293 295 return &spz->spzones[spz->info->parent_id]; 294 296 } 295 297 298 + static int scmi_powercap_register_zone(struct scmi_powercap_root *pr, 299 + struct scmi_powercap_zone *spz, 300 + struct scmi_powercap_zone *parent) 301 + { 302 + int ret = 0; 303 + struct powercap_zone *z; 304 + 305 + if (spz->invalid) { 306 + list_del(&spz->node); 307 + return -EINVAL; 308 + } 309 + 310 + z = powercap_register_zone(&spz->zone, scmi_top_pcntrl, spz->info->name, 311 + parent ? &parent->zone : NULL, 312 + &zone_ops, 1, &constraint_ops); 313 + if (!IS_ERR(z)) { 314 + spz->height = scmi_powercap_get_zone_height(spz); 315 + spz->registered = true; 316 + list_move(&spz->node, &pr->registered_zones[spz->height]); 317 + dev_dbg(spz->dev, "Registered node %s - parent %s - height:%d\n", 318 + spz->info->name, parent ? parent->info->name : "ROOT", 319 + spz->height); 320 + } else { 321 + list_del(&spz->node); 322 + ret = PTR_ERR(z); 323 + dev_err(spz->dev, 324 + "Error registering node:%s - parent:%s - h:%d - ret:%d\n", 325 + spz->info->name, 326 + parent ? parent->info->name : "ROOT", 327 + spz->height, ret); 328 + } 329 + 330 + return ret; 331 + } 332 + 296 333 /** 297 - * scmi_powercap_register_zone - Register an SCMI powercap zone recursively 334 + * scmi_zones_register- Register SCMI powercap zones starting from parent zones 298 335 * 336 + * @dev: A reference to the SCMI device 299 337 * @pr: A reference to the root powercap zones descriptors 300 - * @spz: A reference to the SCMI powercap zone to register 301 338 * 302 339 * When registering SCMI powercap zones with the powercap framework we should 303 340 * take care to always register zones starting from the root ones and to ··· 342 309 * zones provided by the SCMI platform firmware is built to comply with such 343 310 * requirement. 344 311 * 345 - * This function, given an SCMI powercap zone to register, takes care to walk 346 - * the SCMI powercap zones tree up to the root looking recursively for 347 - * unregistered parent zones before registering the provided zone; at the same 348 - * time each registered zone height in such a tree is accounted for and each 312 + * This function, given the set of SCMI powercap zones to register, takes care 313 + * to walk the SCMI powercap zones trees up to the root registering any 314 + * unregistered parent zone before registering the child zones; at the same 315 + * time each registered-zone height in such a tree is accounted for and each 349 316 * zone, once registered, is stored in the @registered_zones array that is 350 317 * indexed by zone height: this way will be trivial, at unregister time, to walk 351 318 * the @registered_zones array backward and unregister all the zones starting ··· 363 330 * 364 331 * Return: 0 on Success 365 332 */ 366 - static int scmi_powercap_register_zone(struct scmi_powercap_root *pr, 367 - struct scmi_powercap_zone *spz) 333 + static int scmi_zones_register(struct device *dev, 334 + struct scmi_powercap_root *pr) 368 335 { 369 336 int ret = 0; 370 - struct scmi_powercap_zone *parent; 337 + unsigned int sp = 0, reg_zones = 0; 338 + struct scmi_powercap_zone *spz, **zones_stack; 371 339 372 - if (!spz->info) 373 - return ret; 340 + zones_stack = kcalloc(pr->num_zones, sizeof(spz), GFP_KERNEL); 341 + if (!zones_stack) 342 + return -ENOMEM; 374 343 375 - parent = scmi_powercap_get_parent_zone(spz); 376 - if (parent && !scmi_powercap_is_zone_registered(parent)) { 377 - /* 378 - * Bail out if a parent domain was marked as unsupported: 379 - * only domains participating as leaves can be skipped. 380 - */ 381 - if (!parent->info) 382 - return -ENODEV; 344 + spz = list_first_entry_or_null(&pr->scmi_zones, 345 + struct scmi_powercap_zone, node); 346 + while (spz) { 347 + struct scmi_powercap_zone *parent; 383 348 384 - ret = scmi_powercap_register_zone(pr, parent); 385 - if (ret) 386 - return ret; 387 - } 388 - 389 - if (!scmi_powercap_is_zone_registered(spz)) { 390 - struct powercap_zone *z; 391 - 392 - z = powercap_register_zone(&spz->zone, 393 - scmi_top_pcntrl, 394 - spz->info->name, 395 - parent ? &parent->zone : NULL, 396 - &zone_ops, 1, &constraint_ops); 397 - if (!IS_ERR(z)) { 398 - spz->height = scmi_powercap_get_zone_height(spz); 399 - list_add(&spz->node, 400 - &pr->registered_zones[spz->height]); 401 - dev_dbg(spz->dev, 402 - "Registered node %s - parent %s - height:%d\n", 403 - spz->info->name, 404 - parent ? parent->info->name : "ROOT", 405 - spz->height); 406 - ret = 0; 349 + parent = scmi_powercap_get_parent_zone(spz); 350 + if (parent && !parent->registered) { 351 + zones_stack[sp++] = spz; 352 + spz = parent; 407 353 } else { 408 - ret = PTR_ERR(z); 409 - dev_err(spz->dev, 410 - "Error registering node:%s - parent:%s - h:%d - ret:%d\n", 411 - spz->info->name, 412 - parent ? parent->info->name : "ROOT", 413 - spz->height, ret); 354 + ret = scmi_powercap_register_zone(pr, spz, parent); 355 + if (!ret) { 356 + reg_zones++; 357 + } else if (sp) { 358 + /* Failed to register a non-leaf zone. 359 + * Bail-out. 360 + */ 361 + dev_err(dev, 362 + "Failed to register non-leaf zone - ret:%d\n", 363 + ret); 364 + scmi_powercap_unregister_all_zones(pr); 365 + reg_zones = 0; 366 + goto out; 367 + } 368 + /* Pick next zone to process */ 369 + if (sp) 370 + spz = zones_stack[--sp]; 371 + else 372 + spz = list_first_entry_or_null(&pr->scmi_zones, 373 + struct scmi_powercap_zone, 374 + node); 414 375 } 415 376 } 377 + 378 + out: 379 + kfree(zones_stack); 380 + dev_info(dev, "Registered %d SCMI Powercap domains !\n", reg_zones); 416 381 417 382 return ret; 418 383 } ··· 455 424 if (!pr->registered_zones) 456 425 return -ENOMEM; 457 426 427 + INIT_LIST_HEAD(&pr->scmi_zones); 428 + 458 429 for (i = 0, spz = pr->spzones; i < pr->num_zones; i++, spz++) { 459 430 /* 460 431 * Powercap domains are validate by the protocol layer, i.e. ··· 471 438 INIT_LIST_HEAD(&spz->node); 472 439 INIT_LIST_HEAD(&pr->registered_zones[i]); 473 440 441 + list_add_tail(&spz->node, &pr->scmi_zones); 474 442 /* 475 443 * Forcibly skip powercap domains using an abstract scale. 476 444 * Note that only leaves domains can be skipped, so this could ··· 482 448 dev_warn(dev, 483 449 "Abstract power scale not supported. Skip %s.\n", 484 450 spz->info->name); 485 - spz->info = NULL; 451 + spz->invalid = true; 486 452 continue; 487 453 } 488 454 } ··· 491 457 * Scan array of retrieved SCMI powercap domains and register them 492 458 * recursively starting from the root domains. 493 459 */ 494 - for (i = 0, spz = pr->spzones; i < pr->num_zones; i++, spz++) { 495 - ret = scmi_powercap_register_zone(pr, spz); 496 - if (ret) { 497 - dev_err(dev, 498 - "Failed to register powercap zone %s - ret:%d\n", 499 - spz->info->name, ret); 500 - scmi_powercap_unregister_all_zones(pr); 501 - return ret; 502 - } 503 - } 460 + ret = scmi_zones_register(dev, pr); 461 + if (ret) 462 + return ret; 504 463 505 464 dev_set_drvdata(dev, pr); 506 - 507 - dev_info(dev, "Registered %d SCMI Powercap domains !\n", pr->num_zones); 508 465 509 466 return ret; 510 467 }
+1 -1
drivers/powercap/intel_rapl_common.c
··· 1485 1485 } 1486 1486 pr_debug("found %d domains on %s\n", rp->nr_domains, rp->name); 1487 1487 1488 - rp->domains = kcalloc(rp->nr_domains + 1, sizeof(struct rapl_domain), 1488 + rp->domains = kcalloc(rp->nr_domains, sizeof(struct rapl_domain), 1489 1489 GFP_KERNEL); 1490 1490 if (!rp->domains) 1491 1491 return -ENOMEM;
+4 -12
include/linux/cpufreq.h
··· 19 19 #include <linux/pm_qos.h> 20 20 #include <linux/spinlock.h> 21 21 #include <linux/sysfs.h> 22 + #include <linux/minmax.h> 22 23 23 24 /********************************************************************* 24 25 * CPUFREQ INTERFACE * ··· 371 370 int (*target_intermediate)(struct cpufreq_policy *policy, 372 371 unsigned int index); 373 372 374 - /* should be defined, if possible */ 373 + /* should be defined, if possible, return 0 on error */ 375 374 unsigned int (*get)(unsigned int cpu); 376 375 377 376 /* Called to update policy limits on firmware notifications. */ ··· 468 467 unsigned int min, 469 468 unsigned int max) 470 469 { 471 - if (policy->min < min) 472 - policy->min = min; 473 - if (policy->max < min) 474 - policy->max = min; 475 - if (policy->min > max) 476 - policy->min = max; 477 - if (policy->max > max) 478 - policy->max = max; 479 - if (policy->min > policy->max) 480 - policy->min = policy->max; 481 - return; 470 + policy->max = clamp(policy->max, min, max); 471 + policy->min = clamp(policy->min, min, policy->max); 482 472 } 483 473 484 474 static inline void
+54 -18
include/linux/pm_opp.h
··· 103 103 104 104 unsigned long dev_pm_opp_get_power(struct dev_pm_opp *opp); 105 105 106 - unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp); 106 + unsigned long dev_pm_opp_get_freq_indexed(struct dev_pm_opp *opp, u32 index); 107 107 108 108 unsigned int dev_pm_opp_get_level(struct dev_pm_opp *opp); 109 109 ··· 121 121 struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, 122 122 unsigned long freq, 123 123 bool available); 124 + 125 + struct dev_pm_opp * 126 + dev_pm_opp_find_freq_exact_indexed(struct device *dev, unsigned long freq, 127 + u32 index, bool available); 128 + 124 129 struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, 125 130 unsigned long *freq); 126 131 127 - struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, 128 - unsigned int level); 129 - struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev, 130 - unsigned int *level); 132 + struct dev_pm_opp *dev_pm_opp_find_freq_floor_indexed(struct device *dev, 133 + unsigned long *freq, u32 index); 131 134 132 135 struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, 133 136 unsigned long *freq); 137 + 138 + struct dev_pm_opp *dev_pm_opp_find_freq_ceil_indexed(struct device *dev, 139 + unsigned long *freq, u32 index); 140 + 141 + struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, 142 + unsigned int level); 143 + 144 + struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev, 145 + unsigned int *level); 134 146 135 147 struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev, 136 148 unsigned int *bw, int index); ··· 212 200 return 0; 213 201 } 214 202 215 - static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp) 203 + static inline unsigned long dev_pm_opp_get_freq_indexed(struct dev_pm_opp *opp, u32 index) 216 204 { 217 205 return 0; 218 206 } ··· 259 247 return 0; 260 248 } 261 249 262 - static inline struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, 263 - unsigned int level) 264 - { 265 - return ERR_PTR(-EOPNOTSUPP); 266 - } 267 - 268 - static inline struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev, 269 - unsigned int *level) 270 - { 271 - return ERR_PTR(-EOPNOTSUPP); 272 - } 273 - 274 250 static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, 275 251 unsigned long freq, bool available) 252 + { 253 + return ERR_PTR(-EOPNOTSUPP); 254 + } 255 + 256 + static inline struct dev_pm_opp * 257 + dev_pm_opp_find_freq_exact_indexed(struct device *dev, unsigned long freq, 258 + u32 index, bool available) 276 259 { 277 260 return ERR_PTR(-EOPNOTSUPP); 278 261 } ··· 278 271 return ERR_PTR(-EOPNOTSUPP); 279 272 } 280 273 274 + static inline struct dev_pm_opp * 275 + dev_pm_opp_find_freq_floor_indexed(struct device *dev, unsigned long *freq, u32 index) 276 + { 277 + return ERR_PTR(-EOPNOTSUPP); 278 + } 279 + 281 280 static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, 282 281 unsigned long *freq) 282 + { 283 + return ERR_PTR(-EOPNOTSUPP); 284 + } 285 + 286 + static inline struct dev_pm_opp * 287 + dev_pm_opp_find_freq_ceil_indexed(struct device *dev, unsigned long *freq, u32 index) 288 + { 289 + return ERR_PTR(-EOPNOTSUPP); 290 + } 291 + 292 + static inline struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, 293 + unsigned int level) 294 + { 295 + return ERR_PTR(-EOPNOTSUPP); 296 + } 297 + 298 + static inline struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev, 299 + unsigned int *level) 283 300 { 284 301 return ERR_PTR(-EOPNOTSUPP); 285 302 } ··· 660 629 static inline void dev_pm_opp_put_prop_name(int token) 661 630 { 662 631 dev_pm_opp_clear_config(token); 632 + } 633 + 634 + static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp) 635 + { 636 + return dev_pm_opp_get_freq_indexed(opp, 0); 663 637 } 664 638 665 639 #endif /* __LINUX_OPP_H__ */
-2
include/linux/pm_runtime.h
··· 85 85 extern void __pm_runtime_use_autosuspend(struct device *dev, bool use); 86 86 extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay); 87 87 extern u64 pm_runtime_autosuspend_expiration(struct device *dev); 88 - extern void pm_runtime_update_max_time_suspended(struct device *dev, 89 - s64 delta_ns); 90 88 extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable); 91 89 extern void pm_runtime_get_suppliers(struct device *dev); 92 90 extern void pm_runtime_put_suppliers(struct device *dev);
+10
include/linux/pm_wakeup.h
··· 194 194 195 195 #endif /* !CONFIG_PM_SLEEP */ 196 196 197 + static inline bool device_awake_path(struct device *dev) 198 + { 199 + return device_wakeup_path(dev); 200 + } 201 + 202 + static inline void device_set_awake_path(struct device *dev) 203 + { 204 + device_set_wakeup_path(dev); 205 + } 206 + 197 207 static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) 198 208 { 199 209 return pm_wakeup_ws_event(ws, msec, false);
+7 -2
kernel/power/qos.c
··· 220 220 .type = PM_QOS_MIN, 221 221 }; 222 222 223 + static inline bool cpu_latency_qos_value_invalid(s32 value) 224 + { 225 + return value < 0 && value != PM_QOS_DEFAULT_VALUE; 226 + } 227 + 223 228 /** 224 229 * cpu_latency_qos_limit - Return current system-wide CPU latency QoS limit. 225 230 */ ··· 268 263 */ 269 264 void cpu_latency_qos_add_request(struct pm_qos_request *req, s32 value) 270 265 { 271 - if (!req) 266 + if (!req || cpu_latency_qos_value_invalid(value)) 272 267 return; 273 268 274 269 if (cpu_latency_qos_request_active(req)) { ··· 294 289 */ 295 290 void cpu_latency_qos_update_request(struct pm_qos_request *req, s32 new_value) 296 291 { 297 - if (!req) 292 + if (!req || cpu_latency_qos_value_invalid(new_value)) 298 293 return; 299 294 300 295 if (!cpu_latency_qos_request_active(req)) {
+149 -38
kernel/power/snapshot.c
··· 404 404 struct mem_zone_bm_rtree *zone; 405 405 struct rtree_node *node; 406 406 unsigned long node_pfn; 407 + unsigned long cur_pfn; 407 408 int node_bit; 408 409 }; 409 410 ··· 590 589 bm->cur.node = list_entry(bm->cur.zone->leaves.next, 591 590 struct rtree_node, list); 592 591 bm->cur.node_pfn = 0; 592 + bm->cur.cur_pfn = BM_END_OF_MAP; 593 593 bm->cur.node_bit = 0; 594 594 } 595 595 ··· 801 799 bm->cur.zone = zone; 802 800 bm->cur.node = node; 803 801 bm->cur.node_pfn = (pfn - zone->start_pfn) & ~BM_BLOCK_MASK; 802 + bm->cur.cur_pfn = pfn; 804 803 805 804 /* Set return values */ 806 805 *addr = node->data; ··· 851 848 852 849 bit = max(bm->cur.node_bit - 1, 0); 853 850 clear_bit(bit, bm->cur.node->data); 851 + } 852 + 853 + static unsigned long memory_bm_get_current(struct memory_bitmap *bm) 854 + { 855 + return bm->cur.cur_pfn; 854 856 } 855 857 856 858 static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) ··· 937 929 if (bit < bits) { 938 930 pfn = bm->cur.zone->start_pfn + bm->cur.node_pfn + bit; 939 931 bm->cur.node_bit = bit + 1; 932 + bm->cur.cur_pfn = pfn; 940 933 return pfn; 941 934 } 942 935 } while (rtree_next_node(bm)); 943 936 937 + bm->cur.cur_pfn = BM_END_OF_MAP; 944 938 return BM_END_OF_MAP; 945 939 } 946 940 ··· 1433 1423 1434 1424 /* 1435 1425 * This is needed, because copy_page and memcpy are not usable for copying 1436 - * task structs. 1426 + * task structs. Returns true if the page was filled with only zeros, 1427 + * otherwise false. 1437 1428 */ 1438 - static inline void do_copy_page(long *dst, long *src) 1429 + static inline bool do_copy_page(long *dst, long *src) 1439 1430 { 1431 + long z = 0; 1440 1432 int n; 1441 1433 1442 - for (n = PAGE_SIZE / sizeof(long); n; n--) 1434 + for (n = PAGE_SIZE / sizeof(long); n; n--) { 1435 + z |= *src; 1443 1436 *dst++ = *src++; 1437 + } 1438 + return !z; 1444 1439 } 1445 1440 1446 1441 /** ··· 1454 1439 * Check if the page we are going to copy is marked as present in the kernel 1455 1440 * page tables. This always is the case if CONFIG_DEBUG_PAGEALLOC or 1456 1441 * CONFIG_ARCH_HAS_SET_DIRECT_MAP is not set. In that case kernel_page_present() 1457 - * always returns 'true'. 1442 + * always returns 'true'. Returns true if the page was entirely composed of 1443 + * zeros, otherwise it will return false. 1458 1444 */ 1459 - static void safe_copy_page(void *dst, struct page *s_page) 1445 + static bool safe_copy_page(void *dst, struct page *s_page) 1460 1446 { 1447 + bool zeros_only; 1448 + 1461 1449 if (kernel_page_present(s_page)) { 1462 - do_copy_page(dst, page_address(s_page)); 1450 + zeros_only = do_copy_page(dst, page_address(s_page)); 1463 1451 } else { 1464 1452 hibernate_map_page(s_page); 1465 - do_copy_page(dst, page_address(s_page)); 1453 + zeros_only = do_copy_page(dst, page_address(s_page)); 1466 1454 hibernate_unmap_page(s_page); 1467 1455 } 1456 + return zeros_only; 1468 1457 } 1469 1458 1470 1459 #ifdef CONFIG_HIGHMEM ··· 1478 1459 saveable_highmem_page(zone, pfn) : saveable_page(zone, pfn); 1479 1460 } 1480 1461 1481 - static void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) 1462 + static bool copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) 1482 1463 { 1483 1464 struct page *s_page, *d_page; 1484 1465 void *src, *dst; 1466 + bool zeros_only; 1485 1467 1486 1468 s_page = pfn_to_page(src_pfn); 1487 1469 d_page = pfn_to_page(dst_pfn); 1488 1470 if (PageHighMem(s_page)) { 1489 1471 src = kmap_atomic(s_page); 1490 1472 dst = kmap_atomic(d_page); 1491 - do_copy_page(dst, src); 1473 + zeros_only = do_copy_page(dst, src); 1492 1474 kunmap_atomic(dst); 1493 1475 kunmap_atomic(src); 1494 1476 } else { ··· 1498 1478 * The page pointed to by src may contain some kernel 1499 1479 * data modified by kmap_atomic() 1500 1480 */ 1501 - safe_copy_page(buffer, s_page); 1481 + zeros_only = safe_copy_page(buffer, s_page); 1502 1482 dst = kmap_atomic(d_page); 1503 1483 copy_page(dst, buffer); 1504 1484 kunmap_atomic(dst); 1505 1485 } else { 1506 - safe_copy_page(page_address(d_page), s_page); 1486 + zeros_only = safe_copy_page(page_address(d_page), s_page); 1507 1487 } 1508 1488 } 1489 + return zeros_only; 1509 1490 } 1510 1491 #else 1511 1492 #define page_is_saveable(zone, pfn) saveable_page(zone, pfn) 1512 1493 1513 - static inline void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) 1494 + static inline int copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) 1514 1495 { 1515 - safe_copy_page(page_address(pfn_to_page(dst_pfn)), 1496 + return safe_copy_page(page_address(pfn_to_page(dst_pfn)), 1516 1497 pfn_to_page(src_pfn)); 1517 1498 } 1518 1499 #endif /* CONFIG_HIGHMEM */ 1519 1500 1520 - static void copy_data_pages(struct memory_bitmap *copy_bm, 1521 - struct memory_bitmap *orig_bm) 1501 + /* 1502 + * Copy data pages will copy all pages into pages pulled from the copy_bm. 1503 + * If a page was entirely filled with zeros it will be marked in the zero_bm. 1504 + * 1505 + * Returns the number of pages copied. 1506 + */ 1507 + static unsigned long copy_data_pages(struct memory_bitmap *copy_bm, 1508 + struct memory_bitmap *orig_bm, 1509 + struct memory_bitmap *zero_bm) 1522 1510 { 1511 + unsigned long copied_pages = 0; 1523 1512 struct zone *zone; 1524 - unsigned long pfn; 1513 + unsigned long pfn, copy_pfn; 1525 1514 1526 1515 for_each_populated_zone(zone) { 1527 1516 unsigned long max_zone_pfn; ··· 1543 1514 } 1544 1515 memory_bm_position_reset(orig_bm); 1545 1516 memory_bm_position_reset(copy_bm); 1517 + copy_pfn = memory_bm_next_pfn(copy_bm); 1546 1518 for(;;) { 1547 1519 pfn = memory_bm_next_pfn(orig_bm); 1548 1520 if (unlikely(pfn == BM_END_OF_MAP)) 1549 1521 break; 1550 - copy_data_page(memory_bm_next_pfn(copy_bm), pfn); 1522 + if (copy_data_page(copy_pfn, pfn)) { 1523 + memory_bm_set_bit(zero_bm, pfn); 1524 + /* Use this copy_pfn for a page that is not full of zeros */ 1525 + continue; 1526 + } 1527 + copied_pages++; 1528 + copy_pfn = memory_bm_next_pfn(copy_bm); 1551 1529 } 1530 + return copied_pages; 1552 1531 } 1553 1532 1554 1533 /* Total number of image pages */ 1555 1534 static unsigned int nr_copy_pages; 1556 1535 /* Number of pages needed for saving the original pfns of the image pages */ 1557 1536 static unsigned int nr_meta_pages; 1537 + /* Number of zero pages */ 1538 + static unsigned int nr_zero_pages; 1539 + 1558 1540 /* 1559 1541 * Numbers of normal and highmem page frames allocated for hibernation image 1560 1542 * before suspending devices. ··· 1585 1545 * this purpose. 1586 1546 */ 1587 1547 static struct memory_bitmap copy_bm; 1548 + 1549 + /* Memory bitmap which tracks which saveable pages were zero filled. */ 1550 + static struct memory_bitmap zero_bm; 1588 1551 1589 1552 /** 1590 1553 * swsusp_free - Free pages allocated for hibernation image. ··· 1633 1590 out: 1634 1591 nr_copy_pages = 0; 1635 1592 nr_meta_pages = 0; 1593 + nr_zero_pages = 0; 1636 1594 restore_pblist = NULL; 1637 1595 buffer = NULL; 1638 1596 alloc_normal = 0; ··· 1852 1808 goto err_out; 1853 1809 } 1854 1810 1811 + error = memory_bm_create(&zero_bm, GFP_IMAGE, PG_ANY); 1812 + if (error) { 1813 + pr_err("Cannot allocate zero bitmap\n"); 1814 + goto err_out; 1815 + } 1816 + 1855 1817 alloc_normal = 0; 1856 1818 alloc_highmem = 0; 1819 + nr_zero_pages = 0; 1857 1820 1858 1821 /* Count the number of saveable data pages. */ 1859 1822 save_highmem = count_highmem_pages(); ··· 2140 2089 * Kill them. 2141 2090 */ 2142 2091 drain_local_pages(NULL); 2143 - copy_data_pages(&copy_bm, &orig_bm); 2092 + nr_copy_pages = copy_data_pages(&copy_bm, &orig_bm, &zero_bm); 2144 2093 2145 2094 /* 2146 2095 * End of critical section. From now on, we can write to memory, 2147 2096 * but we should not touch disk. This specially means we must _not_ 2148 2097 * touch swap space! Except we must write out our image of course. 2149 2098 */ 2150 - 2151 2099 nr_pages += nr_highmem; 2152 - nr_copy_pages = nr_pages; 2100 + /* We don't actually copy the zero pages */ 2101 + nr_zero_pages = nr_pages - nr_copy_pages; 2153 2102 nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE); 2154 2103 2155 - pr_info("Image created (%d pages copied)\n", nr_pages); 2104 + pr_info("Image created (%d pages copied, %d zero pages)\n", nr_copy_pages, nr_zero_pages); 2156 2105 2157 2106 return 0; 2158 2107 } ··· 2197 2146 return init_header_complete(info); 2198 2147 } 2199 2148 2149 + #define ENCODED_PFN_ZERO_FLAG ((unsigned long)1 << (BITS_PER_LONG - 1)) 2150 + #define ENCODED_PFN_MASK (~ENCODED_PFN_ZERO_FLAG) 2151 + 2200 2152 /** 2201 2153 * pack_pfns - Prepare PFNs for saving. 2202 2154 * @bm: Memory bitmap. 2203 2155 * @buf: Memory buffer to store the PFNs in. 2156 + * @zero_bm: Memory bitmap containing PFNs of zero pages. 2204 2157 * 2205 2158 * PFNs corresponding to set bits in @bm are stored in the area of memory 2206 - * pointed to by @buf (1 page at a time). 2159 + * pointed to by @buf (1 page at a time). Pages which were filled with only 2160 + * zeros will have the highest bit set in the packed format to distinguish 2161 + * them from PFNs which will be contained in the image file. 2207 2162 */ 2208 - static inline void pack_pfns(unsigned long *buf, struct memory_bitmap *bm) 2163 + static inline void pack_pfns(unsigned long *buf, struct memory_bitmap *bm, 2164 + struct memory_bitmap *zero_bm) 2209 2165 { 2210 2166 int j; 2211 2167 ··· 2220 2162 buf[j] = memory_bm_next_pfn(bm); 2221 2163 if (unlikely(buf[j] == BM_END_OF_MAP)) 2222 2164 break; 2165 + if (memory_bm_test_bit(zero_bm, buf[j])) 2166 + buf[j] |= ENCODED_PFN_ZERO_FLAG; 2223 2167 } 2224 2168 } 2225 2169 ··· 2263 2203 memory_bm_position_reset(&copy_bm); 2264 2204 } else if (handle->cur <= nr_meta_pages) { 2265 2205 clear_page(buffer); 2266 - pack_pfns(buffer, &orig_bm); 2206 + pack_pfns(buffer, &orig_bm, &zero_bm); 2267 2207 } else { 2268 2208 struct page *page; 2269 2209 ··· 2359 2299 * unpack_orig_pfns - Set bits corresponding to given PFNs in a memory bitmap. 2360 2300 * @bm: Memory bitmap. 2361 2301 * @buf: Area of memory containing the PFNs. 2302 + * @zero_bm: Memory bitmap with the zero PFNs marked. 2362 2303 * 2363 2304 * For each element of the array pointed to by @buf (1 page at a time), set the 2364 - * corresponding bit in @bm. 2305 + * corresponding bit in @bm. If the page was originally populated with only 2306 + * zeros then a corresponding bit will also be set in @zero_bm. 2365 2307 */ 2366 - static int unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm) 2308 + static int unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm, 2309 + struct memory_bitmap *zero_bm) 2367 2310 { 2311 + unsigned long decoded_pfn; 2312 + bool zero; 2368 2313 int j; 2369 2314 2370 2315 for (j = 0; j < PAGE_SIZE / sizeof(long); j++) { 2371 2316 if (unlikely(buf[j] == BM_END_OF_MAP)) 2372 2317 break; 2373 2318 2374 - if (pfn_valid(buf[j]) && memory_bm_pfn_present(bm, buf[j])) { 2375 - memory_bm_set_bit(bm, buf[j]); 2319 + zero = !!(buf[j] & ENCODED_PFN_ZERO_FLAG); 2320 + decoded_pfn = buf[j] & ENCODED_PFN_MASK; 2321 + if (pfn_valid(decoded_pfn) && memory_bm_pfn_present(bm, decoded_pfn)) { 2322 + memory_bm_set_bit(bm, decoded_pfn); 2323 + if (zero) { 2324 + memory_bm_set_bit(zero_bm, decoded_pfn); 2325 + nr_zero_pages++; 2326 + } 2376 2327 } else { 2377 - if (!pfn_valid(buf[j])) 2328 + if (!pfn_valid(decoded_pfn)) 2378 2329 pr_err(FW_BUG "Memory map mismatch at 0x%llx after hibernation\n", 2379 - (unsigned long long)PFN_PHYS(buf[j])); 2330 + (unsigned long long)PFN_PHYS(decoded_pfn)); 2380 2331 return -EFAULT; 2381 2332 } 2382 2333 } ··· 2609 2538 * prepare_image - Make room for loading hibernation image. 2610 2539 * @new_bm: Uninitialized memory bitmap structure. 2611 2540 * @bm: Memory bitmap with unsafe pages marked. 2541 + * @zero_bm: Memory bitmap containing the zero pages. 2612 2542 * 2613 2543 * Use @bm to mark the pages that will be overwritten in the process of 2614 2544 * restoring the system memory state from the suspend image ("unsafe" pages) ··· 2620 2548 * pages will be used for just yet. Instead, we mark them all as allocated and 2621 2549 * create a lists of "safe" pages to be used later. On systems with high 2622 2550 * memory a list of "safe" highmem pages is created too. 2551 + * 2552 + * Because it was not known which pages were unsafe when @zero_bm was created, 2553 + * make a copy of it and recreate it within safe pages. 2623 2554 */ 2624 - static int prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm) 2555 + static int prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm, 2556 + struct memory_bitmap *zero_bm) 2625 2557 { 2626 2558 unsigned int nr_pages, nr_highmem; 2559 + struct memory_bitmap tmp; 2627 2560 struct linked_page *lp; 2628 2561 int error; 2629 2562 ··· 2645 2568 2646 2569 duplicate_memory_bitmap(new_bm, bm); 2647 2570 memory_bm_free(bm, PG_UNSAFE_KEEP); 2571 + 2572 + /* Make a copy of zero_bm so it can be created in safe pages */ 2573 + error = memory_bm_create(&tmp, GFP_ATOMIC, PG_ANY); 2574 + if (error) 2575 + goto Free; 2576 + 2577 + duplicate_memory_bitmap(&tmp, zero_bm); 2578 + memory_bm_free(zero_bm, PG_UNSAFE_KEEP); 2579 + 2580 + /* Recreate zero_bm in safe pages */ 2581 + error = memory_bm_create(zero_bm, GFP_ATOMIC, PG_SAFE); 2582 + if (error) 2583 + goto Free; 2584 + 2585 + duplicate_memory_bitmap(zero_bm, &tmp); 2586 + memory_bm_free(&tmp, PG_UNSAFE_KEEP); 2587 + /* At this point zero_bm is in safe pages and it can be used for restoring. */ 2588 + 2648 2589 if (nr_highmem > 0) { 2649 2590 error = prepare_highmem_image(bm, &nr_highmem); 2650 2591 if (error) ··· 2677 2582 * 2678 2583 * nr_copy_pages cannot be less than allocated_unsafe_pages too. 2679 2584 */ 2680 - nr_pages = nr_copy_pages - nr_highmem - allocated_unsafe_pages; 2585 + nr_pages = (nr_zero_pages + nr_copy_pages) - nr_highmem - allocated_unsafe_pages; 2681 2586 nr_pages = DIV_ROUND_UP(nr_pages, PBES_PER_LINKED_PAGE); 2682 2587 while (nr_pages > 0) { 2683 2588 lp = get_image_page(GFP_ATOMIC, PG_SAFE); ··· 2690 2595 nr_pages--; 2691 2596 } 2692 2597 /* Preallocate memory for the image */ 2693 - nr_pages = nr_copy_pages - nr_highmem - allocated_unsafe_pages; 2598 + nr_pages = (nr_zero_pages + nr_copy_pages) - nr_highmem - allocated_unsafe_pages; 2694 2599 while (nr_pages > 0) { 2695 2600 lp = (struct linked_page *)get_zeroed_page(GFP_ATOMIC); 2696 2601 if (!lp) { ··· 2778 2683 static struct chain_allocator ca; 2779 2684 int error = 0; 2780 2685 2686 + next: 2781 2687 /* Check if we have already loaded the entire image */ 2782 - if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages) 2688 + if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages + nr_zero_pages) 2783 2689 return 0; 2784 2690 2785 2691 handle->sync_read = 1; ··· 2805 2709 if (error) 2806 2710 return error; 2807 2711 2712 + error = memory_bm_create(&zero_bm, GFP_ATOMIC, PG_ANY); 2713 + if (error) 2714 + return error; 2715 + 2716 + nr_zero_pages = 0; 2717 + 2808 2718 hibernate_restore_protection_begin(); 2809 2719 } else if (handle->cur <= nr_meta_pages + 1) { 2810 - error = unpack_orig_pfns(buffer, &copy_bm); 2720 + error = unpack_orig_pfns(buffer, &copy_bm, &zero_bm); 2811 2721 if (error) 2812 2722 return error; 2813 2723 2814 2724 if (handle->cur == nr_meta_pages + 1) { 2815 - error = prepare_image(&orig_bm, &copy_bm); 2725 + error = prepare_image(&orig_bm, &copy_bm, &zero_bm); 2816 2726 if (error) 2817 2727 return error; 2818 2728 2819 2729 chain_init(&ca, GFP_ATOMIC, PG_SAFE); 2820 2730 memory_bm_position_reset(&orig_bm); 2731 + memory_bm_position_reset(&zero_bm); 2821 2732 restore_pblist = NULL; 2822 2733 handle->buffer = get_buffer(&orig_bm, &ca); 2823 2734 handle->sync_read = 0; ··· 2841 2738 handle->sync_read = 0; 2842 2739 } 2843 2740 handle->cur++; 2741 + 2742 + /* Zero pages were not included in the image, memset it and move on. */ 2743 + if (handle->cur > nr_meta_pages + 1 && 2744 + memory_bm_test_bit(&zero_bm, memory_bm_get_current(&orig_bm))) { 2745 + memset(handle->buffer, 0, PAGE_SIZE); 2746 + goto next; 2747 + } 2748 + 2844 2749 return PAGE_SIZE; 2845 2750 } 2846 2751 ··· 2865 2754 copy_last_highmem_page(); 2866 2755 hibernate_restore_protect_page(handle->buffer); 2867 2756 /* Do that only if we have loaded the image entirely */ 2868 - if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages) { 2757 + if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages + nr_zero_pages) { 2869 2758 memory_bm_recycle(&orig_bm); 2870 2759 free_highmem_data(); 2871 2760 } ··· 2874 2763 int snapshot_image_loaded(struct snapshot_handle *handle) 2875 2764 { 2876 2765 return !(!nr_copy_pages || !last_highmem_page_copied() || 2877 - handle->cur <= nr_meta_pages + nr_copy_pages); 2766 + handle->cur <= nr_meta_pages + nr_copy_pages + nr_zero_pages); 2878 2767 } 2879 2768 2880 2769 #ifdef CONFIG_HIGHMEM
+1 -1
tools/power/cpupower/Makefile
··· 53 53 54 54 VERSION:= $(shell ./utils/version-gen.sh) 55 55 LIB_MAJ= 0.0.1 56 - LIB_MIN= 0 56 + LIB_MIN= 1 57 57 58 58 PACKAGE = cpupower 59 59 PACKAGE_BUGREPORT = linux-pm@vger.kernel.org
+7
tools/power/cpupower/lib/cpupower.c
··· 14 14 #include "cpupower.h" 15 15 #include "cpupower_intern.h" 16 16 17 + int is_valid_path(const char *path) 18 + { 19 + if (access(path, F_OK) == -1) 20 + return 0; 21 + return 1; 22 + } 23 + 17 24 unsigned int cpupower_read_sysfs(const char *path, char *buf, size_t buflen) 18 25 { 19 26 ssize_t numread;
+1
tools/power/cpupower/lib/cpupower_intern.h
··· 7 7 8 8 #define SYSFS_PATH_MAX 255 9 9 10 + int is_valid_path(const char *path); 10 11 unsigned int cpupower_read_sysfs(const char *path, char *buf, size_t buflen); 11 12 unsigned int cpupower_write_sysfs(const char *path, char *buf, size_t buflen);
+7 -9
tools/power/cpupower/utils/cpuidle-set.c
··· 41 41 cont = 0; 42 42 break; 43 43 case 'd': 44 - if (param) { 45 - param = -1; 46 - cont = 0; 47 - break; 48 - } 49 - param = ret; 50 - idlestate = atoi(optarg); 51 - break; 52 44 case 'e': 53 45 if (param) { 54 46 param = -1; ··· 48 56 break; 49 57 } 50 58 param = ret; 51 - idlestate = atoi(optarg); 59 + strtol(optarg, &endptr, 10); 60 + if (*endptr != '\0') { 61 + printf(_("Bad value: %s, Integer expected\n"), optarg); 62 + exit(EXIT_FAILURE); 63 + } else { 64 + idlestate = atoi(optarg); 65 + } 52 66 break; 53 67 case 'D': 54 68 if (param) {
+63 -2
tools/power/cpupower/utils/cpupower-set.c
··· 18 18 19 19 static struct option set_opts[] = { 20 20 {"perf-bias", required_argument, NULL, 'b'}, 21 + {"epp", required_argument, NULL, 'e'}, 22 + {"amd-pstate-mode", required_argument, NULL, 'm'}, 23 + {"turbo-boost", required_argument, NULL, 't'}, 21 24 { }, 22 25 }; 23 26 ··· 40 37 union { 41 38 struct { 42 39 int perf_bias:1; 40 + int epp:1; 41 + int mode:1; 42 + int turbo_boost:1; 43 43 }; 44 44 int params; 45 45 } params; 46 - int perf_bias = 0; 46 + int perf_bias = 0, turbo_boost = 1; 47 47 int ret = 0; 48 + char epp[30], mode[20]; 48 49 49 50 ret = uname(&uts); 50 51 if (!ret && (!strcmp(uts.machine, "ppc64le") || ··· 62 55 63 56 params.params = 0; 64 57 /* parameter parsing */ 65 - while ((ret = getopt_long(argc, argv, "b:", 58 + while ((ret = getopt_long(argc, argv, "b:e:m:", 66 59 set_opts, NULL)) != -1) { 67 60 switch (ret) { 68 61 case 'b': ··· 76 69 } 77 70 params.perf_bias = 1; 78 71 break; 72 + case 'e': 73 + if (params.epp) 74 + print_wrong_arg_exit(); 75 + if (sscanf(optarg, "%29s", epp) != 1) { 76 + print_wrong_arg_exit(); 77 + return -EINVAL; 78 + } 79 + params.epp = 1; 80 + break; 81 + case 'm': 82 + if (cpupower_cpu_info.vendor != X86_VENDOR_AMD) 83 + print_wrong_arg_exit(); 84 + if (params.mode) 85 + print_wrong_arg_exit(); 86 + if (sscanf(optarg, "%19s", mode) != 1) { 87 + print_wrong_arg_exit(); 88 + return -EINVAL; 89 + } 90 + params.mode = 1; 91 + break; 92 + case 't': 93 + if (params.turbo_boost) 94 + print_wrong_arg_exit(); 95 + turbo_boost = atoi(optarg); 96 + if (turbo_boost < 0 || turbo_boost > 1) { 97 + printf("--turbo-boost param out of range [0-1]\n"); 98 + print_wrong_arg_exit(); 99 + } 100 + params.turbo_boost = 1; 101 + break; 102 + 103 + 79 104 default: 80 105 print_wrong_arg_exit(); 81 106 } ··· 115 76 116 77 if (!params.params) 117 78 print_wrong_arg_exit(); 79 + 80 + if (params.mode) { 81 + ret = cpupower_set_amd_pstate_mode(mode); 82 + if (ret) 83 + fprintf(stderr, "Error setting mode\n"); 84 + } 85 + 86 + if (params.turbo_boost) { 87 + ret = cpupower_set_turbo_boost(turbo_boost); 88 + if (ret) 89 + fprintf(stderr, "Error setting turbo-boost\n"); 90 + } 118 91 119 92 /* Default is: set all CPUs */ 120 93 if (bitmask_isallclear(cpus_chosen)) ··· 153 102 break; 154 103 } 155 104 } 105 + 106 + if (params.epp) { 107 + ret = cpupower_set_epp(cpu, epp); 108 + if (ret) { 109 + fprintf(stderr, 110 + "Error setting epp value on CPU %d\n", cpu); 111 + break; 112 + } 113 + } 114 + 156 115 } 157 116 return ret; 158 117 }
+11
tools/power/cpupower/utils/helpers/helpers.h
··· 116 116 extern int cpupower_intel_get_perf_bias(unsigned int cpu); 117 117 extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu); 118 118 119 + extern int cpupower_set_epp(unsigned int cpu, char *epp); 120 + extern int cpupower_set_amd_pstate_mode(char *mode); 121 + extern int cpupower_set_turbo_boost(int turbo_boost); 122 + 119 123 /* Read/Write msr ****************************/ 120 124 121 125 /* PCI stuff ****************************/ ··· 176 172 { return -1; }; 177 173 static inline unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu) 178 174 { return 0; }; 175 + 176 + static inline int cpupower_set_epp(unsigned int cpu, char *epp) 177 + { return -1; }; 178 + static inline int cpupower_set_amd_pstate_mode(char *mode) 179 + { return -1; }; 180 + static inline int cpupower_set_turbo_boost(int turbo_boost) 181 + { return -1; }; 179 182 180 183 /* Read/Write msr ****************************/ 181 184
+56 -1
tools/power/cpupower/utils/helpers/misc.c
··· 87 87 return 0; 88 88 } 89 89 90 + int cpupower_set_epp(unsigned int cpu, char *epp) 91 + { 92 + char path[SYSFS_PATH_MAX]; 93 + char linebuf[30] = {}; 94 + 95 + snprintf(path, sizeof(path), 96 + PATH_TO_CPU "cpu%u/cpufreq/energy_performance_preference", cpu); 97 + 98 + if (!is_valid_path(path)) 99 + return -1; 100 + 101 + snprintf(linebuf, sizeof(linebuf), "%s", epp); 102 + 103 + if (cpupower_write_sysfs(path, linebuf, 30) <= 0) 104 + return -1; 105 + 106 + return 0; 107 + } 108 + 109 + int cpupower_set_amd_pstate_mode(char *mode) 110 + { 111 + char path[SYSFS_PATH_MAX]; 112 + char linebuf[20] = {}; 113 + 114 + snprintf(path, sizeof(path), PATH_TO_CPU "amd_pstate/status"); 115 + 116 + if (!is_valid_path(path)) 117 + return -1; 118 + 119 + snprintf(linebuf, sizeof(linebuf), "%s\n", mode); 120 + 121 + if (cpupower_write_sysfs(path, linebuf, 20) <= 0) 122 + return -1; 123 + 124 + return 0; 125 + } 126 + 127 + int cpupower_set_turbo_boost(int turbo_boost) 128 + { 129 + char path[SYSFS_PATH_MAX]; 130 + char linebuf[2] = {}; 131 + 132 + snprintf(path, sizeof(path), PATH_TO_CPU "cpufreq/boost"); 133 + 134 + if (!is_valid_path(path)) 135 + return -1; 136 + 137 + snprintf(linebuf, sizeof(linebuf), "%d", turbo_boost); 138 + 139 + if (cpupower_write_sysfs(path, linebuf, 2) <= 0) 140 + return -1; 141 + 142 + return 0; 143 + } 144 + 90 145 bool cpupower_amd_pstate_enabled(void) 91 146 { 92 147 char *driver = cpufreq_get_driver(0); ··· 150 95 if (!driver) 151 96 return ret; 152 97 153 - if (!strcmp(driver, "amd-pstate")) 98 + if (!strncmp(driver, "amd", 3)) 154 99 ret = true; 155 100 156 101 cpufreq_put_driver(driver);