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

Configure Feed

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

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

Pull power management updates from Rafael Wysocki:
"These include a rework of the main suspend-to-idle code flow (related
to the handling of spurious wakeups), a switch over of several users
of cpufreq notifiers to QoS-based limits, a new devfreq driver for
Tegra20, a new cpuidle driver and governor for virtualized guests, an
extension of the wakeup sources framework to expose wakeup sources as
device objects in sysfs, and more.

Specifics:

- Rework the main suspend-to-idle control flow to avoid repeating
"noirq" device resume and suspend operations in case of spurious
wakeups from the ACPI EC and decouple the ACPI EC wakeups support
from the LPS0 _DSM support (Rafael Wysocki).

- Extend the wakeup sources framework to expose wakeup sources as
device objects in sysfs (Tri Vo, Stephen Boyd).

- Expose system suspend statistics in sysfs (Kalesh Singh).

- Introduce a new haltpoll cpuidle driver and a new matching governor
for virtualized guests wanting to do guest-side polling in the idle
loop (Marcelo Tosatti, Joao Martins, Wanpeng Li, Stephen Rothwell).

- Fix the menu and teo cpuidle governors to allow the scheduler tick
to be stopped if PM QoS is used to limit the CPU idle state exit
latency in some cases (Rafael Wysocki).

- Increase the resolution of the play_idle() argument to microseconds
for more fine-grained injection of CPU idle cycles (Daniel
Lezcano).

- Switch over some users of cpuidle notifiers to the new QoS-based
frequency limits and drop the CPUFREQ_ADJUST and CPUFREQ_NOTIFY
policy notifier events (Viresh Kumar).

- Add new cpufreq driver based on nvmem for sun50i (Yangtao Li).

- Add support for MT8183 and MT8516 to the mediatek cpufreq driver
(Andrew-sh.Cheng, Fabien Parent).

- Add i.MX8MN support to the imx-cpufreq-dt cpufreq driver (Anson
Huang).

- Add qcs404 to cpufreq-dt-platdev blacklist (Jorge Ramirez-Ortiz).

- Update the qcom cpufreq driver (among other things, to make it
easier to extend and to use kryo cpufreq for other nvmem-based
SoCs) and add qcs404 support to it (Niklas Cassel, Douglas
RAILLARD, Sibi Sankar, Sricharan R).

- Fix assorted issues and make assorted minor improvements in the
cpufreq code (Colin Ian King, Douglas RAILLARD, Florian Fainelli,
Gustavo Silva, Hariprasad Kelam).

- Add new devfreq driver for NVidia Tegra20 (Dmitry Osipenko, Arnd
Bergmann).

- Add new Exynos PPMU events to devfreq events and extend that
mechanism (Lukasz Luba).

- Fix and clean up the exynos-bus devfreq driver (Kamil Konieczny).

- Improve devfreq documentation and governor code, fix spelling typos
in devfreq (Ezequiel Garcia, Krzysztof Kozlowski, Leonard Crestez,
MyungJoo Ham, Gaël PORTAY).

- Add regulators enable and disable to the OPP (operating performance
points) framework (Kamil Konieczny).

- Update the OPP framework to support multiple opp-suspend properties
(Anson Huang).

- Fix assorted issues and make assorted minor improvements in the OPP
code (Niklas Cassel, Viresh Kumar, Yue Hu).

- Clean up the generic power domains (genpd) framework (Ulf Hansson).

- Clean up assorted pieces of power management code and documentation
(Akinobu Mita, Amit Kucheria, Chuhong Yuan).

- Update the pm-graph tool to version 5.5 including multiple fixes
and improvements (Todd Brandt).

- Update the cpupower utility (Benjamin Weis, Geert Uytterhoeven,
Sébastien Szymanski)"

* tag 'pm-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (126 commits)
cpuidle-haltpoll: Enable kvm guest polling when dedicated physical CPUs are available
cpuidle-haltpoll: do not set an owner to allow modunload
cpuidle-haltpoll: return -ENODEV on modinit failure
cpuidle-haltpoll: set haltpoll as preferred governor
cpuidle: allow governor switch on cpuidle_register_driver()
PM: runtime: Documentation: add runtime_status ABI document
pm-graph: make setVal unbuffered again for python2 and python3
powercap: idle_inject: Use higher resolution for idle injection
cpuidle: play_idle: Increase the resolution to usec
cpuidle-haltpoll: vcpu hotplug support
cpufreq: Add qcs404 to cpufreq-dt-platdev blacklist
cpufreq: qcom: Add support for qcs404 on nvmem driver
cpufreq: qcom: Refactor the driver to make it easier to extend
cpufreq: qcom: Re-organise kryo cpufreq to use it for other nvmem based qcom socs
dt-bindings: opp: Add qcom-opp bindings with properties needed for CPR
dt-bindings: opp: qcom-nvmem: Support pstates provided by a power domain
Documentation: cpufreq: Update policy notifier documentation
cpufreq: Remove CPUFREQ_ADJUST and CPUFREQ_NOTIFY policy notifier events
PM / Domains: Verify PM domain type in dev_pm_genpd_set_performance_state()
PM / Domains: Simplify genpd_lookup_dev()
...

+4053 -1925
+76
Documentation/ABI/testing/sysfs-class-wakeup
··· 1 + What: /sys/class/wakeup/ 2 + Date: June 2019 3 + Contact: Tri Vo <trong@android.com> 4 + Description: 5 + The /sys/class/wakeup/ directory contains pointers to all 6 + wakeup sources in the kernel at that moment in time. 7 + 8 + What: /sys/class/wakeup/.../name 9 + Date: June 2019 10 + Contact: Tri Vo <trong@android.com> 11 + Description: 12 + This file contains the name of the wakeup source. 13 + 14 + What: /sys/class/wakeup/.../active_count 15 + Date: June 2019 16 + Contact: Tri Vo <trong@android.com> 17 + Description: 18 + This file contains the number of times the wakeup source was 19 + activated. 20 + 21 + What: /sys/class/wakeup/.../event_count 22 + Date: June 2019 23 + Contact: Tri Vo <trong@android.com> 24 + Description: 25 + This file contains the number of signaled wakeup events 26 + associated with the wakeup source. 27 + 28 + What: /sys/class/wakeup/.../wakeup_count 29 + Date: June 2019 30 + Contact: Tri Vo <trong@android.com> 31 + Description: 32 + This file contains the number of times the wakeup source might 33 + abort suspend. 34 + 35 + What: /sys/class/wakeup/.../expire_count 36 + Date: June 2019 37 + Contact: Tri Vo <trong@android.com> 38 + Description: 39 + This file contains the number of times the wakeup source's 40 + timeout has expired. 41 + 42 + What: /sys/class/wakeup/.../active_time_ms 43 + Date: June 2019 44 + Contact: Tri Vo <trong@android.com> 45 + Description: 46 + This file contains the amount of time the wakeup source has 47 + been continuously active, in milliseconds. If the wakeup 48 + source is not active, this file contains '0'. 49 + 50 + What: /sys/class/wakeup/.../total_time_ms 51 + Date: June 2019 52 + Contact: Tri Vo <trong@android.com> 53 + Description: 54 + This file contains the total amount of time this wakeup source 55 + has been active, in milliseconds. 56 + 57 + What: /sys/class/wakeup/.../max_time_ms 58 + Date: June 2019 59 + Contact: Tri Vo <trong@android.com> 60 + Description: 61 + This file contains the maximum amount of time this wakeup 62 + source has been continuously active, in milliseconds. 63 + 64 + What: /sys/class/wakeup/.../last_change_ms 65 + Date: June 2019 66 + Contact: Tri Vo <trong@android.com> 67 + Description: 68 + This file contains the monotonic clock time when the wakeup 69 + source was touched last time, in milliseconds. 70 + 71 + What: /sys/class/wakeup/.../prevent_suspend_time_ms 72 + Date: June 2019 73 + Contact: Tri Vo <trong@android.com> 74 + Description: 75 + The file contains the total amount of time this wakeup source 76 + has been preventing autosleep, in milliseconds.
+9
Documentation/ABI/testing/sysfs-devices-power
··· 260 260 261 261 This attribute has no effect on system-wide suspend/resume and 262 262 hibernation. 263 + 264 + What: /sys/devices/.../power/runtime_status 265 + Date: April 2010 266 + Contact: Rafael J. Wysocki <rjw@rjwysocki.net> 267 + Description: 268 + The /sys/devices/.../power/runtime_status attribute contains 269 + the current runtime PM status of the device, which may be 270 + "suspended", "suspending", "resuming", "active", "error" (fatal 271 + error), or "unsupported" (runtime PM is disabled).
+106
Documentation/ABI/testing/sysfs-power
··· 301 301 302 302 Using this sysfs file will override any values that were 303 303 set using the kernel command line for disk offset. 304 + 305 + What: /sys/power/suspend_stats 306 + Date: July 2019 307 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 308 + Description: 309 + The /sys/power/suspend_stats directory contains suspend related 310 + statistics. 311 + 312 + What: /sys/power/suspend_stats/success 313 + Date: July 2019 314 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 315 + Description: 316 + The /sys/power/suspend_stats/success file contains the number 317 + of times entering system sleep state succeeded. 318 + 319 + What: /sys/power/suspend_stats/fail 320 + Date: July 2019 321 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 322 + Description: 323 + The /sys/power/suspend_stats/fail file contains the number 324 + of times entering system sleep state failed. 325 + 326 + What: /sys/power/suspend_stats/failed_freeze 327 + Date: July 2019 328 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 329 + Description: 330 + The /sys/power/suspend_stats/failed_freeze file contains the 331 + number of times freezing processes failed. 332 + 333 + What: /sys/power/suspend_stats/failed_prepare 334 + Date: July 2019 335 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 336 + Description: 337 + The /sys/power/suspend_stats/failed_prepare file contains the 338 + number of times preparing all non-sysdev devices for 339 + a system PM transition failed. 340 + 341 + What: /sys/power/suspend_stats/failed_resume 342 + Date: July 2019 343 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 344 + Description: 345 + The /sys/power/suspend_stats/failed_resume file contains the 346 + number of times executing "resume" callbacks of 347 + non-sysdev devices failed. 348 + 349 + What: /sys/power/suspend_stats/failed_resume_early 350 + Date: July 2019 351 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 352 + Description: 353 + The /sys/power/suspend_stats/failed_resume_early file contains 354 + the number of times executing "early resume" callbacks 355 + of devices failed. 356 + 357 + What: /sys/power/suspend_stats/failed_resume_noirq 358 + Date: July 2019 359 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 360 + Description: 361 + The /sys/power/suspend_stats/failed_resume_noirq file contains 362 + the number of times executing "noirq resume" callbacks 363 + of devices failed. 364 + 365 + What: /sys/power/suspend_stats/failed_suspend 366 + Date: July 2019 367 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 368 + Description: 369 + The /sys/power/suspend_stats/failed_suspend file contains 370 + the number of times executing "suspend" callbacks 371 + of all non-sysdev devices failed. 372 + 373 + What: /sys/power/suspend_stats/failed_suspend_late 374 + Date: July 2019 375 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 376 + Description: 377 + The /sys/power/suspend_stats/failed_suspend_late file contains 378 + the number of times executing "late suspend" callbacks 379 + of all devices failed. 380 + 381 + What: /sys/power/suspend_stats/failed_suspend_noirq 382 + Date: July 2019 383 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 384 + Description: 385 + The /sys/power/suspend_stats/failed_suspend_noirq file contains 386 + the number of times executing "noirq suspend" callbacks 387 + of all devices failed. 388 + 389 + What: /sys/power/suspend_stats/last_failed_dev 390 + Date: July 2019 391 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 392 + Description: 393 + The /sys/power/suspend_stats/last_failed_dev file contains 394 + the last device for which a suspend/resume callback failed. 395 + 396 + What: /sys/power/suspend_stats/last_failed_errno 397 + Date: July 2019 398 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 399 + Description: 400 + The /sys/power/suspend_stats/last_failed_errno file contains 401 + the errno of the last failed attempt at entering 402 + system sleep state. 403 + 404 + What: /sys/power/suspend_stats/last_failed_step 405 + Date: July 2019 406 + Contact: Kalesh Singh <kaleshsingh96@gmail.com> 407 + Description: 408 + The /sys/power/suspend_stats/last_failed_step file contains 409 + the last failed step in the suspend/resume path.
+4 -12
Documentation/cpu-freq/core.txt
··· 57 57 2.1 CPUFreq policy notifiers 58 58 ---------------------------- 59 59 60 - These are notified when a new policy is intended to be set. Each 61 - CPUFreq policy notifier is called twice for a policy transition: 60 + These are notified when a new policy is created or removed. 62 61 63 - 1.) During CPUFREQ_ADJUST all CPUFreq notifiers may change the limit if 64 - they see a need for this - may it be thermal considerations or 65 - hardware limitations. 66 - 67 - 2.) And during CPUFREQ_NOTIFY all notifiers are informed of the new policy 68 - - if two hardware drivers failed to agree on a new policy before this 69 - stage, the incompatible hardware shall be shut down, and the user 70 - informed of this. 71 - 72 - The phase is specified in the second argument to the notifier. 62 + The phase is specified in the second argument to the notifier. The phase is 63 + CPUFREQ_CREATE_POLICY when the policy is first created and it is 64 + CPUFREQ_REMOVE_POLICY when the policy is removed. 73 65 74 66 The third argument, a void *pointer, points to a struct cpufreq_policy 75 67 consisting of several values, including min, max (the lower and upper
+121 -6
Documentation/devicetree/bindings/opp/kryo-cpufreq.txt Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
··· 1 - Qualcomm Technologies, Inc. KRYO CPUFreq and OPP bindings 1 + Qualcomm Technologies, Inc. NVMEM CPUFreq and OPP bindings 2 2 =================================== 3 3 4 - In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996 5 - that have KRYO processors, the CPU ferequencies subset and voltage value 6 - of each OPP varies based on the silicon variant in use. 4 + In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996, 5 + the CPU frequencies subset and voltage value of each OPP varies based on 6 + the silicon variant in use. 7 7 Qualcomm Technologies, Inc. Process Voltage Scaling Tables 8 8 defines the voltage and frequency value based on the msm-id in SMEM 9 9 and speedbin blown in the efuse combination. 10 - The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC 10 + The qcom-cpufreq-nvmem driver reads the msm-id and efuse value from the SoC 11 11 to provide the OPP framework with required information (existing HW bitmap). 12 12 This is used to determine the voltage and frequency value for each OPP of 13 13 operating-points-v2 table when it is parsed by the OPP framework. 14 14 15 15 Required properties: 16 16 -------------------- 17 - In 'cpus' nodes: 17 + In 'cpu' nodes: 18 18 - operating-points-v2: Phandle to the operating-points-v2 table to use. 19 19 20 20 In 'operating-points-v2' table: 21 21 - compatible: Should be 22 22 - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996. 23 + 24 + Optional properties: 25 + -------------------- 26 + In 'cpu' nodes: 27 + - power-domains: A phandle pointing to the PM domain specifier which provides 28 + the performance states available for active state management. 29 + Please refer to the power-domains bindings 30 + Documentation/devicetree/bindings/power/power_domain.txt 31 + and also examples below. 32 + - power-domain-names: Should be 33 + - 'cpr' for qcs404. 34 + 35 + In 'operating-points-v2' table: 23 36 - nvmem-cells: A phandle pointing to a nvmem-cells node representing the 24 37 efuse registers that has information about the 25 38 speedbin that is used to select the right frequency/voltage ··· 689 676 reg = <0x133 0x1>; 690 677 bits = <5 3>; 691 678 }; 679 + }; 680 + }; 681 + 682 + Example 2: 683 + --------- 684 + 685 + cpus { 686 + #address-cells = <1>; 687 + #size-cells = <0>; 688 + 689 + CPU0: cpu@100 { 690 + device_type = "cpu"; 691 + compatible = "arm,cortex-a53"; 692 + reg = <0x100>; 693 + .... 694 + clocks = <&apcs_glb>; 695 + operating-points-v2 = <&cpu_opp_table>; 696 + power-domains = <&cpr>; 697 + power-domain-names = "cpr"; 698 + }; 699 + 700 + CPU1: cpu@101 { 701 + device_type = "cpu"; 702 + compatible = "arm,cortex-a53"; 703 + reg = <0x101>; 704 + .... 705 + clocks = <&apcs_glb>; 706 + operating-points-v2 = <&cpu_opp_table>; 707 + power-domains = <&cpr>; 708 + power-domain-names = "cpr"; 709 + }; 710 + 711 + CPU2: cpu@102 { 712 + device_type = "cpu"; 713 + compatible = "arm,cortex-a53"; 714 + reg = <0x102>; 715 + .... 716 + clocks = <&apcs_glb>; 717 + operating-points-v2 = <&cpu_opp_table>; 718 + power-domains = <&cpr>; 719 + power-domain-names = "cpr"; 720 + }; 721 + 722 + CPU3: cpu@103 { 723 + device_type = "cpu"; 724 + compatible = "arm,cortex-a53"; 725 + reg = <0x103>; 726 + .... 727 + clocks = <&apcs_glb>; 728 + operating-points-v2 = <&cpu_opp_table>; 729 + power-domains = <&cpr>; 730 + power-domain-names = "cpr"; 731 + }; 732 + }; 733 + 734 + cpu_opp_table: cpu-opp-table { 735 + compatible = "operating-points-v2-kryo-cpu"; 736 + opp-shared; 737 + 738 + opp-1094400000 { 739 + opp-hz = /bits/ 64 <1094400000>; 740 + required-opps = <&cpr_opp1>; 741 + }; 742 + opp-1248000000 { 743 + opp-hz = /bits/ 64 <1248000000>; 744 + required-opps = <&cpr_opp2>; 745 + }; 746 + opp-1401600000 { 747 + opp-hz = /bits/ 64 <1401600000>; 748 + required-opps = <&cpr_opp3>; 749 + }; 750 + }; 751 + 752 + cpr_opp_table: cpr-opp-table { 753 + compatible = "operating-points-v2-qcom-level"; 754 + 755 + cpr_opp1: opp1 { 756 + opp-level = <1>; 757 + qcom,opp-fuse-level = <1>; 758 + }; 759 + cpr_opp2: opp2 { 760 + opp-level = <2>; 761 + qcom,opp-fuse-level = <2>; 762 + }; 763 + cpr_opp3: opp3 { 764 + opp-level = <3>; 765 + qcom,opp-fuse-level = <3>; 766 + }; 767 + }; 768 + 769 + .... 770 + 771 + soc { 772 + .... 773 + cpr: power-controller@b018000 { 774 + compatible = "qcom,qcs404-cpr", "qcom,cpr"; 775 + reg = <0x0b018000 0x1000>; 776 + .... 777 + vdd-apc-supply = <&pms405_s3>; 778 + #power-domain-cells = <0>; 779 + operating-points-v2 = <&cpr_opp_table>; 780 + .... 692 781 }; 693 782 };
+2 -2
Documentation/devicetree/bindings/opp/opp.txt
··· 140 140 frequency for a short duration of time limited by the device's power, current 141 141 and thermal limits. 142 142 143 - - opp-suspend: Marks the OPP to be used during device suspend. Only one OPP in 144 - the table should have this. 143 + - opp-suspend: Marks the OPP to be used during device suspend. If multiple OPPs 144 + in the table have this, the OPP with highest opp-hz will be used. 145 145 146 146 - opp-supported-hw: This enables us to select only a subset of OPPs from the 147 147 larger OPP table, based on what version of the hardware we are running on. We
+19
Documentation/devicetree/bindings/opp/qcom-opp.txt
··· 1 + Qualcomm OPP bindings to describe OPP nodes 2 + 3 + The bindings are based on top of the operating-points-v2 bindings 4 + described in Documentation/devicetree/bindings/opp/opp.txt 5 + Additional properties are described below. 6 + 7 + * OPP Table Node 8 + 9 + Required properties: 10 + - compatible: Allow OPPs to express their compatibility. It should be: 11 + "operating-points-v2-qcom-level" 12 + 13 + * OPP Node 14 + 15 + Required properties: 16 + - qcom,opp-fuse-level: A positive value representing the fuse corner/level 17 + associated with this OPP node. Sometimes several corners/levels shares 18 + a certain fuse corner/level. A fuse corner/level contains e.g. ref uV, 19 + min uV, and max uV.
+167
Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt
··· 1 + Allwinner Technologies, Inc. NVMEM CPUFreq and OPP bindings 2 + =================================== 3 + 4 + For some SoCs, the CPU frequency subset and voltage value of each OPP 5 + varies based on the silicon variant in use. Allwinner Process Voltage 6 + Scaling Tables defines the voltage and frequency value based on the 7 + speedbin blown in the efuse combination. The sun50i-cpufreq-nvmem driver 8 + reads the efuse value from the SoC to provide the OPP framework with 9 + required information. 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 + - 'allwinner,sun50i-h6-operating-points'. 19 + - nvmem-cells: A phandle pointing to a nvmem-cells node representing the 20 + efuse registers that has information about the speedbin 21 + that is used to select the right frequency/voltage value 22 + pair. Please refer the for nvmem-cells bindings 23 + Documentation/devicetree/bindings/nvmem/nvmem.txt and 24 + also examples below. 25 + 26 + In every OPP node: 27 + - opp-microvolt-<name>: Voltage in micro Volts. 28 + At runtime, the platform can pick a <name> and 29 + matching opp-microvolt-<name> property. 30 + [See: opp.txt] 31 + HW: <name>: 32 + sun50i-h6 speed0 speed1 speed2 33 + 34 + Example 1: 35 + --------- 36 + 37 + cpus { 38 + #address-cells = <1>; 39 + #size-cells = <0>; 40 + 41 + cpu0: cpu@0 { 42 + compatible = "arm,cortex-a53"; 43 + device_type = "cpu"; 44 + reg = <0>; 45 + enable-method = "psci"; 46 + clocks = <&ccu CLK_CPUX>; 47 + clock-latency-ns = <244144>; /* 8 32k periods */ 48 + operating-points-v2 = <&cpu_opp_table>; 49 + #cooling-cells = <2>; 50 + }; 51 + 52 + cpu1: cpu@1 { 53 + compatible = "arm,cortex-a53"; 54 + device_type = "cpu"; 55 + reg = <1>; 56 + enable-method = "psci"; 57 + clocks = <&ccu CLK_CPUX>; 58 + clock-latency-ns = <244144>; /* 8 32k periods */ 59 + operating-points-v2 = <&cpu_opp_table>; 60 + #cooling-cells = <2>; 61 + }; 62 + 63 + cpu2: cpu@2 { 64 + compatible = "arm,cortex-a53"; 65 + device_type = "cpu"; 66 + reg = <2>; 67 + enable-method = "psci"; 68 + clocks = <&ccu CLK_CPUX>; 69 + clock-latency-ns = <244144>; /* 8 32k periods */ 70 + operating-points-v2 = <&cpu_opp_table>; 71 + #cooling-cells = <2>; 72 + }; 73 + 74 + cpu3: cpu@3 { 75 + compatible = "arm,cortex-a53"; 76 + device_type = "cpu"; 77 + reg = <3>; 78 + enable-method = "psci"; 79 + clocks = <&ccu CLK_CPUX>; 80 + clock-latency-ns = <244144>; /* 8 32k periods */ 81 + operating-points-v2 = <&cpu_opp_table>; 82 + #cooling-cells = <2>; 83 + }; 84 + }; 85 + 86 + cpu_opp_table: opp_table { 87 + compatible = "allwinner,sun50i-h6-operating-points"; 88 + nvmem-cells = <&speedbin_efuse>; 89 + opp-shared; 90 + 91 + opp@480000000 { 92 + clock-latency-ns = <244144>; /* 8 32k periods */ 93 + opp-hz = /bits/ 64 <480000000>; 94 + 95 + opp-microvolt-speed0 = <880000>; 96 + opp-microvolt-speed1 = <820000>; 97 + opp-microvolt-speed2 = <800000>; 98 + }; 99 + 100 + opp@720000000 { 101 + clock-latency-ns = <244144>; /* 8 32k periods */ 102 + opp-hz = /bits/ 64 <720000000>; 103 + 104 + opp-microvolt-speed0 = <880000>; 105 + opp-microvolt-speed1 = <820000>; 106 + opp-microvolt-speed2 = <800000>; 107 + }; 108 + 109 + opp@816000000 { 110 + clock-latency-ns = <244144>; /* 8 32k periods */ 111 + opp-hz = /bits/ 64 <816000000>; 112 + 113 + opp-microvolt-speed0 = <880000>; 114 + opp-microvolt-speed1 = <820000>; 115 + opp-microvolt-speed2 = <800000>; 116 + }; 117 + 118 + opp@888000000 { 119 + clock-latency-ns = <244144>; /* 8 32k periods */ 120 + opp-hz = /bits/ 64 <888000000>; 121 + 122 + opp-microvolt-speed0 = <940000>; 123 + opp-microvolt-speed1 = <820000>; 124 + opp-microvolt-speed2 = <800000>; 125 + }; 126 + 127 + opp@1080000000 { 128 + clock-latency-ns = <244144>; /* 8 32k periods */ 129 + opp-hz = /bits/ 64 <1080000000>; 130 + 131 + opp-microvolt-speed0 = <1060000>; 132 + opp-microvolt-speed1 = <880000>; 133 + opp-microvolt-speed2 = <840000>; 134 + }; 135 + 136 + opp@1320000000 { 137 + clock-latency-ns = <244144>; /* 8 32k periods */ 138 + opp-hz = /bits/ 64 <1320000000>; 139 + 140 + opp-microvolt-speed0 = <1160000>; 141 + opp-microvolt-speed1 = <940000>; 142 + opp-microvolt-speed2 = <900000>; 143 + }; 144 + 145 + opp@1488000000 { 146 + clock-latency-ns = <244144>; /* 8 32k periods */ 147 + opp-hz = /bits/ 64 <1488000000>; 148 + 149 + opp-microvolt-speed0 = <1160000>; 150 + opp-microvolt-speed1 = <1000000>; 151 + opp-microvolt-speed2 = <960000>; 152 + }; 153 + }; 154 + .... 155 + soc { 156 + .... 157 + sid: sid@3006000 { 158 + compatible = "allwinner,sun50i-h6-sid"; 159 + reg = <0x03006000 0x400>; 160 + #address-cells = <1>; 161 + #size-cells = <1>; 162 + .... 163 + speedbin_efuse: speed@1c { 164 + reg = <0x1c 4>; 165 + }; 166 + }; 167 + };
+1 -1
Documentation/power/opp.rst
··· 46 46 ---------------------------------------- 47 47 48 48 OPP library provides a set of helper functions to organize and query the OPP 49 - information. The library is located in drivers/base/power/opp.c and the header 49 + information. The library is located in drivers/opp/ directory and the header 50 50 is located in include/linux/pm_opp.h. OPP library can be enabled by enabling 51 51 CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on 52 52 CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to
+2 -3
Documentation/power/pm_qos_interface.rst
··· 7 7 one of the parameters. 8 8 9 9 Two different PM QoS frameworks are available: 10 - 1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput, 11 - memory_bandwidth. 10 + 1. PM QoS classes for cpu_dma_latency 12 11 2. the per-device PM QoS framework provides the API to manage the per-device latency 13 12 constraints and PM QoS flags. 14 13 ··· 78 79 parameter requests in the following way: 79 80 80 81 To register the default pm_qos target for the specific parameter, the process 81 - must open one of /dev/[cpu_dma_latency, network_latency, network_throughput] 82 + must open /dev/cpu_dma_latency 82 83 83 84 As long as the device node is held open that process has a registered 84 85 request on the parameter.
+78
Documentation/virtual/guest-halt-polling.txt
··· 1 + Guest halt polling 2 + ================== 3 + 4 + The cpuidle_haltpoll driver, with the haltpoll governor, allows 5 + the guest vcpus to poll for a specified amount of time before 6 + halting. 7 + This provides the following benefits to host side polling: 8 + 9 + 1) The POLL flag is set while polling is performed, which allows 10 + a remote vCPU to avoid sending an IPI (and the associated 11 + cost of handling the IPI) when performing a wakeup. 12 + 13 + 2) The VM-exit cost can be avoided. 14 + 15 + The downside of guest side polling is that polling is performed 16 + even with other runnable tasks in the host. 17 + 18 + The basic logic as follows: A global value, guest_halt_poll_ns, 19 + is configured by the user, indicating the maximum amount of 20 + time polling is allowed. This value is fixed. 21 + 22 + Each vcpu has an adjustable guest_halt_poll_ns 23 + ("per-cpu guest_halt_poll_ns"), which is adjusted by the algorithm 24 + in response to events (explained below). 25 + 26 + Module Parameters 27 + ================= 28 + 29 + The haltpoll governor has 5 tunable module parameters: 30 + 31 + 1) guest_halt_poll_ns: 32 + Maximum amount of time, in nanoseconds, that polling is 33 + performed before halting. 34 + 35 + Default: 200000 36 + 37 + 2) guest_halt_poll_shrink: 38 + Division factor used to shrink per-cpu guest_halt_poll_ns when 39 + wakeup event occurs after the global guest_halt_poll_ns. 40 + 41 + Default: 2 42 + 43 + 3) guest_halt_poll_grow: 44 + Multiplication factor used to grow per-cpu guest_halt_poll_ns 45 + when event occurs after per-cpu guest_halt_poll_ns 46 + but before global guest_halt_poll_ns. 47 + 48 + Default: 2 49 + 50 + 4) guest_halt_poll_grow_start: 51 + The per-cpu guest_halt_poll_ns eventually reaches zero 52 + in case of an idle system. This value sets the initial 53 + per-cpu guest_halt_poll_ns when growing. This can 54 + be increased from 10000, to avoid misses during the initial 55 + growth stage: 56 + 57 + 10k, 20k, 40k, ... (example assumes guest_halt_poll_grow=2). 58 + 59 + Default: 50000 60 + 61 + 5) guest_halt_poll_allow_shrink: 62 + 63 + Bool parameter which allows shrinking. Set to N 64 + to avoid it (per-cpu guest_halt_poll_ns will remain 65 + high once achieves global guest_halt_poll_ns value). 66 + 67 + Default: Y 68 + 69 + The module parameters can be set from the debugfs files in: 70 + 71 + /sys/module/haltpoll/parameters/ 72 + 73 + Further Notes 74 + ============= 75 + 76 + - Care should be taken when setting the guest_halt_poll_ns parameter as a 77 + large value has the potential to drive the cpu usage to 100% on a machine which 78 + would be almost entirely idle otherwise.
+9 -2
MAINTAINERS
··· 668 668 S: Maintained 669 669 F: drivers/staging/media/allegro-dvt/ 670 670 671 + ALLWINNER CPUFREQ DRIVER 672 + M: Yangtao Li <tiny.windzz@gmail.com> 673 + L: linux-pm@vger.kernel.org 674 + S: Maintained 675 + F: Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt 676 + F: drivers/cpufreq/sun50i-cpufreq-nvmem.c 677 + 671 678 ALLWINNER SECURITY SYSTEM 672 679 M: Corentin Labbe <clabbe.montjoie@gmail.com> 673 680 L: linux-crypto@vger.kernel.org ··· 13318 13311 M: Ilia Lin <ilia.lin@kernel.org> 13319 13312 L: linux-pm@vger.kernel.org 13320 13313 S: Maintained 13321 - F: Documentation/devicetree/bindings/opp/kryo-cpufreq.txt 13322 - F: drivers/cpufreq/qcom-cpufreq-kryo.c 13314 + F: Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt 13315 + F: drivers/cpufreq/qcom-cpufreq-nvmem.c 13323 13316 13324 13317 QUALCOMM EMAC GIGABIT ETHERNET DRIVER 13325 13318 M: Timur Tabi <timur@kernel.org>
+7
arch/x86/Kconfig
··· 794 794 bool "KVM Guest support (including kvmclock)" 795 795 depends on PARAVIRT 796 796 select PARAVIRT_CLOCK 797 + select ARCH_CPUIDLE_HALTPOLL 797 798 default y 798 799 ---help--- 799 800 This option enables various optimizations for running under the KVM ··· 802 801 of relying on a PIT (or probably other) emulation by the 803 802 underlying device model, the host provides the guest with 804 803 timing infrastructure such as time of day, and system time 804 + 805 + config ARCH_CPUIDLE_HALTPOLL 806 + def_bool n 807 + prompt "Disable host haltpoll when loading haltpoll driver" 808 + help 809 + If virtualized under KVM, disable host haltpoll. 805 810 806 811 config PVH 807 812 bool "Support for running PVH guests"
+8
arch/x86/include/asm/cpuidle_haltpoll.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _ARCH_HALTPOLL_H 3 + #define _ARCH_HALTPOLL_H 4 + 5 + void arch_haltpoll_enable(unsigned int cpu); 6 + void arch_haltpoll_disable(unsigned int cpu); 7 + 8 + #endif
+37
arch/x86/kernel/kvm.c
··· 705 705 { 706 706 return cpuid_edx(kvm_cpuid_base() | KVM_CPUID_FEATURES); 707 707 } 708 + EXPORT_SYMBOL_GPL(kvm_arch_para_hints); 708 709 709 710 static uint32_t __init kvm_detect(void) 710 711 { ··· 868 867 } 869 868 870 869 #endif /* CONFIG_PARAVIRT_SPINLOCKS */ 870 + 871 + #ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL 872 + 873 + static void kvm_disable_host_haltpoll(void *i) 874 + { 875 + wrmsrl(MSR_KVM_POLL_CONTROL, 0); 876 + } 877 + 878 + static void kvm_enable_host_haltpoll(void *i) 879 + { 880 + wrmsrl(MSR_KVM_POLL_CONTROL, 1); 881 + } 882 + 883 + void arch_haltpoll_enable(unsigned int cpu) 884 + { 885 + if (!kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL)) { 886 + pr_err_once("kvm: host does not support poll control\n"); 887 + pr_err_once("kvm: host upgrade recommended\n"); 888 + return; 889 + } 890 + 891 + /* Enable guest halt poll disables host halt poll */ 892 + smp_call_function_single(cpu, kvm_disable_host_haltpoll, NULL, 1); 893 + } 894 + EXPORT_SYMBOL_GPL(arch_haltpoll_enable); 895 + 896 + void arch_haltpoll_disable(unsigned int cpu) 897 + { 898 + if (!kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL)) 899 + return; 900 + 901 + /* Enable guest halt poll disables host halt poll */ 902 + smp_call_function_single(cpu, kvm_enable_host_haltpoll, NULL, 1); 903 + } 904 + EXPORT_SYMBOL_GPL(arch_haltpoll_disable); 905 + #endif
+1 -1
arch/x86/kernel/process.c
··· 580 580 safe_halt(); 581 581 trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); 582 582 } 583 - #ifdef CONFIG_APM_MODULE 583 + #if defined(CONFIG_APM_MODULE) || defined(CONFIG_HALTPOLL_CPUIDLE_MODULE) 584 584 EXPORT_SYMBOL(default_idle); 585 585 #endif 586 586
+3 -3
drivers/acpi/acpica/evxfgpe.c
··· 644 644 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 645 645 * gpe_number - GPE level within the GPE block 646 646 * 647 - * RETURN: None 647 + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 648 648 * 649 649 * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function 650 650 * (e.g. EC) or method (e.g. _Lxx/_Exx) handler. 651 651 * 652 652 ******************************************************************************/ 653 - void acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number) 653 + u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number) 654 654 { 655 655 ACPI_FUNCTION_TRACE(acpi_dispatch_gpe); 656 656 657 - acpi_ev_detect_gpe(gpe_device, NULL, gpe_number); 657 + return acpi_ev_detect_gpe(gpe_device, NULL, gpe_number); 658 658 } 659 659 660 660 ACPI_EXPORT_SYMBOL(acpi_dispatch_gpe)
+6 -1
drivers/acpi/device_pm.c
··· 166 166 || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) 167 167 return -EINVAL; 168 168 169 + acpi_handle_debug(device->handle, "Power state change: %s -> %s\n", 170 + acpi_power_state_string(device->power.state), 171 + acpi_power_state_string(state)); 172 + 169 173 /* Make sure this is a valid target state */ 170 174 171 175 /* There is a special case for D0 addressed below. */ ··· 501 497 goto out; 502 498 503 499 mutex_lock(&acpi_pm_notifier_lock); 504 - adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev)); 500 + adev->wakeup.ws = wakeup_source_register(&adev->dev, 501 + dev_name(&adev->dev)); 505 502 adev->wakeup.context.dev = dev; 506 503 adev->wakeup.context.func = func; 507 504 adev->wakeup.flags.notifier_present = true;
+33 -24
drivers/acpi/ec.c
··· 25 25 #include <linux/list.h> 26 26 #include <linux/spinlock.h> 27 27 #include <linux/slab.h> 28 + #include <linux/suspend.h> 28 29 #include <linux/acpi.h> 29 30 #include <linux/dmi.h> 30 31 #include <asm/io.h> ··· 1049 1048 acpi_ec_start(first_ec, true); 1050 1049 } 1051 1050 1052 - void acpi_ec_mark_gpe_for_wake(void) 1053 - { 1054 - if (first_ec && !ec_no_wakeup) 1055 - acpi_mark_gpe_for_wake(NULL, first_ec->gpe); 1056 - } 1057 - 1058 - void acpi_ec_set_gpe_wake_mask(u8 action) 1059 - { 1060 - if (first_ec && !ec_no_wakeup) 1061 - acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action); 1062 - } 1063 - 1064 - void acpi_ec_dispatch_gpe(void) 1065 - { 1066 - if (first_ec) 1067 - acpi_dispatch_gpe(NULL, first_ec->gpe); 1068 - } 1069 - 1070 1051 /* -------------------------------------------------------------------------- 1071 1052 Event Management 1072 1053 -------------------------------------------------------------------------- */ ··· 1914 1931 struct acpi_ec *ec = 1915 1932 acpi_driver_data(to_acpi_device(dev)); 1916 1933 1917 - if (acpi_sleep_no_ec_events() && ec_freeze_events) 1934 + if (!pm_suspend_no_platform() && ec_freeze_events) 1918 1935 acpi_ec_disable_event(ec); 1919 1936 return 0; 1920 1937 } ··· 1931 1948 ec->reference_count >= 1) 1932 1949 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE); 1933 1950 1934 - if (acpi_sleep_no_ec_events()) 1935 - acpi_ec_enter_noirq(ec); 1951 + acpi_ec_enter_noirq(ec); 1936 1952 1937 1953 return 0; 1938 1954 } ··· 1940 1958 { 1941 1959 struct acpi_ec *ec = acpi_driver_data(to_acpi_device(dev)); 1942 1960 1943 - if (acpi_sleep_no_ec_events()) 1944 - acpi_ec_leave_noirq(ec); 1961 + acpi_ec_leave_noirq(ec); 1945 1962 1946 1963 if (ec_no_wakeup && test_bit(EC_FLAGS_STARTED, &ec->flags) && 1947 1964 ec->reference_count >= 1) ··· 1957 1976 acpi_ec_enable_event(ec); 1958 1977 return 0; 1959 1978 } 1960 - #endif 1979 + 1980 + void acpi_ec_mark_gpe_for_wake(void) 1981 + { 1982 + if (first_ec && !ec_no_wakeup) 1983 + acpi_mark_gpe_for_wake(NULL, first_ec->gpe); 1984 + } 1985 + EXPORT_SYMBOL_GPL(acpi_ec_mark_gpe_for_wake); 1986 + 1987 + void acpi_ec_set_gpe_wake_mask(u8 action) 1988 + { 1989 + if (pm_suspend_no_platform() && first_ec && !ec_no_wakeup) 1990 + acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action); 1991 + } 1992 + 1993 + bool acpi_ec_dispatch_gpe(void) 1994 + { 1995 + u32 ret; 1996 + 1997 + if (!first_ec) 1998 + return false; 1999 + 2000 + ret = acpi_dispatch_gpe(NULL, first_ec->gpe); 2001 + if (ret == ACPI_INTERRUPT_HANDLED) { 2002 + pm_pr_dbg("EC GPE dispatched\n"); 2003 + return true; 2004 + } 2005 + return false; 2006 + } 2007 + #endif /* CONFIG_PM_SLEEP */ 1961 2008 1962 2009 static const struct dev_pm_ops acpi_ec_pm = { 1963 2010 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend_noirq, acpi_ec_resume_noirq)
+1 -5
drivers/acpi/internal.h
··· 194 194 void acpi_ec_dsdt_probe(void); 195 195 void acpi_ec_block_transactions(void); 196 196 void acpi_ec_unblock_transactions(void); 197 - void acpi_ec_mark_gpe_for_wake(void); 198 - void acpi_ec_set_gpe_wake_mask(u8 action); 199 - void acpi_ec_dispatch_gpe(void); 200 197 int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, 201 198 acpi_handle handle, acpi_ec_query_func func, 202 199 void *data); ··· 201 204 202 205 #ifdef CONFIG_PM_SLEEP 203 206 void acpi_ec_flush_work(void); 207 + bool acpi_ec_dispatch_gpe(void); 204 208 #endif 205 209 206 210 ··· 210 212 -------------------------------------------------------------------------- */ 211 213 #ifdef CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT 212 214 extern bool acpi_s2idle_wakeup(void); 213 - extern bool acpi_sleep_no_ec_events(void); 214 215 extern int acpi_sleep_init(void); 215 216 #else 216 217 static inline bool acpi_s2idle_wakeup(void) { return false; } 217 - static inline bool acpi_sleep_no_ec_events(void) { return true; } 218 218 static inline int acpi_sleep_init(void) { return -ENXIO; } 219 219 #endif 220 220
+35 -4
drivers/acpi/processor_driver.c
··· 284 284 return 0; 285 285 } 286 286 287 + bool acpi_processor_cpufreq_init; 288 + 289 + static int acpi_processor_notifier(struct notifier_block *nb, 290 + unsigned long event, void *data) 291 + { 292 + struct cpufreq_policy *policy = data; 293 + int cpu = policy->cpu; 294 + 295 + if (event == CPUFREQ_CREATE_POLICY) { 296 + acpi_thermal_cpufreq_init(cpu); 297 + acpi_processor_ppc_init(cpu); 298 + } else if (event == CPUFREQ_REMOVE_POLICY) { 299 + acpi_processor_ppc_exit(cpu); 300 + acpi_thermal_cpufreq_exit(cpu); 301 + } 302 + 303 + return 0; 304 + } 305 + 306 + static struct notifier_block acpi_processor_notifier_block = { 307 + .notifier_call = acpi_processor_notifier, 308 + }; 309 + 287 310 /* 288 311 * We keep the driver loaded even when ACPI is not running. 289 312 * This is needed for the powernow-k8 driver, that works even without ··· 333 310 cpuhp_setup_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD, "acpi/cpu-drv:dead", 334 311 NULL, acpi_soft_cpu_dead); 335 312 336 - acpi_thermal_cpufreq_init(); 337 - acpi_processor_ppc_init(); 313 + if (!cpufreq_register_notifier(&acpi_processor_notifier_block, 314 + CPUFREQ_POLICY_NOTIFIER)) { 315 + acpi_processor_cpufreq_init = true; 316 + acpi_processor_ignore_ppc_init(); 317 + } 318 + 338 319 acpi_processor_throttling_init(); 339 320 return 0; 340 321 err: ··· 351 324 if (acpi_disabled) 352 325 return; 353 326 354 - acpi_processor_ppc_exit(); 355 - acpi_thermal_cpufreq_exit(); 327 + if (acpi_processor_cpufreq_init) { 328 + cpufreq_unregister_notifier(&acpi_processor_notifier_block, 329 + CPUFREQ_POLICY_NOTIFIER); 330 + acpi_processor_cpufreq_init = false; 331 + } 332 + 356 333 cpuhp_remove_state_nocalls(hp_online); 357 334 cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD); 358 335 driver_unregister(&acpi_processor_driver);
+38 -62
drivers/acpi/processor_perflib.c
··· 50 50 MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \ 51 51 "limited by BIOS, this should help"); 52 52 53 - #define PPC_REGISTERED 1 54 - #define PPC_IN_USE 2 55 - 56 - static int acpi_processor_ppc_status; 57 - 58 - static int acpi_processor_ppc_notifier(struct notifier_block *nb, 59 - unsigned long event, void *data) 60 - { 61 - struct cpufreq_policy *policy = data; 62 - struct acpi_processor *pr; 63 - unsigned int ppc = 0; 64 - 65 - if (ignore_ppc < 0) 66 - ignore_ppc = 0; 67 - 68 - if (ignore_ppc) 69 - return 0; 70 - 71 - if (event != CPUFREQ_ADJUST) 72 - return 0; 73 - 74 - mutex_lock(&performance_mutex); 75 - 76 - pr = per_cpu(processors, policy->cpu); 77 - if (!pr || !pr->performance) 78 - goto out; 79 - 80 - ppc = (unsigned int)pr->performance_platform_limit; 81 - 82 - if (ppc >= pr->performance->state_count) 83 - goto out; 84 - 85 - cpufreq_verify_within_limits(policy, 0, 86 - pr->performance->states[ppc]. 87 - core_frequency * 1000); 88 - 89 - out: 90 - mutex_unlock(&performance_mutex); 91 - 92 - return 0; 93 - } 94 - 95 - static struct notifier_block acpi_ppc_notifier_block = { 96 - .notifier_call = acpi_processor_ppc_notifier, 97 - }; 53 + static bool acpi_processor_ppc_in_use; 98 54 99 55 static int acpi_processor_get_platform_limit(struct acpi_processor *pr) 100 56 { 101 57 acpi_status status = 0; 102 58 unsigned long long ppc = 0; 103 - 59 + int ret; 104 60 105 61 if (!pr) 106 62 return -EINVAL; ··· 68 112 status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc); 69 113 70 114 if (status != AE_NOT_FOUND) 71 - acpi_processor_ppc_status |= PPC_IN_USE; 115 + acpi_processor_ppc_in_use = true; 72 116 73 117 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 74 118 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC")); ··· 79 123 (int)ppc, ppc ? "" : "not"); 80 124 81 125 pr->performance_platform_limit = (int)ppc; 126 + 127 + if (ppc >= pr->performance->state_count || 128 + unlikely(!dev_pm_qos_request_active(&pr->perflib_req))) 129 + return 0; 130 + 131 + ret = dev_pm_qos_update_request(&pr->perflib_req, 132 + pr->performance->states[ppc].core_frequency * 1000); 133 + if (ret < 0) { 134 + pr_warn("Failed to update perflib freq constraint: CPU%d (%d)\n", 135 + pr->id, ret); 136 + } 82 137 83 138 return 0; 84 139 } ··· 151 184 } 152 185 EXPORT_SYMBOL(acpi_processor_get_bios_limit); 153 186 154 - void acpi_processor_ppc_init(void) 187 + void acpi_processor_ignore_ppc_init(void) 155 188 { 156 - if (!cpufreq_register_notifier 157 - (&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER)) 158 - acpi_processor_ppc_status |= PPC_REGISTERED; 159 - else 160 - printk(KERN_DEBUG 161 - "Warning: Processor Platform Limit not supported.\n"); 189 + if (ignore_ppc < 0) 190 + ignore_ppc = 0; 162 191 } 163 192 164 - void acpi_processor_ppc_exit(void) 193 + void acpi_processor_ppc_init(int cpu) 165 194 { 166 - if (acpi_processor_ppc_status & PPC_REGISTERED) 167 - cpufreq_unregister_notifier(&acpi_ppc_notifier_block, 168 - CPUFREQ_POLICY_NOTIFIER); 195 + struct acpi_processor *pr = per_cpu(processors, cpu); 196 + int ret; 169 197 170 - acpi_processor_ppc_status &= ~PPC_REGISTERED; 198 + ret = dev_pm_qos_add_request(get_cpu_device(cpu), 199 + &pr->perflib_req, DEV_PM_QOS_MAX_FREQUENCY, 200 + INT_MAX); 201 + if (ret < 0) { 202 + pr_err("Failed to add freq constraint for CPU%d (%d)\n", cpu, 203 + ret); 204 + return; 205 + } 206 + } 207 + 208 + void acpi_processor_ppc_exit(int cpu) 209 + { 210 + struct acpi_processor *pr = per_cpu(processors, cpu); 211 + 212 + dev_pm_qos_remove_request(&pr->perflib_req); 171 213 } 172 214 173 215 static int acpi_processor_get_performance_control(struct acpi_processor *pr) ··· 453 477 static int is_done = 0; 454 478 int result; 455 479 456 - if (!(acpi_processor_ppc_status & PPC_REGISTERED)) 480 + if (!acpi_processor_cpufreq_init) 457 481 return -EBUSY; 458 482 459 483 if (!try_module_get(calling_module)) ··· 489 513 * we can allow the cpufreq driver to be rmmod'ed. */ 490 514 is_done = 1; 491 515 492 - if (!(acpi_processor_ppc_status & PPC_IN_USE)) 516 + if (!acpi_processor_ppc_in_use) 493 517 module_put(calling_module); 494 518 495 519 return 0; ··· 718 742 { 719 743 struct acpi_processor *pr; 720 744 721 - if (!(acpi_processor_ppc_status & PPC_REGISTERED)) 745 + if (!acpi_processor_cpufreq_init) 722 746 return -EINVAL; 723 747 724 748 mutex_lock(&performance_mutex);
+40 -42
drivers/acpi/processor_thermal.c
··· 35 35 #define CPUFREQ_THERMAL_MAX_STEP 3 36 36 37 37 static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg); 38 - static unsigned int acpi_thermal_cpufreq_is_init = 0; 39 38 40 39 #define reduction_pctg(cpu) \ 41 40 per_cpu(cpufreq_thermal_reduction_pctg, phys_package_first_cpu(cpu)) ··· 60 61 static int cpu_has_cpufreq(unsigned int cpu) 61 62 { 62 63 struct cpufreq_policy policy; 63 - if (!acpi_thermal_cpufreq_is_init || cpufreq_get_policy(&policy, cpu)) 64 + if (!acpi_processor_cpufreq_init || cpufreq_get_policy(&policy, cpu)) 64 65 return 0; 65 66 return 1; 66 67 } 67 - 68 - static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, 69 - unsigned long event, void *data) 70 - { 71 - struct cpufreq_policy *policy = data; 72 - unsigned long max_freq = 0; 73 - 74 - if (event != CPUFREQ_ADJUST) 75 - goto out; 76 - 77 - max_freq = ( 78 - policy->cpuinfo.max_freq * 79 - (100 - reduction_pctg(policy->cpu) * 20) 80 - ) / 100; 81 - 82 - cpufreq_verify_within_limits(policy, 0, max_freq); 83 - 84 - out: 85 - return 0; 86 - } 87 - 88 - static struct notifier_block acpi_thermal_cpufreq_notifier_block = { 89 - .notifier_call = acpi_thermal_cpufreq_notifier, 90 - }; 91 68 92 69 static int cpufreq_get_max_state(unsigned int cpu) 93 70 { ··· 83 108 84 109 static int cpufreq_set_cur_state(unsigned int cpu, int state) 85 110 { 86 - int i; 111 + struct cpufreq_policy *policy; 112 + struct acpi_processor *pr; 113 + unsigned long max_freq; 114 + int i, ret; 87 115 88 116 if (!cpu_has_cpufreq(cpu)) 89 117 return 0; ··· 99 121 * frequency. 100 122 */ 101 123 for_each_online_cpu(i) { 102 - if (topology_physical_package_id(i) == 124 + if (topology_physical_package_id(i) != 103 125 topology_physical_package_id(cpu)) 104 - cpufreq_update_policy(i); 126 + continue; 127 + 128 + pr = per_cpu(processors, i); 129 + 130 + if (unlikely(!dev_pm_qos_request_active(&pr->thermal_req))) 131 + continue; 132 + 133 + policy = cpufreq_cpu_get(i); 134 + if (!policy) 135 + return -EINVAL; 136 + 137 + max_freq = (policy->cpuinfo.max_freq * (100 - reduction_pctg(i) * 20)) / 100; 138 + 139 + cpufreq_cpu_put(policy); 140 + 141 + ret = dev_pm_qos_update_request(&pr->thermal_req, max_freq); 142 + if (ret < 0) { 143 + pr_warn("Failed to update thermal freq constraint: CPU%d (%d)\n", 144 + pr->id, ret); 145 + } 105 146 } 106 147 return 0; 107 148 } 108 149 109 - void acpi_thermal_cpufreq_init(void) 150 + void acpi_thermal_cpufreq_init(int cpu) 110 151 { 111 - int i; 152 + struct acpi_processor *pr = per_cpu(processors, cpu); 153 + int ret; 112 154 113 - i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, 114 - CPUFREQ_POLICY_NOTIFIER); 115 - if (!i) 116 - acpi_thermal_cpufreq_is_init = 1; 155 + ret = dev_pm_qos_add_request(get_cpu_device(cpu), 156 + &pr->thermal_req, DEV_PM_QOS_MAX_FREQUENCY, 157 + INT_MAX); 158 + if (ret < 0) { 159 + pr_err("Failed to add freq constraint for CPU%d (%d)\n", cpu, 160 + ret); 161 + return; 162 + } 117 163 } 118 164 119 - void acpi_thermal_cpufreq_exit(void) 165 + void acpi_thermal_cpufreq_exit(int cpu) 120 166 { 121 - if (acpi_thermal_cpufreq_is_init) 122 - cpufreq_unregister_notifier 123 - (&acpi_thermal_cpufreq_notifier_block, 124 - CPUFREQ_POLICY_NOTIFIER); 167 + struct acpi_processor *pr = per_cpu(processors, cpu); 125 168 126 - acpi_thermal_cpufreq_is_init = 0; 169 + dev_pm_qos_remove_request(&pr->thermal_req); 127 170 } 128 - 129 171 #else /* ! CONFIG_CPU_FREQ */ 130 172 static int cpufreq_get_max_state(unsigned int cpu) 131 173 {
+90 -79
drivers/acpi/sleep.c
··· 89 89 } 90 90 91 91 #ifdef CONFIG_ACPI_SLEEP 92 + static bool sleep_no_lps0 __read_mostly; 93 + module_param(sleep_no_lps0, bool, 0644); 94 + MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface"); 95 + 92 96 static u32 acpi_target_sleep_state = ACPI_STATE_S0; 93 97 94 98 u32 acpi_target_system_state(void) ··· 162 158 return 0; 163 159 } 164 160 165 - static bool acpi_sleep_no_lps0; 161 + static bool acpi_sleep_default_s3; 166 162 167 - static int __init init_no_lps0(const struct dmi_system_id *d) 163 + static int __init init_default_s3(const struct dmi_system_id *d) 168 164 { 169 - acpi_sleep_no_lps0 = true; 165 + acpi_sleep_default_s3 = true; 170 166 return 0; 171 167 } 172 168 ··· 367 363 * S0 Idle firmware interface. 368 364 */ 369 365 { 370 - .callback = init_no_lps0, 366 + .callback = init_default_s3, 371 367 .ident = "Dell XPS13 9360", 372 368 .matches = { 373 369 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ··· 380 376 * https://bugzilla.kernel.org/show_bug.cgi?id=199057). 381 377 */ 382 378 { 383 - .callback = init_no_lps0, 379 + .callback = init_default_s3, 384 380 .ident = "ThinkPad X1 Tablet(2016)", 385 381 .matches = { 386 382 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ··· 528 524 acpi_sleep_tts_switch(acpi_target_sleep_state); 529 525 } 530 526 #else /* !CONFIG_ACPI_SLEEP */ 527 + #define sleep_no_lps0 (1) 531 528 #define acpi_target_sleep_state ACPI_STATE_S0 532 - #define acpi_sleep_no_lps0 (false) 529 + #define acpi_sleep_default_s3 (1) 533 530 static inline void acpi_sleep_dmi_check(void) {} 534 531 #endif /* CONFIG_ACPI_SLEEP */ 535 532 ··· 696 691 .recover = acpi_pm_finish, 697 692 }; 698 693 699 - static bool s2idle_in_progress; 700 694 static bool s2idle_wakeup; 701 695 702 696 /* ··· 908 904 if (lps0_device_handle) 909 905 return 0; 910 906 911 - if (acpi_sleep_no_lps0) { 912 - acpi_handle_info(adev->handle, 913 - "Low Power S0 Idle interface disabled\n"); 914 - return 0; 915 - } 916 - 917 907 if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) 918 908 return 0; 919 909 920 910 guid_parse(ACPI_LPS0_DSM_UUID, &lps0_dsm_guid); 921 911 /* Check if the _DSM is present and as expected. */ 922 912 out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 1, 0, NULL); 923 - if (out_obj && out_obj->type == ACPI_TYPE_BUFFER) { 924 - char bitmask = *(char *)out_obj->buffer.pointer; 925 - 926 - lps0_dsm_func_mask = bitmask; 927 - lps0_device_handle = adev->handle; 928 - /* 929 - * Use suspend-to-idle by default if the default 930 - * suspend mode was not set from the command line. 931 - */ 932 - if (mem_sleep_default > PM_SUSPEND_MEM) 933 - mem_sleep_current = PM_SUSPEND_TO_IDLE; 934 - 935 - acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n", 936 - bitmask); 937 - 938 - acpi_ec_mark_gpe_for_wake(); 939 - } else { 913 + if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER) { 940 914 acpi_handle_debug(adev->handle, 941 915 "_DSM function 0 evaluation failed\n"); 916 + return 0; 942 917 } 918 + 919 + lps0_dsm_func_mask = *(char *)out_obj->buffer.pointer; 920 + 943 921 ACPI_FREE(out_obj); 944 922 923 + acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n", 924 + lps0_dsm_func_mask); 925 + 926 + lps0_device_handle = adev->handle; 927 + 945 928 lpi_device_get_constraints(); 929 + 930 + /* 931 + * Use suspend-to-idle by default if the default suspend mode was not 932 + * set from the command line. 933 + */ 934 + if (mem_sleep_default > PM_SUSPEND_MEM && !acpi_sleep_default_s3) 935 + mem_sleep_current = PM_SUSPEND_TO_IDLE; 936 + 937 + /* 938 + * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the 939 + * EC GPE to be enabled while suspended for certain wakeup devices to 940 + * work, so mark it as wakeup-capable. 941 + */ 942 + acpi_ec_mark_gpe_for_wake(); 946 943 947 944 return 0; 948 945 } ··· 956 951 static int acpi_s2idle_begin(void) 957 952 { 958 953 acpi_scan_lock_acquire(); 959 - s2idle_in_progress = true; 960 954 return 0; 961 955 } 962 956 963 957 static int acpi_s2idle_prepare(void) 964 958 { 965 - if (lps0_device_handle) { 966 - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); 967 - acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); 968 - 959 + if (acpi_sci_irq_valid()) { 960 + enable_irq_wake(acpi_sci_irq); 969 961 acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE); 970 962 } 971 - 972 - if (acpi_sci_irq_valid()) 973 - enable_irq_wake(acpi_sci_irq); 974 963 975 964 acpi_enable_wakeup_devices(ACPI_STATE_S0); 976 965 977 966 /* Change the configuration of GPEs to avoid spurious wakeup. */ 978 967 acpi_enable_all_wakeup_gpes(); 979 968 acpi_os_wait_events_complete(); 969 + 970 + s2idle_wakeup = true; 971 + return 0; 972 + } 973 + 974 + static int acpi_s2idle_prepare_late(void) 975 + { 976 + if (!lps0_device_handle || sleep_no_lps0) 977 + return 0; 978 + 979 + if (pm_debug_messages_on) 980 + lpi_check_constraints(); 981 + 982 + acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); 983 + acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); 984 + 980 985 return 0; 981 986 } 982 987 983 988 static void acpi_s2idle_wake(void) 984 989 { 985 - if (!lps0_device_handle) 990 + /* 991 + * If IRQD_WAKEUP_ARMED is set for the SCI at this point, the SCI has 992 + * not triggered while suspended, so bail out. 993 + */ 994 + if (!acpi_sci_irq_valid() || 995 + irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) 986 996 return; 987 997 988 - if (pm_debug_messages_on) 989 - lpi_check_constraints(); 990 - 991 998 /* 992 - * If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means 993 - * that the SCI has triggered while suspended, so cancel the wakeup in 994 - * case it has not been a wakeup event (the GPEs will be checked later). 999 + * If there are EC events to process, the wakeup may be a spurious one 1000 + * coming from the EC. 995 1001 */ 996 - if (acpi_sci_irq_valid() && 997 - !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) { 998 - pm_system_cancel_wakeup(); 999 - s2idle_wakeup = true; 1002 + if (acpi_ec_dispatch_gpe()) { 1000 1003 /* 1001 - * On some platforms with the LPS0 _DSM device noirq resume 1002 - * takes too much time for EC wakeup events to survive, so look 1003 - * for them now. 1004 + * Cancel the wakeup and process all pending events in case 1005 + * there are any wakeup ones in there. 1006 + * 1007 + * Note that if any non-EC GPEs are active at this point, the 1008 + * SCI will retrigger after the rearming below, so no events 1009 + * should be missed by canceling the wakeup here. 1004 1010 */ 1005 - acpi_ec_dispatch_gpe(); 1011 + pm_system_cancel_wakeup(); 1012 + /* 1013 + * The EC driver uses the system workqueue and an additional 1014 + * special one, so those need to be flushed too. 1015 + */ 1016 + acpi_os_wait_events_complete(); /* synchronize EC GPE processing */ 1017 + acpi_ec_flush_work(); 1018 + acpi_os_wait_events_complete(); /* synchronize Notify handling */ 1019 + 1020 + rearm_wake_irq(acpi_sci_irq); 1006 1021 } 1007 1022 } 1008 1023 1009 - static void acpi_s2idle_sync(void) 1024 + static void acpi_s2idle_restore_early(void) 1010 1025 { 1011 - /* 1012 - * Process all pending events in case there are any wakeup ones. 1013 - * 1014 - * The EC driver uses the system workqueue and an additional special 1015 - * one, so those need to be flushed too. 1016 - */ 1017 - acpi_os_wait_events_complete(); /* synchronize SCI IRQ handling */ 1018 - acpi_ec_flush_work(); 1019 - acpi_os_wait_events_complete(); /* synchronize Notify handling */ 1020 - s2idle_wakeup = false; 1026 + if (!lps0_device_handle || sleep_no_lps0) 1027 + return; 1028 + 1029 + acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); 1030 + acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); 1021 1031 } 1022 1032 1023 1033 static void acpi_s2idle_restore(void) 1024 1034 { 1035 + s2idle_wakeup = false; 1036 + 1025 1037 acpi_enable_all_runtime_gpes(); 1026 1038 1027 1039 acpi_disable_wakeup_devices(ACPI_STATE_S0); 1028 1040 1029 - if (acpi_sci_irq_valid()) 1030 - disable_irq_wake(acpi_sci_irq); 1031 - 1032 - if (lps0_device_handle) { 1041 + if (acpi_sci_irq_valid()) { 1033 1042 acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE); 1034 - 1035 - acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); 1036 - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); 1043 + disable_irq_wake(acpi_sci_irq); 1037 1044 } 1038 1045 } 1039 1046 1040 1047 static void acpi_s2idle_end(void) 1041 1048 { 1042 - s2idle_in_progress = false; 1043 1049 acpi_scan_lock_release(); 1044 1050 } 1045 1051 1046 1052 static const struct platform_s2idle_ops acpi_s2idle_ops = { 1047 1053 .begin = acpi_s2idle_begin, 1048 1054 .prepare = acpi_s2idle_prepare, 1055 + .prepare_late = acpi_s2idle_prepare_late, 1049 1056 .wake = acpi_s2idle_wake, 1050 - .sync = acpi_s2idle_sync, 1057 + .restore_early = acpi_s2idle_restore_early, 1051 1058 .restore = acpi_s2idle_restore, 1052 1059 .end = acpi_s2idle_end, 1053 1060 }; ··· 1080 1063 } 1081 1064 1082 1065 #else /* !CONFIG_SUSPEND */ 1083 - #define s2idle_in_progress (false) 1084 1066 #define s2idle_wakeup (false) 1085 1067 #define lps0_device_handle (NULL) 1086 1068 static inline void acpi_sleep_suspend_setup(void) {} ··· 1088 1072 bool acpi_s2idle_wakeup(void) 1089 1073 { 1090 1074 return s2idle_wakeup; 1091 - } 1092 - 1093 - bool acpi_sleep_no_ec_events(void) 1094 - { 1095 - return !s2idle_in_progress || !lps0_device_handle; 1096 1075 } 1097 1076 1098 1077 #ifdef CONFIG_PM_SLEEP
+1 -1
drivers/base/arch_topology.c
··· 179 179 if (!raw_capacity) 180 180 return 0; 181 181 182 - if (val != CPUFREQ_NOTIFY) 182 + if (val != CPUFREQ_CREATE_POLICY) 183 183 return 0; 184 184 185 185 pr_debug("cpu_capacity: init cpu capacity for CPUs [%*pbl] (to_visit=%*pbl)\n",
+1 -1
drivers/base/power/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o runtime.o wakeirq.o 3 - obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o 3 + obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o wakeup_stats.o 4 4 obj-$(CONFIG_PM_TRACE_RTC) += trace.o 5 5 obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o domain_governor.o 6 6 obj-$(CONFIG_HAVE_CLK) += clock_ops.o
+10 -15
drivers/base/power/domain.c
··· 149 149 return ret; 150 150 } 151 151 152 + static int genpd_runtime_suspend(struct device *dev); 153 + 152 154 /* 153 155 * Get the generic PM domain for a particular struct device. 154 156 * This validates the struct device pointer, the PM domain pointer, 155 157 * and checks that the PM domain pointer is a real generic PM domain. 156 158 * Any failure results in NULL being returned. 157 159 */ 158 - static struct generic_pm_domain *genpd_lookup_dev(struct device *dev) 160 + static struct generic_pm_domain *dev_to_genpd_safe(struct device *dev) 159 161 { 160 - struct generic_pm_domain *genpd = NULL, *gpd; 161 - 162 162 if (IS_ERR_OR_NULL(dev) || IS_ERR_OR_NULL(dev->pm_domain)) 163 163 return NULL; 164 164 165 - mutex_lock(&gpd_list_lock); 166 - list_for_each_entry(gpd, &gpd_list, gpd_list_node) { 167 - if (&gpd->domain == dev->pm_domain) { 168 - genpd = gpd; 169 - break; 170 - } 171 - } 172 - mutex_unlock(&gpd_list_lock); 165 + /* A genpd's always have its ->runtime_suspend() callback assigned. */ 166 + if (dev->pm_domain->ops.runtime_suspend == genpd_runtime_suspend) 167 + return pd_to_genpd(dev->pm_domain); 173 168 174 - return genpd; 169 + return NULL; 175 170 } 176 171 177 172 /* ··· 380 385 unsigned int prev; 381 386 int ret; 382 387 383 - genpd = dev_to_genpd(dev); 384 - if (IS_ERR(genpd)) 388 + genpd = dev_to_genpd_safe(dev); 389 + if (!genpd) 385 390 return -ENODEV; 386 391 387 392 if (unlikely(!genpd->set_performance_state)) ··· 1605 1610 */ 1606 1611 int pm_genpd_remove_device(struct device *dev) 1607 1612 { 1608 - struct generic_pm_domain *genpd = genpd_lookup_dev(dev); 1613 + struct generic_pm_domain *genpd = dev_to_genpd_safe(dev); 1609 1614 1610 1615 if (!genpd) 1611 1616 return -EINVAL;
+12 -23
drivers/base/power/main.c
··· 716 716 put_device(dev); 717 717 } 718 718 719 - void dpm_noirq_resume_devices(pm_message_t state) 719 + static void dpm_noirq_resume_devices(pm_message_t state) 720 720 { 721 721 struct device *dev; 722 722 ktime_t starttime = ktime_get(); ··· 760 760 trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false); 761 761 } 762 762 763 - void dpm_noirq_end(void) 764 - { 765 - resume_device_irqs(); 766 - device_wakeup_disarm_wake_irqs(); 767 - cpuidle_resume(); 768 - } 769 - 770 763 /** 771 764 * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices. 772 765 * @state: PM transition of the system being carried out. ··· 770 777 void dpm_resume_noirq(pm_message_t state) 771 778 { 772 779 dpm_noirq_resume_devices(state); 773 - dpm_noirq_end(); 780 + 781 + resume_device_irqs(); 782 + device_wakeup_disarm_wake_irqs(); 783 + 784 + cpuidle_resume(); 774 785 } 775 786 776 787 static pm_callback_t dpm_subsys_resume_early_cb(struct device *dev, ··· 1288 1291 if (async_error) 1289 1292 goto Complete; 1290 1293 1291 - if (pm_wakeup_pending()) { 1292 - async_error = -EBUSY; 1293 - goto Complete; 1294 - } 1295 - 1296 1294 if (dev->power.syscore || dev->power.direct_complete) 1297 1295 goto Complete; 1298 1296 ··· 1354 1362 return __device_suspend_noirq(dev, pm_transition, false); 1355 1363 } 1356 1364 1357 - void dpm_noirq_begin(void) 1358 - { 1359 - cpuidle_pause(); 1360 - device_wakeup_arm_wake_irqs(); 1361 - suspend_device_irqs(); 1362 - } 1363 - 1364 - int dpm_noirq_suspend_devices(pm_message_t state) 1365 + static int dpm_noirq_suspend_devices(pm_message_t state) 1365 1366 { 1366 1367 ktime_t starttime = ktime_get(); 1367 1368 int error = 0; ··· 1411 1426 { 1412 1427 int ret; 1413 1428 1414 - dpm_noirq_begin(); 1429 + cpuidle_pause(); 1430 + 1431 + device_wakeup_arm_wake_irqs(); 1432 + suspend_device_irqs(); 1433 + 1415 1434 ret = dpm_noirq_suspend_devices(state); 1416 1435 if (ret) 1417 1436 dpm_resume_noirq(resume_event(state));
+18
drivers/base/power/power.h
··· 149 149 device_pm_sleep_init(dev); 150 150 pm_runtime_init(dev); 151 151 } 152 + 153 + #ifdef CONFIG_PM_SLEEP 154 + 155 + /* drivers/base/power/wakeup_stats.c */ 156 + extern int wakeup_source_sysfs_add(struct device *parent, 157 + struct wakeup_source *ws); 158 + extern void wakeup_source_sysfs_remove(struct wakeup_source *ws); 159 + 160 + extern int pm_wakeup_source_sysfs_add(struct device *parent); 161 + 162 + #else /* !CONFIG_PM_SLEEP */ 163 + 164 + static inline int pm_wakeup_source_sysfs_add(struct device *parent) 165 + { 166 + return 0; 167 + } 168 + 169 + #endif /* CONFIG_PM_SLEEP */
+6
drivers/base/power/sysfs.c
··· 5 5 #include <linux/export.h> 6 6 #include <linux/pm_qos.h> 7 7 #include <linux/pm_runtime.h> 8 + #include <linux/pm_wakeup.h> 8 9 #include <linux/atomic.h> 9 10 #include <linux/jiffies.h> 10 11 #include "power.h" ··· 668 667 if (rc) 669 668 goto err_wakeup; 670 669 } 670 + rc = pm_wakeup_source_sysfs_add(dev); 671 + if (rc) 672 + goto err_latency; 671 673 return 0; 672 674 675 + err_latency: 676 + sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group); 673 677 err_wakeup: 674 678 sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); 675 679 err_runtime:
+46 -26
drivers/base/power/wakeup.c
··· 72 72 .lock = __SPIN_LOCK_UNLOCKED(deleted_ws.lock), 73 73 }; 74 74 75 - /** 76 - * wakeup_source_prepare - Prepare a new wakeup source for initialization. 77 - * @ws: Wakeup source to prepare. 78 - * @name: Pointer to the name of the new wakeup source. 79 - * 80 - * Callers must ensure that the @name string won't be freed when @ws is still in 81 - * use. 82 - */ 83 - void wakeup_source_prepare(struct wakeup_source *ws, const char *name) 84 - { 85 - if (ws) { 86 - memset(ws, 0, sizeof(*ws)); 87 - ws->name = name; 88 - } 89 - } 90 - EXPORT_SYMBOL_GPL(wakeup_source_prepare); 75 + static DEFINE_IDA(wakeup_ida); 91 76 92 77 /** 93 78 * wakeup_source_create - Create a struct wakeup_source object. ··· 81 96 struct wakeup_source *wakeup_source_create(const char *name) 82 97 { 83 98 struct wakeup_source *ws; 99 + const char *ws_name; 100 + int id; 84 101 85 - ws = kmalloc(sizeof(*ws), GFP_KERNEL); 102 + ws = kzalloc(sizeof(*ws), GFP_KERNEL); 86 103 if (!ws) 87 - return NULL; 104 + goto err_ws; 88 105 89 - wakeup_source_prepare(ws, name ? kstrdup_const(name, GFP_KERNEL) : NULL); 106 + ws_name = kstrdup_const(name, GFP_KERNEL); 107 + if (!ws_name) 108 + goto err_name; 109 + ws->name = ws_name; 110 + 111 + id = ida_alloc(&wakeup_ida, GFP_KERNEL); 112 + if (id < 0) 113 + goto err_id; 114 + ws->id = id; 115 + 90 116 return ws; 117 + 118 + err_id: 119 + kfree_const(ws->name); 120 + err_name: 121 + kfree(ws); 122 + err_ws: 123 + return NULL; 91 124 } 92 125 EXPORT_SYMBOL_GPL(wakeup_source_create); 93 126 ··· 137 134 spin_unlock_irqrestore(&deleted_ws.lock, flags); 138 135 } 139 136 137 + static void wakeup_source_free(struct wakeup_source *ws) 138 + { 139 + ida_free(&wakeup_ida, ws->id); 140 + kfree_const(ws->name); 141 + kfree(ws); 142 + } 143 + 140 144 /** 141 145 * wakeup_source_destroy - Destroy a struct wakeup_source object. 142 146 * @ws: Wakeup source to destroy. ··· 157 147 158 148 __pm_relax(ws); 159 149 wakeup_source_record(ws); 160 - kfree_const(ws->name); 161 - kfree(ws); 150 + wakeup_source_free(ws); 162 151 } 163 152 EXPORT_SYMBOL_GPL(wakeup_source_destroy); 164 153 ··· 209 200 210 201 /** 211 202 * wakeup_source_register - Create wakeup source and add it to the list. 203 + * @dev: Device this wakeup source is associated with (or NULL if virtual). 212 204 * @name: Name of the wakeup source to register. 213 205 */ 214 - struct wakeup_source *wakeup_source_register(const char *name) 206 + struct wakeup_source *wakeup_source_register(struct device *dev, 207 + const char *name) 215 208 { 216 209 struct wakeup_source *ws; 210 + int ret; 217 211 218 212 ws = wakeup_source_create(name); 219 - if (ws) 213 + if (ws) { 214 + if (!dev || device_is_registered(dev)) { 215 + ret = wakeup_source_sysfs_add(dev, ws); 216 + if (ret) { 217 + wakeup_source_free(ws); 218 + return NULL; 219 + } 220 + } 220 221 wakeup_source_add(ws); 221 - 222 + } 222 223 return ws; 223 224 } 224 225 EXPORT_SYMBOL_GPL(wakeup_source_register); ··· 241 222 { 242 223 if (ws) { 243 224 wakeup_source_remove(ws); 225 + wakeup_source_sysfs_remove(ws); 244 226 wakeup_source_destroy(ws); 245 227 } 246 228 } ··· 285 265 if (pm_suspend_target_state != PM_SUSPEND_ON) 286 266 dev_dbg(dev, "Suspicious %s() during system transition!\n", __func__); 287 267 288 - ws = wakeup_source_register(dev_name(dev)); 268 + ws = wakeup_source_register(dev, dev_name(dev)); 289 269 if (!ws) 290 270 return -ENOMEM; 291 271 ··· 879 859 880 860 void pm_system_cancel_wakeup(void) 881 861 { 882 - atomic_dec(&pm_abort_suspend); 862 + atomic_dec_if_positive(&pm_abort_suspend); 883 863 } 884 864 885 865 void pm_wakeup_clear(bool reset)
+214
drivers/base/power/wakeup_stats.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Wakeup statistics in sysfs 4 + * 5 + * Copyright (c) 2019 Linux Foundation 6 + * Copyright (c) 2019 Greg Kroah-Hartman <gregkh@linuxfoundation.org> 7 + * Copyright (c) 2019 Google Inc. 8 + */ 9 + 10 + #include <linux/device.h> 11 + #include <linux/idr.h> 12 + #include <linux/init.h> 13 + #include <linux/kdev_t.h> 14 + #include <linux/kernel.h> 15 + #include <linux/kobject.h> 16 + #include <linux/slab.h> 17 + #include <linux/timekeeping.h> 18 + 19 + #include "power.h" 20 + 21 + static struct class *wakeup_class; 22 + 23 + #define wakeup_attr(_name) \ 24 + static ssize_t _name##_show(struct device *dev, \ 25 + struct device_attribute *attr, char *buf) \ 26 + { \ 27 + struct wakeup_source *ws = dev_get_drvdata(dev); \ 28 + \ 29 + return sprintf(buf, "%lu\n", ws->_name); \ 30 + } \ 31 + static DEVICE_ATTR_RO(_name) 32 + 33 + wakeup_attr(active_count); 34 + wakeup_attr(event_count); 35 + wakeup_attr(wakeup_count); 36 + wakeup_attr(expire_count); 37 + 38 + static ssize_t active_time_ms_show(struct device *dev, 39 + struct device_attribute *attr, char *buf) 40 + { 41 + struct wakeup_source *ws = dev_get_drvdata(dev); 42 + ktime_t active_time = 43 + ws->active ? ktime_sub(ktime_get(), ws->last_time) : 0; 44 + 45 + return sprintf(buf, "%lld\n", ktime_to_ms(active_time)); 46 + } 47 + static DEVICE_ATTR_RO(active_time_ms); 48 + 49 + static ssize_t total_time_ms_show(struct device *dev, 50 + struct device_attribute *attr, char *buf) 51 + { 52 + struct wakeup_source *ws = dev_get_drvdata(dev); 53 + ktime_t active_time; 54 + ktime_t total_time = ws->total_time; 55 + 56 + if (ws->active) { 57 + active_time = ktime_sub(ktime_get(), ws->last_time); 58 + total_time = ktime_add(total_time, active_time); 59 + } 60 + return sprintf(buf, "%lld\n", ktime_to_ms(total_time)); 61 + } 62 + static DEVICE_ATTR_RO(total_time_ms); 63 + 64 + static ssize_t max_time_ms_show(struct device *dev, 65 + struct device_attribute *attr, char *buf) 66 + { 67 + struct wakeup_source *ws = dev_get_drvdata(dev); 68 + ktime_t active_time; 69 + ktime_t max_time = ws->max_time; 70 + 71 + if (ws->active) { 72 + active_time = ktime_sub(ktime_get(), ws->last_time); 73 + if (active_time > max_time) 74 + max_time = active_time; 75 + } 76 + return sprintf(buf, "%lld\n", ktime_to_ms(max_time)); 77 + } 78 + static DEVICE_ATTR_RO(max_time_ms); 79 + 80 + static ssize_t last_change_ms_show(struct device *dev, 81 + struct device_attribute *attr, char *buf) 82 + { 83 + struct wakeup_source *ws = dev_get_drvdata(dev); 84 + 85 + return sprintf(buf, "%lld\n", ktime_to_ms(ws->last_time)); 86 + } 87 + static DEVICE_ATTR_RO(last_change_ms); 88 + 89 + static ssize_t name_show(struct device *dev, struct device_attribute *attr, 90 + char *buf) 91 + { 92 + struct wakeup_source *ws = dev_get_drvdata(dev); 93 + 94 + return sprintf(buf, "%s\n", ws->name); 95 + } 96 + static DEVICE_ATTR_RO(name); 97 + 98 + static ssize_t prevent_suspend_time_ms_show(struct device *dev, 99 + struct device_attribute *attr, 100 + char *buf) 101 + { 102 + struct wakeup_source *ws = dev_get_drvdata(dev); 103 + ktime_t prevent_sleep_time = ws->prevent_sleep_time; 104 + 105 + if (ws->active && ws->autosleep_enabled) { 106 + prevent_sleep_time = ktime_add(prevent_sleep_time, 107 + ktime_sub(ktime_get(), ws->start_prevent_time)); 108 + } 109 + return sprintf(buf, "%lld\n", ktime_to_ms(prevent_sleep_time)); 110 + } 111 + static DEVICE_ATTR_RO(prevent_suspend_time_ms); 112 + 113 + static struct attribute *wakeup_source_attrs[] = { 114 + &dev_attr_name.attr, 115 + &dev_attr_active_count.attr, 116 + &dev_attr_event_count.attr, 117 + &dev_attr_wakeup_count.attr, 118 + &dev_attr_expire_count.attr, 119 + &dev_attr_active_time_ms.attr, 120 + &dev_attr_total_time_ms.attr, 121 + &dev_attr_max_time_ms.attr, 122 + &dev_attr_last_change_ms.attr, 123 + &dev_attr_prevent_suspend_time_ms.attr, 124 + NULL, 125 + }; 126 + ATTRIBUTE_GROUPS(wakeup_source); 127 + 128 + static void device_create_release(struct device *dev) 129 + { 130 + kfree(dev); 131 + } 132 + 133 + static struct device *wakeup_source_device_create(struct device *parent, 134 + struct wakeup_source *ws) 135 + { 136 + struct device *dev = NULL; 137 + int retval = -ENODEV; 138 + 139 + dev = kzalloc(sizeof(*dev), GFP_KERNEL); 140 + if (!dev) { 141 + retval = -ENOMEM; 142 + goto error; 143 + } 144 + 145 + device_initialize(dev); 146 + dev->devt = MKDEV(0, 0); 147 + dev->class = wakeup_class; 148 + dev->parent = parent; 149 + dev->groups = wakeup_source_groups; 150 + dev->release = device_create_release; 151 + dev_set_drvdata(dev, ws); 152 + device_set_pm_not_required(dev); 153 + 154 + retval = kobject_set_name(&dev->kobj, "wakeup%d", ws->id); 155 + if (retval) 156 + goto error; 157 + 158 + retval = device_add(dev); 159 + if (retval) 160 + goto error; 161 + 162 + return dev; 163 + 164 + error: 165 + put_device(dev); 166 + return ERR_PTR(retval); 167 + } 168 + 169 + /** 170 + * wakeup_source_sysfs_add - Add wakeup_source attributes to sysfs. 171 + * @parent: Device given wakeup source is associated with (or NULL if virtual). 172 + * @ws: Wakeup source to be added in sysfs. 173 + */ 174 + int wakeup_source_sysfs_add(struct device *parent, struct wakeup_source *ws) 175 + { 176 + struct device *dev; 177 + 178 + dev = wakeup_source_device_create(parent, ws); 179 + if (IS_ERR(dev)) 180 + return PTR_ERR(dev); 181 + ws->dev = dev; 182 + 183 + return 0; 184 + } 185 + 186 + /** 187 + * pm_wakeup_source_sysfs_add - Add wakeup_source attributes to sysfs 188 + * for a device if they're missing. 189 + * @parent: Device given wakeup source is associated with 190 + */ 191 + int pm_wakeup_source_sysfs_add(struct device *parent) 192 + { 193 + if (!parent->power.wakeup || parent->power.wakeup->dev) 194 + return 0; 195 + 196 + return wakeup_source_sysfs_add(parent, parent->power.wakeup); 197 + } 198 + 199 + /** 200 + * wakeup_source_sysfs_remove - Remove wakeup_source attributes from sysfs. 201 + * @ws: Wakeup source to be removed from sysfs. 202 + */ 203 + void wakeup_source_sysfs_remove(struct wakeup_source *ws) 204 + { 205 + device_unregister(ws->dev); 206 + } 207 + 208 + static int __init wakeup_sources_sysfs_init(void) 209 + { 210 + wakeup_class = class_create(THIS_MODULE, "wakeup"); 211 + 212 + return PTR_ERR_OR_ZERO(wakeup_class); 213 + } 214 + postcore_initcall(wakeup_sources_sysfs_init);
+14 -2
drivers/cpufreq/Kconfig.arm
··· 19 19 20 20 If in doubt, say N. 21 21 22 + config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM 23 + tristate "Allwinner nvmem based SUN50I CPUFreq driver" 24 + depends on ARCH_SUNXI 25 + depends on NVMEM_SUNXI_SID 26 + select PM_OPP 27 + help 28 + This adds the nvmem based CPUFreq driver for Allwinner 29 + h6 SoC. 30 + 31 + To compile this driver as a module, choose M here: the 32 + module will be called sun50i-cpufreq-nvmem. 33 + 22 34 config ARM_ARMADA_37XX_CPUFREQ 23 35 tristate "Armada 37xx CPUFreq support" 24 36 depends on ARCH_MVEBU && CPUFREQ_DT ··· 132 120 depends on ARCH_OMAP2PLUS 133 121 default ARCH_OMAP2PLUS 134 122 135 - config ARM_QCOM_CPUFREQ_KRYO 136 - tristate "Qualcomm Kryo based CPUFreq" 123 + config ARM_QCOM_CPUFREQ_NVMEM 124 + tristate "Qualcomm nvmem based CPUFreq" 137 125 depends on ARM64 138 126 depends on QCOM_QFPROM 139 127 depends on QCOM_SMEM
+2 -1
drivers/cpufreq/Makefile
··· 64 64 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o 65 65 obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o 66 66 obj-$(CONFIG_ARM_QCOM_CPUFREQ_HW) += qcom-cpufreq-hw.o 67 - obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO) += qcom-cpufreq-kryo.o 67 + obj-$(CONFIG_ARM_QCOM_CPUFREQ_NVMEM) += qcom-cpufreq-nvmem.o 68 68 obj-$(CONFIG_ARM_RASPBERRYPI_CPUFREQ) += raspberrypi-cpufreq.o 69 69 obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o 70 70 obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o ··· 80 80 obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o 81 81 obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o 82 82 obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o 83 + obj-$(CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM) += sun50i-cpufreq-nvmem.o 83 84 obj-$(CONFIG_ARM_TANGO_CPUFREQ) += tango-cpufreq.o 84 85 obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o 85 86 obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
+2
drivers/cpufreq/armada-8k-cpufreq.c
··· 136 136 137 137 nb_cpus = num_possible_cpus(); 138 138 freq_tables = kcalloc(nb_cpus, sizeof(*freq_tables), GFP_KERNEL); 139 + if (!freq_tables) 140 + return -ENOMEM; 139 141 cpumask_copy(&cpus, cpu_possible_mask); 140 142 141 143 /*
+5
drivers/cpufreq/cpufreq-dt-platdev.c
··· 101 101 * platforms using "operating-points-v2" property. 102 102 */ 103 103 static const struct of_device_id blacklist[] __initconst = { 104 + { .compatible = "allwinner,sun50i-h6", }, 105 + 104 106 { .compatible = "calxeda,highbank", }, 105 107 { .compatible = "calxeda,ecx-2000", }, 106 108 107 109 { .compatible = "fsl,imx7d", }, 108 110 { .compatible = "fsl,imx8mq", }, 109 111 { .compatible = "fsl,imx8mm", }, 112 + { .compatible = "fsl,imx8mn", }, 110 113 111 114 { .compatible = "marvell,armadaxp", }, 112 115 ··· 120 117 { .compatible = "mediatek,mt817x", }, 121 118 { .compatible = "mediatek,mt8173", }, 122 119 { .compatible = "mediatek,mt8176", }, 120 + { .compatible = "mediatek,mt8183", }, 123 121 124 122 { .compatible = "nvidia,tegra124", }, 125 123 { .compatible = "nvidia,tegra210", }, 126 124 127 125 { .compatible = "qcom,apq8096", }, 128 126 { .compatible = "qcom,msm8996", }, 127 + { .compatible = "qcom,qcs404", }, 129 128 130 129 { .compatible = "st,stih407", }, 131 130 { .compatible = "st,stih410", },
+24 -33
drivers/cpufreq/cpufreq.c
··· 1266 1266 DEV_PM_QOS_MAX_FREQUENCY); 1267 1267 dev_pm_qos_remove_notifier(dev, &policy->nb_min, 1268 1268 DEV_PM_QOS_MIN_FREQUENCY); 1269 - dev_pm_qos_remove_request(policy->max_freq_req); 1269 + 1270 + if (policy->max_freq_req) { 1271 + /* 1272 + * CPUFREQ_CREATE_POLICY notification is sent only after 1273 + * successfully adding max_freq_req request. 1274 + */ 1275 + blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 1276 + CPUFREQ_REMOVE_POLICY, policy); 1277 + dev_pm_qos_remove_request(policy->max_freq_req); 1278 + } 1279 + 1270 1280 dev_pm_qos_remove_request(policy->min_freq_req); 1271 1281 kfree(policy->min_freq_req); 1272 1282 ··· 1401 1391 ret); 1402 1392 goto out_destroy_policy; 1403 1393 } 1394 + 1395 + blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 1396 + CPUFREQ_CREATE_POLICY, policy); 1404 1397 } 1405 1398 1406 1399 if (cpufreq_driver->get && has_target()) { ··· 1820 1807 } 1821 1808 1822 1809 if (cpufreq_driver->suspend && cpufreq_driver->suspend(policy)) 1823 - pr_err("%s: Failed to suspend driver: %p\n", __func__, 1824 - policy); 1810 + pr_err("%s: Failed to suspend driver: %s\n", __func__, 1811 + cpufreq_driver->name); 1825 1812 } 1826 1813 1827 1814 suspend: ··· 2153 2140 unsigned int target_freq, 2154 2141 unsigned int relation) 2155 2142 { 2156 - int ret = -EINVAL; 2143 + int ret; 2157 2144 2158 2145 down_write(&policy->rwsem); 2159 2146 ··· 2360 2347 * @policy: Policy object to modify. 2361 2348 * @new_policy: New policy data. 2362 2349 * 2363 - * Pass @new_policy to the cpufreq driver's ->verify() callback, run the 2364 - * installed policy notifiers for it with the CPUFREQ_ADJUST value, pass it to 2365 - * the driver's ->verify() callback again and run the notifiers for it again 2366 - * with the CPUFREQ_NOTIFY value. Next, copy the min and max parameters 2367 - * of @new_policy to @policy and either invoke the driver's ->setpolicy() 2368 - * callback (if present) or carry out a governor update for @policy. That is, 2369 - * run the current governor's ->limits() callback (if the governor field in 2370 - * @new_policy points to the same object as the one in @policy) or replace the 2371 - * governor for @policy with the new one stored in @new_policy. 2350 + * Pass @new_policy to the cpufreq driver's ->verify() callback. Next, copy the 2351 + * min and max parameters of @new_policy to @policy and either invoke the 2352 + * driver's ->setpolicy() callback (if present) or carry out a governor update 2353 + * for @policy. That is, run the current governor's ->limits() callback (if the 2354 + * governor field in @new_policy points to the same object as the one in 2355 + * @policy) or replace the governor for @policy with the new one stored in 2356 + * @new_policy. 2372 2357 * 2373 2358 * The cpuinfo part of @policy is not updated by this function. 2374 2359 */ ··· 2393 2382 ret = cpufreq_driver->verify(new_policy); 2394 2383 if (ret) 2395 2384 return ret; 2396 - 2397 - /* 2398 - * The notifier-chain shall be removed once all the users of 2399 - * CPUFREQ_ADJUST are moved to use the QoS framework. 2400 - */ 2401 - /* adjust if necessary - all reasons */ 2402 - blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 2403 - CPUFREQ_ADJUST, new_policy); 2404 - 2405 - /* 2406 - * verify the cpu speed can be set within this limit, which might be 2407 - * different to the first one 2408 - */ 2409 - ret = cpufreq_driver->verify(new_policy); 2410 - if (ret) 2411 - return ret; 2412 - 2413 - /* notification of the new policy */ 2414 - blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 2415 - CPUFREQ_NOTIFY, new_policy); 2416 2385 2417 2386 policy->min = new_policy->min; 2418 2387 policy->max = new_policy->max;
+7 -1
drivers/cpufreq/imx-cpufreq-dt.c
··· 16 16 17 17 #define OCOTP_CFG3_SPEED_GRADE_SHIFT 8 18 18 #define OCOTP_CFG3_SPEED_GRADE_MASK (0x3 << 8) 19 + #define IMX8MN_OCOTP_CFG3_SPEED_GRADE_MASK (0xf << 8) 19 20 #define OCOTP_CFG3_MKT_SEGMENT_SHIFT 6 20 21 #define OCOTP_CFG3_MKT_SEGMENT_MASK (0x3 << 6) 21 22 ··· 35 34 if (ret) 36 35 return ret; 37 36 38 - speed_grade = (cell_value & OCOTP_CFG3_SPEED_GRADE_MASK) >> OCOTP_CFG3_SPEED_GRADE_SHIFT; 37 + if (of_machine_is_compatible("fsl,imx8mn")) 38 + speed_grade = (cell_value & IMX8MN_OCOTP_CFG3_SPEED_GRADE_MASK) 39 + >> OCOTP_CFG3_SPEED_GRADE_SHIFT; 40 + else 41 + speed_grade = (cell_value & OCOTP_CFG3_SPEED_GRADE_MASK) 42 + >> OCOTP_CFG3_SPEED_GRADE_SHIFT; 39 43 mkt_segment = (cell_value & OCOTP_CFG3_MKT_SEGMENT_MASK) >> OCOTP_CFG3_MKT_SEGMENT_SHIFT; 40 44 41 45 /*
+116 -4
drivers/cpufreq/intel_pstate.c
··· 24 24 #include <linux/fs.h> 25 25 #include <linux/acpi.h> 26 26 #include <linux/vmalloc.h> 27 + #include <linux/pm_qos.h> 27 28 #include <trace/events/power.h> 28 29 29 30 #include <asm/div64.h> ··· 1086 1085 return count; 1087 1086 } 1088 1087 1088 + static struct cpufreq_driver intel_pstate; 1089 + 1090 + static void update_qos_request(enum dev_pm_qos_req_type type) 1091 + { 1092 + int max_state, turbo_max, freq, i, perf_pct; 1093 + struct dev_pm_qos_request *req; 1094 + struct cpufreq_policy *policy; 1095 + 1096 + for_each_possible_cpu(i) { 1097 + struct cpudata *cpu = all_cpu_data[i]; 1098 + 1099 + policy = cpufreq_cpu_get(i); 1100 + if (!policy) 1101 + continue; 1102 + 1103 + req = policy->driver_data; 1104 + cpufreq_cpu_put(policy); 1105 + 1106 + if (!req) 1107 + continue; 1108 + 1109 + if (hwp_active) 1110 + intel_pstate_get_hwp_max(i, &turbo_max, &max_state); 1111 + else 1112 + turbo_max = cpu->pstate.turbo_pstate; 1113 + 1114 + if (type == DEV_PM_QOS_MIN_FREQUENCY) { 1115 + perf_pct = global.min_perf_pct; 1116 + } else { 1117 + req++; 1118 + perf_pct = global.max_perf_pct; 1119 + } 1120 + 1121 + freq = DIV_ROUND_UP(turbo_max * perf_pct, 100); 1122 + freq *= cpu->pstate.scaling; 1123 + 1124 + if (dev_pm_qos_update_request(req, freq) < 0) 1125 + pr_warn("Failed to update freq constraint: CPU%d\n", i); 1126 + } 1127 + } 1128 + 1089 1129 static ssize_t store_max_perf_pct(struct kobject *a, struct kobj_attribute *b, 1090 1130 const char *buf, size_t count) 1091 1131 { ··· 1150 1108 1151 1109 mutex_unlock(&intel_pstate_limits_lock); 1152 1110 1153 - intel_pstate_update_policies(); 1111 + if (intel_pstate_driver == &intel_pstate) 1112 + intel_pstate_update_policies(); 1113 + else 1114 + update_qos_request(DEV_PM_QOS_MAX_FREQUENCY); 1154 1115 1155 1116 mutex_unlock(&intel_pstate_driver_lock); 1156 1117 ··· 1184 1139 1185 1140 mutex_unlock(&intel_pstate_limits_lock); 1186 1141 1187 - intel_pstate_update_policies(); 1142 + if (intel_pstate_driver == &intel_pstate) 1143 + intel_pstate_update_policies(); 1144 + else 1145 + update_qos_request(DEV_PM_QOS_MIN_FREQUENCY); 1188 1146 1189 1147 mutex_unlock(&intel_pstate_driver_lock); 1190 1148 ··· 2380 2332 2381 2333 static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy) 2382 2334 { 2383 - int ret = __intel_pstate_cpu_init(policy); 2335 + int max_state, turbo_max, min_freq, max_freq, ret; 2336 + struct dev_pm_qos_request *req; 2337 + struct cpudata *cpu; 2338 + struct device *dev; 2384 2339 2340 + dev = get_cpu_device(policy->cpu); 2341 + if (!dev) 2342 + return -ENODEV; 2343 + 2344 + ret = __intel_pstate_cpu_init(policy); 2385 2345 if (ret) 2386 2346 return ret; 2387 2347 ··· 2398 2342 /* This reflects the intel_pstate_get_cpu_pstates() setting. */ 2399 2343 policy->cur = policy->cpuinfo.min_freq; 2400 2344 2345 + req = kcalloc(2, sizeof(*req), GFP_KERNEL); 2346 + if (!req) { 2347 + ret = -ENOMEM; 2348 + goto pstate_exit; 2349 + } 2350 + 2351 + cpu = all_cpu_data[policy->cpu]; 2352 + 2353 + if (hwp_active) 2354 + intel_pstate_get_hwp_max(policy->cpu, &turbo_max, &max_state); 2355 + else 2356 + turbo_max = cpu->pstate.turbo_pstate; 2357 + 2358 + min_freq = DIV_ROUND_UP(turbo_max * global.min_perf_pct, 100); 2359 + min_freq *= cpu->pstate.scaling; 2360 + max_freq = DIV_ROUND_UP(turbo_max * global.max_perf_pct, 100); 2361 + max_freq *= cpu->pstate.scaling; 2362 + 2363 + ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_MIN_FREQUENCY, 2364 + min_freq); 2365 + if (ret < 0) { 2366 + dev_err(dev, "Failed to add min-freq constraint (%d)\n", ret); 2367 + goto free_req; 2368 + } 2369 + 2370 + ret = dev_pm_qos_add_request(dev, req + 1, DEV_PM_QOS_MAX_FREQUENCY, 2371 + max_freq); 2372 + if (ret < 0) { 2373 + dev_err(dev, "Failed to add max-freq constraint (%d)\n", ret); 2374 + goto remove_min_req; 2375 + } 2376 + 2377 + policy->driver_data = req; 2378 + 2401 2379 return 0; 2380 + 2381 + remove_min_req: 2382 + dev_pm_qos_remove_request(req); 2383 + free_req: 2384 + kfree(req); 2385 + pstate_exit: 2386 + intel_pstate_exit_perf_limits(policy); 2387 + 2388 + return ret; 2389 + } 2390 + 2391 + static int intel_cpufreq_cpu_exit(struct cpufreq_policy *policy) 2392 + { 2393 + struct dev_pm_qos_request *req; 2394 + 2395 + req = policy->driver_data; 2396 + 2397 + dev_pm_qos_remove_request(req + 1); 2398 + dev_pm_qos_remove_request(req); 2399 + kfree(req); 2400 + 2401 + return intel_pstate_cpu_exit(policy); 2402 2402 } 2403 2403 2404 2404 static struct cpufreq_driver intel_cpufreq = { ··· 2463 2351 .target = intel_cpufreq_target, 2464 2352 .fast_switch = intel_cpufreq_fast_switch, 2465 2353 .init = intel_cpufreq_cpu_init, 2466 - .exit = intel_pstate_cpu_exit, 2354 + .exit = intel_cpufreq_cpu_exit, 2467 2355 .stop_cpu = intel_cpufreq_stop_cpu, 2468 2356 .update_limits = intel_pstate_update_limits, 2469 2357 .name = "intel_cpufreq",
+3 -1
drivers/cpufreq/mediatek-cpufreq.c
··· 338 338 goto out_free_resources; 339 339 } 340 340 341 - proc_reg = regulator_get_exclusive(cpu_dev, "proc"); 341 + proc_reg = regulator_get_optional(cpu_dev, "proc"); 342 342 if (IS_ERR(proc_reg)) { 343 343 if (PTR_ERR(proc_reg) == -EPROBE_DEFER) 344 344 pr_warn("proc regulator for cpu%d not ready, retry.\n", ··· 535 535 { .compatible = "mediatek,mt817x", }, 536 536 { .compatible = "mediatek,mt8173", }, 537 537 { .compatible = "mediatek,mt8176", }, 538 + { .compatible = "mediatek,mt8183", }, 539 + { .compatible = "mediatek,mt8516", }, 538 540 539 541 { } 540 542 };
+18 -1
drivers/cpufreq/ppc_cbe_cpufreq.c
··· 110 110 #endif 111 111 112 112 policy->freq_table = cbe_freqs; 113 + cbe_cpufreq_pmi_policy_init(policy); 114 + return 0; 115 + } 116 + 117 + static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy) 118 + { 119 + cbe_cpufreq_pmi_policy_exit(policy); 113 120 return 0; 114 121 } 115 122 ··· 136 129 .verify = cpufreq_generic_frequency_table_verify, 137 130 .target_index = cbe_cpufreq_target, 138 131 .init = cbe_cpufreq_cpu_init, 132 + .exit = cbe_cpufreq_cpu_exit, 139 133 .name = "cbe-cpufreq", 140 134 .flags = CPUFREQ_CONST_LOOPS, 141 135 }; ··· 147 139 148 140 static int __init cbe_cpufreq_init(void) 149 141 { 142 + int ret; 143 + 150 144 if (!machine_is(cell)) 151 145 return -ENODEV; 152 146 153 - return cpufreq_register_driver(&cbe_cpufreq_driver); 147 + cbe_cpufreq_pmi_init(); 148 + 149 + ret = cpufreq_register_driver(&cbe_cpufreq_driver); 150 + if (ret) 151 + cbe_cpufreq_pmi_exit(); 152 + 153 + return ret; 154 154 } 155 155 156 156 static void __exit cbe_cpufreq_exit(void) 157 157 { 158 158 cpufreq_unregister_driver(&cbe_cpufreq_driver); 159 + cbe_cpufreq_pmi_exit(); 159 160 } 160 161 161 162 module_init(cbe_cpufreq_init);
+8
drivers/cpufreq/ppc_cbe_cpufreq.h
··· 20 20 21 21 #if IS_ENABLED(CONFIG_CPU_FREQ_CBE_PMI) 22 22 extern bool cbe_cpufreq_has_pmi; 23 + void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy *policy); 24 + void cbe_cpufreq_pmi_policy_exit(struct cpufreq_policy *policy); 25 + void cbe_cpufreq_pmi_init(void); 26 + void cbe_cpufreq_pmi_exit(void); 23 27 #else 24 28 #define cbe_cpufreq_has_pmi (0) 29 + static inline void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy *policy) {} 30 + static inline void cbe_cpufreq_pmi_policy_exit(struct cpufreq_policy *policy) {} 31 + static inline void cbe_cpufreq_pmi_init(void) {} 32 + static inline void cbe_cpufreq_pmi_exit(void) {} 25 33 #endif
+62 -38
drivers/cpufreq/ppc_cbe_cpufreq_pmi.c
··· 12 12 #include <linux/timer.h> 13 13 #include <linux/init.h> 14 14 #include <linux/of_platform.h> 15 + #include <linux/pm_qos.h> 15 16 16 17 #include <asm/processor.h> 17 18 #include <asm/prom.h> ··· 24 23 #endif 25 24 26 25 #include "ppc_cbe_cpufreq.h" 27 - 28 - static u8 pmi_slow_mode_limit[MAX_CBE]; 29 26 30 27 bool cbe_cpufreq_has_pmi = false; 31 28 EXPORT_SYMBOL_GPL(cbe_cpufreq_has_pmi); ··· 64 65 65 66 static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg) 66 67 { 68 + struct cpufreq_policy *policy; 69 + struct dev_pm_qos_request *req; 67 70 u8 node, slow_mode; 71 + int cpu, ret; 68 72 69 73 BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE); 70 74 71 75 node = pmi_msg.data1; 72 76 slow_mode = pmi_msg.data2; 73 77 74 - pmi_slow_mode_limit[node] = slow_mode; 78 + cpu = cbe_node_to_cpu(node); 75 79 76 80 pr_debug("cbe_handle_pmi: node: %d max_freq: %d\n", node, slow_mode); 77 - } 78 81 79 - static int pmi_notifier(struct notifier_block *nb, 80 - unsigned long event, void *data) 81 - { 82 - struct cpufreq_policy *policy = data; 83 - struct cpufreq_frequency_table *cbe_freqs = policy->freq_table; 84 - u8 node; 85 - 86 - /* Should this really be called for CPUFREQ_ADJUST and CPUFREQ_NOTIFY 87 - * policy events?) 88 - */ 89 - node = cbe_cpu_to_node(policy->cpu); 90 - 91 - pr_debug("got notified, event=%lu, node=%u\n", event, node); 92 - 93 - if (pmi_slow_mode_limit[node] != 0) { 94 - pr_debug("limiting node %d to slow mode %d\n", 95 - node, pmi_slow_mode_limit[node]); 96 - 97 - cpufreq_verify_within_limits(policy, 0, 98 - 99 - cbe_freqs[pmi_slow_mode_limit[node]].frequency); 82 + policy = cpufreq_cpu_get(cpu); 83 + if (!policy) { 84 + pr_warn("cpufreq policy not found cpu%d\n", cpu); 85 + return; 100 86 } 101 87 102 - return 0; 103 - } 88 + req = policy->driver_data; 104 89 105 - static struct notifier_block pmi_notifier_block = { 106 - .notifier_call = pmi_notifier, 107 - }; 90 + ret = dev_pm_qos_update_request(req, 91 + policy->freq_table[slow_mode].frequency); 92 + if (ret < 0) 93 + pr_warn("Failed to update freq constraint: %d\n", ret); 94 + else 95 + pr_debug("limiting node %d to slow mode %d\n", node, slow_mode); 96 + 97 + cpufreq_cpu_put(policy); 98 + } 108 99 109 100 static struct pmi_handler cbe_pmi_handler = { 110 101 .type = PMI_TYPE_FREQ_CHANGE, 111 102 .handle_pmi_message = cbe_cpufreq_handle_pmi, 112 103 }; 113 104 114 - 115 - 116 - static int __init cbe_cpufreq_pmi_init(void) 105 + void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy *policy) 117 106 { 118 - cbe_cpufreq_has_pmi = pmi_register_handler(&cbe_pmi_handler) == 0; 107 + struct dev_pm_qos_request *req; 108 + int ret; 119 109 120 110 if (!cbe_cpufreq_has_pmi) 121 - return -ENODEV; 111 + return; 122 112 123 - cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER); 113 + req = kzalloc(sizeof(*req), GFP_KERNEL); 114 + if (!req) 115 + return; 124 116 125 - return 0; 117 + ret = dev_pm_qos_add_request(get_cpu_device(policy->cpu), req, 118 + DEV_PM_QOS_MAX_FREQUENCY, 119 + policy->freq_table[0].frequency); 120 + if (ret < 0) { 121 + pr_err("Failed to add freq constraint (%d)\n", ret); 122 + kfree(req); 123 + return; 124 + } 125 + 126 + policy->driver_data = req; 126 127 } 127 - device_initcall(cbe_cpufreq_pmi_init); 128 + EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_policy_init); 129 + 130 + void cbe_cpufreq_pmi_policy_exit(struct cpufreq_policy *policy) 131 + { 132 + struct dev_pm_qos_request *req = policy->driver_data; 133 + 134 + if (cbe_cpufreq_has_pmi) { 135 + dev_pm_qos_remove_request(req); 136 + kfree(req); 137 + } 138 + } 139 + EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_policy_exit); 140 + 141 + void cbe_cpufreq_pmi_init(void) 142 + { 143 + if (!pmi_register_handler(&cbe_pmi_handler)) 144 + cbe_cpufreq_has_pmi = true; 145 + } 146 + EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_init); 147 + 148 + void cbe_cpufreq_pmi_exit(void) 149 + { 150 + pmi_unregister_handler(&cbe_pmi_handler); 151 + cbe_cpufreq_has_pmi = false; 152 + } 153 + EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_exit);
+15 -8
drivers/cpufreq/qcom-cpufreq-hw.c
··· 20 20 #define LUT_VOLT GENMASK(11, 0) 21 21 #define LUT_ROW_SIZE 32 22 22 #define CLK_HW_DIV 2 23 + #define LUT_TURBO_IND 1 23 24 24 25 /* Register offsets */ 25 26 #define REG_ENABLE 0x0 ··· 35 34 unsigned int index) 36 35 { 37 36 void __iomem *perf_state_reg = policy->driver_data; 37 + unsigned long freq = policy->freq_table[index].frequency; 38 38 39 39 writel_relaxed(index, perf_state_reg); 40 40 41 + arch_set_freq_scale(policy->related_cpus, freq, 42 + policy->cpuinfo.max_freq); 41 43 return 0; 42 44 } 43 45 ··· 67 63 { 68 64 void __iomem *perf_state_reg = policy->driver_data; 69 65 int index; 66 + unsigned long freq; 70 67 71 68 index = policy->cached_resolved_idx; 72 69 if (index < 0) ··· 75 70 76 71 writel_relaxed(index, perf_state_reg); 77 72 78 - return policy->freq_table[index].frequency; 73 + freq = policy->freq_table[index].frequency; 74 + arch_set_freq_scale(policy->related_cpus, freq, 75 + policy->cpuinfo.max_freq); 76 + 77 + return freq; 79 78 } 80 79 81 80 static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev, 82 81 struct cpufreq_policy *policy, 83 82 void __iomem *base) 84 83 { 85 - u32 data, src, lval, i, core_count, prev_cc = 0, prev_freq = 0, freq; 84 + u32 data, src, lval, i, core_count, prev_freq = 0, freq; 86 85 u32 volt; 87 - unsigned int max_cores = cpumask_weight(policy->cpus); 88 86 struct cpufreq_frequency_table *table; 89 87 90 88 table = kcalloc(LUT_MAX_ENTRIES + 1, sizeof(*table), GFP_KERNEL); ··· 110 102 else 111 103 freq = cpu_hw_rate / 1000; 112 104 113 - if (freq != prev_freq && core_count == max_cores) { 105 + if (freq != prev_freq && core_count != LUT_TURBO_IND) { 114 106 table[i].frequency = freq; 115 107 dev_pm_opp_add(cpu_dev, freq * 1000, volt); 116 108 dev_dbg(cpu_dev, "index=%d freq=%d, core_count %d\n", i, 117 109 freq, core_count); 118 - } else { 110 + } else if (core_count == LUT_TURBO_IND) { 119 111 table[i].frequency = CPUFREQ_ENTRY_INVALID; 120 112 } 121 113 ··· 123 115 * Two of the same frequencies with the same core counts means 124 116 * end of table 125 117 */ 126 - if (i > 0 && prev_freq == freq && prev_cc == core_count) { 118 + if (i > 0 && prev_freq == freq) { 127 119 struct cpufreq_frequency_table *prev = &table[i - 1]; 128 120 129 121 /* 130 122 * Only treat the last frequency that might be a boost 131 123 * as the boost frequency 132 124 */ 133 - if (prev_cc != max_cores) { 125 + if (prev->frequency == CPUFREQ_ENTRY_INVALID) { 134 126 prev->frequency = prev_freq; 135 127 prev->flags = CPUFREQ_BOOST_FREQ; 136 128 dev_pm_opp_add(cpu_dev, prev_freq * 1000, volt); ··· 139 131 break; 140 132 } 141 133 142 - prev_cc = core_count; 143 134 prev_freq = freq; 144 135 } 145 136
-249
drivers/cpufreq/qcom-cpufreq-kryo.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 - */ 5 - 6 - /* 7 - * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors, 8 - * the CPU frequency subset and voltage value of each OPP varies 9 - * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables 10 - * defines the voltage and frequency value based on the msm-id in SMEM 11 - * and speedbin blown in the efuse combination. 12 - * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC 13 - * to provide the OPP framework with required information. 14 - * This is used to determine the voltage and frequency value for each OPP of 15 - * operating-points-v2 table when it is parsed by the OPP framework. 16 - */ 17 - 18 - #include <linux/cpu.h> 19 - #include <linux/err.h> 20 - #include <linux/init.h> 21 - #include <linux/kernel.h> 22 - #include <linux/module.h> 23 - #include <linux/nvmem-consumer.h> 24 - #include <linux/of.h> 25 - #include <linux/platform_device.h> 26 - #include <linux/pm_opp.h> 27 - #include <linux/slab.h> 28 - #include <linux/soc/qcom/smem.h> 29 - 30 - #define MSM_ID_SMEM 137 31 - 32 - enum _msm_id { 33 - MSM8996V3 = 0xF6ul, 34 - APQ8096V3 = 0x123ul, 35 - MSM8996SG = 0x131ul, 36 - APQ8096SG = 0x138ul, 37 - }; 38 - 39 - enum _msm8996_version { 40 - MSM8996_V3, 41 - MSM8996_SG, 42 - NUM_OF_MSM8996_VERSIONS, 43 - }; 44 - 45 - static struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev; 46 - 47 - static enum _msm8996_version qcom_cpufreq_kryo_get_msm_id(void) 48 - { 49 - size_t len; 50 - u32 *msm_id; 51 - enum _msm8996_version version; 52 - 53 - msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len); 54 - if (IS_ERR(msm_id)) 55 - return NUM_OF_MSM8996_VERSIONS; 56 - 57 - /* The first 4 bytes are format, next to them is the actual msm-id */ 58 - msm_id++; 59 - 60 - switch ((enum _msm_id)*msm_id) { 61 - case MSM8996V3: 62 - case APQ8096V3: 63 - version = MSM8996_V3; 64 - break; 65 - case MSM8996SG: 66 - case APQ8096SG: 67 - version = MSM8996_SG; 68 - break; 69 - default: 70 - version = NUM_OF_MSM8996_VERSIONS; 71 - } 72 - 73 - return version; 74 - } 75 - 76 - static int qcom_cpufreq_kryo_probe(struct platform_device *pdev) 77 - { 78 - struct opp_table **opp_tables; 79 - enum _msm8996_version msm8996_version; 80 - struct nvmem_cell *speedbin_nvmem; 81 - struct device_node *np; 82 - struct device *cpu_dev; 83 - unsigned cpu; 84 - u8 *speedbin; 85 - u32 versions; 86 - size_t len; 87 - int ret; 88 - 89 - cpu_dev = get_cpu_device(0); 90 - if (!cpu_dev) 91 - return -ENODEV; 92 - 93 - msm8996_version = qcom_cpufreq_kryo_get_msm_id(); 94 - if (NUM_OF_MSM8996_VERSIONS == msm8996_version) { 95 - dev_err(cpu_dev, "Not Snapdragon 820/821!"); 96 - return -ENODEV; 97 - } 98 - 99 - np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); 100 - if (!np) 101 - return -ENOENT; 102 - 103 - ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu"); 104 - if (!ret) { 105 - of_node_put(np); 106 - return -ENOENT; 107 - } 108 - 109 - speedbin_nvmem = of_nvmem_cell_get(np, NULL); 110 - of_node_put(np); 111 - if (IS_ERR(speedbin_nvmem)) { 112 - if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER) 113 - dev_err(cpu_dev, "Could not get nvmem cell: %ld\n", 114 - PTR_ERR(speedbin_nvmem)); 115 - return PTR_ERR(speedbin_nvmem); 116 - } 117 - 118 - speedbin = nvmem_cell_read(speedbin_nvmem, &len); 119 - nvmem_cell_put(speedbin_nvmem); 120 - if (IS_ERR(speedbin)) 121 - return PTR_ERR(speedbin); 122 - 123 - switch (msm8996_version) { 124 - case MSM8996_V3: 125 - versions = 1 << (unsigned int)(*speedbin); 126 - break; 127 - case MSM8996_SG: 128 - versions = 1 << ((unsigned int)(*speedbin) + 4); 129 - break; 130 - default: 131 - BUG(); 132 - break; 133 - } 134 - kfree(speedbin); 135 - 136 - opp_tables = kcalloc(num_possible_cpus(), sizeof(*opp_tables), GFP_KERNEL); 137 - if (!opp_tables) 138 - return -ENOMEM; 139 - 140 - for_each_possible_cpu(cpu) { 141 - cpu_dev = get_cpu_device(cpu); 142 - if (NULL == cpu_dev) { 143 - ret = -ENODEV; 144 - goto free_opp; 145 - } 146 - 147 - opp_tables[cpu] = dev_pm_opp_set_supported_hw(cpu_dev, 148 - &versions, 1); 149 - if (IS_ERR(opp_tables[cpu])) { 150 - ret = PTR_ERR(opp_tables[cpu]); 151 - dev_err(cpu_dev, "Failed to set supported hardware\n"); 152 - goto free_opp; 153 - } 154 - } 155 - 156 - cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1, 157 - NULL, 0); 158 - if (!IS_ERR(cpufreq_dt_pdev)) { 159 - platform_set_drvdata(pdev, opp_tables); 160 - return 0; 161 - } 162 - 163 - ret = PTR_ERR(cpufreq_dt_pdev); 164 - dev_err(cpu_dev, "Failed to register platform device\n"); 165 - 166 - free_opp: 167 - for_each_possible_cpu(cpu) { 168 - if (IS_ERR_OR_NULL(opp_tables[cpu])) 169 - break; 170 - dev_pm_opp_put_supported_hw(opp_tables[cpu]); 171 - } 172 - kfree(opp_tables); 173 - 174 - return ret; 175 - } 176 - 177 - static int qcom_cpufreq_kryo_remove(struct platform_device *pdev) 178 - { 179 - struct opp_table **opp_tables = platform_get_drvdata(pdev); 180 - unsigned int cpu; 181 - 182 - platform_device_unregister(cpufreq_dt_pdev); 183 - 184 - for_each_possible_cpu(cpu) 185 - dev_pm_opp_put_supported_hw(opp_tables[cpu]); 186 - 187 - kfree(opp_tables); 188 - 189 - return 0; 190 - } 191 - 192 - static struct platform_driver qcom_cpufreq_kryo_driver = { 193 - .probe = qcom_cpufreq_kryo_probe, 194 - .remove = qcom_cpufreq_kryo_remove, 195 - .driver = { 196 - .name = "qcom-cpufreq-kryo", 197 - }, 198 - }; 199 - 200 - static const struct of_device_id qcom_cpufreq_kryo_match_list[] __initconst = { 201 - { .compatible = "qcom,apq8096", }, 202 - { .compatible = "qcom,msm8996", }, 203 - {} 204 - }; 205 - 206 - /* 207 - * Since the driver depends on smem and nvmem drivers, which may 208 - * return EPROBE_DEFER, all the real activity is done in the probe, 209 - * which may be defered as well. The init here is only registering 210 - * the driver and the platform device. 211 - */ 212 - static int __init qcom_cpufreq_kryo_init(void) 213 - { 214 - struct device_node *np = of_find_node_by_path("/"); 215 - const struct of_device_id *match; 216 - int ret; 217 - 218 - if (!np) 219 - return -ENODEV; 220 - 221 - match = of_match_node(qcom_cpufreq_kryo_match_list, np); 222 - of_node_put(np); 223 - if (!match) 224 - return -ENODEV; 225 - 226 - ret = platform_driver_register(&qcom_cpufreq_kryo_driver); 227 - if (unlikely(ret < 0)) 228 - return ret; 229 - 230 - kryo_cpufreq_pdev = platform_device_register_simple( 231 - "qcom-cpufreq-kryo", -1, NULL, 0); 232 - ret = PTR_ERR_OR_ZERO(kryo_cpufreq_pdev); 233 - if (0 == ret) 234 - return 0; 235 - 236 - platform_driver_unregister(&qcom_cpufreq_kryo_driver); 237 - return ret; 238 - } 239 - module_init(qcom_cpufreq_kryo_init); 240 - 241 - static void __exit qcom_cpufreq_kryo_exit(void) 242 - { 243 - platform_device_unregister(kryo_cpufreq_pdev); 244 - platform_driver_unregister(&qcom_cpufreq_kryo_driver); 245 - } 246 - module_exit(qcom_cpufreq_kryo_exit); 247 - 248 - MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Kryo CPUfreq driver"); 249 - MODULE_LICENSE("GPL v2");
+352
drivers/cpufreq/qcom-cpufreq-nvmem.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + /* 7 + * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors, 8 + * the CPU frequency subset and voltage value of each OPP varies 9 + * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables 10 + * defines the voltage and frequency value based on the msm-id in SMEM 11 + * and speedbin blown in the efuse combination. 12 + * The qcom-cpufreq-nvmem driver reads the msm-id and efuse value from the SoC 13 + * to provide the OPP framework with required information. 14 + * This is used to determine the voltage and frequency value for each OPP of 15 + * operating-points-v2 table when it is parsed by the OPP framework. 16 + */ 17 + 18 + #include <linux/cpu.h> 19 + #include <linux/err.h> 20 + #include <linux/init.h> 21 + #include <linux/kernel.h> 22 + #include <linux/module.h> 23 + #include <linux/nvmem-consumer.h> 24 + #include <linux/of.h> 25 + #include <linux/of_device.h> 26 + #include <linux/platform_device.h> 27 + #include <linux/pm_domain.h> 28 + #include <linux/pm_opp.h> 29 + #include <linux/slab.h> 30 + #include <linux/soc/qcom/smem.h> 31 + 32 + #define MSM_ID_SMEM 137 33 + 34 + enum _msm_id { 35 + MSM8996V3 = 0xF6ul, 36 + APQ8096V3 = 0x123ul, 37 + MSM8996SG = 0x131ul, 38 + APQ8096SG = 0x138ul, 39 + }; 40 + 41 + enum _msm8996_version { 42 + MSM8996_V3, 43 + MSM8996_SG, 44 + NUM_OF_MSM8996_VERSIONS, 45 + }; 46 + 47 + struct qcom_cpufreq_drv; 48 + 49 + struct qcom_cpufreq_match_data { 50 + int (*get_version)(struct device *cpu_dev, 51 + struct nvmem_cell *speedbin_nvmem, 52 + struct qcom_cpufreq_drv *drv); 53 + const char **genpd_names; 54 + }; 55 + 56 + struct qcom_cpufreq_drv { 57 + struct opp_table **opp_tables; 58 + struct opp_table **genpd_opp_tables; 59 + u32 versions; 60 + const struct qcom_cpufreq_match_data *data; 61 + }; 62 + 63 + static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev; 64 + 65 + static enum _msm8996_version qcom_cpufreq_get_msm_id(void) 66 + { 67 + size_t len; 68 + u32 *msm_id; 69 + enum _msm8996_version version; 70 + 71 + msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len); 72 + if (IS_ERR(msm_id)) 73 + return NUM_OF_MSM8996_VERSIONS; 74 + 75 + /* The first 4 bytes are format, next to them is the actual msm-id */ 76 + msm_id++; 77 + 78 + switch ((enum _msm_id)*msm_id) { 79 + case MSM8996V3: 80 + case APQ8096V3: 81 + version = MSM8996_V3; 82 + break; 83 + case MSM8996SG: 84 + case APQ8096SG: 85 + version = MSM8996_SG; 86 + break; 87 + default: 88 + version = NUM_OF_MSM8996_VERSIONS; 89 + } 90 + 91 + return version; 92 + } 93 + 94 + static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev, 95 + struct nvmem_cell *speedbin_nvmem, 96 + struct qcom_cpufreq_drv *drv) 97 + { 98 + size_t len; 99 + u8 *speedbin; 100 + enum _msm8996_version msm8996_version; 101 + 102 + msm8996_version = qcom_cpufreq_get_msm_id(); 103 + if (NUM_OF_MSM8996_VERSIONS == msm8996_version) { 104 + dev_err(cpu_dev, "Not Snapdragon 820/821!"); 105 + return -ENODEV; 106 + } 107 + 108 + speedbin = nvmem_cell_read(speedbin_nvmem, &len); 109 + if (IS_ERR(speedbin)) 110 + return PTR_ERR(speedbin); 111 + 112 + switch (msm8996_version) { 113 + case MSM8996_V3: 114 + drv->versions = 1 << (unsigned int)(*speedbin); 115 + break; 116 + case MSM8996_SG: 117 + drv->versions = 1 << ((unsigned int)(*speedbin) + 4); 118 + break; 119 + default: 120 + BUG(); 121 + break; 122 + } 123 + 124 + kfree(speedbin); 125 + return 0; 126 + } 127 + 128 + static const struct qcom_cpufreq_match_data match_data_kryo = { 129 + .get_version = qcom_cpufreq_kryo_name_version, 130 + }; 131 + 132 + static const char *qcs404_genpd_names[] = { "cpr", NULL }; 133 + 134 + static const struct qcom_cpufreq_match_data match_data_qcs404 = { 135 + .genpd_names = qcs404_genpd_names, 136 + }; 137 + 138 + static int qcom_cpufreq_probe(struct platform_device *pdev) 139 + { 140 + struct qcom_cpufreq_drv *drv; 141 + struct nvmem_cell *speedbin_nvmem; 142 + struct device_node *np; 143 + struct device *cpu_dev; 144 + unsigned cpu; 145 + const struct of_device_id *match; 146 + int ret; 147 + 148 + cpu_dev = get_cpu_device(0); 149 + if (!cpu_dev) 150 + return -ENODEV; 151 + 152 + np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); 153 + if (!np) 154 + return -ENOENT; 155 + 156 + ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu"); 157 + if (!ret) { 158 + of_node_put(np); 159 + return -ENOENT; 160 + } 161 + 162 + drv = kzalloc(sizeof(*drv), GFP_KERNEL); 163 + if (!drv) 164 + return -ENOMEM; 165 + 166 + match = pdev->dev.platform_data; 167 + drv->data = match->data; 168 + if (!drv->data) { 169 + ret = -ENODEV; 170 + goto free_drv; 171 + } 172 + 173 + if (drv->data->get_version) { 174 + speedbin_nvmem = of_nvmem_cell_get(np, NULL); 175 + if (IS_ERR(speedbin_nvmem)) { 176 + if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER) 177 + dev_err(cpu_dev, 178 + "Could not get nvmem cell: %ld\n", 179 + PTR_ERR(speedbin_nvmem)); 180 + ret = PTR_ERR(speedbin_nvmem); 181 + goto free_drv; 182 + } 183 + 184 + ret = drv->data->get_version(cpu_dev, speedbin_nvmem, drv); 185 + if (ret) { 186 + nvmem_cell_put(speedbin_nvmem); 187 + goto free_drv; 188 + } 189 + nvmem_cell_put(speedbin_nvmem); 190 + } 191 + of_node_put(np); 192 + 193 + drv->opp_tables = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tables), 194 + GFP_KERNEL); 195 + if (!drv->opp_tables) { 196 + ret = -ENOMEM; 197 + goto free_drv; 198 + } 199 + 200 + drv->genpd_opp_tables = kcalloc(num_possible_cpus(), 201 + sizeof(*drv->genpd_opp_tables), 202 + GFP_KERNEL); 203 + if (!drv->genpd_opp_tables) { 204 + ret = -ENOMEM; 205 + goto free_opp; 206 + } 207 + 208 + for_each_possible_cpu(cpu) { 209 + cpu_dev = get_cpu_device(cpu); 210 + if (NULL == cpu_dev) { 211 + ret = -ENODEV; 212 + goto free_genpd_opp; 213 + } 214 + 215 + if (drv->data->get_version) { 216 + drv->opp_tables[cpu] = 217 + dev_pm_opp_set_supported_hw(cpu_dev, 218 + &drv->versions, 1); 219 + if (IS_ERR(drv->opp_tables[cpu])) { 220 + ret = PTR_ERR(drv->opp_tables[cpu]); 221 + dev_err(cpu_dev, 222 + "Failed to set supported hardware\n"); 223 + goto free_genpd_opp; 224 + } 225 + } 226 + 227 + if (drv->data->genpd_names) { 228 + drv->genpd_opp_tables[cpu] = 229 + dev_pm_opp_attach_genpd(cpu_dev, 230 + drv->data->genpd_names, 231 + NULL); 232 + if (IS_ERR(drv->genpd_opp_tables[cpu])) { 233 + ret = PTR_ERR(drv->genpd_opp_tables[cpu]); 234 + if (ret != -EPROBE_DEFER) 235 + dev_err(cpu_dev, 236 + "Could not attach to pm_domain: %d\n", 237 + ret); 238 + goto free_genpd_opp; 239 + } 240 + } 241 + } 242 + 243 + cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1, 244 + NULL, 0); 245 + if (!IS_ERR(cpufreq_dt_pdev)) { 246 + platform_set_drvdata(pdev, drv); 247 + return 0; 248 + } 249 + 250 + ret = PTR_ERR(cpufreq_dt_pdev); 251 + dev_err(cpu_dev, "Failed to register platform device\n"); 252 + 253 + free_genpd_opp: 254 + for_each_possible_cpu(cpu) { 255 + if (IS_ERR_OR_NULL(drv->genpd_opp_tables[cpu])) 256 + break; 257 + dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]); 258 + } 259 + kfree(drv->genpd_opp_tables); 260 + free_opp: 261 + for_each_possible_cpu(cpu) { 262 + if (IS_ERR_OR_NULL(drv->opp_tables[cpu])) 263 + break; 264 + dev_pm_opp_put_supported_hw(drv->opp_tables[cpu]); 265 + } 266 + kfree(drv->opp_tables); 267 + free_drv: 268 + kfree(drv); 269 + 270 + return ret; 271 + } 272 + 273 + static int qcom_cpufreq_remove(struct platform_device *pdev) 274 + { 275 + struct qcom_cpufreq_drv *drv = platform_get_drvdata(pdev); 276 + unsigned int cpu; 277 + 278 + platform_device_unregister(cpufreq_dt_pdev); 279 + 280 + for_each_possible_cpu(cpu) { 281 + if (drv->opp_tables[cpu]) 282 + dev_pm_opp_put_supported_hw(drv->opp_tables[cpu]); 283 + if (drv->genpd_opp_tables[cpu]) 284 + dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]); 285 + } 286 + 287 + kfree(drv->opp_tables); 288 + kfree(drv->genpd_opp_tables); 289 + kfree(drv); 290 + 291 + return 0; 292 + } 293 + 294 + static struct platform_driver qcom_cpufreq_driver = { 295 + .probe = qcom_cpufreq_probe, 296 + .remove = qcom_cpufreq_remove, 297 + .driver = { 298 + .name = "qcom-cpufreq-nvmem", 299 + }, 300 + }; 301 + 302 + static const struct of_device_id qcom_cpufreq_match_list[] __initconst = { 303 + { .compatible = "qcom,apq8096", .data = &match_data_kryo }, 304 + { .compatible = "qcom,msm8996", .data = &match_data_kryo }, 305 + { .compatible = "qcom,qcs404", .data = &match_data_qcs404 }, 306 + {}, 307 + }; 308 + 309 + /* 310 + * Since the driver depends on smem and nvmem drivers, which may 311 + * return EPROBE_DEFER, all the real activity is done in the probe, 312 + * which may be defered as well. The init here is only registering 313 + * the driver and the platform device. 314 + */ 315 + static int __init qcom_cpufreq_init(void) 316 + { 317 + struct device_node *np = of_find_node_by_path("/"); 318 + const struct of_device_id *match; 319 + int ret; 320 + 321 + if (!np) 322 + return -ENODEV; 323 + 324 + match = of_match_node(qcom_cpufreq_match_list, np); 325 + of_node_put(np); 326 + if (!match) 327 + return -ENODEV; 328 + 329 + ret = platform_driver_register(&qcom_cpufreq_driver); 330 + if (unlikely(ret < 0)) 331 + return ret; 332 + 333 + cpufreq_pdev = platform_device_register_data(NULL, "qcom-cpufreq-nvmem", 334 + -1, match, sizeof(*match)); 335 + ret = PTR_ERR_OR_ZERO(cpufreq_pdev); 336 + if (0 == ret) 337 + return 0; 338 + 339 + platform_driver_unregister(&qcom_cpufreq_driver); 340 + return ret; 341 + } 342 + module_init(qcom_cpufreq_init); 343 + 344 + static void __exit qcom_cpufreq_exit(void) 345 + { 346 + platform_device_unregister(cpufreq_pdev); 347 + platform_driver_unregister(&qcom_cpufreq_driver); 348 + } 349 + module_exit(qcom_cpufreq_exit); 350 + 351 + MODULE_DESCRIPTION("Qualcomm Technologies, Inc. CPUfreq driver"); 352 + MODULE_LICENSE("GPL v2");
+226
drivers/cpufreq/sun50i-cpufreq-nvmem.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Allwinner CPUFreq nvmem based driver 4 + * 5 + * The sun50i-cpufreq-nvmem driver reads the efuse value from the SoC to 6 + * provide the OPP framework with required information. 7 + * 8 + * Copyright (C) 2019 Yangtao Li <tiny.windzz@gmail.com> 9 + */ 10 + 11 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 + 13 + #include <linux/module.h> 14 + #include <linux/nvmem-consumer.h> 15 + #include <linux/of_device.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/pm_opp.h> 18 + #include <linux/slab.h> 19 + 20 + #define MAX_NAME_LEN 7 21 + 22 + #define NVMEM_MASK 0x7 23 + #define NVMEM_SHIFT 5 24 + 25 + static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev; 26 + 27 + /** 28 + * sun50i_cpufreq_get_efuse() - Parse and return efuse value present on SoC 29 + * @versions: Set to the value parsed from efuse 30 + * 31 + * Returns 0 if success. 32 + */ 33 + static int sun50i_cpufreq_get_efuse(u32 *versions) 34 + { 35 + struct nvmem_cell *speedbin_nvmem; 36 + struct device_node *np; 37 + struct device *cpu_dev; 38 + u32 *speedbin, efuse_value; 39 + size_t len; 40 + int ret; 41 + 42 + cpu_dev = get_cpu_device(0); 43 + if (!cpu_dev) 44 + return -ENODEV; 45 + 46 + np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); 47 + if (!np) 48 + return -ENOENT; 49 + 50 + ret = of_device_is_compatible(np, 51 + "allwinner,sun50i-h6-operating-points"); 52 + if (!ret) { 53 + of_node_put(np); 54 + return -ENOENT; 55 + } 56 + 57 + speedbin_nvmem = of_nvmem_cell_get(np, NULL); 58 + of_node_put(np); 59 + if (IS_ERR(speedbin_nvmem)) { 60 + if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER) 61 + pr_err("Could not get nvmem cell: %ld\n", 62 + PTR_ERR(speedbin_nvmem)); 63 + return PTR_ERR(speedbin_nvmem); 64 + } 65 + 66 + speedbin = nvmem_cell_read(speedbin_nvmem, &len); 67 + nvmem_cell_put(speedbin_nvmem); 68 + if (IS_ERR(speedbin)) 69 + return PTR_ERR(speedbin); 70 + 71 + efuse_value = (*speedbin >> NVMEM_SHIFT) & NVMEM_MASK; 72 + switch (efuse_value) { 73 + case 0b0001: 74 + *versions = 1; 75 + break; 76 + case 0b0011: 77 + *versions = 2; 78 + break; 79 + default: 80 + /* 81 + * For other situations, we treat it as bin0. 82 + * This vf table can be run for any good cpu. 83 + */ 84 + *versions = 0; 85 + break; 86 + } 87 + 88 + kfree(speedbin); 89 + return 0; 90 + }; 91 + 92 + static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev) 93 + { 94 + struct opp_table **opp_tables; 95 + char name[MAX_NAME_LEN]; 96 + unsigned int cpu; 97 + u32 speed = 0; 98 + int ret; 99 + 100 + opp_tables = kcalloc(num_possible_cpus(), sizeof(*opp_tables), 101 + GFP_KERNEL); 102 + if (!opp_tables) 103 + return -ENOMEM; 104 + 105 + ret = sun50i_cpufreq_get_efuse(&speed); 106 + if (ret) 107 + return ret; 108 + 109 + snprintf(name, MAX_NAME_LEN, "speed%d", speed); 110 + 111 + for_each_possible_cpu(cpu) { 112 + struct device *cpu_dev = get_cpu_device(cpu); 113 + 114 + if (!cpu_dev) { 115 + ret = -ENODEV; 116 + goto free_opp; 117 + } 118 + 119 + opp_tables[cpu] = dev_pm_opp_set_prop_name(cpu_dev, name); 120 + if (IS_ERR(opp_tables[cpu])) { 121 + ret = PTR_ERR(opp_tables[cpu]); 122 + pr_err("Failed to set prop name\n"); 123 + goto free_opp; 124 + } 125 + } 126 + 127 + cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1, 128 + NULL, 0); 129 + if (!IS_ERR(cpufreq_dt_pdev)) { 130 + platform_set_drvdata(pdev, opp_tables); 131 + return 0; 132 + } 133 + 134 + ret = PTR_ERR(cpufreq_dt_pdev); 135 + pr_err("Failed to register platform device\n"); 136 + 137 + free_opp: 138 + for_each_possible_cpu(cpu) { 139 + if (IS_ERR_OR_NULL(opp_tables[cpu])) 140 + break; 141 + dev_pm_opp_put_prop_name(opp_tables[cpu]); 142 + } 143 + kfree(opp_tables); 144 + 145 + return ret; 146 + } 147 + 148 + static int sun50i_cpufreq_nvmem_remove(struct platform_device *pdev) 149 + { 150 + struct opp_table **opp_tables = platform_get_drvdata(pdev); 151 + unsigned int cpu; 152 + 153 + platform_device_unregister(cpufreq_dt_pdev); 154 + 155 + for_each_possible_cpu(cpu) 156 + dev_pm_opp_put_prop_name(opp_tables[cpu]); 157 + 158 + kfree(opp_tables); 159 + 160 + return 0; 161 + } 162 + 163 + static struct platform_driver sun50i_cpufreq_driver = { 164 + .probe = sun50i_cpufreq_nvmem_probe, 165 + .remove = sun50i_cpufreq_nvmem_remove, 166 + .driver = { 167 + .name = "sun50i-cpufreq-nvmem", 168 + }, 169 + }; 170 + 171 + static const struct of_device_id sun50i_cpufreq_match_list[] = { 172 + { .compatible = "allwinner,sun50i-h6" }, 173 + {} 174 + }; 175 + 176 + static const struct of_device_id *sun50i_cpufreq_match_node(void) 177 + { 178 + const struct of_device_id *match; 179 + struct device_node *np; 180 + 181 + np = of_find_node_by_path("/"); 182 + match = of_match_node(sun50i_cpufreq_match_list, np); 183 + of_node_put(np); 184 + 185 + return match; 186 + } 187 + 188 + /* 189 + * Since the driver depends on nvmem drivers, which may return EPROBE_DEFER, 190 + * all the real activity is done in the probe, which may be defered as well. 191 + * The init here is only registering the driver and the platform device. 192 + */ 193 + static int __init sun50i_cpufreq_init(void) 194 + { 195 + const struct of_device_id *match; 196 + int ret; 197 + 198 + match = sun50i_cpufreq_match_node(); 199 + if (!match) 200 + return -ENODEV; 201 + 202 + ret = platform_driver_register(&sun50i_cpufreq_driver); 203 + if (unlikely(ret < 0)) 204 + return ret; 205 + 206 + sun50i_cpufreq_pdev = 207 + platform_device_register_simple("sun50i-cpufreq-nvmem", 208 + -1, NULL, 0); 209 + ret = PTR_ERR_OR_ZERO(sun50i_cpufreq_pdev); 210 + if (ret == 0) 211 + return 0; 212 + 213 + platform_driver_unregister(&sun50i_cpufreq_driver); 214 + return ret; 215 + } 216 + module_init(sun50i_cpufreq_init); 217 + 218 + static void __exit sun50i_cpufreq_exit(void) 219 + { 220 + platform_device_unregister(sun50i_cpufreq_pdev); 221 + platform_driver_unregister(&sun50i_cpufreq_driver); 222 + } 223 + module_exit(sun50i_cpufreq_exit); 224 + 225 + MODULE_DESCRIPTION("Sun50i-h6 cpufreq driver"); 226 + MODULE_LICENSE("GPL v2");
+1
drivers/cpufreq/ti-cpufreq.c
··· 77 77 case DRA7_EFUSE_HAS_ALL_MPU_OPP: 78 78 case DRA7_EFUSE_HAS_HIGH_MPU_OPP: 79 79 calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP; 80 + /* Fall through */ 80 81 case DRA7_EFUSE_HAS_OD_MPU_OPP: 81 82 calculated_efuse |= DRA7_EFUSE_OD_MPU_OPP; 82 83 }
+20
drivers/cpuidle/Kconfig
··· 33 33 Some workloads benefit from using it and it generally should be safe 34 34 to use. Say Y here if you are not happy with the alternatives. 35 35 36 + config CPU_IDLE_GOV_HALTPOLL 37 + bool "Haltpoll governor (for virtualized systems)" 38 + depends on KVM_GUEST 39 + help 40 + This governor implements haltpoll idle state selection, to be 41 + used in conjunction with the haltpoll cpuidle driver, allowing 42 + for polling for a certain amount of time before entering idle 43 + state. 44 + 45 + Some virtualized workloads benefit from using it. 46 + 36 47 config DT_IDLE_STATES 37 48 bool 38 49 ··· 61 50 depends on PPC 62 51 source "drivers/cpuidle/Kconfig.powerpc" 63 52 endmenu 53 + 54 + config HALTPOLL_CPUIDLE 55 + tristate "Halt poll cpuidle driver" 56 + depends on X86 && KVM_GUEST 57 + default y 58 + help 59 + This option enables halt poll cpuidle driver, which allows to poll 60 + before halting in the guest (more efficient than polling in the 61 + host via halt_poll_ns for some scenarios). 64 62 65 63 endif 66 64
+1
drivers/cpuidle/Makefile
··· 7 7 obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o 8 8 obj-$(CONFIG_DT_IDLE_STATES) += dt_idle_states.o 9 9 obj-$(CONFIG_ARCH_HAS_CPU_RELAX) += poll_state.o 10 + obj-$(CONFIG_HALTPOLL_CPUIDLE) += cpuidle-haltpoll.o 10 11 11 12 ################################################################################## 12 13 # ARM SoC drivers
+134
drivers/cpuidle/cpuidle-haltpoll.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * cpuidle driver for haltpoll governor. 4 + * 5 + * Copyright 2019 Red Hat, Inc. and/or its affiliates. 6 + * 7 + * This work is licensed under the terms of the GNU GPL, version 2. See 8 + * the COPYING file in the top-level directory. 9 + * 10 + * Authors: Marcelo Tosatti <mtosatti@redhat.com> 11 + */ 12 + 13 + #include <linux/init.h> 14 + #include <linux/cpu.h> 15 + #include <linux/cpuidle.h> 16 + #include <linux/module.h> 17 + #include <linux/sched/idle.h> 18 + #include <linux/kvm_para.h> 19 + #include <linux/cpuidle_haltpoll.h> 20 + 21 + static struct cpuidle_device __percpu *haltpoll_cpuidle_devices; 22 + static enum cpuhp_state haltpoll_hp_state; 23 + 24 + static int default_enter_idle(struct cpuidle_device *dev, 25 + struct cpuidle_driver *drv, int index) 26 + { 27 + if (current_clr_polling_and_test()) { 28 + local_irq_enable(); 29 + return index; 30 + } 31 + default_idle(); 32 + return index; 33 + } 34 + 35 + static struct cpuidle_driver haltpoll_driver = { 36 + .name = "haltpoll", 37 + .governor = "haltpoll", 38 + .states = { 39 + { /* entry 0 is for polling */ }, 40 + { 41 + .enter = default_enter_idle, 42 + .exit_latency = 1, 43 + .target_residency = 1, 44 + .power_usage = -1, 45 + .name = "haltpoll idle", 46 + .desc = "default architecture idle", 47 + }, 48 + }, 49 + .safe_state_index = 0, 50 + .state_count = 2, 51 + }; 52 + 53 + static int haltpoll_cpu_online(unsigned int cpu) 54 + { 55 + struct cpuidle_device *dev; 56 + 57 + dev = per_cpu_ptr(haltpoll_cpuidle_devices, cpu); 58 + if (!dev->registered) { 59 + dev->cpu = cpu; 60 + if (cpuidle_register_device(dev)) { 61 + pr_notice("cpuidle_register_device %d failed!\n", cpu); 62 + return -EIO; 63 + } 64 + arch_haltpoll_enable(cpu); 65 + } 66 + 67 + return 0; 68 + } 69 + 70 + static int haltpoll_cpu_offline(unsigned int cpu) 71 + { 72 + struct cpuidle_device *dev; 73 + 74 + dev = per_cpu_ptr(haltpoll_cpuidle_devices, cpu); 75 + if (dev->registered) { 76 + arch_haltpoll_disable(cpu); 77 + cpuidle_unregister_device(dev); 78 + } 79 + 80 + return 0; 81 + } 82 + 83 + static void haltpoll_uninit(void) 84 + { 85 + if (haltpoll_hp_state) 86 + cpuhp_remove_state(haltpoll_hp_state); 87 + cpuidle_unregister_driver(&haltpoll_driver); 88 + 89 + free_percpu(haltpoll_cpuidle_devices); 90 + haltpoll_cpuidle_devices = NULL; 91 + } 92 + 93 + static int __init haltpoll_init(void) 94 + { 95 + int ret; 96 + struct cpuidle_driver *drv = &haltpoll_driver; 97 + 98 + cpuidle_poll_state_init(drv); 99 + 100 + if (!kvm_para_available() || 101 + !kvm_para_has_hint(KVM_HINTS_REALTIME)) 102 + return -ENODEV; 103 + 104 + ret = cpuidle_register_driver(drv); 105 + if (ret < 0) 106 + return ret; 107 + 108 + haltpoll_cpuidle_devices = alloc_percpu(struct cpuidle_device); 109 + if (haltpoll_cpuidle_devices == NULL) { 110 + cpuidle_unregister_driver(drv); 111 + return -ENOMEM; 112 + } 113 + 114 + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "cpuidle/haltpoll:online", 115 + haltpoll_cpu_online, haltpoll_cpu_offline); 116 + if (ret < 0) { 117 + haltpoll_uninit(); 118 + } else { 119 + haltpoll_hp_state = ret; 120 + ret = 0; 121 + } 122 + 123 + return ret; 124 + } 125 + 126 + static void __exit haltpoll_exit(void) 127 + { 128 + haltpoll_uninit(); 129 + } 130 + 131 + module_init(haltpoll_init); 132 + module_exit(haltpoll_exit); 133 + MODULE_LICENSE("GPL"); 134 + MODULE_AUTHOR("Marcelo Tosatti <mtosatti@redhat.com>");
+30
drivers/cpuidle/cpuidle.c
··· 362 362 } 363 363 364 364 /** 365 + * cpuidle_poll_time - return amount of time to poll for, 366 + * governors can override dev->poll_limit_ns if necessary 367 + * 368 + * @drv: the cpuidle driver tied with the cpu 369 + * @dev: the cpuidle device 370 + * 371 + */ 372 + u64 cpuidle_poll_time(struct cpuidle_driver *drv, 373 + struct cpuidle_device *dev) 374 + { 375 + int i; 376 + u64 limit_ns; 377 + 378 + if (dev->poll_limit_ns) 379 + return dev->poll_limit_ns; 380 + 381 + limit_ns = TICK_NSEC; 382 + for (i = 1; i < drv->state_count; i++) { 383 + if (drv->states[i].disabled || dev->states_usage[i].disable) 384 + continue; 385 + 386 + limit_ns = (u64)drv->states[i].target_residency * NSEC_PER_USEC; 387 + } 388 + 389 + dev->poll_limit_ns = limit_ns; 390 + 391 + return dev->poll_limit_ns; 392 + } 393 + 394 + /** 365 395 * cpuidle_install_idle_handler - installs the cpuidle idle loop handler 366 396 */ 367 397 void cpuidle_install_idle_handler(void)
+2
drivers/cpuidle/cpuidle.h
··· 9 9 /* For internal use only */ 10 10 extern char param_governor[]; 11 11 extern struct cpuidle_governor *cpuidle_curr_governor; 12 + extern struct cpuidle_governor *cpuidle_prev_governor; 12 13 extern struct list_head cpuidle_governors; 13 14 extern struct list_head cpuidle_detected_devices; 14 15 extern struct mutex cpuidle_lock; ··· 23 22 extern void cpuidle_uninstall_idle_handler(void); 24 23 25 24 /* governors */ 25 + extern struct cpuidle_governor *cpuidle_find_governor(const char *str); 26 26 extern int cpuidle_switch_governor(struct cpuidle_governor *gov); 27 27 28 28 /* sysfs */
+25
drivers/cpuidle/driver.c
··· 254 254 */ 255 255 int cpuidle_register_driver(struct cpuidle_driver *drv) 256 256 { 257 + struct cpuidle_governor *gov; 257 258 int ret; 258 259 259 260 spin_lock(&cpuidle_driver_lock); 260 261 ret = __cpuidle_register_driver(drv); 261 262 spin_unlock(&cpuidle_driver_lock); 263 + 264 + if (!ret && !strlen(param_governor) && drv->governor && 265 + (cpuidle_get_driver() == drv)) { 266 + mutex_lock(&cpuidle_lock); 267 + gov = cpuidle_find_governor(drv->governor); 268 + if (gov) { 269 + cpuidle_prev_governor = cpuidle_curr_governor; 270 + if (cpuidle_switch_governor(gov) < 0) 271 + cpuidle_prev_governor = NULL; 272 + } 273 + mutex_unlock(&cpuidle_lock); 274 + } 262 275 263 276 return ret; 264 277 } ··· 287 274 */ 288 275 void cpuidle_unregister_driver(struct cpuidle_driver *drv) 289 276 { 277 + bool enabled = (cpuidle_get_driver() == drv); 278 + 290 279 spin_lock(&cpuidle_driver_lock); 291 280 __cpuidle_unregister_driver(drv); 292 281 spin_unlock(&cpuidle_driver_lock); 282 + 283 + if (!enabled) 284 + return; 285 + 286 + mutex_lock(&cpuidle_lock); 287 + if (cpuidle_prev_governor) { 288 + if (!cpuidle_switch_governor(cpuidle_prev_governor)) 289 + cpuidle_prev_governor = NULL; 290 + } 291 + mutex_unlock(&cpuidle_lock); 293 292 } 294 293 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver); 295 294
+4 -3
drivers/cpuidle/governor.c
··· 20 20 21 21 LIST_HEAD(cpuidle_governors); 22 22 struct cpuidle_governor *cpuidle_curr_governor; 23 + struct cpuidle_governor *cpuidle_prev_governor; 23 24 24 25 /** 25 - * __cpuidle_find_governor - finds a governor of the specified name 26 + * cpuidle_find_governor - finds a governor of the specified name 26 27 * @str: the name 27 28 * 28 29 * Must be called with cpuidle_lock acquired. 29 30 */ 30 - static struct cpuidle_governor * __cpuidle_find_governor(const char *str) 31 + struct cpuidle_governor *cpuidle_find_governor(const char *str) 31 32 { 32 33 struct cpuidle_governor *gov; 33 34 ··· 88 87 return -ENODEV; 89 88 90 89 mutex_lock(&cpuidle_lock); 91 - if (__cpuidle_find_governor(gov->name) == NULL) { 90 + if (cpuidle_find_governor(gov->name) == NULL) { 92 91 ret = 0; 93 92 list_add_tail(&gov->governor_list, &cpuidle_governors); 94 93 if (!cpuidle_curr_governor ||
+1
drivers/cpuidle/governors/Makefile
··· 6 6 obj-$(CONFIG_CPU_IDLE_GOV_LADDER) += ladder.o 7 7 obj-$(CONFIG_CPU_IDLE_GOV_MENU) += menu.o 8 8 obj-$(CONFIG_CPU_IDLE_GOV_TEO) += teo.o 9 + obj-$(CONFIG_CPU_IDLE_GOV_HALTPOLL) += haltpoll.o
+150
drivers/cpuidle/governors/haltpoll.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * haltpoll.c - haltpoll idle governor 4 + * 5 + * Copyright 2019 Red Hat, Inc. and/or its affiliates. 6 + * 7 + * This work is licensed under the terms of the GNU GPL, version 2. See 8 + * the COPYING file in the top-level directory. 9 + * 10 + * Authors: Marcelo Tosatti <mtosatti@redhat.com> 11 + */ 12 + 13 + #include <linux/kernel.h> 14 + #include <linux/cpuidle.h> 15 + #include <linux/time.h> 16 + #include <linux/ktime.h> 17 + #include <linux/hrtimer.h> 18 + #include <linux/tick.h> 19 + #include <linux/sched.h> 20 + #include <linux/module.h> 21 + #include <linux/kvm_para.h> 22 + 23 + static unsigned int guest_halt_poll_ns __read_mostly = 200000; 24 + module_param(guest_halt_poll_ns, uint, 0644); 25 + 26 + /* division factor to shrink halt_poll_ns */ 27 + static unsigned int guest_halt_poll_shrink __read_mostly = 2; 28 + module_param(guest_halt_poll_shrink, uint, 0644); 29 + 30 + /* multiplication factor to grow per-cpu poll_limit_ns */ 31 + static unsigned int guest_halt_poll_grow __read_mostly = 2; 32 + module_param(guest_halt_poll_grow, uint, 0644); 33 + 34 + /* value in us to start growing per-cpu halt_poll_ns */ 35 + static unsigned int guest_halt_poll_grow_start __read_mostly = 50000; 36 + module_param(guest_halt_poll_grow_start, uint, 0644); 37 + 38 + /* allow shrinking guest halt poll */ 39 + static bool guest_halt_poll_allow_shrink __read_mostly = true; 40 + module_param(guest_halt_poll_allow_shrink, bool, 0644); 41 + 42 + /** 43 + * haltpoll_select - selects the next idle state to enter 44 + * @drv: cpuidle driver containing state data 45 + * @dev: the CPU 46 + * @stop_tick: indication on whether or not to stop the tick 47 + */ 48 + static int haltpoll_select(struct cpuidle_driver *drv, 49 + struct cpuidle_device *dev, 50 + bool *stop_tick) 51 + { 52 + int latency_req = cpuidle_governor_latency_req(dev->cpu); 53 + 54 + if (!drv->state_count || latency_req == 0) { 55 + *stop_tick = false; 56 + return 0; 57 + } 58 + 59 + if (dev->poll_limit_ns == 0) 60 + return 1; 61 + 62 + /* Last state was poll? */ 63 + if (dev->last_state_idx == 0) { 64 + /* Halt if no event occurred on poll window */ 65 + if (dev->poll_time_limit == true) 66 + return 1; 67 + 68 + *stop_tick = false; 69 + /* Otherwise, poll again */ 70 + return 0; 71 + } 72 + 73 + *stop_tick = false; 74 + /* Last state was halt: poll */ 75 + return 0; 76 + } 77 + 78 + static void adjust_poll_limit(struct cpuidle_device *dev, unsigned int block_us) 79 + { 80 + unsigned int val; 81 + u64 block_ns = block_us*NSEC_PER_USEC; 82 + 83 + /* Grow cpu_halt_poll_us if 84 + * cpu_halt_poll_us < block_ns < guest_halt_poll_us 85 + */ 86 + if (block_ns > dev->poll_limit_ns && block_ns <= guest_halt_poll_ns) { 87 + val = dev->poll_limit_ns * guest_halt_poll_grow; 88 + 89 + if (val < guest_halt_poll_grow_start) 90 + val = guest_halt_poll_grow_start; 91 + if (val > guest_halt_poll_ns) 92 + val = guest_halt_poll_ns; 93 + 94 + dev->poll_limit_ns = val; 95 + } else if (block_ns > guest_halt_poll_ns && 96 + guest_halt_poll_allow_shrink) { 97 + unsigned int shrink = guest_halt_poll_shrink; 98 + 99 + val = dev->poll_limit_ns; 100 + if (shrink == 0) 101 + val = 0; 102 + else 103 + val /= shrink; 104 + dev->poll_limit_ns = val; 105 + } 106 + } 107 + 108 + /** 109 + * haltpoll_reflect - update variables and update poll time 110 + * @dev: the CPU 111 + * @index: the index of actual entered state 112 + */ 113 + static void haltpoll_reflect(struct cpuidle_device *dev, int index) 114 + { 115 + dev->last_state_idx = index; 116 + 117 + if (index != 0) 118 + adjust_poll_limit(dev, dev->last_residency); 119 + } 120 + 121 + /** 122 + * haltpoll_enable_device - scans a CPU's states and does setup 123 + * @drv: cpuidle driver 124 + * @dev: the CPU 125 + */ 126 + static int haltpoll_enable_device(struct cpuidle_driver *drv, 127 + struct cpuidle_device *dev) 128 + { 129 + dev->poll_limit_ns = 0; 130 + 131 + return 0; 132 + } 133 + 134 + static struct cpuidle_governor haltpoll_governor = { 135 + .name = "haltpoll", 136 + .rating = 9, 137 + .enable = haltpoll_enable_device, 138 + .select = haltpoll_select, 139 + .reflect = haltpoll_reflect, 140 + }; 141 + 142 + static int __init init_haltpoll(void) 143 + { 144 + if (kvm_para_available()) 145 + return cpuidle_register_governor(&haltpoll_governor); 146 + 147 + return 0; 148 + } 149 + 150 + postcore_initcall(init_haltpoll);
+10 -11
drivers/cpuidle/governors/ladder.c
··· 38 38 39 39 struct ladder_device { 40 40 struct ladder_device_state states[CPUIDLE_STATE_MAX]; 41 - int last_state_idx; 42 41 }; 43 42 44 43 static DEFINE_PER_CPU(struct ladder_device, ladder_devices); ··· 48 49 * @old_idx: the current state index 49 50 * @new_idx: the new target state index 50 51 */ 51 - static inline void ladder_do_selection(struct ladder_device *ldev, 52 + static inline void ladder_do_selection(struct cpuidle_device *dev, 53 + struct ladder_device *ldev, 52 54 int old_idx, int new_idx) 53 55 { 54 56 ldev->states[old_idx].stats.promotion_count = 0; 55 57 ldev->states[old_idx].stats.demotion_count = 0; 56 - ldev->last_state_idx = new_idx; 58 + dev->last_state_idx = new_idx; 57 59 } 58 60 59 61 /** ··· 68 68 { 69 69 struct ladder_device *ldev = this_cpu_ptr(&ladder_devices); 70 70 struct ladder_device_state *last_state; 71 - int last_residency, last_idx = ldev->last_state_idx; 71 + int last_residency, last_idx = dev->last_state_idx; 72 72 int first_idx = drv->states[0].flags & CPUIDLE_FLAG_POLLING ? 1 : 0; 73 73 int latency_req = cpuidle_governor_latency_req(dev->cpu); 74 74 75 75 /* Special case when user has set very strict latency requirement */ 76 76 if (unlikely(latency_req == 0)) { 77 - ladder_do_selection(ldev, last_idx, 0); 77 + ladder_do_selection(dev, ldev, last_idx, 0); 78 78 return 0; 79 79 } 80 80 ··· 91 91 last_state->stats.promotion_count++; 92 92 last_state->stats.demotion_count = 0; 93 93 if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) { 94 - ladder_do_selection(ldev, last_idx, last_idx + 1); 94 + ladder_do_selection(dev, ldev, last_idx, last_idx + 1); 95 95 return last_idx + 1; 96 96 } 97 97 } ··· 107 107 if (drv->states[i].exit_latency <= latency_req) 108 108 break; 109 109 } 110 - ladder_do_selection(ldev, last_idx, i); 110 + ladder_do_selection(dev, ldev, last_idx, i); 111 111 return i; 112 112 } 113 113 ··· 116 116 last_state->stats.demotion_count++; 117 117 last_state->stats.promotion_count = 0; 118 118 if (last_state->stats.demotion_count >= last_state->threshold.demotion_count) { 119 - ladder_do_selection(ldev, last_idx, last_idx - 1); 119 + ladder_do_selection(dev, ldev, last_idx, last_idx - 1); 120 120 return last_idx - 1; 121 121 } 122 122 } ··· 139 139 struct ladder_device_state *lstate; 140 140 struct cpuidle_state *state; 141 141 142 - ldev->last_state_idx = first_idx; 142 + dev->last_state_idx = first_idx; 143 143 144 144 for (i = first_idx; i < drv->state_count; i++) { 145 145 state = &drv->states[i]; ··· 167 167 */ 168 168 static void ladder_reflect(struct cpuidle_device *dev, int index) 169 169 { 170 - struct ladder_device *ldev = this_cpu_ptr(&ladder_devices); 171 170 if (index > 0) 172 - ldev->last_state_idx = index; 171 + dev->last_state_idx = index; 173 172 } 174 173 175 174 static struct cpuidle_governor ladder_governor = {
+7 -14
drivers/cpuidle/governors/menu.c
··· 117 117 */ 118 118 119 119 struct menu_device { 120 - int last_state_idx; 121 120 int needs_update; 122 121 int tick_wakeup; 123 122 ··· 301 302 !drv->states[0].disabled && !dev->states_usage[0].disable)) { 302 303 /* 303 304 * In this case state[0] will be used no matter what, so return 304 - * it right away and keep the tick running. 305 + * it right away and keep the tick running if state[0] is a 306 + * polling one. 305 307 */ 306 - *stop_tick = false; 308 + *stop_tick = !(drv->states[0].flags & CPUIDLE_FLAG_POLLING); 307 309 return 0; 308 310 } 309 311 ··· 395 395 396 396 return idx; 397 397 } 398 - if (s->exit_latency > latency_req) { 399 - /* 400 - * If we break out of the loop for latency reasons, use 401 - * the target residency of the selected state as the 402 - * expected idle duration so that the tick is retained 403 - * as long as that target residency is low enough. 404 - */ 405 - predicted_us = drv->states[idx].target_residency; 398 + if (s->exit_latency > latency_req) 406 399 break; 407 - } 400 + 408 401 idx = i; 409 402 } 410 403 ··· 448 455 { 449 456 struct menu_device *data = this_cpu_ptr(&menu_devices); 450 457 451 - data->last_state_idx = index; 458 + dev->last_state_idx = index; 452 459 data->needs_update = 1; 453 460 data->tick_wakeup = tick_nohz_idle_got_tick(); 454 461 } ··· 461 468 static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) 462 469 { 463 470 struct menu_device *data = this_cpu_ptr(&menu_devices); 464 - int last_idx = data->last_state_idx; 471 + int last_idx = dev->last_state_idx; 465 472 struct cpuidle_state *target = &drv->states[last_idx]; 466 473 unsigned int measured_us; 467 474 unsigned int new_factor;
+26 -34
drivers/cpuidle/governors/teo.c
··· 96 96 * @time_span_ns: Time between idle state selection and post-wakeup update. 97 97 * @sleep_length_ns: Time till the closest timer event (at the selection time). 98 98 * @states: Idle states data corresponding to this CPU. 99 - * @last_state: Idle state entered by the CPU last time. 100 99 * @interval_idx: Index of the most recent saved idle interval. 101 100 * @intervals: Saved idle duration values. 102 101 */ ··· 103 104 u64 time_span_ns; 104 105 u64 sleep_length_ns; 105 106 struct teo_idle_state states[CPUIDLE_STATE_MAX]; 106 - int last_state; 107 107 int interval_idx; 108 108 unsigned int intervals[INTERVALS]; 109 109 }; ··· 123 125 124 126 if (cpu_data->time_span_ns >= cpu_data->sleep_length_ns) { 125 127 /* 126 - * One of the safety nets has triggered or this was a timer 127 - * wakeup (or equivalent). 128 + * One of the safety nets has triggered or the wakeup was close 129 + * enough to the closest timer event expected at the idle state 130 + * selection time to be discarded. 128 131 */ 129 - measured_us = sleep_length_us; 132 + measured_us = UINT_MAX; 130 133 } else { 131 - unsigned int lat = drv->states[cpu_data->last_state].exit_latency; 134 + unsigned int lat; 135 + 136 + lat = drv->states[dev->last_state_idx].exit_latency; 132 137 133 138 measured_us = ktime_to_us(cpu_data->time_span_ns); 134 139 /* ··· 190 189 } 191 190 192 191 /* 193 - * If the total time span between idle state selection and the "reflect" 194 - * callback is greater than or equal to the sleep length determined at 195 - * the idle state selection time, the wakeup is likely to be due to a 196 - * timer event. 197 - */ 198 - if (cpu_data->time_span_ns >= cpu_data->sleep_length_ns) 199 - measured_us = UINT_MAX; 200 - 201 - /* 202 192 * Save idle duration values corresponding to non-timer wakeups for 203 193 * pattern detection. 204 194 */ ··· 234 242 struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu); 235 243 int latency_req = cpuidle_governor_latency_req(dev->cpu); 236 244 unsigned int duration_us, count; 237 - int max_early_idx, idx, i; 245 + int max_early_idx, constraint_idx, idx, i; 238 246 ktime_t delta_tick; 239 247 240 - if (cpu_data->last_state >= 0) { 248 + if (dev->last_state_idx >= 0) { 241 249 teo_update(drv, dev); 242 - cpu_data->last_state = -1; 250 + dev->last_state_idx = -1; 243 251 } 244 252 245 253 cpu_data->time_span_ns = local_clock(); ··· 249 257 250 258 count = 0; 251 259 max_early_idx = -1; 260 + constraint_idx = drv->state_count; 252 261 idx = -1; 253 262 254 263 for (i = 0; i < drv->state_count; i++) { ··· 279 286 if (s->target_residency > duration_us) 280 287 break; 281 288 282 - if (s->exit_latency > latency_req) { 283 - /* 284 - * If we break out of the loop for latency reasons, use 285 - * the target residency of the selected state as the 286 - * expected idle duration to avoid stopping the tick 287 - * as long as that target residency is low enough. 288 - */ 289 - duration_us = drv->states[idx].target_residency; 290 - goto refine; 291 - } 289 + if (s->exit_latency > latency_req && constraint_idx > i) 290 + constraint_idx = i; 292 291 293 292 idx = i; 294 293 ··· 306 321 duration_us = drv->states[idx].target_residency; 307 322 } 308 323 309 - refine: 324 + /* 325 + * If there is a latency constraint, it may be necessary to use a 326 + * shallower idle state than the one selected so far. 327 + */ 328 + if (constraint_idx < idx) 329 + idx = constraint_idx; 330 + 310 331 if (idx < 0) { 311 332 idx = 0; /* No states enabled. Must use 0. */ 312 333 } else if (idx > 0) { ··· 322 331 323 332 /* 324 333 * Count and sum the most recent idle duration values less than 325 - * the target residency of the state selected so far, find the 326 - * max. 334 + * the current expected idle duration value. 327 335 */ 328 336 for (i = 0; i < INTERVALS; i++) { 329 337 unsigned int val = cpu_data->intervals[i]; 330 338 331 - if (val >= drv->states[idx].target_residency) 339 + if (val >= duration_us) 332 340 continue; 333 341 334 342 count++; ··· 346 356 * would be too shallow. 347 357 */ 348 358 if (!(tick_nohz_tick_stopped() && avg_us < TICK_USEC)) { 349 - idx = teo_find_shallower_state(drv, dev, idx, avg_us); 350 359 duration_us = avg_us; 360 + if (drv->states[idx].target_residency > avg_us) 361 + idx = teo_find_shallower_state(drv, dev, 362 + idx, avg_us); 351 363 } 352 364 } 353 365 } ··· 386 394 { 387 395 struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu); 388 396 389 - cpu_data->last_state = state; 397 + dev->last_state_idx = state; 390 398 /* 391 399 * If the wakeup was not "natural", but triggered by one of the safety 392 400 * nets, assume that the CPU might have been idle for the entire sleep
+2 -9
drivers/cpuidle/poll_state.c
··· 20 20 local_irq_enable(); 21 21 if (!current_set_polling_and_test()) { 22 22 unsigned int loop_count = 0; 23 - u64 limit = TICK_NSEC; 24 - int i; 23 + u64 limit; 25 24 26 - for (i = 1; i < drv->state_count; i++) { 27 - if (drv->states[i].disabled || dev->states_usage[i].disable) 28 - continue; 29 - 30 - limit = (u64)drv->states[i].target_residency * NSEC_PER_USEC; 31 - break; 32 - } 25 + limit = cpuidle_poll_time(drv, dev); 33 26 34 27 while (!need_resched()) { 35 28 cpu_relax();
+7
drivers/cpuidle/sysfs.c
··· 334 334 struct cpuidle_state_usage *state_usage; 335 335 struct completion kobj_unregister; 336 336 struct kobject kobj; 337 + struct cpuidle_device *device; 337 338 }; 338 339 339 340 #ifdef CONFIG_SUSPEND ··· 392 391 #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj) 393 392 #define kobj_to_state(k) (kobj_to_state_obj(k)->state) 394 393 #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage) 394 + #define kobj_to_device(k) (kobj_to_state_obj(k)->device) 395 395 #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr) 396 396 397 397 static ssize_t cpuidle_state_show(struct kobject *kobj, struct attribute *attr, ··· 416 414 struct cpuidle_state *state = kobj_to_state(kobj); 417 415 struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj); 418 416 struct cpuidle_state_attr *cattr = attr_to_stateattr(attr); 417 + struct cpuidle_device *dev = kobj_to_device(kobj); 419 418 420 419 if (cattr->store) 421 420 ret = cattr->store(state, state_usage, buf, size); 421 + 422 + /* reset poll time cache */ 423 + dev->poll_limit_ns = 0; 422 424 423 425 return ret; 424 426 } ··· 474 468 } 475 469 kobj->state = &drv->states[i]; 476 470 kobj->state_usage = &device->states_usage[i]; 471 + kobj->device = device; 477 472 init_completion(&kobj->kobj_unregister); 478 473 479 474 ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
+16 -3
drivers/devfreq/Kconfig
··· 93 93 This does not yet operate with optimal voltages. 94 94 95 95 config ARM_TEGRA_DEVFREQ 96 - tristate "Tegra DEVFREQ Driver" 97 - depends on ARCH_TEGRA_124_SOC 98 - select DEVFREQ_GOV_SIMPLE_ONDEMAND 96 + tristate "NVIDIA Tegra30/114/124/210 DEVFREQ Driver" 97 + depends on ARCH_TEGRA_3x_SOC || ARCH_TEGRA_114_SOC || \ 98 + ARCH_TEGRA_132_SOC || ARCH_TEGRA_124_SOC || \ 99 + ARCH_TEGRA_210_SOC || \ 100 + COMPILE_TEST 99 101 select PM_OPP 100 102 help 101 103 This adds the DEVFREQ driver for the Tegra family of SoCs. 102 104 It reads ACTMON counters of memory controllers and adjusts the 103 105 operating frequencies and voltages with OPP support. 106 + 107 + config ARM_TEGRA20_DEVFREQ 108 + tristate "NVIDIA Tegra20 DEVFREQ Driver" 109 + depends on (TEGRA_MC && TEGRA20_EMC) || COMPILE_TEST 110 + depends on COMMON_CLK 111 + select DEVFREQ_GOV_SIMPLE_ONDEMAND 112 + select PM_OPP 113 + help 114 + This adds the DEVFREQ driver for the Tegra20 family of SoCs. 115 + It reads Memory Controller counters and adjusts the operating 116 + frequencies and voltages with OPP support. 104 117 105 118 config ARM_RK3399_DMC_DEVFREQ 106 119 tristate "ARM RK3399 DMC DEVFREQ Driver"
+2 -1
drivers/devfreq/Makefile
··· 10 10 # DEVFREQ Drivers 11 11 obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o 12 12 obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o 13 - obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra-devfreq.o 13 + obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o 14 + obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o 14 15 15 16 # DEVFREQ Event Drivers 16 17 obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/
+6 -6
drivers/devfreq/devfreq.c
··· 254 254 /* Restore previous state before return */ 255 255 mutex_lock(&devfreq_list_lock); 256 256 if (err) 257 - return ERR_PTR(err); 257 + return (err < 0) ? ERR_PTR(err) : ERR_PTR(-EINVAL); 258 258 259 259 governor = find_devfreq_governor(name); 260 260 } ··· 402 402 * devfreq_monitor_start() - Start load monitoring of devfreq instance 403 403 * @devfreq: the devfreq instance. 404 404 * 405 - * Helper function for starting devfreq device load monitoing. By 405 + * Helper function for starting devfreq device load monitoring. By 406 406 * default delayed work based monitoring is supported. Function 407 407 * to be called from governor in response to DEVFREQ_GOV_START 408 408 * event when device is added to devfreq framework. ··· 420 420 * devfreq_monitor_stop() - Stop load monitoring of a devfreq instance 421 421 * @devfreq: the devfreq instance. 422 422 * 423 - * Helper function to stop devfreq device load monitoing. Function 423 + * Helper function to stop devfreq device load monitoring. Function 424 424 * to be called from governor in response to DEVFREQ_GOV_STOP 425 425 * event when device is removed from devfreq framework. 426 426 */ ··· 434 434 * devfreq_monitor_suspend() - Suspend load monitoring of a devfreq instance 435 435 * @devfreq: the devfreq instance. 436 436 * 437 - * Helper function to suspend devfreq device load monitoing. Function 437 + * Helper function to suspend devfreq device load monitoring. Function 438 438 * to be called from governor in response to DEVFREQ_GOV_SUSPEND 439 439 * event or when polling interval is set to zero. 440 440 * ··· 461 461 * devfreq_monitor_resume() - Resume load monitoring of a devfreq instance 462 462 * @devfreq: the devfreq instance. 463 463 * 464 - * Helper function to resume devfreq device load monitoing. Function 464 + * Helper function to resume devfreq device load monitoring. Function 465 465 * to be called from governor in response to DEVFREQ_GOV_RESUME 466 466 * event or when polling interval is set to non-zero. 467 467 */ ··· 867 867 868 868 /** 869 869 * devm_devfreq_remove_device() - Resource-managed devfreq_remove_device() 870 - * @dev: the device to add devfreq feature. 870 + * @dev: the device from which to remove devfreq feature. 871 871 * @devfreq: the devfreq instance to be removed 872 872 */ 873 873 void devm_devfreq_remove_device(struct device *dev, struct devfreq *devfreq)
+72 -32
drivers/devfreq/event/exynos-ppmu.c
··· 13 13 #include <linux/kernel.h> 14 14 #include <linux/module.h> 15 15 #include <linux/of_address.h> 16 + #include <linux/of_device.h> 16 17 #include <linux/platform_device.h> 17 18 #include <linux/regmap.h> 18 19 #include <linux/suspend.h> 19 20 #include <linux/devfreq-event.h> 20 21 21 22 #include "exynos-ppmu.h" 23 + 24 + enum exynos_ppmu_type { 25 + EXYNOS_TYPE_PPMU, 26 + EXYNOS_TYPE_PPMU_V2, 27 + }; 22 28 23 29 struct exynos_ppmu_data { 24 30 struct clk *clk; ··· 39 33 struct regmap *regmap; 40 34 41 35 struct exynos_ppmu_data ppmu; 36 + enum exynos_ppmu_type ppmu_type; 42 37 }; 43 38 44 39 #define PPMU_EVENT(name) \ ··· 93 86 PPMU_EVENT(d1-cpu), 94 87 PPMU_EVENT(d1-general), 95 88 PPMU_EVENT(d1-rt), 89 + 90 + /* For Exynos5422 SoC */ 91 + PPMU_EVENT(dmc0_0), 92 + PPMU_EVENT(dmc0_1), 93 + PPMU_EVENT(dmc1_0), 94 + PPMU_EVENT(dmc1_1), 96 95 }; 97 96 98 97 static int exynos_ppmu_find_ppmu_id(struct devfreq_event_dev *edev) ··· 164 151 if (ret < 0) 165 152 return ret; 166 153 167 - /* Set the event of Read/Write data count */ 154 + /* Set the event of proper data type monitoring */ 168 155 ret = regmap_write(info->regmap, PPMU_BEVTxSEL(id), 169 - PPMU_RO_DATA_CNT | PPMU_WO_DATA_CNT); 156 + edev->desc->event_type); 170 157 if (ret < 0) 171 158 return ret; 172 159 ··· 378 365 if (ret < 0) 379 366 return ret; 380 367 381 - /* Set the event of Read/Write data count */ 382 - switch (id) { 383 - case PPMU_PMNCNT0: 384 - case PPMU_PMNCNT1: 385 - case PPMU_PMNCNT2: 386 - ret = regmap_write(info->regmap, PPMU_V2_CH_EVx_TYPE(id), 387 - PPMU_V2_RO_DATA_CNT | PPMU_V2_WO_DATA_CNT); 388 - if (ret < 0) 389 - return ret; 390 - break; 391 - case PPMU_PMNCNT3: 392 - ret = regmap_write(info->regmap, PPMU_V2_CH_EVx_TYPE(id), 393 - PPMU_V2_EVT3_RW_DATA_CNT); 394 - if (ret < 0) 395 - return ret; 396 - break; 397 - } 368 + /* Set the event of proper data type monitoring */ 369 + ret = regmap_write(info->regmap, PPMU_V2_CH_EVx_TYPE(id), 370 + edev->desc->event_type); 371 + if (ret < 0) 372 + return ret; 398 373 399 374 /* Reset cycle counter/performance counter and enable PPMU */ 400 375 ret = regmap_read(info->regmap, PPMU_V2_PMNC, &pmnc); ··· 481 480 static const struct of_device_id exynos_ppmu_id_match[] = { 482 481 { 483 482 .compatible = "samsung,exynos-ppmu", 484 - .data = (void *)&exynos_ppmu_ops, 483 + .data = (void *)EXYNOS_TYPE_PPMU, 485 484 }, { 486 485 .compatible = "samsung,exynos-ppmu-v2", 487 - .data = (void *)&exynos_ppmu_v2_ops, 486 + .data = (void *)EXYNOS_TYPE_PPMU_V2, 488 487 }, 489 488 { /* sentinel */ }, 490 489 }; 491 490 MODULE_DEVICE_TABLE(of, exynos_ppmu_id_match); 492 491 493 - static struct devfreq_event_ops *exynos_bus_get_ops(struct device_node *np) 494 - { 495 - const struct of_device_id *match; 496 - 497 - match = of_match_node(exynos_ppmu_id_match, np); 498 - return (struct devfreq_event_ops *)match->data; 499 - } 500 - 501 492 static int of_get_devfreq_events(struct device_node *np, 502 493 struct exynos_ppmu *info) 503 494 { 504 495 struct devfreq_event_desc *desc; 505 - struct devfreq_event_ops *event_ops; 506 496 struct device *dev = info->dev; 507 497 struct device_node *events_np, *node; 508 498 int i, j, count; 499 + const struct of_device_id *of_id; 500 + int ret; 509 501 510 502 events_np = of_get_child_by_name(np, "events"); 511 503 if (!events_np) { ··· 506 512 "failed to get child node of devfreq-event devices\n"); 507 513 return -EINVAL; 508 514 } 509 - event_ops = exynos_bus_get_ops(np); 510 515 511 516 count = of_get_child_count(events_np); 512 517 desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL); 513 518 if (!desc) 514 519 return -ENOMEM; 515 520 info->num_events = count; 521 + 522 + of_id = of_match_device(exynos_ppmu_id_match, dev); 523 + if (of_id) 524 + info->ppmu_type = (enum exynos_ppmu_type)of_id->data; 525 + else 526 + return -EINVAL; 516 527 517 528 j = 0; 518 529 for_each_child_of_node(events_np, node) { ··· 536 537 continue; 537 538 } 538 539 539 - desc[j].ops = event_ops; 540 + switch (info->ppmu_type) { 541 + case EXYNOS_TYPE_PPMU: 542 + desc[j].ops = &exynos_ppmu_ops; 543 + break; 544 + case EXYNOS_TYPE_PPMU_V2: 545 + desc[j].ops = &exynos_ppmu_v2_ops; 546 + break; 547 + } 548 + 540 549 desc[j].driver_data = info; 541 550 542 551 of_property_read_string(node, "event-name", &desc[j].name); 552 + ret = of_property_read_u32(node, "event-data-type", 553 + &desc[j].event_type); 554 + if (ret) { 555 + /* Set the event of proper data type counting. 556 + * Check if the data type has been defined in DT, 557 + * use default if not. 558 + */ 559 + if (info->ppmu_type == EXYNOS_TYPE_PPMU_V2) { 560 + struct devfreq_event_dev edev; 561 + int id; 562 + /* Not all registers take the same value for 563 + * read+write data count. 564 + */ 565 + edev.desc = &desc[j]; 566 + id = exynos_ppmu_find_ppmu_id(&edev); 567 + 568 + switch (id) { 569 + case PPMU_PMNCNT0: 570 + case PPMU_PMNCNT1: 571 + case PPMU_PMNCNT2: 572 + desc[j].event_type = PPMU_V2_RO_DATA_CNT 573 + | PPMU_V2_WO_DATA_CNT; 574 + break; 575 + case PPMU_PMNCNT3: 576 + desc[j].event_type = 577 + PPMU_V2_EVT3_RW_DATA_CNT; 578 + break; 579 + } 580 + } else { 581 + desc[j].event_type = PPMU_RO_DATA_CNT | 582 + PPMU_WO_DATA_CNT; 583 + } 584 + } 543 585 544 586 j++; 545 587 }
+37 -116
drivers/devfreq/exynos-bus.c
··· 22 22 #include <linux/slab.h> 23 23 24 24 #define DEFAULT_SATURATION_RATIO 40 25 - #define DEFAULT_VOLTAGE_TOLERANCE 2 26 25 27 26 struct exynos_bus { 28 27 struct device *dev; ··· 33 34 34 35 unsigned long curr_freq; 35 36 36 - struct regulator *regulator; 37 + struct opp_table *opp_table; 37 38 struct clk *clk; 38 - unsigned int voltage_tolerance; 39 39 unsigned int ratio; 40 40 }; 41 41 ··· 88 90 } 89 91 90 92 /* 91 - * Must necessary function for devfreq simple-ondemand governor 93 + * devfreq function for both simple-ondemand and passive governor 92 94 */ 93 95 static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags) 94 96 { 95 97 struct exynos_bus *bus = dev_get_drvdata(dev); 96 98 struct dev_pm_opp *new_opp; 97 - unsigned long old_freq, new_freq, new_volt, tol; 98 99 int ret = 0; 99 100 100 - /* Get new opp-bus instance according to new bus clock */ 101 + /* Get correct frequency for bus. */ 101 102 new_opp = devfreq_recommended_opp(dev, freq, flags); 102 103 if (IS_ERR(new_opp)) { 103 104 dev_err(dev, "failed to get recommended opp instance\n"); 104 105 return PTR_ERR(new_opp); 105 106 } 106 107 107 - new_freq = dev_pm_opp_get_freq(new_opp); 108 - new_volt = dev_pm_opp_get_voltage(new_opp); 109 108 dev_pm_opp_put(new_opp); 110 - 111 - old_freq = bus->curr_freq; 112 - 113 - if (old_freq == new_freq) 114 - return 0; 115 - tol = new_volt * bus->voltage_tolerance / 100; 116 109 117 110 /* Change voltage and frequency according to new OPP level */ 118 111 mutex_lock(&bus->lock); 112 + ret = dev_pm_opp_set_rate(dev, *freq); 113 + if (!ret) 114 + bus->curr_freq = *freq; 119 115 120 - if (old_freq < new_freq) { 121 - ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol); 122 - if (ret < 0) { 123 - dev_err(bus->dev, "failed to set voltage\n"); 124 - goto out; 125 - } 126 - } 127 - 128 - ret = clk_set_rate(bus->clk, new_freq); 129 - if (ret < 0) { 130 - dev_err(dev, "failed to change clock of bus\n"); 131 - clk_set_rate(bus->clk, old_freq); 132 - goto out; 133 - } 134 - 135 - if (old_freq > new_freq) { 136 - ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol); 137 - if (ret < 0) { 138 - dev_err(bus->dev, "failed to set voltage\n"); 139 - goto out; 140 - } 141 - } 142 - bus->curr_freq = new_freq; 143 - 144 - dev_dbg(dev, "Set the frequency of bus (%luHz -> %luHz, %luHz)\n", 145 - old_freq, new_freq, clk_get_rate(bus->clk)); 146 - out: 147 116 mutex_unlock(&bus->lock); 148 117 149 118 return ret; ··· 156 191 if (ret < 0) 157 192 dev_warn(dev, "failed to disable the devfreq-event devices\n"); 158 193 159 - if (bus->regulator) 160 - regulator_disable(bus->regulator); 161 - 162 194 dev_pm_opp_of_remove_table(dev); 163 195 clk_disable_unprepare(bus->clk); 164 - } 165 - 166 - /* 167 - * Must necessary function for devfreq passive governor 168 - */ 169 - static int exynos_bus_passive_target(struct device *dev, unsigned long *freq, 170 - u32 flags) 171 - { 172 - struct exynos_bus *bus = dev_get_drvdata(dev); 173 - struct dev_pm_opp *new_opp; 174 - unsigned long old_freq, new_freq; 175 - int ret = 0; 176 - 177 - /* Get new opp-bus instance according to new bus clock */ 178 - new_opp = devfreq_recommended_opp(dev, freq, flags); 179 - if (IS_ERR(new_opp)) { 180 - dev_err(dev, "failed to get recommended opp instance\n"); 181 - return PTR_ERR(new_opp); 196 + if (bus->opp_table) { 197 + dev_pm_opp_put_regulators(bus->opp_table); 198 + bus->opp_table = NULL; 182 199 } 183 - 184 - new_freq = dev_pm_opp_get_freq(new_opp); 185 - dev_pm_opp_put(new_opp); 186 - 187 - old_freq = bus->curr_freq; 188 - 189 - if (old_freq == new_freq) 190 - return 0; 191 - 192 - /* Change the frequency according to new OPP level */ 193 - mutex_lock(&bus->lock); 194 - 195 - ret = clk_set_rate(bus->clk, new_freq); 196 - if (ret < 0) { 197 - dev_err(dev, "failed to set the clock of bus\n"); 198 - goto out; 199 - } 200 - 201 - *freq = new_freq; 202 - bus->curr_freq = new_freq; 203 - 204 - dev_dbg(dev, "Set the frequency of bus (%luHz -> %luHz, %luHz)\n", 205 - old_freq, new_freq, clk_get_rate(bus->clk)); 206 - out: 207 - mutex_unlock(&bus->lock); 208 - 209 - return ret; 210 200 } 211 201 212 202 static void exynos_bus_passive_exit(struct device *dev) ··· 176 256 struct exynos_bus *bus) 177 257 { 178 258 struct device *dev = bus->dev; 259 + struct opp_table *opp_table; 260 + const char *vdd = "vdd"; 179 261 int i, ret, count, size; 180 262 181 - /* Get the regulator to provide each bus with the power */ 182 - bus->regulator = devm_regulator_get(dev, "vdd"); 183 - if (IS_ERR(bus->regulator)) { 184 - dev_err(dev, "failed to get VDD regulator\n"); 185 - return PTR_ERR(bus->regulator); 186 - } 187 - 188 - ret = regulator_enable(bus->regulator); 189 - if (ret < 0) { 190 - dev_err(dev, "failed to enable VDD regulator\n"); 263 + opp_table = dev_pm_opp_set_regulators(dev, &vdd, 1); 264 + if (IS_ERR(opp_table)) { 265 + ret = PTR_ERR(opp_table); 266 + dev_err(dev, "failed to set regulators %d\n", ret); 191 267 return ret; 192 268 } 269 + 270 + bus->opp_table = opp_table; 193 271 194 272 /* 195 273 * Get the devfreq-event devices to get the current utilization of ··· 229 311 if (of_property_read_u32(np, "exynos,saturation-ratio", &bus->ratio)) 230 312 bus->ratio = DEFAULT_SATURATION_RATIO; 231 313 232 - if (of_property_read_u32(np, "exynos,voltage-tolerance", 233 - &bus->voltage_tolerance)) 234 - bus->voltage_tolerance = DEFAULT_VOLTAGE_TOLERANCE; 235 - 236 314 return 0; 237 315 238 316 err_regulator: 239 - regulator_disable(bus->regulator); 317 + dev_pm_opp_put_regulators(bus->opp_table); 318 + bus->opp_table = NULL; 240 319 241 320 return ret; 242 321 } ··· 298 383 struct exynos_bus *bus; 299 384 int ret, max_state; 300 385 unsigned long min_freq, max_freq; 386 + bool passive = false; 301 387 302 388 if (!np) { 303 389 dev_err(dev, "failed to find devicetree node\n"); ··· 312 396 bus->dev = &pdev->dev; 313 397 platform_set_drvdata(pdev, bus); 314 398 315 - /* Parse the device-tree to get the resource information */ 316 - ret = exynos_bus_parse_of(np, bus); 317 - if (ret < 0) 318 - return ret; 319 - 320 399 profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL); 321 - if (!profile) { 322 - ret = -ENOMEM; 323 - goto err; 324 - } 400 + if (!profile) 401 + return -ENOMEM; 325 402 326 403 node = of_parse_phandle(dev->of_node, "devfreq", 0); 327 404 if (node) { 328 405 of_node_put(node); 329 - goto passive; 406 + passive = true; 330 407 } else { 331 408 ret = exynos_bus_parent_parse_of(np, bus); 409 + if (ret < 0) 410 + return ret; 332 411 } 333 412 413 + /* Parse the device-tree to get the resource information */ 414 + ret = exynos_bus_parse_of(np, bus); 334 415 if (ret < 0) 335 - goto err; 416 + goto err_reg; 417 + 418 + if (passive) 419 + goto passive; 336 420 337 421 /* Initialize the struct profile and governor data for parent device */ 338 422 profile->polling_ms = 50; ··· 384 468 goto out; 385 469 passive: 386 470 /* Initialize the struct profile and governor data for passive device */ 387 - profile->target = exynos_bus_passive_target; 471 + profile->target = exynos_bus_target; 388 472 profile->exit = exynos_bus_passive_exit; 389 473 390 474 /* Get the instance of parent devfreq device */ ··· 423 507 err: 424 508 dev_pm_opp_of_remove_table(dev); 425 509 clk_disable_unprepare(bus->clk); 510 + err_reg: 511 + if (!passive) { 512 + dev_pm_opp_put_regulators(bus->opp_table); 513 + bus->opp_table = NULL; 514 + } 426 515 427 516 return ret; 428 517 }
+3 -4
drivers/devfreq/governor_passive.c
··· 149 149 static int devfreq_passive_event_handler(struct devfreq *devfreq, 150 150 unsigned int event, void *data) 151 151 { 152 - struct device *dev = devfreq->dev.parent; 153 152 struct devfreq_passive_data *p_data 154 153 = (struct devfreq_passive_data *)devfreq->data; 155 154 struct devfreq *parent = (struct devfreq *)p_data->parent; ··· 164 165 p_data->this = devfreq; 165 166 166 167 nb->notifier_call = devfreq_passive_notifier_call; 167 - ret = devm_devfreq_register_notifier(dev, parent, nb, 168 + ret = devfreq_register_notifier(parent, nb, 168 169 DEVFREQ_TRANSITION_NOTIFIER); 169 170 break; 170 171 case DEVFREQ_GOV_STOP: 171 - devm_devfreq_unregister_notifier(dev, parent, nb, 172 - DEVFREQ_TRANSITION_NOTIFIER); 172 + WARN_ON(devfreq_unregister_notifier(parent, nb, 173 + DEVFREQ_TRANSITION_NOTIFIER)); 173 174 break; 174 175 default: 175 176 break;
+1 -1
drivers/devfreq/rk3399_dmc.c
··· 351 351 352 352 /* 353 353 * Get dram timing and pass it to arm trust firmware, 354 - * the dram drvier in arm trust firmware will get these 354 + * the dram driver in arm trust firmware will get these 355 355 * timing and to do dram initial. 356 356 */ 357 357 if (!of_get_ddr_timings(&data->timing, np)) {
+145 -170
drivers/devfreq/tegra-devfreq.c drivers/devfreq/tegra30-devfreq.c
··· 132 132 struct tegra_devfreq_device { 133 133 const struct tegra_devfreq_device_config *config; 134 134 void __iomem *regs; 135 - spinlock_t lock; 136 135 137 136 /* Average event count sampled in the last interrupt */ 138 137 u32 avg_count; ··· 159 160 struct notifier_block rate_change_nb; 160 161 161 162 struct tegra_devfreq_device devices[ARRAY_SIZE(actmon_device_configs)]; 163 + 164 + int irq; 162 165 }; 163 166 164 167 struct tegra_actmon_emc_ratio { ··· 180 179 181 180 static u32 actmon_readl(struct tegra_devfreq *tegra, u32 offset) 182 181 { 183 - return readl(tegra->regs + offset); 182 + return readl_relaxed(tegra->regs + offset); 184 183 } 185 184 186 185 static void actmon_writel(struct tegra_devfreq *tegra, u32 val, u32 offset) 187 186 { 188 - writel(val, tegra->regs + offset); 187 + writel_relaxed(val, tegra->regs + offset); 189 188 } 190 189 191 190 static u32 device_readl(struct tegra_devfreq_device *dev, u32 offset) 192 191 { 193 - return readl(dev->regs + offset); 192 + return readl_relaxed(dev->regs + offset); 194 193 } 195 194 196 195 static void device_writel(struct tegra_devfreq_device *dev, u32 val, 197 196 u32 offset) 198 197 { 199 - writel(val, dev->regs + offset); 198 + writel_relaxed(val, dev->regs + offset); 200 199 } 201 200 202 201 static unsigned long do_percent(unsigned long val, unsigned int pct) ··· 232 231 static void actmon_write_barrier(struct tegra_devfreq *tegra) 233 232 { 234 233 /* ensure the update has reached the ACTMON */ 235 - wmb(); 236 - actmon_readl(tegra, ACTMON_GLB_STATUS); 234 + readl(tegra->regs + ACTMON_GLB_STATUS); 237 235 } 238 236 239 237 static void actmon_isr_device(struct tegra_devfreq *tegra, 240 238 struct tegra_devfreq_device *dev) 241 239 { 242 - unsigned long flags; 243 240 u32 intr_status, dev_ctrl; 244 - 245 - spin_lock_irqsave(&dev->lock, flags); 246 241 247 242 dev->avg_count = device_readl(dev, ACTMON_DEV_AVG_COUNT); 248 243 tegra_devfreq_update_avg_wmark(tegra, dev); ··· 288 291 device_writel(dev, ACTMON_INTR_STATUS_CLEAR, ACTMON_DEV_INTR_STATUS); 289 292 290 293 actmon_write_barrier(tegra); 291 - 292 - spin_unlock_irqrestore(&dev->lock, flags); 293 - } 294 - 295 - static irqreturn_t actmon_isr(int irq, void *data) 296 - { 297 - struct tegra_devfreq *tegra = data; 298 - bool handled = false; 299 - unsigned int i; 300 - u32 val; 301 - 302 - val = actmon_readl(tegra, ACTMON_GLB_STATUS); 303 - for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 304 - if (val & tegra->devices[i].config->irq_mask) { 305 - actmon_isr_device(tegra, tegra->devices + i); 306 - handled = true; 307 - } 308 - } 309 - 310 - return handled ? IRQ_WAKE_THREAD : IRQ_NONE; 311 294 } 312 295 313 296 static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra, ··· 314 337 unsigned long cpu_freq = 0; 315 338 unsigned long static_cpu_emc_freq = 0; 316 339 unsigned int avg_sustain_coef; 317 - unsigned long flags; 318 340 319 341 if (dev->config->avg_dependency_threshold) { 320 342 cpu_freq = cpufreq_get(0); 321 343 static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra, cpu_freq); 322 344 } 323 - 324 - spin_lock_irqsave(&dev->lock, flags); 325 345 326 346 dev->target_freq = dev->avg_count / ACTMON_SAMPLING_PERIOD; 327 347 avg_sustain_coef = 100 * 100 / dev->config->boost_up_threshold; ··· 327 353 328 354 if (dev->avg_count >= dev->config->avg_dependency_threshold) 329 355 dev->target_freq = max(dev->target_freq, static_cpu_emc_freq); 330 - 331 - spin_unlock_irqrestore(&dev->lock, flags); 332 356 } 333 357 334 358 static irqreturn_t actmon_thread_isr(int irq, void *data) 335 359 { 336 360 struct tegra_devfreq *tegra = data; 361 + bool handled = false; 362 + unsigned int i; 363 + u32 val; 337 364 338 365 mutex_lock(&tegra->devfreq->lock); 339 - update_devfreq(tegra->devfreq); 366 + 367 + val = actmon_readl(tegra, ACTMON_GLB_STATUS); 368 + for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 369 + if (val & tegra->devices[i].config->irq_mask) { 370 + actmon_isr_device(tegra, tegra->devices + i); 371 + handled = true; 372 + } 373 + } 374 + 375 + if (handled) 376 + update_devfreq(tegra->devfreq); 377 + 340 378 mutex_unlock(&tegra->devfreq->lock); 341 379 342 - return IRQ_HANDLED; 380 + return handled ? IRQ_HANDLED : IRQ_NONE; 343 381 } 344 382 345 383 static int tegra_actmon_rate_notify_cb(struct notifier_block *nb, ··· 361 375 struct tegra_devfreq *tegra; 362 376 struct tegra_devfreq_device *dev; 363 377 unsigned int i; 364 - unsigned long flags; 365 378 366 379 if (action != POST_RATE_CHANGE) 367 380 return NOTIFY_OK; ··· 372 387 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 373 388 dev = &tegra->devices[i]; 374 389 375 - spin_lock_irqsave(&dev->lock, flags); 376 390 tegra_devfreq_update_wmark(tegra, dev); 377 - spin_unlock_irqrestore(&dev->lock, flags); 378 391 } 379 392 380 393 actmon_write_barrier(tegra); 381 394 382 395 return NOTIFY_OK; 383 - } 384 - 385 - static void tegra_actmon_enable_interrupts(struct tegra_devfreq *tegra) 386 - { 387 - struct tegra_devfreq_device *dev; 388 - u32 val; 389 - unsigned int i; 390 - 391 - for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 392 - dev = &tegra->devices[i]; 393 - 394 - val = device_readl(dev, ACTMON_DEV_CTRL); 395 - val |= ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN; 396 - val |= ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN; 397 - val |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN; 398 - val |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN; 399 - 400 - device_writel(dev, val, ACTMON_DEV_CTRL); 401 - } 402 - 403 - actmon_write_barrier(tegra); 404 - } 405 - 406 - static void tegra_actmon_disable_interrupts(struct tegra_devfreq *tegra) 407 - { 408 - struct tegra_devfreq_device *dev; 409 - u32 val; 410 - unsigned int i; 411 - 412 - for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 413 - dev = &tegra->devices[i]; 414 - 415 - val = device_readl(dev, ACTMON_DEV_CTRL); 416 - val &= ~ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN; 417 - val &= ~ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN; 418 - val &= ~ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN; 419 - val &= ~ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN; 420 - 421 - device_writel(dev, val, ACTMON_DEV_CTRL); 422 - } 423 - 424 - actmon_write_barrier(tegra); 425 396 } 426 397 427 398 static void tegra_actmon_configure_device(struct tegra_devfreq *tegra, ··· 403 462 << ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_NUM_SHIFT; 404 463 val |= (ACTMON_ABOVE_WMARK_WINDOW - 1) 405 464 << ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_NUM_SHIFT; 465 + val |= ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN; 466 + val |= ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN; 467 + val |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN; 468 + val |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN; 406 469 val |= ACTMON_DEV_CTRL_ENB; 407 470 408 471 device_writel(dev, val, ACTMON_DEV_CTRL); 472 + } 473 + 474 + static void tegra_actmon_start(struct tegra_devfreq *tegra) 475 + { 476 + unsigned int i; 477 + 478 + disable_irq(tegra->irq); 479 + 480 + actmon_writel(tegra, ACTMON_SAMPLING_PERIOD - 1, 481 + ACTMON_GLB_PERIOD_CTRL); 482 + 483 + for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) 484 + tegra_actmon_configure_device(tegra, &tegra->devices[i]); 409 485 410 486 actmon_write_barrier(tegra); 487 + 488 + enable_irq(tegra->irq); 489 + } 490 + 491 + static void tegra_actmon_stop(struct tegra_devfreq *tegra) 492 + { 493 + unsigned int i; 494 + 495 + disable_irq(tegra->irq); 496 + 497 + for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 498 + device_writel(&tegra->devices[i], 0x00000000, ACTMON_DEV_CTRL); 499 + device_writel(&tegra->devices[i], ACTMON_INTR_STATUS_CLEAR, 500 + ACTMON_DEV_INTR_STATUS); 501 + } 502 + 503 + actmon_write_barrier(tegra); 504 + 505 + enable_irq(tegra->irq); 411 506 } 412 507 413 508 static int tegra_devfreq_target(struct device *dev, unsigned long *freq, 414 509 u32 flags) 415 510 { 416 511 struct tegra_devfreq *tegra = dev_get_drvdata(dev); 512 + struct devfreq *devfreq = tegra->devfreq; 417 513 struct dev_pm_opp *opp; 418 - unsigned long rate = *freq * KHZ; 514 + unsigned long rate; 515 + int err; 419 516 420 - opp = devfreq_recommended_opp(dev, &rate, flags); 517 + opp = devfreq_recommended_opp(dev, freq, flags); 421 518 if (IS_ERR(opp)) { 422 - dev_err(dev, "Failed to find opp for %lu KHz\n", *freq); 519 + dev_err(dev, "Failed to find opp for %lu Hz\n", *freq); 423 520 return PTR_ERR(opp); 424 521 } 425 522 rate = dev_pm_opp_get_freq(opp); 426 523 dev_pm_opp_put(opp); 427 524 428 - clk_set_min_rate(tegra->emc_clock, rate); 429 - clk_set_rate(tegra->emc_clock, 0); 525 + err = clk_set_min_rate(tegra->emc_clock, rate); 526 + if (err) 527 + return err; 430 528 431 - *freq = rate; 529 + err = clk_set_rate(tegra->emc_clock, 0); 530 + if (err) 531 + goto restore_min_rate; 432 532 433 533 return 0; 534 + 535 + restore_min_rate: 536 + clk_set_min_rate(tegra->emc_clock, devfreq->previous_freq); 537 + 538 + return err; 434 539 } 435 540 436 541 static int tegra_devfreq_get_dev_status(struct device *dev, ··· 484 497 { 485 498 struct tegra_devfreq *tegra = dev_get_drvdata(dev); 486 499 struct tegra_devfreq_device *actmon_dev; 500 + unsigned long cur_freq; 487 501 488 - stat->current_frequency = tegra->cur_freq; 502 + cur_freq = READ_ONCE(tegra->cur_freq); 489 503 490 504 /* To be used by the tegra governor */ 491 505 stat->private_data = tegra; 492 506 493 507 /* The below are to be used by the other governors */ 508 + stat->current_frequency = cur_freq * KHZ; 494 509 495 510 actmon_dev = &tegra->devices[MCALL]; 496 511 ··· 503 514 stat->busy_time *= 100 / BUS_SATURATION_RATIO; 504 515 505 516 /* Number of cycles in a sampling period */ 506 - stat->total_time = ACTMON_SAMPLING_PERIOD * tegra->cur_freq; 517 + stat->total_time = ACTMON_SAMPLING_PERIOD * cur_freq; 507 518 508 519 stat->busy_time = min(stat->busy_time, stat->total_time); 509 520 ··· 542 553 target_freq = max(target_freq, dev->target_freq); 543 554 } 544 555 545 - *freq = target_freq; 556 + *freq = target_freq * KHZ; 546 557 547 558 return 0; 548 559 } ··· 555 566 switch (event) { 556 567 case DEVFREQ_GOV_START: 557 568 devfreq_monitor_start(devfreq); 558 - tegra_actmon_enable_interrupts(tegra); 569 + tegra_actmon_start(tegra); 559 570 break; 560 571 561 572 case DEVFREQ_GOV_STOP: 562 - tegra_actmon_disable_interrupts(tegra); 573 + tegra_actmon_stop(tegra); 563 574 devfreq_monitor_stop(devfreq); 564 575 break; 565 576 566 577 case DEVFREQ_GOV_SUSPEND: 567 - tegra_actmon_disable_interrupts(tegra); 578 + tegra_actmon_stop(tegra); 568 579 devfreq_monitor_suspend(devfreq); 569 580 break; 570 581 571 582 case DEVFREQ_GOV_RESUME: 572 583 devfreq_monitor_resume(devfreq); 573 - tegra_actmon_enable_interrupts(tegra); 584 + tegra_actmon_start(tegra); 574 585 break; 575 586 } 576 587 ··· 581 592 .name = "tegra_actmon", 582 593 .get_target_freq = tegra_governor_get_target, 583 594 .event_handler = tegra_governor_event_handler, 595 + .immutable = true, 584 596 }; 585 597 586 598 static int tegra_devfreq_probe(struct platform_device *pdev) 587 599 { 588 600 struct tegra_devfreq *tegra; 589 601 struct tegra_devfreq_device *dev; 590 - struct resource *res; 591 602 unsigned int i; 592 603 unsigned long rate; 593 - int irq; 594 604 int err; 595 605 596 606 tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL); 597 607 if (!tegra) 598 608 return -ENOMEM; 599 609 600 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 601 - 602 - tegra->regs = devm_ioremap_resource(&pdev->dev, res); 610 + tegra->regs = devm_platform_ioremap_resource(pdev, 0); 603 611 if (IS_ERR(tegra->regs)) 604 612 return PTR_ERR(tegra->regs); 605 613 ··· 618 632 return PTR_ERR(tegra->emc_clock); 619 633 } 620 634 621 - clk_set_rate(tegra->emc_clock, ULONG_MAX); 622 - 623 - tegra->rate_change_nb.notifier_call = tegra_actmon_rate_notify_cb; 624 - err = clk_notifier_register(tegra->emc_clock, &tegra->rate_change_nb); 625 - if (err) { 626 - dev_err(&pdev->dev, 627 - "Failed to register rate change notifier\n"); 635 + tegra->irq = platform_get_irq(pdev, 0); 636 + if (tegra->irq < 0) { 637 + err = tegra->irq; 638 + dev_err(&pdev->dev, "Failed to get IRQ: %d\n", err); 628 639 return err; 629 640 } 630 641 ··· 639 656 tegra->max_freq = clk_round_rate(tegra->emc_clock, ULONG_MAX) / KHZ; 640 657 tegra->cur_freq = clk_get_rate(tegra->emc_clock) / KHZ; 641 658 642 - actmon_writel(tegra, ACTMON_SAMPLING_PERIOD - 1, 643 - ACTMON_GLB_PERIOD_CTRL); 644 - 645 659 for (i = 0; i < ARRAY_SIZE(actmon_device_configs); i++) { 646 660 dev = tegra->devices + i; 647 661 dev->config = actmon_device_configs + i; 648 662 dev->regs = tegra->regs + dev->config->offset; 649 - spin_lock_init(&dev->lock); 650 - 651 - tegra_actmon_configure_device(tegra, dev); 652 663 } 653 664 654 665 for (rate = 0; rate <= tegra->max_freq * KHZ; rate++) { 655 666 rate = clk_round_rate(tegra->emc_clock, rate); 656 - dev_pm_opp_add(&pdev->dev, rate, 0); 657 - } 658 667 659 - irq = platform_get_irq(pdev, 0); 660 - if (irq < 0) { 661 - dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq); 662 - return irq; 668 + err = dev_pm_opp_add(&pdev->dev, rate, 0); 669 + if (err) { 670 + dev_err(&pdev->dev, "Failed to add OPP: %d\n", err); 671 + goto remove_opps; 672 + } 663 673 } 664 674 665 675 platform_set_drvdata(pdev, tegra); 666 676 667 - err = devm_request_threaded_irq(&pdev->dev, irq, actmon_isr, 668 - actmon_thread_isr, IRQF_SHARED, 669 - "tegra-devfreq", tegra); 677 + tegra->rate_change_nb.notifier_call = tegra_actmon_rate_notify_cb; 678 + err = clk_notifier_register(tegra->emc_clock, &tegra->rate_change_nb); 670 679 if (err) { 671 - dev_err(&pdev->dev, "Interrupt request failed\n"); 672 - return err; 680 + dev_err(&pdev->dev, 681 + "Failed to register rate change notifier\n"); 682 + goto remove_opps; 683 + } 684 + 685 + err = devfreq_add_governor(&tegra_devfreq_governor); 686 + if (err) { 687 + dev_err(&pdev->dev, "Failed to add governor: %d\n", err); 688 + goto unreg_notifier; 673 689 } 674 690 675 691 tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock); 676 - tegra->devfreq = devm_devfreq_add_device(&pdev->dev, 677 - &tegra_devfreq_profile, 678 - "tegra_actmon", 679 - NULL); 692 + tegra->devfreq = devfreq_add_device(&pdev->dev, 693 + &tegra_devfreq_profile, 694 + "tegra_actmon", 695 + NULL); 696 + if (IS_ERR(tegra->devfreq)) { 697 + err = PTR_ERR(tegra->devfreq); 698 + goto remove_governor; 699 + } 700 + 701 + err = devm_request_threaded_irq(&pdev->dev, tegra->irq, NULL, 702 + actmon_thread_isr, IRQF_ONESHOT, 703 + "tegra-devfreq", tegra); 704 + if (err) { 705 + dev_err(&pdev->dev, "Interrupt request failed: %d\n", err); 706 + goto remove_devfreq; 707 + } 680 708 681 709 return 0; 710 + 711 + remove_devfreq: 712 + devfreq_remove_device(tegra->devfreq); 713 + 714 + remove_governor: 715 + devfreq_remove_governor(&tegra_devfreq_governor); 716 + 717 + unreg_notifier: 718 + clk_notifier_unregister(tegra->emc_clock, &tegra->rate_change_nb); 719 + 720 + remove_opps: 721 + dev_pm_opp_remove_all_dynamic(&pdev->dev); 722 + 723 + reset_control_reset(tegra->reset); 724 + clk_disable_unprepare(tegra->clock); 725 + 726 + return err; 682 727 } 683 728 684 729 static int tegra_devfreq_remove(struct platform_device *pdev) 685 730 { 686 731 struct tegra_devfreq *tegra = platform_get_drvdata(pdev); 687 - int irq = platform_get_irq(pdev, 0); 688 - u32 val; 689 - unsigned int i; 690 732 691 - for (i = 0; i < ARRAY_SIZE(actmon_device_configs); i++) { 692 - val = device_readl(&tegra->devices[i], ACTMON_DEV_CTRL); 693 - val &= ~ACTMON_DEV_CTRL_ENB; 694 - device_writel(&tegra->devices[i], val, ACTMON_DEV_CTRL); 695 - } 696 - 697 - actmon_write_barrier(tegra); 698 - 699 - devm_free_irq(&pdev->dev, irq, tegra); 733 + devfreq_remove_device(tegra->devfreq); 734 + devfreq_remove_governor(&tegra_devfreq_governor); 700 735 701 736 clk_notifier_unregister(tegra->emc_clock, &tegra->rate_change_nb); 737 + dev_pm_opp_remove_all_dynamic(&pdev->dev); 702 738 739 + reset_control_reset(tegra->reset); 703 740 clk_disable_unprepare(tegra->clock); 704 741 705 742 return 0; 706 743 } 707 744 708 745 static const struct of_device_id tegra_devfreq_of_match[] = { 746 + { .compatible = "nvidia,tegra30-actmon" }, 709 747 { .compatible = "nvidia,tegra124-actmon" }, 710 748 { }, 711 749 }; ··· 741 737 .of_match_table = tegra_devfreq_of_match, 742 738 }, 743 739 }; 744 - 745 - static int __init tegra_devfreq_init(void) 746 - { 747 - int ret = 0; 748 - 749 - ret = devfreq_add_governor(&tegra_devfreq_governor); 750 - if (ret) { 751 - pr_err("%s: failed to add governor: %d\n", __func__, ret); 752 - return ret; 753 - } 754 - 755 - ret = platform_driver_register(&tegra_devfreq_driver); 756 - if (ret) 757 - devfreq_remove_governor(&tegra_devfreq_governor); 758 - 759 - return ret; 760 - } 761 - module_init(tegra_devfreq_init) 762 - 763 - static void __exit tegra_devfreq_exit(void) 764 - { 765 - int ret = 0; 766 - 767 - platform_driver_unregister(&tegra_devfreq_driver); 768 - 769 - ret = devfreq_remove_governor(&tegra_devfreq_governor); 770 - if (ret) 771 - pr_err("%s: failed to remove governor: %d\n", __func__, ret); 772 - } 773 - module_exit(tegra_devfreq_exit) 740 + module_platform_driver(tegra_devfreq_driver); 774 741 775 742 MODULE_LICENSE("GPL v2"); 776 743 MODULE_DESCRIPTION("Tegra devfreq driver");
+212
drivers/devfreq/tegra20-devfreq.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * NVIDIA Tegra20 devfreq driver 4 + * 5 + * Copyright (C) 2019 GRATE-DRIVER project 6 + */ 7 + 8 + #include <linux/clk.h> 9 + #include <linux/devfreq.h> 10 + #include <linux/io.h> 11 + #include <linux/kernel.h> 12 + #include <linux/module.h> 13 + #include <linux/of_device.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/pm_opp.h> 16 + #include <linux/slab.h> 17 + 18 + #include <soc/tegra/mc.h> 19 + 20 + #include "governor.h" 21 + 22 + #define MC_STAT_CONTROL 0x90 23 + #define MC_STAT_EMC_CLOCK_LIMIT 0xa0 24 + #define MC_STAT_EMC_CLOCKS 0xa4 25 + #define MC_STAT_EMC_CONTROL 0xa8 26 + #define MC_STAT_EMC_COUNT 0xb8 27 + 28 + #define EMC_GATHER_CLEAR (1 << 8) 29 + #define EMC_GATHER_ENABLE (3 << 8) 30 + 31 + struct tegra_devfreq { 32 + struct devfreq *devfreq; 33 + struct clk *emc_clock; 34 + void __iomem *regs; 35 + }; 36 + 37 + static int tegra_devfreq_target(struct device *dev, unsigned long *freq, 38 + u32 flags) 39 + { 40 + struct tegra_devfreq *tegra = dev_get_drvdata(dev); 41 + struct devfreq *devfreq = tegra->devfreq; 42 + struct dev_pm_opp *opp; 43 + unsigned long rate; 44 + int err; 45 + 46 + opp = devfreq_recommended_opp(dev, freq, flags); 47 + if (IS_ERR(opp)) 48 + return PTR_ERR(opp); 49 + 50 + rate = dev_pm_opp_get_freq(opp); 51 + dev_pm_opp_put(opp); 52 + 53 + err = clk_set_min_rate(tegra->emc_clock, rate); 54 + if (err) 55 + return err; 56 + 57 + err = clk_set_rate(tegra->emc_clock, 0); 58 + if (err) 59 + goto restore_min_rate; 60 + 61 + return 0; 62 + 63 + restore_min_rate: 64 + clk_set_min_rate(tegra->emc_clock, devfreq->previous_freq); 65 + 66 + return err; 67 + } 68 + 69 + static int tegra_devfreq_get_dev_status(struct device *dev, 70 + struct devfreq_dev_status *stat) 71 + { 72 + struct tegra_devfreq *tegra = dev_get_drvdata(dev); 73 + 74 + /* 75 + * EMC_COUNT returns number of memory events, that number is lower 76 + * than the number of clocks. Conversion ratio of 1/8 results in a 77 + * bit higher bandwidth than actually needed, it is good enough for 78 + * the time being because drivers don't support requesting minimum 79 + * needed memory bandwidth yet. 80 + * 81 + * TODO: adjust the ratio value once relevant drivers will support 82 + * memory bandwidth management. 83 + */ 84 + stat->busy_time = readl_relaxed(tegra->regs + MC_STAT_EMC_COUNT); 85 + stat->total_time = readl_relaxed(tegra->regs + MC_STAT_EMC_CLOCKS) / 8; 86 + stat->current_frequency = clk_get_rate(tegra->emc_clock); 87 + 88 + writel_relaxed(EMC_GATHER_CLEAR, tegra->regs + MC_STAT_CONTROL); 89 + writel_relaxed(EMC_GATHER_ENABLE, tegra->regs + MC_STAT_CONTROL); 90 + 91 + return 0; 92 + } 93 + 94 + static struct devfreq_dev_profile tegra_devfreq_profile = { 95 + .polling_ms = 500, 96 + .target = tegra_devfreq_target, 97 + .get_dev_status = tegra_devfreq_get_dev_status, 98 + }; 99 + 100 + static struct tegra_mc *tegra_get_memory_controller(void) 101 + { 102 + struct platform_device *pdev; 103 + struct device_node *np; 104 + struct tegra_mc *mc; 105 + 106 + np = of_find_compatible_node(NULL, NULL, "nvidia,tegra20-mc-gart"); 107 + if (!np) 108 + return ERR_PTR(-ENOENT); 109 + 110 + pdev = of_find_device_by_node(np); 111 + of_node_put(np); 112 + if (!pdev) 113 + return ERR_PTR(-ENODEV); 114 + 115 + mc = platform_get_drvdata(pdev); 116 + if (!mc) 117 + return ERR_PTR(-EPROBE_DEFER); 118 + 119 + return mc; 120 + } 121 + 122 + static int tegra_devfreq_probe(struct platform_device *pdev) 123 + { 124 + struct tegra_devfreq *tegra; 125 + struct tegra_mc *mc; 126 + unsigned long max_rate; 127 + unsigned long rate; 128 + int err; 129 + 130 + mc = tegra_get_memory_controller(); 131 + if (IS_ERR(mc)) { 132 + err = PTR_ERR(mc); 133 + dev_err(&pdev->dev, "failed to get memory controller: %d\n", 134 + err); 135 + return err; 136 + } 137 + 138 + tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL); 139 + if (!tegra) 140 + return -ENOMEM; 141 + 142 + /* EMC is a system-critical clock that is always enabled */ 143 + tegra->emc_clock = devm_clk_get(&pdev->dev, "emc"); 144 + if (IS_ERR(tegra->emc_clock)) { 145 + err = PTR_ERR(tegra->emc_clock); 146 + dev_err(&pdev->dev, "failed to get emc clock: %d\n", err); 147 + return err; 148 + } 149 + 150 + tegra->regs = mc->regs; 151 + 152 + max_rate = clk_round_rate(tegra->emc_clock, ULONG_MAX); 153 + 154 + for (rate = 0; rate <= max_rate; rate++) { 155 + rate = clk_round_rate(tegra->emc_clock, rate); 156 + 157 + err = dev_pm_opp_add(&pdev->dev, rate, 0); 158 + if (err) { 159 + dev_err(&pdev->dev, "failed to add opp: %d\n", err); 160 + goto remove_opps; 161 + } 162 + } 163 + 164 + /* 165 + * Reset statistic gathers state, select global bandwidth for the 166 + * statistics collection mode and set clocks counter saturation 167 + * limit to maximum. 168 + */ 169 + writel_relaxed(0x00000000, tegra->regs + MC_STAT_CONTROL); 170 + writel_relaxed(0x00000000, tegra->regs + MC_STAT_EMC_CONTROL); 171 + writel_relaxed(0xffffffff, tegra->regs + MC_STAT_EMC_CLOCK_LIMIT); 172 + 173 + platform_set_drvdata(pdev, tegra); 174 + 175 + tegra->devfreq = devfreq_add_device(&pdev->dev, &tegra_devfreq_profile, 176 + DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL); 177 + if (IS_ERR(tegra->devfreq)) { 178 + err = PTR_ERR(tegra->devfreq); 179 + goto remove_opps; 180 + } 181 + 182 + return 0; 183 + 184 + remove_opps: 185 + dev_pm_opp_remove_all_dynamic(&pdev->dev); 186 + 187 + return err; 188 + } 189 + 190 + static int tegra_devfreq_remove(struct platform_device *pdev) 191 + { 192 + struct tegra_devfreq *tegra = platform_get_drvdata(pdev); 193 + 194 + devfreq_remove_device(tegra->devfreq); 195 + dev_pm_opp_remove_all_dynamic(&pdev->dev); 196 + 197 + return 0; 198 + } 199 + 200 + static struct platform_driver tegra_devfreq_driver = { 201 + .probe = tegra_devfreq_probe, 202 + .remove = tegra_devfreq_remove, 203 + .driver = { 204 + .name = "tegra20-devfreq", 205 + }, 206 + }; 207 + module_platform_driver(tegra_devfreq_driver); 208 + 209 + MODULE_ALIAS("platform:tegra20-devfreq"); 210 + MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>"); 211 + MODULE_DESCRIPTION("NVIDIA Tegra20 devfreq driver"); 212 + MODULE_LICENSE("GPL v2");
+50 -27
drivers/macintosh/windfarm_cpufreq_clamp.c
··· 3 3 #include <linux/errno.h> 4 4 #include <linux/kernel.h> 5 5 #include <linux/delay.h> 6 + #include <linux/pm_qos.h> 6 7 #include <linux/slab.h> 7 8 #include <linux/init.h> 8 9 #include <linux/wait.h> 10 + #include <linux/cpu.h> 9 11 #include <linux/cpufreq.h> 10 12 11 13 #include <asm/prom.h> ··· 18 16 19 17 static int clamped; 20 18 static struct wf_control *clamp_control; 21 - 22 - static int clamp_notifier_call(struct notifier_block *self, 23 - unsigned long event, void *data) 24 - { 25 - struct cpufreq_policy *p = data; 26 - unsigned long max_freq; 27 - 28 - if (event != CPUFREQ_ADJUST) 29 - return 0; 30 - 31 - max_freq = clamped ? (p->cpuinfo.min_freq) : (p->cpuinfo.max_freq); 32 - cpufreq_verify_within_limits(p, 0, max_freq); 33 - 34 - return 0; 35 - } 36 - 37 - static struct notifier_block clamp_notifier = { 38 - .notifier_call = clamp_notifier_call, 39 - }; 19 + static struct dev_pm_qos_request qos_req; 20 + static unsigned int min_freq, max_freq; 40 21 41 22 static int clamp_set(struct wf_control *ct, s32 value) 42 23 { 43 - if (value) 24 + unsigned int freq; 25 + 26 + if (value) { 27 + freq = min_freq; 44 28 printk(KERN_INFO "windfarm: Clamping CPU frequency to " 45 29 "minimum !\n"); 46 - else 30 + } else { 31 + freq = max_freq; 47 32 printk(KERN_INFO "windfarm: CPU frequency unclamped !\n"); 33 + } 48 34 clamped = value; 49 - cpufreq_update_policy(0); 50 - return 0; 35 + 36 + return dev_pm_qos_update_request(&qos_req, freq); 51 37 } 52 38 53 39 static int clamp_get(struct wf_control *ct, s32 *value) ··· 64 74 65 75 static int __init wf_cpufreq_clamp_init(void) 66 76 { 77 + struct cpufreq_policy *policy; 67 78 struct wf_control *clamp; 79 + struct device *dev; 80 + int ret; 81 + 82 + policy = cpufreq_cpu_get(0); 83 + if (!policy) { 84 + pr_warn("%s: cpufreq policy not found cpu0\n", __func__); 85 + return -EPROBE_DEFER; 86 + } 87 + 88 + min_freq = policy->cpuinfo.min_freq; 89 + max_freq = policy->cpuinfo.max_freq; 90 + cpufreq_cpu_put(policy); 91 + 92 + dev = get_cpu_device(0); 93 + if (unlikely(!dev)) { 94 + pr_warn("%s: No cpu device for cpu0\n", __func__); 95 + return -ENODEV; 96 + } 68 97 69 98 clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL); 70 99 if (clamp == NULL) 71 100 return -ENOMEM; 72 - cpufreq_register_notifier(&clamp_notifier, CPUFREQ_POLICY_NOTIFIER); 101 + 102 + ret = dev_pm_qos_add_request(dev, &qos_req, DEV_PM_QOS_MAX_FREQUENCY, 103 + max_freq); 104 + if (ret < 0) { 105 + pr_err("%s: Failed to add freq constraint (%d)\n", __func__, 106 + ret); 107 + goto free; 108 + } 109 + 73 110 clamp->ops = &clamp_ops; 74 111 clamp->name = "cpufreq-clamp"; 75 - if (wf_register_control(clamp)) 112 + ret = wf_register_control(clamp); 113 + if (ret) 76 114 goto fail; 77 115 clamp_control = clamp; 78 116 return 0; 79 117 fail: 118 + dev_pm_qos_remove_request(&qos_req); 119 + 120 + free: 80 121 kfree(clamp); 81 - return -ENODEV; 122 + return ret; 82 123 } 83 124 84 125 static void __exit wf_cpufreq_clamp_exit(void) 85 126 { 86 - if (clamp_control) 127 + if (clamp_control) { 87 128 wf_unregister_control(clamp_control); 129 + dev_pm_qos_remove_request(&qos_req); 130 + } 88 131 } 89 132 90 133
+72 -13
drivers/opp/core.c
··· 401 401 } 402 402 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact); 403 403 404 + /** 405 + * dev_pm_opp_find_level_exact() - search for an exact level 406 + * @dev: device for which we do this operation 407 + * @level: level to search for 408 + * 409 + * Return: Searches for exact match in the opp table and returns pointer to the 410 + * matching opp if found, else returns ERR_PTR in case of error and should 411 + * be handled using IS_ERR. Error return values can be: 412 + * EINVAL: for bad pointer 413 + * ERANGE: no match found for search 414 + * ENODEV: if device not found in list of registered devices 415 + * 416 + * The callers are required to call dev_pm_opp_put() for the returned OPP after 417 + * use. 418 + */ 419 + struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, 420 + unsigned int level) 421 + { 422 + struct opp_table *opp_table; 423 + struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); 424 + 425 + opp_table = _find_opp_table(dev); 426 + if (IS_ERR(opp_table)) { 427 + int r = PTR_ERR(opp_table); 428 + 429 + dev_err(dev, "%s: OPP table not found (%d)\n", __func__, r); 430 + return ERR_PTR(r); 431 + } 432 + 433 + mutex_lock(&opp_table->lock); 434 + 435 + list_for_each_entry(temp_opp, &opp_table->opp_list, node) { 436 + if (temp_opp->level == level) { 437 + opp = temp_opp; 438 + 439 + /* Increment the reference count of OPP */ 440 + dev_pm_opp_get(opp); 441 + break; 442 + } 443 + } 444 + 445 + mutex_unlock(&opp_table->lock); 446 + dev_pm_opp_put_opp_table(opp_table); 447 + 448 + return opp; 449 + } 450 + EXPORT_SYMBOL_GPL(dev_pm_opp_find_level_exact); 451 + 404 452 static noinline struct dev_pm_opp *_find_freq_ceil(struct opp_table *opp_table, 405 453 unsigned long *freq) 406 454 { ··· 988 940 BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head); 989 941 INIT_LIST_HEAD(&opp_table->opp_list); 990 942 kref_init(&opp_table->kref); 943 + kref_init(&opp_table->list_kref); 991 944 992 945 /* Secure the device table modification */ 993 946 list_add(&opp_table->node, &opp_tables); ··· 1626 1577 goto free_regulators; 1627 1578 } 1628 1579 1580 + ret = regulator_enable(reg); 1581 + if (ret < 0) { 1582 + regulator_put(reg); 1583 + goto free_regulators; 1584 + } 1585 + 1629 1586 opp_table->regulators[i] = reg; 1630 1587 } 1631 1588 ··· 1645 1590 return opp_table; 1646 1591 1647 1592 free_regulators: 1648 - while (i != 0) 1649 - regulator_put(opp_table->regulators[--i]); 1593 + while (i--) { 1594 + regulator_disable(opp_table->regulators[i]); 1595 + regulator_put(opp_table->regulators[i]); 1596 + } 1650 1597 1651 1598 kfree(opp_table->regulators); 1652 1599 opp_table->regulators = NULL; ··· 1674 1617 /* Make sure there are no concurrent readers while updating opp_table */ 1675 1618 WARN_ON(!list_empty(&opp_table->opp_list)); 1676 1619 1677 - for (i = opp_table->regulator_count - 1; i >= 0; i--) 1620 + for (i = opp_table->regulator_count - 1; i >= 0; i--) { 1621 + regulator_disable(opp_table->regulators[i]); 1678 1622 regulator_put(opp_table->regulators[i]); 1623 + } 1679 1624 1680 1625 _free_set_opp_data(opp_table); 1681 1626 ··· 1830 1771 * dev_pm_opp_attach_genpd - Attach genpd(s) for the device and save virtual device pointer 1831 1772 * @dev: Consumer device for which the genpd is getting attached. 1832 1773 * @names: Null terminated array of pointers containing names of genpd to attach. 1774 + * @virt_devs: Pointer to return the array of virtual devices. 1833 1775 * 1834 1776 * Multiple generic power domains for a device are supported with the help of 1835 1777 * virtual genpd devices, which are created for each consumer device - genpd ··· 1844 1784 * 1845 1785 * This helper needs to be called once with a list of all genpd to attach. 1846 1786 * Otherwise the original device structure will be used instead by the OPP core. 1787 + * 1788 + * The order of entries in the names array must match the order in which 1789 + * "required-opps" are added in DT. 1847 1790 */ 1848 - struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names) 1791 + struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, 1792 + const char **names, struct device ***virt_devs) 1849 1793 { 1850 1794 struct opp_table *opp_table; 1851 1795 struct device *virt_dev; 1852 - int index, ret = -EINVAL; 1796 + int index = 0, ret = -EINVAL; 1853 1797 const char **name = names; 1854 1798 1855 1799 opp_table = dev_pm_opp_get_opp_table(dev); ··· 1879 1815 goto unlock; 1880 1816 1881 1817 while (*name) { 1882 - index = of_property_match_string(dev->of_node, 1883 - "power-domain-names", *name); 1884 - if (index < 0) { 1885 - dev_err(dev, "Failed to find power domain: %s (%d)\n", 1886 - *name, index); 1887 - goto err; 1888 - } 1889 - 1890 1818 if (index >= opp_table->required_opp_count) { 1891 1819 dev_err(dev, "Index can't be greater than required-opp-count - 1, %s (%d : %d)\n", 1892 1820 *name, opp_table->required_opp_count, index); ··· 1899 1843 } 1900 1844 1901 1845 opp_table->genpd_virt_devs[index] = virt_dev; 1846 + index++; 1902 1847 name++; 1903 1848 } 1904 1849 1850 + if (virt_devs) 1851 + *virt_devs = opp_table->genpd_virt_devs; 1905 1852 mutex_unlock(&opp_table->genpd_virt_dev_lock); 1906 1853 1907 1854 return opp_table;
+10 -20
drivers/opp/of.c
··· 617 617 /* OPP to select on device suspend */ 618 618 if (of_property_read_bool(np, "opp-suspend")) { 619 619 if (opp_table->suspend_opp) { 620 - dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n", 621 - __func__, opp_table->suspend_opp->rate, 622 - new_opp->rate); 620 + /* Pick the OPP with higher rate as suspend OPP */ 621 + if (new_opp->rate > opp_table->suspend_opp->rate) { 622 + opp_table->suspend_opp->suspend = false; 623 + new_opp->suspend = true; 624 + opp_table->suspend_opp = new_opp; 625 + } 623 626 } else { 624 627 new_opp->suspend = true; 625 628 opp_table->suspend_opp = new_opp; ··· 665 662 return 0; 666 663 } 667 664 668 - kref_init(&opp_table->list_kref); 669 - 670 665 /* We have opp-table node now, iterate over it and add OPPs */ 671 666 for_each_available_child_of_node(opp_table->np, np) { 672 667 opp = _opp_add_static_v2(opp_table, dev, np); ··· 673 672 dev_err(dev, "%s: Failed to add OPP, %d\n", __func__, 674 673 ret); 675 674 of_node_put(np); 676 - goto put_list_kref; 675 + return ret; 677 676 } else if (opp) { 678 677 count++; 679 678 } 680 679 } 681 680 682 681 /* There should be one of more OPP defined */ 683 - if (WARN_ON(!count)) { 684 - ret = -ENOENT; 685 - goto put_list_kref; 686 - } 682 + if (WARN_ON(!count)) 683 + return -ENOENT; 687 684 688 685 list_for_each_entry(opp, &opp_table->opp_list, node) 689 686 pstate_count += !!opp->pstate; ··· 690 691 if (pstate_count && pstate_count != count) { 691 692 dev_err(dev, "Not all nodes have performance state set (%d: %d)\n", 692 693 count, pstate_count); 693 - ret = -ENOENT; 694 - goto put_list_kref; 694 + return -ENOENT; 695 695 } 696 696 697 697 if (pstate_count) ··· 699 701 opp_table->parsed_static_opps = true; 700 702 701 703 return 0; 702 - 703 - put_list_kref: 704 - _put_opp_list_kref(opp_table); 705 - 706 - return ret; 707 704 } 708 705 709 706 /* Initializes OPP tables based on old-deprecated bindings */ ··· 724 731 return -EINVAL; 725 732 } 726 733 727 - kref_init(&opp_table->list_kref); 728 - 729 734 val = prop->value; 730 735 while (nr) { 731 736 unsigned long freq = be32_to_cpup(val++) * 1000; ··· 733 742 if (ret) { 734 743 dev_err(dev, "%s: Failed to add OPP %ld (%d)\n", 735 744 __func__, freq, ret); 736 - _put_opp_list_kref(opp_table); 737 745 return ret; 738 746 } 739 747 nr -= 2;
+26 -10
drivers/platform/x86/intel-hid.c
··· 253 253 254 254 static int intel_hid_pm_prepare(struct device *device) 255 255 { 256 + if (device_may_wakeup(device)) { 257 + struct intel_hid_priv *priv = dev_get_drvdata(device); 258 + 259 + priv->wakeup_mode = true; 260 + } 261 + return 0; 262 + } 263 + 264 + static void intel_hid_pm_complete(struct device *device) 265 + { 256 266 struct intel_hid_priv *priv = dev_get_drvdata(device); 257 267 258 - priv->wakeup_mode = true; 259 - return 0; 268 + priv->wakeup_mode = false; 260 269 } 261 270 262 271 static int intel_hid_pl_suspend_handler(struct device *device) 263 272 { 264 - if (pm_suspend_via_firmware()) { 273 + intel_button_array_enable(device, false); 274 + 275 + if (!pm_suspend_no_platform()) 265 276 intel_hid_set_enable(device, false); 266 - intel_button_array_enable(device, false); 267 - } 277 + 268 278 return 0; 269 279 } 270 280 271 281 static int intel_hid_pl_resume_handler(struct device *device) 272 282 { 273 - struct intel_hid_priv *priv = dev_get_drvdata(device); 283 + intel_hid_pm_complete(device); 274 284 275 - priv->wakeup_mode = false; 276 - if (pm_resume_via_firmware()) { 285 + if (!pm_suspend_no_platform()) 277 286 intel_hid_set_enable(device, true); 278 - intel_button_array_enable(device, true); 279 - } 287 + 288 + intel_button_array_enable(device, true); 280 289 return 0; 281 290 } 282 291 283 292 static const struct dev_pm_ops intel_hid_pl_pm_ops = { 284 293 .prepare = intel_hid_pm_prepare, 294 + .complete = intel_hid_pm_complete, 285 295 .freeze = intel_hid_pl_suspend_handler, 286 296 .thaw = intel_hid_pl_resume_handler, 287 297 .restore = intel_hid_pl_resume_handler, ··· 501 491 } 502 492 503 493 device_init_wakeup(&device->dev, true); 494 + /* 495 + * In order for system wakeup to work, the EC GPE has to be marked as 496 + * a wakeup one, so do that here (this setting will persist, but it has 497 + * no effect until the wakeup mask is set for the EC GPE). 498 + */ 499 + acpi_ec_mark_gpe_for_wake(); 504 500 return 0; 505 501 506 502 err_remove_notify:
+17 -3
drivers/platform/x86/intel-vbtn.c
··· 176 176 return -EBUSY; 177 177 178 178 device_init_wakeup(&device->dev, true); 179 + /* 180 + * In order for system wakeup to work, the EC GPE has to be marked as 181 + * a wakeup one, so do that here (this setting will persist, but it has 182 + * no effect until the wakeup mask is set for the EC GPE). 183 + */ 184 + acpi_ec_mark_gpe_for_wake(); 179 185 return 0; 180 186 } 181 187 ··· 201 195 202 196 static int intel_vbtn_pm_prepare(struct device *dev) 203 197 { 204 - struct intel_vbtn_priv *priv = dev_get_drvdata(dev); 198 + if (device_may_wakeup(dev)) { 199 + struct intel_vbtn_priv *priv = dev_get_drvdata(dev); 205 200 206 - priv->wakeup_mode = true; 201 + priv->wakeup_mode = true; 202 + } 207 203 return 0; 208 204 } 209 205 210 - static int intel_vbtn_pm_resume(struct device *dev) 206 + static void intel_vbtn_pm_complete(struct device *dev) 211 207 { 212 208 struct intel_vbtn_priv *priv = dev_get_drvdata(dev); 213 209 214 210 priv->wakeup_mode = false; 211 + } 212 + 213 + static int intel_vbtn_pm_resume(struct device *dev) 214 + { 215 + intel_vbtn_pm_complete(dev); 215 216 return 0; 216 217 } 217 218 218 219 static const struct dev_pm_ops intel_vbtn_pm_ops = { 219 220 .prepare = intel_vbtn_pm_prepare, 221 + .complete = intel_vbtn_pm_complete, 220 222 .resume = intel_vbtn_pm_resume, 221 223 .restore = intel_vbtn_pm_resume, 222 224 .thaw = intel_vbtn_pm_resume,
+27 -26
drivers/powercap/idle_inject.c
··· 59 59 /** 60 60 * struct idle_inject_device - idle injection data 61 61 * @timer: idle injection period timer 62 - * @idle_duration_ms: duration of CPU idle time to inject 63 - * @run_duration_ms: duration of CPU run time to allow 62 + * @idle_duration_us: duration of CPU idle time to inject 63 + * @run_duration_us: duration of CPU run time to allow 64 64 * @cpumask: mask of CPUs affected by idle injection 65 65 */ 66 66 struct idle_inject_device { 67 67 struct hrtimer timer; 68 - unsigned int idle_duration_ms; 69 - unsigned int run_duration_ms; 68 + unsigned int idle_duration_us; 69 + unsigned int run_duration_us; 70 70 unsigned long int cpumask[0]; 71 71 }; 72 72 ··· 104 104 */ 105 105 static enum hrtimer_restart idle_inject_timer_fn(struct hrtimer *timer) 106 106 { 107 - unsigned int duration_ms; 107 + unsigned int duration_us; 108 108 struct idle_inject_device *ii_dev = 109 109 container_of(timer, struct idle_inject_device, timer); 110 110 111 - duration_ms = READ_ONCE(ii_dev->run_duration_ms); 112 - duration_ms += READ_ONCE(ii_dev->idle_duration_ms); 111 + duration_us = READ_ONCE(ii_dev->run_duration_us); 112 + duration_us += READ_ONCE(ii_dev->idle_duration_us); 113 113 114 114 idle_inject_wakeup(ii_dev); 115 115 116 - hrtimer_forward_now(timer, ms_to_ktime(duration_ms)); 116 + hrtimer_forward_now(timer, ns_to_ktime(duration_us * NSEC_PER_USEC)); 117 117 118 118 return HRTIMER_RESTART; 119 119 } ··· 138 138 */ 139 139 iit->should_run = 0; 140 140 141 - play_idle(READ_ONCE(ii_dev->idle_duration_ms)); 141 + play_idle(READ_ONCE(ii_dev->idle_duration_us)); 142 142 } 143 143 144 144 /** 145 145 * idle_inject_set_duration - idle and run duration update helper 146 - * @run_duration_ms: CPU run time to allow in milliseconds 147 - * @idle_duration_ms: CPU idle time to inject in milliseconds 146 + * @run_duration_us: CPU run time to allow in microseconds 147 + * @idle_duration_us: CPU idle time to inject in microseconds 148 148 */ 149 149 void idle_inject_set_duration(struct idle_inject_device *ii_dev, 150 - unsigned int run_duration_ms, 151 - unsigned int idle_duration_ms) 150 + unsigned int run_duration_us, 151 + unsigned int idle_duration_us) 152 152 { 153 - if (run_duration_ms && idle_duration_ms) { 154 - WRITE_ONCE(ii_dev->run_duration_ms, run_duration_ms); 155 - WRITE_ONCE(ii_dev->idle_duration_ms, idle_duration_ms); 153 + if (run_duration_us && idle_duration_us) { 154 + WRITE_ONCE(ii_dev->run_duration_us, run_duration_us); 155 + WRITE_ONCE(ii_dev->idle_duration_us, idle_duration_us); 156 156 } 157 157 } 158 158 159 159 /** 160 160 * idle_inject_get_duration - idle and run duration retrieval helper 161 - * @run_duration_ms: memory location to store the current CPU run time 162 - * @idle_duration_ms: memory location to store the current CPU idle time 161 + * @run_duration_us: memory location to store the current CPU run time 162 + * @idle_duration_us: memory location to store the current CPU idle time 163 163 */ 164 164 void idle_inject_get_duration(struct idle_inject_device *ii_dev, 165 - unsigned int *run_duration_ms, 166 - unsigned int *idle_duration_ms) 165 + unsigned int *run_duration_us, 166 + unsigned int *idle_duration_us) 167 167 { 168 - *run_duration_ms = READ_ONCE(ii_dev->run_duration_ms); 169 - *idle_duration_ms = READ_ONCE(ii_dev->idle_duration_ms); 168 + *run_duration_us = READ_ONCE(ii_dev->run_duration_us); 169 + *idle_duration_us = READ_ONCE(ii_dev->idle_duration_us); 170 170 } 171 171 172 172 /** ··· 181 181 */ 182 182 int idle_inject_start(struct idle_inject_device *ii_dev) 183 183 { 184 - unsigned int idle_duration_ms = READ_ONCE(ii_dev->idle_duration_ms); 185 - unsigned int run_duration_ms = READ_ONCE(ii_dev->run_duration_ms); 184 + unsigned int idle_duration_us = READ_ONCE(ii_dev->idle_duration_us); 185 + unsigned int run_duration_us = READ_ONCE(ii_dev->run_duration_us); 186 186 187 - if (!idle_duration_ms || !run_duration_ms) 187 + if (!idle_duration_us || !run_duration_us) 188 188 return -EINVAL; 189 189 190 190 pr_debug("Starting injecting idle cycles on CPUs '%*pbl'\n", ··· 193 193 idle_inject_wakeup(ii_dev); 194 194 195 195 hrtimer_start(&ii_dev->timer, 196 - ms_to_ktime(idle_duration_ms + run_duration_ms), 196 + ns_to_ktime((idle_duration_us + run_duration_us) * 197 + NSEC_PER_USEC), 197 198 HRTIMER_MODE_REL); 198 199 199 200 return 0;
+26 -84
drivers/thermal/cpu_cooling.c
··· 16 16 #include <linux/err.h> 17 17 #include <linux/idr.h> 18 18 #include <linux/pm_opp.h> 19 + #include <linux/pm_qos.h> 19 20 #include <linux/slab.h> 20 21 #include <linux/cpu.h> 21 22 #include <linux/cpu_cooling.h> ··· 67 66 * @last_load: load measured by the latest call to cpufreq_get_requested_power() 68 67 * @cpufreq_state: integer value representing the current state of cpufreq 69 68 * cooling devices. 70 - * @clipped_freq: integer value representing the absolute value of the clipped 71 - * frequency. 72 69 * @max_level: maximum cooling level. One less than total number of valid 73 70 * cpufreq frequencies. 74 71 * @freq_table: Freq table in descending order of frequencies ··· 83 84 int id; 84 85 u32 last_load; 85 86 unsigned int cpufreq_state; 86 - unsigned int clipped_freq; 87 87 unsigned int max_level; 88 88 struct freq_table *freq_table; /* In descending order */ 89 89 struct cpufreq_policy *policy; 90 90 struct list_head node; 91 91 struct time_in_idle *idle_time; 92 + struct dev_pm_qos_request qos_req; 92 93 }; 93 94 94 95 static DEFINE_IDA(cpufreq_ida); ··· 115 116 break; 116 117 117 118 return level - 1; 118 - } 119 - 120 - /** 121 - * cpufreq_thermal_notifier - notifier callback for cpufreq policy change. 122 - * @nb: struct notifier_block * with callback info. 123 - * @event: value showing cpufreq event for which this function invoked. 124 - * @data: callback-specific data 125 - * 126 - * Callback to hijack the notification on cpufreq policy transition. 127 - * Every time there is a change in policy, we will intercept and 128 - * update the cpufreq policy with thermal constraints. 129 - * 130 - * Return: 0 (success) 131 - */ 132 - static int cpufreq_thermal_notifier(struct notifier_block *nb, 133 - unsigned long event, void *data) 134 - { 135 - struct cpufreq_policy *policy = data; 136 - unsigned long clipped_freq; 137 - struct cpufreq_cooling_device *cpufreq_cdev; 138 - 139 - if (event != CPUFREQ_ADJUST) 140 - return NOTIFY_DONE; 141 - 142 - mutex_lock(&cooling_list_lock); 143 - list_for_each_entry(cpufreq_cdev, &cpufreq_cdev_list, node) { 144 - /* 145 - * A new copy of the policy is sent to the notifier and can't 146 - * compare that directly. 147 - */ 148 - if (policy->cpu != cpufreq_cdev->policy->cpu) 149 - continue; 150 - 151 - /* 152 - * policy->max is the maximum allowed frequency defined by user 153 - * and clipped_freq is the maximum that thermal constraints 154 - * allow. 155 - * 156 - * If clipped_freq is lower than policy->max, then we need to 157 - * readjust policy->max. 158 - * 159 - * But, if clipped_freq is greater than policy->max, we don't 160 - * need to do anything. 161 - */ 162 - clipped_freq = cpufreq_cdev->clipped_freq; 163 - 164 - if (policy->max > clipped_freq) 165 - cpufreq_verify_within_limits(policy, 0, clipped_freq); 166 - break; 167 - } 168 - mutex_unlock(&cooling_list_lock); 169 - 170 - return NOTIFY_OK; 171 119 } 172 120 173 121 /** ··· 320 374 unsigned long state) 321 375 { 322 376 struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; 323 - unsigned int clip_freq; 324 377 325 378 /* Request state should be less than max_level */ 326 379 if (WARN_ON(state > cpufreq_cdev->max_level)) ··· 329 384 if (cpufreq_cdev->cpufreq_state == state) 330 385 return 0; 331 386 332 - clip_freq = cpufreq_cdev->freq_table[state].frequency; 333 387 cpufreq_cdev->cpufreq_state = state; 334 - cpufreq_cdev->clipped_freq = clip_freq; 335 388 336 - cpufreq_update_policy(cpufreq_cdev->policy->cpu); 337 - 338 - return 0; 389 + return dev_pm_qos_update_request(&cpufreq_cdev->qos_req, 390 + cpufreq_cdev->freq_table[state].frequency); 339 391 } 340 392 341 393 /** ··· 496 554 .power2state = cpufreq_power2state, 497 555 }; 498 556 499 - /* Notifier for cpufreq policy change */ 500 - static struct notifier_block thermal_cpufreq_notifier_block = { 501 - .notifier_call = cpufreq_thermal_notifier, 502 - }; 503 - 504 557 static unsigned int find_next_max(struct cpufreq_frequency_table *table, 505 558 unsigned int prev_max) 506 559 { ··· 533 596 struct cpufreq_cooling_device *cpufreq_cdev; 534 597 char dev_name[THERMAL_NAME_LENGTH]; 535 598 unsigned int freq, i, num_cpus; 599 + struct device *dev; 536 600 int ret; 537 601 struct thermal_cooling_device_ops *cooling_ops; 538 - bool first; 602 + 603 + dev = get_cpu_device(policy->cpu); 604 + if (unlikely(!dev)) { 605 + pr_warn("No cpu device for cpu %d\n", policy->cpu); 606 + return ERR_PTR(-ENODEV); 607 + } 608 + 539 609 540 610 if (IS_ERR_OR_NULL(policy)) { 541 611 pr_err("%s: cpufreq policy isn't valid: %p\n", __func__, policy); ··· 615 671 cooling_ops = &cpufreq_cooling_ops; 616 672 } 617 673 674 + ret = dev_pm_qos_add_request(dev, &cpufreq_cdev->qos_req, 675 + DEV_PM_QOS_MAX_FREQUENCY, 676 + cpufreq_cdev->freq_table[0].frequency); 677 + if (ret < 0) { 678 + pr_err("%s: Failed to add freq constraint (%d)\n", __func__, 679 + ret); 680 + cdev = ERR_PTR(ret); 681 + goto remove_ida; 682 + } 683 + 618 684 cdev = thermal_of_cooling_device_register(np, dev_name, cpufreq_cdev, 619 685 cooling_ops); 620 686 if (IS_ERR(cdev)) 621 - goto remove_ida; 622 - 623 - cpufreq_cdev->clipped_freq = cpufreq_cdev->freq_table[0].frequency; 687 + goto remove_qos_req; 624 688 625 689 mutex_lock(&cooling_list_lock); 626 - /* Register the notifier for first cpufreq cooling device */ 627 - first = list_empty(&cpufreq_cdev_list); 628 690 list_add(&cpufreq_cdev->node, &cpufreq_cdev_list); 629 691 mutex_unlock(&cooling_list_lock); 630 692 631 - if (first) 632 - cpufreq_register_notifier(&thermal_cpufreq_notifier_block, 633 - CPUFREQ_POLICY_NOTIFIER); 634 - 635 693 return cdev; 636 694 695 + remove_qos_req: 696 + dev_pm_qos_remove_request(&cpufreq_cdev->qos_req); 637 697 remove_ida: 638 698 ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id); 639 699 free_table: ··· 725 777 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 726 778 { 727 779 struct cpufreq_cooling_device *cpufreq_cdev; 728 - bool last; 729 780 730 781 if (!cdev) 731 782 return; ··· 733 786 734 787 mutex_lock(&cooling_list_lock); 735 788 list_del(&cpufreq_cdev->node); 736 - /* Unregister the notifier for the last cpufreq cooling device */ 737 - last = list_empty(&cpufreq_cdev_list); 738 789 mutex_unlock(&cooling_list_lock); 739 790 740 - if (last) 741 - cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block, 742 - CPUFREQ_POLICY_NOTIFIER); 743 - 744 791 thermal_cooling_device_unregister(cdev); 792 + dev_pm_qos_remove_request(&cpufreq_cdev->qos_req); 745 793 ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id); 746 794 kfree(cpufreq_cdev->idle_time); 747 795 kfree(cpufreq_cdev->freq_table);
+1 -1
drivers/thermal/intel/intel_powerclamp.c
··· 430 430 if (should_skip) 431 431 goto balance; 432 432 433 - play_idle(jiffies_to_msecs(w_data->duration_jiffies)); 433 + play_idle(jiffies_to_usecs(w_data->duration_jiffies)); 434 434 435 435 balance: 436 436 if (clamping && w_data->clamping && cpu_online(w_data->cpu))
-21
drivers/video/fbdev/pxafb.c
··· 1678 1678 } 1679 1679 return 0; 1680 1680 } 1681 - 1682 - static int 1683 - pxafb_freq_policy(struct notifier_block *nb, unsigned long val, void *data) 1684 - { 1685 - struct pxafb_info *fbi = TO_INF(nb, freq_policy); 1686 - struct fb_var_screeninfo *var = &fbi->fb.var; 1687 - struct cpufreq_policy *policy = data; 1688 - 1689 - switch (val) { 1690 - case CPUFREQ_ADJUST: 1691 - pr_debug("min dma period: %d ps, " 1692 - "new clock %d kHz\n", pxafb_display_dma_period(var), 1693 - policy->max); 1694 - /* TODO: fill in min/max values */ 1695 - break; 1696 - } 1697 - return 0; 1698 - } 1699 1681 #endif 1700 1682 1701 1683 #ifdef CONFIG_PM ··· 2382 2400 2383 2401 #ifdef CONFIG_CPU_FREQ 2384 2402 fbi->freq_transition.notifier_call = pxafb_freq_transition; 2385 - fbi->freq_policy.notifier_call = pxafb_freq_policy; 2386 2403 cpufreq_register_notifier(&fbi->freq_transition, 2387 2404 CPUFREQ_TRANSITION_NOTIFIER); 2388 - cpufreq_register_notifier(&fbi->freq_policy, 2389 - CPUFREQ_POLICY_NOTIFIER); 2390 2405 #endif 2391 2406 2392 2407 /*
-1
drivers/video/fbdev/pxafb.h
··· 162 162 163 163 #ifdef CONFIG_CPU_FREQ 164 164 struct notifier_block freq_transition; 165 - struct notifier_block freq_policy; 166 165 #endif 167 166 168 167 struct regulator *lcd_supply;
-27
drivers/video/fbdev/sa1100fb.c
··· 1005 1005 } 1006 1006 return 0; 1007 1007 } 1008 - 1009 - static int 1010 - sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val, 1011 - void *data) 1012 - { 1013 - struct sa1100fb_info *fbi = TO_INF(nb, freq_policy); 1014 - struct cpufreq_policy *policy = data; 1015 - 1016 - switch (val) { 1017 - case CPUFREQ_ADJUST: 1018 - dev_dbg(fbi->dev, "min dma period: %d ps, " 1019 - "new clock %d kHz\n", sa1100fb_min_dma_period(fbi), 1020 - policy->max); 1021 - /* todo: fill in min/max values */ 1022 - break; 1023 - case CPUFREQ_NOTIFY: 1024 - do {} while(0); 1025 - /* todo: panic if min/max values aren't fulfilled 1026 - * [can't really happen unless there's a bug in the 1027 - * CPU policy verififcation process * 1028 - */ 1029 - break; 1030 - } 1031 - return 0; 1032 - } 1033 1008 #endif 1034 1009 1035 1010 #ifdef CONFIG_PM ··· 1217 1242 1218 1243 #ifdef CONFIG_CPU_FREQ 1219 1244 fbi->freq_transition.notifier_call = sa1100fb_freq_transition; 1220 - fbi->freq_policy.notifier_call = sa1100fb_freq_policy; 1221 1245 cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); 1222 - cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER); 1223 1246 #endif 1224 1247 1225 1248 /* This driver cannot be unloaded at the moment */
-1
drivers/video/fbdev/sa1100fb.h
··· 64 64 65 65 #ifdef CONFIG_CPU_FREQ 66 66 struct notifier_block freq_transition; 67 - struct notifier_block freq_policy; 68 67 #endif 69 68 70 69 const struct sa1100fb_mach_info *inf;
+2 -2
fs/eventpoll.c
··· 1459 1459 struct wakeup_source *ws; 1460 1460 1461 1461 if (!epi->ep->ws) { 1462 - epi->ep->ws = wakeup_source_register("eventpoll"); 1462 + epi->ep->ws = wakeup_source_register(NULL, "eventpoll"); 1463 1463 if (!epi->ep->ws) 1464 1464 return -ENOMEM; 1465 1465 } 1466 1466 1467 1467 name = epi->ffd.file->f_path.dentry->d_name.name; 1468 - ws = wakeup_source_register(name); 1468 + ws = wakeup_source_register(NULL, name); 1469 1469 1470 1470 if (!ws) 1471 1471 return -ENOMEM;
+7 -1
include/acpi/acpixf.h
··· 297 297 #define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \ 298 298 ACPI_EXTERNAL_RETURN_OK(prototype) 299 299 300 + #define ACPI_HW_DEPENDENT_RETURN_UINT32(prototype) \ 301 + ACPI_EXTERNAL_RETURN_UINT32(prototype) 302 + 300 303 #define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ 301 304 ACPI_EXTERNAL_RETURN_VOID(prototype) 302 305 ··· 309 306 310 307 #define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \ 311 308 static ACPI_INLINE prototype {return(AE_OK);} 309 + 310 + #define ACPI_HW_DEPENDENT_RETURN_UINT32(prototype) \ 311 + static ACPI_INLINE prototype {return(0);} 312 312 313 313 #define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ 314 314 static ACPI_INLINE prototype {return;} ··· 744 738 u32 gpe_number, 745 739 acpi_event_status 746 740 *event_status)) 747 - ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number)) 741 + ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number)) 748 742 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void)) 749 743 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void)) 750 744 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))
+18 -8
include/acpi/processor.h
··· 4 4 5 5 #include <linux/kernel.h> 6 6 #include <linux/cpu.h> 7 + #include <linux/cpufreq.h> 8 + #include <linux/pm_qos.h> 7 9 #include <linux/thermal.h> 8 10 #include <asm/acpi.h> 9 11 ··· 232 230 struct acpi_processor_limit limit; 233 231 struct thermal_cooling_device *cdev; 234 232 struct device *dev; /* Processor device. */ 233 + struct dev_pm_qos_request perflib_req; 234 + struct dev_pm_qos_request thermal_req; 235 235 }; 236 236 237 237 struct acpi_processor_errata { ··· 300 296 /* in processor_perflib.c */ 301 297 302 298 #ifdef CONFIG_CPU_FREQ 303 - void acpi_processor_ppc_init(void); 304 - void acpi_processor_ppc_exit(void); 299 + extern bool acpi_processor_cpufreq_init; 300 + void acpi_processor_ignore_ppc_init(void); 301 + void acpi_processor_ppc_init(int cpu); 302 + void acpi_processor_ppc_exit(int cpu); 305 303 void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag); 306 304 extern int acpi_processor_get_bios_limit(int cpu, unsigned int *limit); 307 305 #else 308 - static inline void acpi_processor_ppc_init(void) 306 + static inline void acpi_processor_ignore_ppc_init(void) 309 307 { 310 308 return; 311 309 } 312 - static inline void acpi_processor_ppc_exit(void) 310 + static inline void acpi_processor_ppc_init(int cpu) 311 + { 312 + return; 313 + } 314 + static inline void acpi_processor_ppc_exit(int cpu) 313 315 { 314 316 return; 315 317 } ··· 431 421 int acpi_processor_get_limit_info(struct acpi_processor *pr); 432 422 extern const struct thermal_cooling_device_ops processor_cooling_ops; 433 423 #if defined(CONFIG_ACPI_CPU_FREQ_PSS) & defined(CONFIG_CPU_FREQ) 434 - void acpi_thermal_cpufreq_init(void); 435 - void acpi_thermal_cpufreq_exit(void); 424 + void acpi_thermal_cpufreq_init(int cpu); 425 + void acpi_thermal_cpufreq_exit(int cpu); 436 426 #else 437 - static inline void acpi_thermal_cpufreq_init(void) 427 + static inline void acpi_thermal_cpufreq_init(int cpu) 438 428 { 439 429 return; 440 430 } 441 - static inline void acpi_thermal_cpufreq_exit(void) 431 + static inline void acpi_thermal_cpufreq_exit(int cpu) 442 432 { 443 433 return; 444 434 }
+4
include/linux/acpi.h
··· 931 931 int acpi_subsys_suspend(struct device *dev); 932 932 int acpi_subsys_freeze(struct device *dev); 933 933 int acpi_subsys_poweroff(struct device *dev); 934 + void acpi_ec_mark_gpe_for_wake(void); 935 + void acpi_ec_set_gpe_wake_mask(u8 action); 934 936 #else 935 937 static inline int acpi_subsys_prepare(struct device *dev) { return 0; } 936 938 static inline void acpi_subsys_complete(struct device *dev) {} ··· 941 939 static inline int acpi_subsys_suspend(struct device *dev) { return 0; } 942 940 static inline int acpi_subsys_freeze(struct device *dev) { return 0; } 943 941 static inline int acpi_subsys_poweroff(struct device *dev) { return 0; } 942 + static inline void acpi_ec_mark_gpe_for_wake(void) {} 943 + static inline void acpi_ec_set_gpe_wake_mask(u8 action) {} 944 944 #endif 945 945 946 946 #ifdef CONFIG_ACPI
+1 -1
include/linux/cpu.h
··· 179 179 int cpu_report_state(int cpu); 180 180 int cpu_check_up_prepare(int cpu); 181 181 void cpu_set_state_online(int cpu); 182 - void play_idle(unsigned long duration_ms); 182 + void play_idle(unsigned long duration_us); 183 183 184 184 #ifdef CONFIG_HOTPLUG_CPU 185 185 bool cpu_wait_death(unsigned int cpu, int seconds);
+2 -2
include/linux/cpufreq.h
··· 456 456 #define CPUFREQ_POSTCHANGE (1) 457 457 458 458 /* Policy Notifiers */ 459 - #define CPUFREQ_ADJUST (0) 460 - #define CPUFREQ_NOTIFY (1) 459 + #define CPUFREQ_CREATE_POLICY (0) 460 + #define CPUFREQ_REMOVE_POLICY (1) 461 461 462 462 #ifdef CONFIG_CPU_FREQ 463 463 int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list);
+10
include/linux/cpuidle.h
··· 85 85 unsigned int cpu; 86 86 ktime_t next_hrtimer; 87 87 88 + int last_state_idx; 88 89 int last_residency; 90 + u64 poll_limit_ns; 89 91 struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; 90 92 struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; 91 93 struct cpuidle_driver_kobj *kobj_driver; ··· 121 119 122 120 /* the driver handles the cpus in cpumask */ 123 121 struct cpumask *cpumask; 122 + 123 + /* preferred governor to switch at register time */ 124 + const char *governor; 124 125 }; 125 126 126 127 #ifdef CONFIG_CPU_IDLE ··· 137 132 extern int cpuidle_enter(struct cpuidle_driver *drv, 138 133 struct cpuidle_device *dev, int index); 139 134 extern void cpuidle_reflect(struct cpuidle_device *dev, int index); 135 + extern u64 cpuidle_poll_time(struct cpuidle_driver *drv, 136 + struct cpuidle_device *dev); 140 137 141 138 extern int cpuidle_register_driver(struct cpuidle_driver *drv); 142 139 extern struct cpuidle_driver *cpuidle_get_driver(void); ··· 173 166 struct cpuidle_device *dev, int index) 174 167 {return -ENODEV; } 175 168 static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { } 169 + static inline u64 cpuidle_poll_time(struct cpuidle_driver *drv, 170 + struct cpuidle_device *dev) 171 + {return 0; } 176 172 static inline int cpuidle_register_driver(struct cpuidle_driver *drv) 177 173 {return -ENODEV; } 178 174 static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
+16
include/linux/cpuidle_haltpoll.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _CPUIDLE_HALTPOLL_H 3 + #define _CPUIDLE_HALTPOLL_H 4 + 5 + #ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL 6 + #include <asm/cpuidle_haltpoll.h> 7 + #else 8 + static inline void arch_haltpoll_enable(unsigned int cpu) 9 + { 10 + } 11 + 12 + static inline void arch_haltpoll_disable(unsigned int cpu) 13 + { 14 + } 15 + #endif 16 + #endif
+6
include/linux/devfreq-event.h
··· 78 78 * struct devfreq_event_desc - the descriptor of devfreq-event device 79 79 * 80 80 * @name : the name of devfreq-event device. 81 + * @event_type : the type of the event determined and used by driver 81 82 * @driver_data : the private data for devfreq-event driver. 82 83 * @ops : the operation to control devfreq-event device. 83 84 * 84 85 * Each devfreq-event device is described with a this structure. 85 86 * This structure contains the various data for devfreq-event device. 87 + * The event_type describes what is going to be counted in the register. 88 + * It might choose to count e.g. read requests, write data in bytes, etc. 89 + * The full supported list of types is present in specyfic header in: 90 + * include/dt-bindings/pmu/. 86 91 */ 87 92 struct devfreq_event_desc { 88 93 const char *name; 94 + u32 event_type; 89 95 void *driver_data; 90 96 91 97 const struct devfreq_event_ops *ops;
+4 -4
include/linux/idle_inject.h
··· 20 20 void idle_inject_stop(struct idle_inject_device *ii_dev); 21 21 22 22 void idle_inject_set_duration(struct idle_inject_device *ii_dev, 23 - unsigned int run_duration_ms, 24 - unsigned int idle_duration_ms); 23 + unsigned int run_duration_us, 24 + unsigned int idle_duration_us); 25 25 26 26 void idle_inject_get_duration(struct idle_inject_device *ii_dev, 27 - unsigned int *run_duration_ms, 28 - unsigned int *idle_duration_ms); 27 + unsigned int *run_duration_us, 28 + unsigned int *idle_duration_us); 29 29 #endif /* __IDLE_INJECT_H__ */
+1
include/linux/interrupt.h
··· 238 238 /* The following three functions are for the core kernel use only. */ 239 239 extern void suspend_device_irqs(void); 240 240 extern void resume_device_irqs(void); 241 + extern void rearm_wake_irq(unsigned int irq); 241 242 242 243 /** 243 244 * struct irq_affinity_notify - context for notification of IRQ affinity changes
-4
include/linux/pm.h
··· 712 712 extern void device_pm_lock(void); 713 713 extern void dpm_resume_start(pm_message_t state); 714 714 extern void dpm_resume_end(pm_message_t state); 715 - extern void dpm_noirq_resume_devices(pm_message_t state); 716 - extern void dpm_noirq_end(void); 717 715 extern void dpm_resume_noirq(pm_message_t state); 718 716 extern void dpm_resume_early(pm_message_t state); 719 717 extern void dpm_resume(pm_message_t state); ··· 720 722 extern void device_pm_unlock(void); 721 723 extern int dpm_suspend_end(pm_message_t state); 722 724 extern int dpm_suspend_start(pm_message_t state); 723 - extern void dpm_noirq_begin(void); 724 - extern int dpm_noirq_suspend_devices(pm_message_t state); 725 725 extern int dpm_suspend_noirq(pm_message_t state); 726 726 extern int dpm_suspend_late(pm_message_t state); 727 727 extern int dpm_suspend(pm_message_t state);
+8 -8
include/linux/pm_domain.h
··· 197 197 int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev); 198 198 int pm_genpd_remove_device(struct device *dev); 199 199 int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, 200 - struct generic_pm_domain *new_subdomain); 200 + struct generic_pm_domain *subdomain); 201 201 int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, 202 - struct generic_pm_domain *target); 202 + struct generic_pm_domain *subdomain); 203 203 int pm_genpd_init(struct generic_pm_domain *genpd, 204 204 struct dev_power_governor *gov, bool is_off); 205 205 int pm_genpd_remove(struct generic_pm_domain *genpd); ··· 226 226 return -ENOSYS; 227 227 } 228 228 static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, 229 - struct generic_pm_domain *new_sd) 229 + struct generic_pm_domain *subdomain) 230 230 { 231 231 return -ENOSYS; 232 232 } 233 233 static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, 234 - struct generic_pm_domain *target) 234 + struct generic_pm_domain *subdomain) 235 235 { 236 236 return -ENOSYS; 237 237 } ··· 282 282 struct genpd_onecell_data *data); 283 283 void of_genpd_del_provider(struct device_node *np); 284 284 int of_genpd_add_device(struct of_phandle_args *args, struct device *dev); 285 - int of_genpd_add_subdomain(struct of_phandle_args *parent, 286 - struct of_phandle_args *new_subdomain); 285 + int of_genpd_add_subdomain(struct of_phandle_args *parent_spec, 286 + struct of_phandle_args *subdomain_spec); 287 287 struct generic_pm_domain *of_genpd_remove_last(struct device_node *np); 288 288 int of_genpd_parse_idle_states(struct device_node *dn, 289 289 struct genpd_power_state **states, int *n); ··· 316 316 return -ENODEV; 317 317 } 318 318 319 - static inline int of_genpd_add_subdomain(struct of_phandle_args *parent, 320 - struct of_phandle_args *new_subdomain) 319 + static inline int of_genpd_add_subdomain(struct of_phandle_args *parent_spec, 320 + struct of_phandle_args *subdomain_spec) 321 321 { 322 322 return -ENODEV; 323 323 }
+10 -2
include/linux/pm_opp.h
··· 96 96 struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, 97 97 unsigned long freq, 98 98 bool available); 99 + struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, 100 + unsigned int level); 99 101 100 102 struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, 101 103 unsigned long *freq); ··· 130 128 void dev_pm_opp_put_clkname(struct opp_table *opp_table); 131 129 struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data)); 132 130 void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table); 133 - struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names); 131 + struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names, struct device ***virt_devs); 134 132 void dev_pm_opp_detach_genpd(struct opp_table *opp_table); 135 133 int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate); 136 134 int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq); ··· 198 196 199 197 static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, 200 198 unsigned long freq, bool available) 199 + { 200 + return ERR_PTR(-ENOTSUPP); 201 + } 202 + 203 + static inline struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, 204 + unsigned int level) 201 205 { 202 206 return ERR_PTR(-ENOTSUPP); 203 207 } ··· 300 292 301 293 static inline void dev_pm_opp_put_clkname(struct opp_table *opp_table) {} 302 294 303 - static inline struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names) 295 + static inline struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names, struct device ***virt_devs) 304 296 { 305 297 return ERR_PTR(-ENOTSUPP); 306 298 }
-6
include/linux/pm_qos.h
··· 13 13 enum { 14 14 PM_QOS_RESERVED = 0, 15 15 PM_QOS_CPU_DMA_LATENCY, 16 - PM_QOS_NETWORK_LATENCY, 17 - PM_QOS_NETWORK_THROUGHPUT, 18 - PM_QOS_MEMORY_BANDWIDTH, 19 16 20 17 /* insert new class ID */ 21 18 PM_QOS_NUM_CLASSES, ··· 30 33 #define PM_QOS_LATENCY_ANY_NS ((s64)PM_QOS_LATENCY_ANY * NSEC_PER_USEC) 31 34 32 35 #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) 33 - #define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) 34 - #define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0 35 - #define PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE 0 36 36 #define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE PM_QOS_LATENCY_ANY 37 37 #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY 38 38 #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS
+8 -13
include/linux/pm_wakeup.h
··· 21 21 * struct wakeup_source - Representation of wakeup sources 22 22 * 23 23 * @name: Name of the wakeup source 24 + * @id: Wakeup source id 24 25 * @entry: Wakeup source list entry 25 26 * @lock: Wakeup source lock 26 27 * @wakeirq: Optional device specific wakeirq ··· 36 35 * @relax_count: Number of times the wakeup source was deactivated. 37 36 * @expire_count: Number of times the wakeup source's timeout has expired. 38 37 * @wakeup_count: Number of times the wakeup source might abort suspend. 38 + * @dev: Struct device for sysfs statistics about the wakeup source. 39 39 * @active: Status of the wakeup source. 40 40 * @autosleep_enabled: Autosleep is active, so update @prevent_sleep_time. 41 41 */ 42 42 struct wakeup_source { 43 43 const char *name; 44 + int id; 44 45 struct list_head entry; 45 46 spinlock_t lock; 46 47 struct wake_irq *wakeirq; ··· 58 55 unsigned long relax_count; 59 56 unsigned long expire_count; 60 57 unsigned long wakeup_count; 58 + struct device *dev; 61 59 bool active:1; 62 60 bool autosleep_enabled:1; 63 61 }; ··· 85 81 } 86 82 87 83 /* drivers/base/power/wakeup.c */ 88 - extern void wakeup_source_prepare(struct wakeup_source *ws, const char *name); 89 84 extern struct wakeup_source *wakeup_source_create(const char *name); 90 85 extern void wakeup_source_destroy(struct wakeup_source *ws); 91 86 extern void wakeup_source_add(struct wakeup_source *ws); 92 87 extern void wakeup_source_remove(struct wakeup_source *ws); 93 - extern struct wakeup_source *wakeup_source_register(const char *name); 88 + extern struct wakeup_source *wakeup_source_register(struct device *dev, 89 + const char *name); 94 90 extern void wakeup_source_unregister(struct wakeup_source *ws); 95 91 extern int device_wakeup_enable(struct device *dev); 96 92 extern int device_wakeup_disable(struct device *dev); ··· 116 112 return dev->power.can_wakeup; 117 113 } 118 114 119 - static inline void wakeup_source_prepare(struct wakeup_source *ws, 120 - const char *name) {} 121 - 122 115 static inline struct wakeup_source *wakeup_source_create(const char *name) 123 116 { 124 117 return NULL; ··· 127 126 128 127 static inline void wakeup_source_remove(struct wakeup_source *ws) {} 129 128 130 - static inline struct wakeup_source *wakeup_source_register(const char *name) 129 + static inline struct wakeup_source *wakeup_source_register(struct device *dev, 130 + const char *name) 131 131 { 132 132 return NULL; 133 133 } ··· 182 180 bool hard) {} 183 181 184 182 #endif /* !CONFIG_PM_SLEEP */ 185 - 186 - static inline void wakeup_source_init(struct wakeup_source *ws, 187 - const char *name) 188 - { 189 - wakeup_source_prepare(ws, name); 190 - wakeup_source_add(ws); 191 - } 192 183 193 184 static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) 194 185 {
+3 -1
include/linux/suspend.h
··· 190 190 struct platform_s2idle_ops { 191 191 int (*begin)(void); 192 192 int (*prepare)(void); 193 + int (*prepare_late)(void); 193 194 void (*wake)(void); 194 - void (*sync)(void); 195 + void (*restore_early)(void); 195 196 void (*restore)(void); 196 197 void (*end)(void); 197 198 }; ··· 337 336 static inline void pm_set_resume_via_firmware(void) {} 338 337 static inline bool pm_suspend_via_firmware(void) { return false; } 339 338 static inline bool pm_resume_via_firmware(void) { return false; } 339 + static inline bool pm_suspend_no_platform(void) { return false; } 340 340 static inline bool pm_suspend_default_s2idle(void) { return false; } 341 341 342 342 static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {}
+2 -6
include/trace/events/power.h
··· 379 379 380 380 TP_printk("pm_qos_class=%s value=%d", 381 381 __print_symbolic(__entry->pm_qos_class, 382 - { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }, 383 - { PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" }, 384 - { PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }), 382 + { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }), 385 383 __entry->value) 386 384 ); 387 385 ··· 424 426 425 427 TP_printk("pm_qos_class=%s value=%d, timeout_us=%ld", 426 428 __print_symbolic(__entry->pm_qos_class, 427 - { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }, 428 - { PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" }, 429 - { PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }), 429 + { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }), 430 430 __entry->value, __entry->timeout_us) 431 431 ); 432 432
+20
kernel/irq/pm.c
··· 177 177 } 178 178 179 179 /** 180 + * rearm_wake_irq - rearm a wakeup interrupt line after signaling wakeup 181 + * @irq: Interrupt to rearm 182 + */ 183 + void rearm_wake_irq(unsigned int irq) 184 + { 185 + unsigned long flags; 186 + struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); 187 + 188 + if (!desc || !(desc->istate & IRQS_SUSPENDED) || 189 + !irqd_is_wakeup_set(&desc->irq_data)) 190 + return; 191 + 192 + desc->istate &= ~IRQS_SUSPENDED; 193 + irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED); 194 + __enable_irq(desc); 195 + 196 + irq_put_desc_busunlock(desc, flags); 197 + } 198 + 199 + /** 180 200 * irq_pm_syscore_ops - enable interrupt lines early 181 201 * 182 202 * Enable all interrupt lines with %IRQF_EARLY_RESUME set.
+1 -1
kernel/power/autosleep.c
··· 116 116 117 117 int __init pm_autosleep_init(void) 118 118 { 119 - autosleep_ws = wakeup_source_register("autosleep"); 119 + autosleep_ws = wakeup_source_register(NULL, "autosleep"); 120 120 if (!autosleep_ws) 121 121 return -ENOMEM; 122 122
+96 -3
kernel/power/main.c
··· 254 254 power_attr(pm_test); 255 255 #endif /* CONFIG_PM_SLEEP_DEBUG */ 256 256 257 - #ifdef CONFIG_DEBUG_FS 258 257 static char *suspend_step_name(enum suspend_stat_step step) 259 258 { 260 259 switch (step) { ··· 274 275 } 275 276 } 276 277 278 + #define suspend_attr(_name) \ 279 + static ssize_t _name##_show(struct kobject *kobj, \ 280 + struct kobj_attribute *attr, char *buf) \ 281 + { \ 282 + return sprintf(buf, "%d\n", suspend_stats._name); \ 283 + } \ 284 + static struct kobj_attribute _name = __ATTR_RO(_name) 285 + 286 + suspend_attr(success); 287 + suspend_attr(fail); 288 + suspend_attr(failed_freeze); 289 + suspend_attr(failed_prepare); 290 + suspend_attr(failed_suspend); 291 + suspend_attr(failed_suspend_late); 292 + suspend_attr(failed_suspend_noirq); 293 + suspend_attr(failed_resume); 294 + suspend_attr(failed_resume_early); 295 + suspend_attr(failed_resume_noirq); 296 + 297 + static ssize_t last_failed_dev_show(struct kobject *kobj, 298 + struct kobj_attribute *attr, char *buf) 299 + { 300 + int index; 301 + char *last_failed_dev = NULL; 302 + 303 + index = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1; 304 + index %= REC_FAILED_NUM; 305 + last_failed_dev = suspend_stats.failed_devs[index]; 306 + 307 + return sprintf(buf, "%s\n", last_failed_dev); 308 + } 309 + static struct kobj_attribute last_failed_dev = __ATTR_RO(last_failed_dev); 310 + 311 + static ssize_t last_failed_errno_show(struct kobject *kobj, 312 + struct kobj_attribute *attr, char *buf) 313 + { 314 + int index; 315 + int last_failed_errno; 316 + 317 + index = suspend_stats.last_failed_errno + REC_FAILED_NUM - 1; 318 + index %= REC_FAILED_NUM; 319 + last_failed_errno = suspend_stats.errno[index]; 320 + 321 + return sprintf(buf, "%d\n", last_failed_errno); 322 + } 323 + static struct kobj_attribute last_failed_errno = __ATTR_RO(last_failed_errno); 324 + 325 + static ssize_t last_failed_step_show(struct kobject *kobj, 326 + struct kobj_attribute *attr, char *buf) 327 + { 328 + int index; 329 + enum suspend_stat_step step; 330 + char *last_failed_step = NULL; 331 + 332 + index = suspend_stats.last_failed_step + REC_FAILED_NUM - 1; 333 + index %= REC_FAILED_NUM; 334 + step = suspend_stats.failed_steps[index]; 335 + last_failed_step = suspend_step_name(step); 336 + 337 + return sprintf(buf, "%s\n", last_failed_step); 338 + } 339 + static struct kobj_attribute last_failed_step = __ATTR_RO(last_failed_step); 340 + 341 + static struct attribute *suspend_attrs[] = { 342 + &success.attr, 343 + &fail.attr, 344 + &failed_freeze.attr, 345 + &failed_prepare.attr, 346 + &failed_suspend.attr, 347 + &failed_suspend_late.attr, 348 + &failed_suspend_noirq.attr, 349 + &failed_resume.attr, 350 + &failed_resume_early.attr, 351 + &failed_resume_noirq.attr, 352 + &last_failed_dev.attr, 353 + &last_failed_errno.attr, 354 + &last_failed_step.attr, 355 + NULL, 356 + }; 357 + 358 + static struct attribute_group suspend_attr_group = { 359 + .name = "suspend_stats", 360 + .attrs = suspend_attrs, 361 + }; 362 + 363 + #ifdef CONFIG_DEBUG_FS 277 364 static int suspend_stats_show(struct seq_file *s, void *unused) 278 365 { 279 366 int i, index, last_dev, last_errno, last_step; ··· 580 495 len = p ? p - buf : n; 581 496 582 497 /* Check hibernation first. */ 583 - if (len == 4 && !strncmp(buf, "disk", len)) 498 + if (len == 4 && str_has_prefix(buf, "disk")) 584 499 return PM_SUSPEND_MAX; 585 500 586 501 #ifdef CONFIG_SUSPEND ··· 879 794 .attrs = g, 880 795 }; 881 796 797 + static const struct attribute_group *attr_groups[] = { 798 + &attr_group, 799 + #ifdef CONFIG_PM_SLEEP 800 + &suspend_attr_group, 801 + #endif 802 + NULL, 803 + }; 804 + 882 805 struct workqueue_struct *pm_wq; 883 806 EXPORT_SYMBOL_GPL(pm_wq); 884 807 ··· 908 815 power_kobj = kobject_create_and_add("power", NULL); 909 816 if (!power_kobj) 910 817 return -ENOMEM; 911 - error = sysfs_create_group(power_kobj, &attr_group); 818 + error = sysfs_create_groups(power_kobj, attr_groups); 912 819 if (error) 913 820 return error; 914 821 pm_print_times_init();
-48
kernel/power/qos.c
··· 78 78 .name = "cpu_dma_latency", 79 79 }; 80 80 81 - static BLOCKING_NOTIFIER_HEAD(network_lat_notifier); 82 - static struct pm_qos_constraints network_lat_constraints = { 83 - .list = PLIST_HEAD_INIT(network_lat_constraints.list), 84 - .target_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE, 85 - .default_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE, 86 - .no_constraint_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE, 87 - .type = PM_QOS_MIN, 88 - .notifiers = &network_lat_notifier, 89 - }; 90 - static struct pm_qos_object network_lat_pm_qos = { 91 - .constraints = &network_lat_constraints, 92 - .name = "network_latency", 93 - }; 94 - 95 - 96 - static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier); 97 - static struct pm_qos_constraints network_tput_constraints = { 98 - .list = PLIST_HEAD_INIT(network_tput_constraints.list), 99 - .target_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE, 100 - .default_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE, 101 - .no_constraint_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE, 102 - .type = PM_QOS_MAX, 103 - .notifiers = &network_throughput_notifier, 104 - }; 105 - static struct pm_qos_object network_throughput_pm_qos = { 106 - .constraints = &network_tput_constraints, 107 - .name = "network_throughput", 108 - }; 109 - 110 - 111 - static BLOCKING_NOTIFIER_HEAD(memory_bandwidth_notifier); 112 - static struct pm_qos_constraints memory_bw_constraints = { 113 - .list = PLIST_HEAD_INIT(memory_bw_constraints.list), 114 - .target_value = PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE, 115 - .default_value = PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE, 116 - .no_constraint_value = PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE, 117 - .type = PM_QOS_SUM, 118 - .notifiers = &memory_bandwidth_notifier, 119 - }; 120 - static struct pm_qos_object memory_bandwidth_pm_qos = { 121 - .constraints = &memory_bw_constraints, 122 - .name = "memory_bandwidth", 123 - }; 124 - 125 - 126 81 static struct pm_qos_object *pm_qos_array[] = { 127 82 &null_pm_qos, 128 83 &cpu_dma_pm_qos, 129 - &network_lat_pm_qos, 130 - &network_throughput_pm_qos, 131 - &memory_bandwidth_pm_qos, 132 84 }; 133 85 134 86 static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
+27 -38
kernel/power/suspend.c
··· 121 121 { 122 122 pm_pr_dbg("suspend-to-idle\n"); 123 123 124 + /* 125 + * Suspend-to-idle equals: 126 + * frozen processes + suspended devices + idle processors. 127 + * Thus s2idle_enter() should be called right after all devices have 128 + * been suspended. 129 + * 130 + * Wakeups during the noirq suspend of devices may be spurious, so try 131 + * to avoid them upfront. 132 + */ 124 133 for (;;) { 125 - int error; 126 - 127 - dpm_noirq_begin(); 128 - 129 - /* 130 - * Suspend-to-idle equals 131 - * frozen processes + suspended devices + idle processors. 132 - * Thus s2idle_enter() should be called right after 133 - * all devices have been suspended. 134 - * 135 - * Wakeups during the noirq suspend of devices may be spurious, 136 - * so prevent them from terminating the loop right away. 137 - */ 138 - error = dpm_noirq_suspend_devices(PMSG_SUSPEND); 139 - if (!error) 140 - s2idle_enter(); 141 - else if (error == -EBUSY && pm_wakeup_pending()) 142 - error = 0; 143 - 144 - if (!error && s2idle_ops && s2idle_ops->wake) 134 + if (s2idle_ops && s2idle_ops->wake) 145 135 s2idle_ops->wake(); 146 - 147 - dpm_noirq_resume_devices(PMSG_RESUME); 148 - 149 - dpm_noirq_end(); 150 - 151 - if (error) 152 - break; 153 - 154 - if (s2idle_ops && s2idle_ops->sync) 155 - s2idle_ops->sync(); 156 136 157 137 if (pm_wakeup_pending()) 158 138 break; 159 139 160 140 pm_wakeup_clear(false); 141 + 142 + s2idle_enter(); 161 143 } 162 144 163 145 pm_pr_dbg("resume from suspend-to-idle\n"); ··· 253 271 254 272 static int platform_suspend_prepare_noirq(suspend_state_t state) 255 273 { 256 - return state != PM_SUSPEND_TO_IDLE && suspend_ops->prepare_late ? 257 - suspend_ops->prepare_late() : 0; 274 + if (state == PM_SUSPEND_TO_IDLE) 275 + return s2idle_ops && s2idle_ops->prepare_late ? 276 + s2idle_ops->prepare_late() : 0; 277 + 278 + return suspend_ops->prepare_late ? suspend_ops->prepare_late() : 0; 258 279 } 259 280 260 281 static void platform_resume_noirq(suspend_state_t state) 261 282 { 262 - if (state != PM_SUSPEND_TO_IDLE && suspend_ops->wake) 283 + if (state == PM_SUSPEND_TO_IDLE) { 284 + if (s2idle_ops && s2idle_ops->restore_early) 285 + s2idle_ops->restore_early(); 286 + } else if (suspend_ops->wake) { 263 287 suspend_ops->wake(); 288 + } 264 289 } 265 290 266 291 static void platform_resume_early(suspend_state_t state) ··· 404 415 if (error) 405 416 goto Devices_early_resume; 406 417 407 - if (state == PM_SUSPEND_TO_IDLE && pm_test_level != TEST_PLATFORM) { 408 - s2idle_loop(); 409 - goto Platform_early_resume; 410 - } 411 - 412 418 error = dpm_suspend_noirq(PMSG_SUSPEND); 413 419 if (error) { 414 420 pr_err("noirq suspend of devices failed\n"); ··· 415 431 416 432 if (suspend_test(TEST_PLATFORM)) 417 433 goto Platform_wake; 434 + 435 + if (state == PM_SUSPEND_TO_IDLE) { 436 + s2idle_loop(); 437 + goto Platform_wake; 438 + } 418 439 419 440 error = suspend_disable_secondary_cpus(); 420 441 if (error || suspend_test(TEST_CPUS))
+19 -13
kernel/power/wakelock.c
··· 27 27 struct wakelock { 28 28 char *name; 29 29 struct rb_node node; 30 - struct wakeup_source ws; 30 + struct wakeup_source *ws; 31 31 #ifdef CONFIG_PM_WAKELOCKS_GC 32 32 struct list_head lru; 33 33 #endif ··· 46 46 47 47 for (node = rb_first(&wakelocks_tree); node; node = rb_next(node)) { 48 48 wl = rb_entry(node, struct wakelock, node); 49 - if (wl->ws.active == show_active) 49 + if (wl->ws->active == show_active) 50 50 str += scnprintf(str, end - str, "%s ", wl->name); 51 51 } 52 52 if (str > buf) ··· 112 112 u64 idle_time_ns; 113 113 bool active; 114 114 115 - spin_lock_irq(&wl->ws.lock); 116 - idle_time_ns = ktime_to_ns(ktime_sub(now, wl->ws.last_time)); 117 - active = wl->ws.active; 118 - spin_unlock_irq(&wl->ws.lock); 115 + spin_lock_irq(&wl->ws->lock); 116 + idle_time_ns = ktime_to_ns(ktime_sub(now, wl->ws->last_time)); 117 + active = wl->ws->active; 118 + spin_unlock_irq(&wl->ws->lock); 119 119 120 120 if (idle_time_ns < ((u64)WL_GC_TIME_SEC * NSEC_PER_SEC)) 121 121 break; 122 122 123 123 if (!active) { 124 - wakeup_source_remove(&wl->ws); 124 + wakeup_source_unregister(wl->ws); 125 125 rb_erase(&wl->node, &wakelocks_tree); 126 126 list_del(&wl->lru); 127 127 kfree(wl->name); ··· 187 187 kfree(wl); 188 188 return ERR_PTR(-ENOMEM); 189 189 } 190 - wl->ws.name = wl->name; 191 - wl->ws.last_time = ktime_get(); 192 - wakeup_source_add(&wl->ws); 190 + 191 + wl->ws = wakeup_source_register(NULL, wl->name); 192 + if (!wl->ws) { 193 + kfree(wl->name); 194 + kfree(wl); 195 + return ERR_PTR(-ENOMEM); 196 + } 197 + wl->ws->last_time = ktime_get(); 198 + 193 199 rb_link_node(&wl->node, parent, node); 194 200 rb_insert_color(&wl->node, &wakelocks_tree); 195 201 wakelocks_lru_add(wl); ··· 239 233 u64 timeout_ms = timeout_ns + NSEC_PER_MSEC - 1; 240 234 241 235 do_div(timeout_ms, NSEC_PER_MSEC); 242 - __pm_wakeup_event(&wl->ws, timeout_ms); 236 + __pm_wakeup_event(wl->ws, timeout_ms); 243 237 } else { 244 - __pm_stay_awake(&wl->ws); 238 + __pm_stay_awake(wl->ws); 245 239 } 246 240 247 241 wakelocks_lru_most_recent(wl); ··· 277 271 ret = PTR_ERR(wl); 278 272 goto out; 279 273 } 280 - __pm_relax(&wl->ws); 274 + __pm_relax(wl->ws); 281 275 282 276 wakelocks_lru_most_recent(wl); 283 277 wakelocks_gc();
+6 -1
kernel/sched/cpufreq_schedutil.c
··· 117 117 unsigned int next_freq) 118 118 { 119 119 struct cpufreq_policy *policy = sg_policy->policy; 120 + int cpu; 120 121 121 122 if (!sugov_update_next_freq(sg_policy, time, next_freq)) 122 123 return; ··· 127 126 return; 128 127 129 128 policy->cur = next_freq; 130 - trace_cpu_frequency(next_freq, smp_processor_id()); 129 + 130 + if (trace_cpu_frequency_enabled()) { 131 + for_each_cpu(cpu, policy->cpus) 132 + trace_cpu_frequency(next_freq, cpu); 133 + } 131 134 } 132 135 133 136 static void sugov_deferred_update(struct sugov_policy *sg_policy, u64 time,
+4 -3
kernel/sched/idle.c
··· 312 312 return HRTIMER_NORESTART; 313 313 } 314 314 315 - void play_idle(unsigned long duration_ms) 315 + void play_idle(unsigned long duration_us) 316 316 { 317 317 struct idle_timer it; 318 318 ··· 324 324 WARN_ON_ONCE(current->nr_cpus_allowed != 1); 325 325 WARN_ON_ONCE(!(current->flags & PF_KTHREAD)); 326 326 WARN_ON_ONCE(!(current->flags & PF_NO_SETAFFINITY)); 327 - WARN_ON_ONCE(!duration_ms); 327 + WARN_ON_ONCE(!duration_us); 328 328 329 329 rcu_sleep_check(); 330 330 preempt_disable(); ··· 334 334 it.done = 0; 335 335 hrtimer_init_on_stack(&it.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 336 336 it.timer.function = idle_inject_timer_fn; 337 - hrtimer_start(&it.timer, ms_to_ktime(duration_ms), HRTIMER_MODE_REL_PINNED); 337 + hrtimer_start(&it.timer, ns_to_ktime(duration_us * NSEC_PER_USEC), 338 + HRTIMER_MODE_REL_PINNED); 338 339 339 340 while (!READ_ONCE(it.done)) 340 341 do_idle();
+1 -1
kernel/time/alarmtimer.c
··· 97 97 if (!device_may_wakeup(rtc->dev.parent)) 98 98 return -1; 99 99 100 - __ws = wakeup_source_register("alarmtimer"); 100 + __ws = wakeup_source_register(dev, "alarmtimer"); 101 101 102 102 spin_lock_irqsave(&rtcdev_lock, flags); 103 103 if (!rtcdev) {
+8 -6
tools/power/cpupower/Makefile
··· 18 18 $(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist)) 19 19 endif 20 20 21 - include ../../scripts/Makefile.arch 22 21 23 22 # --- CONFIGURATION BEGIN --- 24 23 ··· 68 69 sbindir ?= /usr/sbin 69 70 mandir ?= /usr/man 70 71 includedir ?= /usr/include 71 - ifeq ($(IS_64_BIT), 1) 72 - libdir ?= /usr/lib64 73 - else 74 - libdir ?= /usr/lib 75 - endif 76 72 localedir ?= /usr/share/locale 77 73 docdir ?= /usr/share/doc/packages/cpupower 78 74 confdir ?= /etc/ ··· 94 100 HOSTCC = gcc 95 101 MKDIR = mkdir 96 102 103 + # 64bit library detection 104 + include ../../scripts/Makefile.arch 105 + 106 + ifeq ($(IS_64_BIT), 1) 107 + libdir ?= /usr/lib64 108 + else 109 + libdir ?= /usr/lib 110 + endif 97 111 98 112 # Now we set up the build system 99 113 #
tools/power/cpupower/bench/cpufreq-bench_plot.sh
tools/power/cpupower/bench/cpufreq-bench_script.sh
+180 -164
tools/power/cpupower/po/de.po
··· 8 8 "Project-Id-Version: cpufrequtils 006\n" 9 9 "Report-Msgid-Bugs-To: \n" 10 10 "POT-Creation-Date: 2011-03-08 17:03+0100\n" 11 - "PO-Revision-Date: 2009-08-08 17:18+0100\n" 12 - "Last-Translator: <linux@dominikbrodowski.net>\n" 11 + "PO-Revision-Date: 2019-06-02 15:23+0200\n" 12 + "Last-Translator: Benjamin Weis <benjamin.weis@gmx.com>\n" 13 13 "Language-Team: NONE\n" 14 14 "Language: \n" 15 15 "MIME-Version: 1.0\n" 16 - "Content-Type: text/plain; charset=ISO-8859-1\n" 16 + "Content-Type: text/plain; charset=UTF-8\n" 17 17 "Content-Transfer-Encoding: 8bit\n" 18 18 "Plural-Forms: nplurals=2; plural=(n != 1);\n" 19 19 20 20 #: utils/idle_monitor/nhm_idle.c:36 21 21 msgid "Processor Core C3" 22 - msgstr "" 22 + msgstr "Prozessorkern C3" 23 23 24 24 #: utils/idle_monitor/nhm_idle.c:43 25 25 msgid "Processor Core C6" 26 - msgstr "" 26 + msgstr "Prozessorkern C6" 27 27 28 28 #: utils/idle_monitor/nhm_idle.c:51 29 29 msgid "Processor Package C3" 30 - msgstr "" 30 + msgstr "Prozessorpaket C3" 31 31 32 32 #: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70 33 33 msgid "Processor Package C6" 34 - msgstr "" 34 + msgstr "Prozessorpaket C6" 35 35 36 36 #: utils/idle_monitor/snb_idle.c:33 37 37 msgid "Processor Core C7" 38 - msgstr "" 38 + msgstr "Prozessorkern C7" 39 39 40 40 #: utils/idle_monitor/snb_idle.c:40 41 41 msgid "Processor Package C2" 42 - msgstr "" 42 + msgstr "Prozessorpaket C2" 43 43 44 44 #: utils/idle_monitor/snb_idle.c:47 45 45 msgid "Processor Package C7" 46 - msgstr "" 46 + msgstr "Prozessorpaket C7" 47 47 48 48 #: utils/idle_monitor/amd_fam14h_idle.c:56 49 49 msgid "Package in sleep state (PC1 or deeper)" 50 - msgstr "" 50 + msgstr "Paket in Schlafzustand (PC1 oder tiefer)" 51 51 52 52 #: utils/idle_monitor/amd_fam14h_idle.c:63 53 53 msgid "Processor Package C1" 54 - msgstr "" 54 + msgstr "Prozessorpaket C1" 55 55 56 56 #: utils/idle_monitor/amd_fam14h_idle.c:77 57 57 msgid "North Bridge P1 boolean counter (returns 0 or 1)" 58 - msgstr "" 58 + msgstr "North Bridge P1 boolescher Zähler (gibt 0 oder 1 zurück)" 59 59 60 60 #: utils/idle_monitor/mperf_monitor.c:35 61 61 msgid "Processor Core not idle" 62 - msgstr "" 62 + msgstr "Prozessorkern ist nicht im Leerlauf" 63 63 64 64 #: utils/idle_monitor/mperf_monitor.c:42 65 65 msgid "Processor Core in an idle state" 66 - msgstr "" 66 + msgstr "Prozessorkern ist in einem Ruhezustand" 67 67 68 68 #: utils/idle_monitor/mperf_monitor.c:50 69 69 msgid "Average Frequency (including boost) in MHz" 70 - msgstr "" 70 + msgstr "Durchschnittliche Frequenz (einschließlich Boost) in MHz" 71 71 72 72 #: utils/idle_monitor/cpupower-monitor.c:66 73 73 #, c-format ··· 75 75 "cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " 76 76 "interval_sec | -c command ...]\n" 77 77 msgstr "" 78 + "cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " 79 + "interval_sec | -c Befehl ...]\n" 78 80 79 81 #: utils/idle_monitor/cpupower-monitor.c:69 80 82 #, c-format ··· 84 82 "cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " 85 83 "interval_sec | -c command ...]\n" 86 84 msgstr "" 85 + "cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " 86 + "interval_sec | -c Befehl ...]\n" 87 87 88 88 #: utils/idle_monitor/cpupower-monitor.c:71 89 89 #, c-format 90 90 msgid "\t -v: be more verbose\n" 91 - msgstr "" 91 + msgstr "\t -v: ausführlicher\n" 92 92 93 93 #: utils/idle_monitor/cpupower-monitor.c:73 94 94 #, c-format 95 95 msgid "\t -h: print this help\n" 96 - msgstr "" 96 + msgstr "\t -h: diese Hilfe ausgeben\n" 97 97 98 98 #: utils/idle_monitor/cpupower-monitor.c:74 99 99 #, c-format 100 100 msgid "\t -i: time interval to measure for in seconds (default 1)\n" 101 - msgstr "" 101 + msgstr "\t -i: Zeitintervall für die Messung in Sekunden (Standard 1)\n" 102 102 103 103 #: utils/idle_monitor/cpupower-monitor.c:75 104 104 #, c-format 105 105 msgid "\t -t: show CPU topology/hierarchy\n" 106 - msgstr "" 106 + msgstr "\t -t: CPU-Topologie/Hierarchie anzeigen\n" 107 107 108 108 #: utils/idle_monitor/cpupower-monitor.c:76 109 109 #, c-format 110 110 msgid "\t -l: list available CPU sleep monitors (for use with -m)\n" 111 111 msgstr "" 112 + "\t -l: verfügbare CPU-Schlafwächter auflisten (für Verwendung mit -m)\n" 112 113 113 114 #: utils/idle_monitor/cpupower-monitor.c:77 114 115 #, c-format 115 116 msgid "\t -m: show specific CPU sleep monitors only (in same order)\n" 116 117 msgstr "" 118 + "\t -m: spezifische CPU-Schlafwächter anzeigen (in gleicher Reihenfolge)\n" 117 119 118 120 #: utils/idle_monitor/cpupower-monitor.c:79 119 121 #, c-format ··· 125 119 "only one of: -t, -l, -m are allowed\n" 126 120 "If none of them is passed," 127 121 msgstr "" 122 + "nur einer von: -t, -l, -m ist erlaubt\n" 123 + "Wenn keiner von ihnen übergeben wird," 128 124 129 125 #: utils/idle_monitor/cpupower-monitor.c:80 130 126 #, c-format 131 127 msgid " all supported monitors are shown\n" 132 - msgstr "" 128 + msgstr " werden alle unterstützten Wächter angezeigt\n" 133 129 134 130 #: utils/idle_monitor/cpupower-monitor.c:197 135 131 #, c-format 136 132 msgid "Monitor %s, Counter %s has no count function. Implementation error\n" 137 - msgstr "" 133 + msgstr "Wächter %s, Zähler %s hat keine Zählfunktion. Implementierungsfehler\n" 138 134 139 135 #: utils/idle_monitor/cpupower-monitor.c:207 140 136 #, c-format 141 137 msgid " *is offline\n" 142 - msgstr "" 138 + msgstr " *ist offline\n" 143 139 144 140 #: utils/idle_monitor/cpupower-monitor.c:236 145 141 #, c-format 146 142 msgid "%s: max monitor name length (%d) exceeded\n" 147 - msgstr "" 143 + msgstr "%s: max. Wächternamenslänge (%d) überschritten\n" 148 144 149 145 #: utils/idle_monitor/cpupower-monitor.c:250 150 146 #, c-format 151 147 msgid "No matching monitor found in %s, try -l option\n" 152 - msgstr "" 148 + msgstr "Kein passender Wächter in %s gefunden, versuchen Sie die Option -l\n" 153 149 154 150 #: utils/idle_monitor/cpupower-monitor.c:266 155 151 #, c-format 156 152 msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n" 157 - msgstr "" 153 + msgstr "Wächter \"%s\" (%d Zustände) - Könnte nach %u s überlaufen\n" 158 154 159 155 #: utils/idle_monitor/cpupower-monitor.c:319 160 156 #, c-format 161 157 msgid "%s took %.5f seconds and exited with status %d\n" 162 - msgstr "" 158 + msgstr "%s hat %.5f Sekunden gedauert und hat sich mit Status %d beendet\n" 163 159 164 160 #: utils/idle_monitor/cpupower-monitor.c:406 165 161 #, c-format 166 162 msgid "Cannot read number of available processors\n" 167 - msgstr "" 163 + msgstr "Anzahl der verfügbaren Prozessoren kann nicht gelesen werden\n" 168 164 169 165 #: utils/idle_monitor/cpupower-monitor.c:417 170 166 #, c-format 171 167 msgid "Available monitor %s needs root access\n" 172 - msgstr "" 168 + msgstr "Verfügbarer Wächter %s benötigt root-Zugriff\n" 173 169 174 170 #: utils/idle_monitor/cpupower-monitor.c:428 175 171 #, c-format 176 172 msgid "No HW Cstate monitors found\n" 177 - msgstr "" 173 + msgstr "Keine HW C-Zustandswächter gefunden\n" 178 174 179 175 #: utils/cpupower.c:78 180 176 #, c-format 181 177 msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n" 182 - msgstr "" 178 + msgstr "cpupower [ -c cpulist ] Unterbefehl [ARGS]\n" 183 179 184 180 #: utils/cpupower.c:79 185 181 #, c-format 186 182 msgid "cpupower --version\n" 187 - msgstr "" 183 + msgstr "cpupower --version\n" 188 184 189 185 #: utils/cpupower.c:80 190 186 #, c-format 191 187 msgid "Supported subcommands are:\n" 192 - msgstr "" 188 + msgstr "Unterstützte Unterbefehle sind:\n" 193 189 194 190 #: utils/cpupower.c:83 195 191 #, c-format ··· 199 191 "\n" 200 192 "Some subcommands can make use of the -c cpulist option.\n" 201 193 msgstr "" 194 + "\n" 195 + "Einige Unterbefehle können die Option -c cpulist verwenden.\n" 202 196 203 197 #: utils/cpupower.c:84 204 198 #, c-format 205 199 msgid "Look at the general cpupower manpage how to use it\n" 206 200 msgstr "" 201 + "Schauen Sie sich die allgemeine cpupower manpage an, um zu erfahren, wie man " 202 + "es benutzt\n" 207 203 208 204 #: utils/cpupower.c:85 209 205 #, c-format ··· 229 217 #: utils/cpupower.c:114 230 218 #, c-format 231 219 msgid "Error parsing cpu list\n" 232 - msgstr "" 220 + msgstr "Fehler beim Parsen der CPU-Liste\n" 233 221 234 222 #: utils/cpupower.c:172 235 223 #, c-format 236 224 msgid "Subcommand %s needs root privileges\n" 237 - msgstr "" 225 + msgstr "Unterbefehl %s benötigt root-Rechte\n" 238 226 239 227 #: utils/cpufreq-info.c:31 240 228 #, c-format 241 229 msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n" 242 230 msgstr "" 243 - "Konnte nicht die Anzahl der CPUs herausfinden (%s : %s), nehme daher 1 an.\n" 231 + "Anzahl der CPUs konnte nicht herausgefinden werden (%s: %s), es wird daher 1 " 232 + "angenommen\n" 244 233 245 234 #: utils/cpufreq-info.c:63 246 235 #, c-format 247 236 msgid "" 248 237 " minimum CPU frequency - maximum CPU frequency - governor\n" 249 - msgstr "" 250 - " minimale CPU-Taktfreq. - maximale CPU-Taktfreq. - Regler \n" 238 + msgstr " minimale CPU-Frequenz - maximale CPU-Frequenz - Regler\n" 251 239 252 240 #: utils/cpufreq-info.c:151 253 241 #, c-format 254 242 msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n" 255 243 msgstr "" 244 + "Fehler beim Evaluieren der Boost-Fähigkeiten bei CPU %d -- sind Sie root?\n" 256 245 257 246 #. P state changes via MSR are identified via cpuid 80000007 258 247 #. on Intel and AMD, but we assume boost capable machines can do that ··· 263 250 #: utils/cpufreq-info.c:161 264 251 #, c-format 265 252 msgid " boost state support: \n" 266 - msgstr "" 253 + msgstr " Boost-Zustand-Unterstützung: \n" 267 254 268 255 #: utils/cpufreq-info.c:163 269 256 #, c-format 270 257 msgid " Supported: %s\n" 271 - msgstr "" 258 + msgstr " Unterstützt: %s\n" 272 259 273 260 #: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 274 261 msgid "yes" 275 - msgstr "" 262 + msgstr "ja" 276 263 277 264 #: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 278 265 msgid "no" 279 - msgstr "" 266 + msgstr "nein" 280 267 281 268 #: utils/cpufreq-info.c:164 282 - #, fuzzy, c-format 269 + #, c-format 283 270 msgid " Active: %s\n" 284 - msgstr " Treiber: %s\n" 271 + msgstr " Aktiv: %s\n" 285 272 286 273 #: utils/cpufreq-info.c:177 287 274 #, c-format 288 275 msgid " Boost States: %d\n" 289 - msgstr "" 276 + msgstr " Boost-Zustände: %d\n" 290 277 291 278 #: utils/cpufreq-info.c:178 292 279 #, c-format 293 280 msgid " Total States: %d\n" 294 - msgstr "" 281 + msgstr " Gesamtzustände: %d\n" 295 282 296 283 #: utils/cpufreq-info.c:181 297 284 #, c-format 298 285 msgid " Pstate-Pb%d: %luMHz (boost state)\n" 299 - msgstr "" 286 + msgstr " Pstate-Pb%d: %luMHz (Boost-Zustand)\n" 300 287 301 288 #: utils/cpufreq-info.c:184 302 289 #, c-format 303 290 msgid " Pstate-P%d: %luMHz\n" 304 - msgstr "" 291 + msgstr " Pstate-P%d: %luMHz\n" 305 292 306 293 #: utils/cpufreq-info.c:211 307 294 #, c-format 308 295 msgid " no or unknown cpufreq driver is active on this CPU\n" 309 - msgstr " kein oder nicht bestimmbarer cpufreq-Treiber aktiv\n" 296 + msgstr " kein oder ein unbekannter cpufreq-Treiber ist auf dieser CPU aktiv\n" 310 297 311 298 #: utils/cpufreq-info.c:213 312 299 #, c-format ··· 316 303 #: utils/cpufreq-info.c:219 317 304 #, c-format 318 305 msgid " CPUs which run at the same hardware frequency: " 319 - msgstr " Folgende CPUs laufen mit der gleichen Hardware-Taktfrequenz: " 306 + msgstr " CPUs, die mit der gleichen Hardwarefrequenz laufen: " 320 307 321 308 #: utils/cpufreq-info.c:230 322 309 #, c-format 323 310 msgid " CPUs which need to have their frequency coordinated by software: " 324 - msgstr " Die Taktfrequenz folgender CPUs werden per Software koordiniert: " 311 + msgstr " CPUs, die ihre Frequenz mit Software koordinieren müssen: " 325 312 326 313 #: utils/cpufreq-info.c:241 327 314 #, c-format ··· 331 318 #: utils/cpufreq-info.c:247 332 319 #, c-format 333 320 msgid " hardware limits: " 334 - msgstr " Hardwarebedingte Grenzen der Taktfrequenz: " 321 + msgstr " Hardwarebegrenzungen: " 335 322 336 323 #: utils/cpufreq-info.c:256 337 324 #, c-format 338 325 msgid " available frequency steps: " 339 - msgstr " mögliche Taktfrequenzen: " 326 + msgstr " verfügbare Frequenzschritte: " 340 327 341 328 #: utils/cpufreq-info.c:269 342 329 #, c-format 343 330 msgid " available cpufreq governors: " 344 - msgstr " mögliche Regler: " 331 + msgstr " verfügbare cpufreq-Regler: " 345 332 346 333 #: utils/cpufreq-info.c:280 347 334 #, c-format 348 335 msgid " current policy: frequency should be within " 349 - msgstr " momentane Taktik: die Frequenz soll innerhalb " 336 + msgstr " momentane Richtlinie: Frequenz sollte innerhalb " 350 337 351 338 #: utils/cpufreq-info.c:282 352 339 #, c-format ··· 359 346 "The governor \"%s\" may decide which speed to use\n" 360 347 " within this range.\n" 361 348 msgstr "" 362 - " liegen. Der Regler \"%s\" kann frei entscheiden,\n" 363 - " welche Taktfrequenz innerhalb dieser Grenze verwendet " 364 - "wird.\n" 349 + " sein. Der Regler \"%s\" kann frei entscheiden,\n" 350 + " welche Geschwindigkeit er in diesem Bereich verwendet.\n" 365 351 366 352 #: utils/cpufreq-info.c:293 367 353 #, c-format 368 354 msgid " current CPU frequency is " 369 - msgstr " momentane Taktfrequenz ist " 355 + msgstr " momentane CPU-Frequenz ist " 370 356 371 357 #: utils/cpufreq-info.c:296 372 358 #, c-format 373 359 msgid " (asserted by call to hardware)" 374 - msgstr " (verifiziert durch Nachfrage bei der Hardware)" 360 + msgstr " (durch Aufruf der Hardware sichergestellt)" 375 361 376 362 #: utils/cpufreq-info.c:304 377 363 #, c-format 378 364 msgid " cpufreq stats: " 379 - msgstr " Statistik:" 365 + msgstr " cpufreq-Statistiken: " 380 366 381 367 #: utils/cpufreq-info.c:472 382 - #, fuzzy, c-format 368 + #, c-format 383 369 msgid "Usage: cpupower freqinfo [options]\n" 384 - msgstr "Aufruf: cpufreq-info [Optionen]\n" 370 + msgstr "Aufruf: cpupower freqinfo [Optionen]\n" 385 371 386 372 #: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23 387 373 #: utils/cpupower-info.c:22 utils/cpuidle-info.c:148 ··· 389 377 msgstr "Optionen:\n" 390 378 391 379 #: utils/cpufreq-info.c:474 392 - #, fuzzy, c-format 380 + #, c-format 393 381 msgid " -e, --debug Prints out debug information [default]\n" 394 - msgstr "" 395 - " -e, --debug Erzeugt detaillierte Informationen, hilfreich\n" 396 - " zum Aufspüren von Fehlern\n" 382 + msgstr " -e, --debug Gibt Debug-Informationen aus [Standard]\n" 397 383 398 384 #: utils/cpufreq-info.c:475 399 385 #, c-format ··· 434 424 #: utils/cpufreq-info.c:482 435 425 #, c-format 436 426 msgid " -g, --governors Determines available cpufreq governors *\n" 437 - msgstr " -g, --governors Erzeugt eine Liste mit verfügbaren Reglern *\n" 427 + msgstr " -g, --governors Ermittelt verfügbare cpufreq-Regler *\n" 438 428 439 429 #: utils/cpufreq-info.c:483 440 430 #, c-format ··· 459 449 #: utils/cpufreq-info.c:486 460 450 #, c-format 461 451 msgid " -s, --stats Shows cpufreq statistics if available\n" 462 - msgstr "" 463 - " -s, --stats Zeigt, sofern möglich, Statistiken über cpufreq an.\n" 452 + msgstr " -s, --stats Zeigt cpufreq-Statistiken an, falls vorhanden\n" 464 453 465 454 #: utils/cpufreq-info.c:487 466 455 #, c-format ··· 473 464 #: utils/cpufreq-info.c:488 474 465 #, c-format 475 466 msgid " -b, --boost Checks for turbo or boost modes *\n" 476 - msgstr "" 467 + msgstr " -b, --boost Prüft auf Turbo- oder Boost-Modi *\n" 477 468 478 469 #: utils/cpufreq-info.c:489 479 470 #, c-format 480 471 msgid "" 481 - " -o, --proc Prints out information like provided by the /proc/" 482 - "cpufreq\n" 472 + " -o, --proc Prints out information like provided by the " 473 + "/proc/cpufreq\n" 483 474 " interface in 2.4. and early 2.6. kernels\n" 484 475 msgstr "" 485 476 " -o, --proc Erzeugt Informationen in einem ähnlichem Format zu " ··· 518 509 "For the arguments marked with *, omitting the -c or --cpu argument is\n" 519 510 "equivalent to setting it to zero\n" 520 511 msgstr "" 521 - "Bei den mit * markierten Parametern wird '--cpu 0' angenommen, soweit nicht\n" 522 - "mittels -c oder --cpu etwas anderes angegeben wird\n" 512 + "Für die mit * markierten Argumente ist das Weglassen des Arguments\n" 513 + "-c oder --cpu gleichbedeutend mit der Einstellung auf Null\n" 523 514 524 515 #: utils/cpufreq-info.c:580 525 516 #, c-format ··· 534 525 "You can't specify more than one --cpu parameter and/or\n" 535 526 "more than one output-specific argument\n" 536 527 msgstr "" 537 - "Man kann nicht mehr als einen --cpu-Parameter und/oder mehr als einen\n" 538 - "informationsspezifischen Parameter gleichzeitig angeben\n" 528 + "Sie können nicht mehr als einen Parameter --cpu und/oder\n" 529 + "mehr als ein ausgabespezifisches Argument angeben\n" 539 530 540 531 #: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42 541 532 #: utils/cpupower-info.c:42 utils/cpuidle-info.c:213 ··· 547 538 #, c-format 548 539 msgid "couldn't analyze CPU %d as it doesn't seem to be present\n" 549 540 msgstr "" 550 - "Konnte nicht die CPU %d analysieren, da sie (scheinbar?) nicht existiert.\n" 541 + "CPU %d konnte nicht analysiert werden, da sie scheinbar nicht existiert\n" 551 542 552 543 #: utils/cpufreq-info.c:620 utils/cpupower-info.c:142 553 544 #, c-format 554 545 msgid "analyzing CPU %d:\n" 555 - msgstr "analysiere CPU %d:\n" 546 + msgstr "CPU %d wird analysiert:\n" 556 547 557 548 #: utils/cpufreq-set.c:25 558 - #, fuzzy, c-format 549 + #, c-format 559 550 msgid "Usage: cpupower frequency-set [options]\n" 560 - msgstr "Aufruf: cpufreq-set [Optionen]\n" 551 + msgstr "Aufruf: cpupower frequency-set [Optionen]\n" 561 552 562 553 #: utils/cpufreq-set.c:27 563 554 #, c-format ··· 565 556 " -d FREQ, --min FREQ new minimum CPU frequency the governor may " 566 557 "select\n" 567 558 msgstr "" 568 - " -d FREQ, --min FREQ neue minimale Taktfrequenz, die der Regler\n" 559 + " -d FREQ, --min FREQ neue minimale CPU-Frequenz, die der Regler\n" 569 560 " auswählen darf\n" 570 561 571 562 #: utils/cpufreq-set.c:28 ··· 580 571 #: utils/cpufreq-set.c:29 581 572 #, c-format 582 573 msgid " -g GOV, --governor GOV new cpufreq governor\n" 583 - msgstr " -g GOV, --governors GOV wechsle zu Regler GOV\n" 574 + msgstr " -g GOV, --governors GOV neuer cpufreq-Regler\n" 584 575 585 576 #: utils/cpufreq-set.c:30 586 577 #, c-format ··· 588 579 " -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n" 589 580 " governor to be available and loaded\n" 590 581 msgstr "" 591 - " -f FREQ, --freq FREQ setze exakte Taktfrequenz. Benötigt den Regler\n" 592 - " 'userspace'.\n" 582 + " -f FREQ, --freq FREQ bestimmte Frequenz, die eingestellt werden soll.\n" 583 + " Erfordert einen verfügbaren und geladenen " 584 + "userspace-Regler\n" 593 585 594 586 #: utils/cpufreq-set.c:32 595 587 #, c-format 596 588 msgid " -r, --related Switches all hardware-related CPUs\n" 597 - msgstr "" 598 - " -r, --related Setze Werte für alle CPUs, deren Taktfrequenz\n" 599 - " hardwarebedingt identisch ist.\n" 589 + msgstr " -r, --related Schaltet alle hardwarebezogenen CPUs um\n" 600 590 601 591 #: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27 602 592 #, c-format 603 593 msgid " -h, --help Prints out this screen\n" 604 - msgstr " -h, --help Gibt diese Kurzübersicht aus\n" 594 + msgstr " -h, --help Gibt diesen Bildschirm aus\n" 605 595 606 596 #: utils/cpufreq-set.c:35 607 - #, fuzzy, c-format 597 + #, c-format 608 598 msgid "" 609 599 "Notes:\n" 610 600 "1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n" 611 601 msgstr "" 612 - "Bei den mit * markierten Parametern wird '--cpu 0' angenommen, soweit nicht\n" 613 - "mittels -c oder --cpu etwas anderes angegeben wird\n" 602 + "Hinweis:\n" 603 + "1. Das Weglassen des Arguments -c oder --cpu ist gleichbedeutend mit der " 604 + "Einstellung auf \"all\"\n" 614 605 615 606 #: utils/cpufreq-set.c:37 616 607 #, fuzzy, c-format ··· 645 636 "frequency\n" 646 637 " or because the userspace governor isn't loaded?\n" 647 638 msgstr "" 648 - "Beim Einstellen ist ein Fehler aufgetreten. Typische Fehlerquellen sind:\n" 649 - "- nicht ausreichende Rechte (Administrator)\n" 650 - "- der Regler ist nicht verfügbar bzw. nicht geladen\n" 651 - "- die angegebene Taktik ist inkorrekt\n" 652 - "- eine spezifische Frequenz wurde angegeben, aber der Regler 'userspace'\n" 653 - " kann entweder hardwarebedingt nicht genutzt werden oder ist nicht geladen\n" 639 + "Fehler beim Festlegen neuer Werte. Häufige Fehler:\n" 640 + "- Verfügen Sie über die erforderlichen Administrationsrechte? (Superuser?)\n" 641 + "- Ist der von Ihnen gewünschte Regler verfügbar und mittels modprobe " 642 + "geladen?\n" 643 + "- Versuchen Sie eine ungültige Richtlinie festzulegen?\n" 644 + "- Versuchen Sie eine bestimmte Frequenz festzulegen, aber der " 645 + "userspace-Regler ist nicht verfügbar,\n" 646 + " z.B. wegen Hardware, die nicht auf eine bestimmte Frequenz eingestellt " 647 + "werden kann\n" 648 + " oder weil der userspace-Regler nicht geladen ist?\n" 654 649 655 650 #: utils/cpufreq-set.c:170 656 651 #, c-format 657 652 msgid "wrong, unknown or unhandled CPU?\n" 658 - msgstr "unbekannte oder nicht regelbare CPU\n" 653 + msgstr "falsche, unbekannte oder nicht regelbare CPU?\n" 659 654 660 655 #: utils/cpufreq-set.c:302 661 656 #, c-format ··· 667 654 "the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n" 668 655 "-g/--governor parameters\n" 669 656 msgstr "" 670 - "Der -f bzw. --freq-Parameter kann nicht mit den Parametern -d/--min, -u/--" 671 - "max\n" 657 + "Der -f bzw. --freq-Parameter kann nicht mit den Parametern -d/--min, " 658 + "-u/--max\n" 672 659 "oder -g/--governor kombiniert werden\n" 673 660 674 661 #: utils/cpufreq-set.c:308 ··· 677 664 "At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n" 678 665 "-g/--governor must be passed\n" 679 666 msgstr "" 680 - "Es muss mindestens ein Parameter aus -f/--freq, -d/--min, -u/--max oder\n" 681 - "-g/--governor angegeben werden.\n" 667 + "Mindestens ein Parameter aus -f/--freq, -d/--min, -u/--max und\n" 668 + "-g/--governor muss übergeben werden\n" 682 669 683 670 #: utils/cpufreq-set.c:347 684 671 #, c-format 685 672 msgid "Setting cpu: %d\n" 686 - msgstr "" 673 + msgstr "CPU einstellen: %d\n" 687 674 688 675 #: utils/cpupower-set.c:22 689 676 #, c-format 690 677 msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n" 691 - msgstr "" 678 + msgstr "Aufruf: cpupower set [ -b val ] [ -m val ] [ -s val ]\n" 692 679 693 680 #: utils/cpupower-set.c:24 694 681 #, c-format ··· 702 689 msgid "" 703 690 " -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n" 704 691 msgstr "" 692 + " -m, --sched-mc [VAL] Legt die Mehrkern-Scheduler-Richtlinie des " 693 + "Kernels fest.\n" 705 694 706 695 #: utils/cpupower-set.c:27 707 696 #, c-format ··· 715 700 #: utils/cpupower-set.c:80 716 701 #, c-format 717 702 msgid "--perf-bias param out of range [0-%d]\n" 718 - msgstr "" 703 + msgstr "--perf-bias-Parameter außerhalb des Bereichs [0-%d]\n" 719 704 720 705 #: utils/cpupower-set.c:91 721 706 #, c-format 722 707 msgid "--sched-mc param out of range [0-%d]\n" 723 - msgstr "" 708 + msgstr "Parameter --sched-mc außerhalb des Bereichs [0-%d]\n" 724 709 725 710 #: utils/cpupower-set.c:102 726 711 #, c-format 727 712 msgid "--sched-smt param out of range [0-%d]\n" 728 - msgstr "" 713 + msgstr "Parameter --sched-smt außerhalb des Bereichs [0-%d]\n" 729 714 730 715 #: utils/cpupower-set.c:121 731 716 #, c-format 732 717 msgid "Error setting sched-mc %s\n" 733 - msgstr "" 718 + msgstr "Fehler beim Einstellen von sched-mc %s\n" 734 719 735 720 #: utils/cpupower-set.c:127 736 721 #, c-format 737 722 msgid "Error setting sched-smt %s\n" 738 - msgstr "" 723 + msgstr "Fehler beim Einstellen von sched-smt %s\n" 739 724 740 725 #: utils/cpupower-set.c:146 741 726 #, c-format 742 727 msgid "Error setting perf-bias value on CPU %d\n" 743 - msgstr "" 728 + msgstr "Fehler beim Einstellen des perf-bias-Wertes auf der CPU %d\n" 744 729 745 730 #: utils/cpupower-info.c:21 746 731 #, c-format 747 732 msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n" 748 - msgstr "" 733 + msgstr "Aufruf: cpupower info [ -b ] [ -m ] [ -s ]\n" 749 734 750 735 #: utils/cpupower-info.c:23 751 736 #, c-format ··· 755 740 msgstr "" 756 741 757 742 #: utils/cpupower-info.c:25 758 - #, fuzzy, c-format 743 + #, c-format 759 744 msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n" 760 - msgstr " -p, --policy Findet die momentane Taktik heraus *\n" 745 + msgstr "" 746 + " -m, --sched-mc Ruft die Mehrkern-Scheduler-Richtlinie des Kernels ab.\n" 761 747 762 748 #: utils/cpupower-info.c:26 763 749 #, c-format ··· 772 756 "\n" 773 757 "Passing no option will show all info, by default only on core 0\n" 774 758 msgstr "" 759 + "\n" 760 + "Wenn Sie keine Option übergeben, werden alle Informationen angezeigt, " 761 + "standardmäßig nur auf Kern 0\n" 775 762 776 763 #: utils/cpupower-info.c:102 777 764 #, c-format 778 765 msgid "System's multi core scheduler setting: " 779 - msgstr "" 766 + msgstr "Mehrkern-Scheduler-Einstellung des Systems: " 780 767 781 768 #. if sysfs file is missing it's: errno == ENOENT 782 769 #: utils/cpupower-info.c:105 utils/cpupower-info.c:114 783 770 #, c-format 784 771 msgid "not supported\n" 785 - msgstr "" 772 + msgstr "nicht unterstützt\n" 786 773 787 774 #: utils/cpupower-info.c:111 788 775 #, c-format ··· 805 786 #: utils/cpupower-info.c:147 806 787 #, c-format 807 788 msgid "Could not read perf-bias value\n" 808 - msgstr "" 789 + msgstr "perf-bias-Wert konnte nicht gelesen werden\n" 809 790 810 791 #: utils/cpupower-info.c:150 811 792 #, c-format 812 793 msgid "perf-bias: %d\n" 813 - msgstr "" 794 + msgstr "perf-bias: %d\n" 814 795 815 796 #: utils/cpuidle-info.c:28 816 - #, fuzzy, c-format 797 + #, c-format 817 798 msgid "Analyzing CPU %d:\n" 818 - msgstr "analysiere CPU %d:\n" 799 + msgstr "CPU %d wird analysiert:\n" 819 800 820 801 #: utils/cpuidle-info.c:32 821 802 #, c-format 822 803 msgid "CPU %u: No idle states\n" 823 - msgstr "" 804 + msgstr "CPU %u: Keine Ruhezustände\n" 824 805 825 806 #: utils/cpuidle-info.c:36 826 807 #, c-format 827 808 msgid "CPU %u: Can't read idle state info\n" 828 - msgstr "" 809 + msgstr "CPU %u: Ruhezustands-Informationen können nicht gelesen werden\n" 829 810 830 811 #: utils/cpuidle-info.c:41 831 812 #, c-format 832 813 msgid "Could not determine max idle state %u\n" 833 - msgstr "" 814 + msgstr "Max. Ruhezustand %u konnte nicht bestimmt werden\n" 834 815 835 816 #: utils/cpuidle-info.c:46 836 817 #, c-format 837 818 msgid "Number of idle states: %d\n" 838 - msgstr "" 819 + msgstr "Anzahl der Ruhezustände: %d\n" 839 820 840 821 #: utils/cpuidle-info.c:48 841 - #, fuzzy, c-format 822 + #, c-format 842 823 msgid "Available idle states:" 843 - msgstr " mögliche Taktfrequenzen: " 824 + msgstr "Verfügbare Ruhezustände:" 844 825 845 826 #: utils/cpuidle-info.c:71 846 827 #, c-format 847 828 msgid "Flags/Description: %s\n" 848 - msgstr "" 829 + msgstr "Merker/Beschreibung: %s\n" 849 830 850 831 #: utils/cpuidle-info.c:74 851 832 #, c-format 852 833 msgid "Latency: %lu\n" 853 - msgstr "" 834 + msgstr "Latenz: %lu\n" 854 835 855 836 #: utils/cpuidle-info.c:76 856 837 #, c-format 857 838 msgid "Usage: %lu\n" 858 - msgstr "" 839 + msgstr "Aufruf: %lu\n" 859 840 860 841 #: utils/cpuidle-info.c:78 861 842 #, c-format 862 843 msgid "Duration: %llu\n" 863 - msgstr "" 844 + msgstr "Dauer: %llu\n" 864 845 865 846 #: utils/cpuidle-info.c:90 866 847 #, c-format 867 848 msgid "Could not determine cpuidle driver\n" 868 - msgstr "" 849 + msgstr "cpuidle-Treiber konnte nicht bestimmt werden\n" 869 850 870 851 #: utils/cpuidle-info.c:94 871 - #, fuzzy, c-format 852 + #, c-format 872 853 msgid "CPUidle driver: %s\n" 873 - msgstr " Treiber: %s\n" 854 + msgstr "CPUidle-Treiber: %s\n" 874 855 875 856 #: utils/cpuidle-info.c:99 876 857 #, c-format 877 858 msgid "Could not determine cpuidle governor\n" 878 - msgstr "" 859 + msgstr "cpuidle-Regler konnte nicht bestimmt werden\n" 879 860 880 861 #: utils/cpuidle-info.c:103 881 862 #, c-format 882 863 msgid "CPUidle governor: %s\n" 883 - msgstr "" 864 + msgstr "CPUidle-Regler: %s\n" 884 865 885 866 #: utils/cpuidle-info.c:122 886 867 #, c-format 887 868 msgid "CPU %u: Can't read C-state info\n" 888 - msgstr "" 869 + msgstr "CPU %u: C-Zustands-Informationen können nicht gelesen werden\n" 889 870 890 871 #. printf("Cstates: %d\n", cstates); 891 872 #: utils/cpuidle-info.c:127 892 873 #, c-format 893 874 msgid "active state: C0\n" 894 - msgstr "" 875 + msgstr "aktiver Zustand: C0\n" 895 876 896 877 #: utils/cpuidle-info.c:128 897 878 #, c-format 898 879 msgid "max_cstate: C%u\n" 899 - msgstr "" 880 + msgstr "max_cstate: C%u\n" 900 881 901 882 #: utils/cpuidle-info.c:129 902 - #, fuzzy, c-format 883 + #, c-format 903 884 msgid "maximum allowed latency: %lu usec\n" 904 - msgstr " Maximale Dauer eines Taktfrequenzwechsels: " 885 + msgstr "maximal erlaubte Latenz: %lu usec\n" 905 886 906 887 #: utils/cpuidle-info.c:130 907 888 #, c-format 908 889 msgid "states:\t\n" 909 - msgstr "" 890 + msgstr "Zustände:\t\n" 910 891 911 892 #: utils/cpuidle-info.c:132 912 893 #, c-format 913 894 msgid " C%d: type[C%d] " 914 - msgstr "" 895 + msgstr " C%d: Typ[C%d] " 915 896 916 897 #: utils/cpuidle-info.c:134 917 898 #, c-format 918 899 msgid "promotion[--] demotion[--] " 919 - msgstr "" 900 + msgstr "promotion[--] demotion[--] " 920 901 921 902 #: utils/cpuidle-info.c:135 922 903 #, c-format 923 904 msgid "latency[%03lu] " 924 - msgstr "" 905 + msgstr "Latenz[%03lu] " 925 906 926 907 #: utils/cpuidle-info.c:137 927 908 #, c-format 928 909 msgid "usage[%08lu] " 929 - msgstr "" 910 + msgstr "Aufruf[%08lu] " 930 911 931 912 #: utils/cpuidle-info.c:139 932 913 #, c-format 933 914 msgid "duration[%020Lu] \n" 934 - msgstr "" 915 + msgstr "Dauer[%020Lu] \n" 935 916 936 917 #: utils/cpuidle-info.c:147 937 - #, fuzzy, c-format 918 + #, c-format 938 919 msgid "Usage: cpupower idleinfo [options]\n" 939 - msgstr "Aufruf: cpufreq-info [Optionen]\n" 920 + msgstr "Aufruf: cpupower idleinfo [Optionen]\n" 940 921 941 922 #: utils/cpuidle-info.c:149 942 - #, fuzzy, c-format 923 + #, c-format 943 924 msgid " -s, --silent Only show general C-state information\n" 944 925 msgstr "" 945 - " -e, --debug Erzeugt detaillierte Informationen, hilfreich\n" 946 - " zum Aufspüren von Fehlern\n" 926 + " -s, --silent Nur allgemeine C-Zustands-Informationen anzeigen\n" 947 927 948 928 #: utils/cpuidle-info.c:150 949 - #, fuzzy, c-format 929 + #, c-format 950 930 msgid "" 951 - " -o, --proc Prints out information like provided by the /proc/" 952 - "acpi/processor/*/power\n" 931 + " -o, --proc Prints out information like provided by the " 932 + "/proc/acpi/processor/*/power\n" 953 933 " interface in older kernels\n" 954 934 msgstr "" 955 - " -o, --proc Erzeugt Informationen in einem ähnlichem Format zu " 956 - "dem\n" 957 - " der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n" 958 - " Kernel-Versionen\n" 935 + " -o, --proc Gibt Informationen so aus, wie sie von der " 936 + "Schnittstelle\n" 937 + " /proc/acpi/processor/*/power in älteren Kerneln " 938 + "bereitgestellt werden\n" 959 939 960 940 #: utils/cpuidle-info.c:209 961 - #, fuzzy, c-format 941 + #, c-format 962 942 msgid "You can't specify more than one output-specific argument\n" 963 - msgstr "" 964 - "Man kann nicht mehr als einen --cpu-Parameter und/oder mehr als einen\n" 965 - "informationsspezifischen Parameter gleichzeitig angeben\n" 943 + msgstr "Sie können nicht mehr als ein ausgabenspezifisches Argument angeben\n" 966 944 967 945 #~ msgid "" 968 946 #~ " -c CPU, --cpu CPU CPU number which information shall be determined " ··· 972 956 #~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be " 973 957 #~ "modified\n" 974 958 #~ msgstr "" 975 - #~ " -c CPU, --cpu CPU Nummer der CPU, deren Taktfrequenz-" 976 - #~ "Einstellung\n" 959 + #~ " -c CPU, --cpu CPU Nummer der CPU, deren " 960 + #~ "Taktfrequenz-Einstellung\n" 977 961 #~ " werden soll\n"
+5 -1
tools/power/pm-graph/README
··· 1 1 p m - g r a p h 2 2 3 3 pm-graph: suspend/resume/boot timing analysis tools 4 - Version: 5.4 4 + Version: 5.5 5 5 Author: Todd Brandt <todd.e.brandt@intel.com> 6 6 Home Page: https://01.org/pm-graph 7 7 ··· 17 17 18 18 - upstream version in git: 19 19 https://github.com/intel/pm-graph/ 20 + 21 + Requirements: 22 + - runs with python2 or python3, choice is made by /usr/bin/python link 23 + - python2 now requires python-configparser be installed 20 24 21 25 Table of Contents 22 26 - Overview
+40 -19
tools/power/pm-graph/bootgraph.py
··· 1 - #!/usr/bin/python2 1 + #!/usr/bin/python 2 2 # SPDX-License-Identifier: GPL-2.0-only 3 3 # 4 4 # Tool for analyzing boot timing 5 5 # Copyright (c) 2013, Intel Corporation. 6 + # 7 + # This program is free software; you can redistribute it and/or modify it 8 + # under the terms and conditions of the GNU General Public License, 9 + # version 2, as published by the Free Software Foundation. 10 + # 11 + # This program is distributed in the hope it will be useful, but WITHOUT 12 + # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 + # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 + # more details. 6 15 # 7 16 # Authors: 8 17 # Todd Brandt <todd.e.brandt@linux.intel.com> ··· 90 81 cmdline = 'initcall_debug log_buf_len=32M' 91 82 if self.useftrace: 92 83 if self.cpucount > 0: 93 - bs = min(self.memtotal / 2, 2*1024*1024) / self.cpucount 84 + bs = min(self.memtotal // 2, 2*1024*1024) // self.cpucount 94 85 else: 95 86 bs = 131072 96 87 cmdline += ' trace_buf_size=%dK trace_clock=global '\ ··· 146 137 if arg in ['-h', '-v', '-cronjob', '-reboot', '-verbose']: 147 138 continue 148 139 elif arg in ['-o', '-dmesg', '-ftrace', '-func']: 149 - args.next() 140 + next(args) 150 141 continue 151 142 elif arg == '-result': 152 - cmdline += ' %s "%s"' % (arg, os.path.abspath(args.next())) 143 + cmdline += ' %s "%s"' % (arg, os.path.abspath(next(args))) 153 144 continue 154 145 elif arg == '-cgskip': 155 - file = self.configFile(args.next()) 146 + file = self.configFile(next(args)) 156 147 cmdline += ' %s "%s"' % (arg, os.path.abspath(file)) 157 148 continue 158 149 cmdline += ' '+arg ··· 301 292 tp = aslib.TestProps() 302 293 devtemp = dict() 303 294 if(sysvals.dmesgfile): 304 - lf = open(sysvals.dmesgfile, 'r') 295 + lf = open(sysvals.dmesgfile, 'rb') 305 296 else: 306 297 lf = Popen('dmesg', stdout=PIPE).stdout 307 298 for line in lf: 308 - line = line.replace('\r\n', '') 299 + line = aslib.ascii(line).replace('\r\n', '') 309 300 # grab the stamp and sysinfo 310 301 if re.match(tp.stampfmt, line): 311 302 tp.stamp = line ··· 658 649 statinfo += '\t"%s": [\n\t\t"%s",\n' % (n, devstats[n]['info']) 659 650 if 'fstat' in devstats[n]: 660 651 funcs = devstats[n]['fstat'] 661 - for f in sorted(funcs, key=funcs.get, reverse=True): 652 + for f in sorted(funcs, key=lambda k:(funcs[k], k), reverse=True): 662 653 if funcs[f][0] < 0.01 and len(funcs) > 10: 663 654 break 664 655 statinfo += '\t\t"%f|%s|%d",\n' % (funcs[f][0], f, funcs[f][1]) ··· 738 729 op.write('@reboot python %s\n' % sysvals.cronjobCmdString()) 739 730 op.close() 740 731 res = call([cmd, cronfile]) 741 - except Exception, e: 732 + except Exception as e: 742 733 pprint('Exception: %s' % str(e)) 743 734 shutil.move(backfile, cronfile) 744 735 res = -1 ··· 754 745 try: 755 746 call(sysvals.blexec, stderr=PIPE, stdout=PIPE, 756 747 env={'PATH': '.:/sbin:/usr/sbin:/usr/bin:/sbin:/bin'}) 757 - except Exception, e: 748 + except Exception as e: 758 749 pprint('Exception: %s\n' % str(e)) 759 750 return 760 751 # extract the option and create a grub config without it ··· 801 792 op.close() 802 793 res = call(sysvals.blexec) 803 794 os.remove(grubfile) 804 - except Exception, e: 795 + except Exception as e: 805 796 pprint('Exception: %s' % str(e)) 806 797 res = -1 807 798 # cleanup ··· 875 866 'Other commands:\n'\ 876 867 ' -flistall Print all functions capable of being captured in ftrace\n'\ 877 868 ' -sysinfo Print out system info extracted from BIOS\n'\ 869 + ' -which exec Print an executable path, should function even without PATH\n'\ 878 870 ' [redo]\n'\ 879 871 ' -dmesg file Create HTML output using dmesg input (used with -ftrace)\n'\ 880 872 ' -ftrace file Create HTML output using ftrace input (used with -dmesg)\n'\ ··· 917 907 sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0) 918 908 elif(arg == '-cgfilter'): 919 909 try: 920 - val = args.next() 910 + val = next(args) 921 911 except: 922 912 doError('No callgraph functions supplied', True) 923 913 sysvals.setCallgraphFilter(val) 924 914 elif(arg == '-cgskip'): 925 915 try: 926 - val = args.next() 916 + val = next(args) 927 917 except: 928 918 doError('No file supplied', True) 929 919 if val.lower() in switchoff: ··· 934 924 doError('%s does not exist' % cgskip) 935 925 elif(arg == '-bl'): 936 926 try: 937 - val = args.next() 927 + val = next(args) 938 928 except: 939 929 doError('No boot loader name supplied', True) 940 930 if val.lower() not in ['grub']: ··· 947 937 sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000) 948 938 elif(arg == '-func'): 949 939 try: 950 - val = args.next() 940 + val = next(args) 951 941 except: 952 942 doError('No filter functions supplied', True) 953 943 sysvals.useftrace = True ··· 956 946 sysvals.setGraphFilter(val) 957 947 elif(arg == '-ftrace'): 958 948 try: 959 - val = args.next() 949 + val = next(args) 960 950 except: 961 951 doError('No ftrace file supplied', True) 962 952 if(os.path.exists(val) == False): ··· 969 959 sysvals.cgexp = True 970 960 elif(arg == '-dmesg'): 971 961 try: 972 - val = args.next() 962 + val = next(args) 973 963 except: 974 964 doError('No dmesg file supplied', True) 975 965 if(os.path.exists(val) == False): ··· 978 968 sysvals.dmesgfile = val 979 969 elif(arg == '-o'): 980 970 try: 981 - val = args.next() 971 + val = next(args) 982 972 except: 983 973 doError('No subdirectory name supplied', True) 984 974 sysvals.testdir = sysvals.setOutputFolder(val) 985 975 elif(arg == '-result'): 986 976 try: 987 - val = args.next() 977 + val = next(args) 988 978 except: 989 979 doError('No result file supplied', True) 990 980 sysvals.result = val ··· 996 986 # remaining options are only for cron job use 997 987 elif(arg == '-cronjob'): 998 988 sysvals.iscronjob = True 989 + elif(arg == '-which'): 990 + try: 991 + val = next(args) 992 + except: 993 + doError('No executable supplied', True) 994 + out = sysvals.getExec(val) 995 + if not out: 996 + print('%s not found' % val) 997 + sys.exit(1) 998 + print(out) 999 + sys.exit(0) 999 1000 else: 1000 1001 doError('Invalid argument: '+arg, True) 1001 1002
+4 -4
tools/power/pm-graph/sleepgraph.8
··· 53 53 Add the dmesg and ftrace logs to the html output. They will be viewable by 54 54 clicking buttons in the timeline. 55 55 .TP 56 - \fB-turbostat\fR 57 - Use turbostat to execute the command in freeze mode (default: disabled). This 58 - will provide turbostat output in the log which will tell you which actual 59 - power modes were entered. 56 + \fB-noturbostat\fR 57 + By default, if turbostat is found and the requested mode is freeze, sleepgraph 58 + will execute the suspend via turbostat and collect data in the timeline log. 59 + This option disables the use of turbostat. 60 60 .TP 61 61 \fB-result \fIfile\fR 62 62 Export a results table to a text file for parsing.
+342 -276
tools/power/pm-graph/sleepgraph.py
··· 1 - #!/usr/bin/python2 1 + #!/usr/bin/python 2 2 # SPDX-License-Identifier: GPL-2.0-only 3 3 # 4 4 # Tool for analyzing suspend/resume timing 5 5 # Copyright (c) 2013, Intel Corporation. 6 + # 7 + # This program is free software; you can redistribute it and/or modify it 8 + # under the terms and conditions of the GNU General Public License, 9 + # version 2, as published by the Free Software Foundation. 10 + # 11 + # This program is distributed in the hope it will be useful, but WITHOUT 12 + # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 + # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 + # more details. 6 15 # 7 16 # Authors: 8 17 # Todd Brandt <todd.e.brandt@linux.intel.com> ··· 57 48 import re 58 49 import platform 59 50 import signal 51 + import codecs 60 52 from datetime import datetime 61 53 import struct 62 - import ConfigParser 54 + import configparser 63 55 import gzip 64 56 from threading import Thread 65 57 from subprocess import call, Popen, PIPE ··· 70 60 print(msg) 71 61 sys.stdout.flush() 72 62 63 + def ascii(text): 64 + return text.decode('ascii', 'ignore') 65 + 73 66 # ----------------- CLASSES -------------------- 74 67 75 68 # Class: SystemValues ··· 81 68 # store system values and test parameters 82 69 class SystemValues: 83 70 title = 'SleepGraph' 84 - version = '5.4' 71 + version = '5.5' 85 72 ansi = False 86 73 rs = 0 87 74 display = '' ··· 91 78 testlog = True 92 79 dmesglog = True 93 80 ftracelog = False 94 - tstat = False 81 + tstat = True 95 82 mindevlen = 0.0 96 83 mincglen = 0.0 97 84 cgphase = '' ··· 160 147 devdump = False 161 148 mixedphaseheight = True 162 149 devprops = dict() 150 + platinfo = [] 163 151 predelay = 0 164 152 postdelay = 0 165 153 pmdebug = '' ··· 337 323 sys.exit(1) 338 324 return False 339 325 def getExec(self, cmd): 340 - dirlist = ['/sbin', '/bin', '/usr/sbin', '/usr/bin', 341 - '/usr/local/sbin', '/usr/local/bin'] 342 - for path in dirlist: 326 + try: 327 + fp = Popen(['which', cmd], stdout=PIPE, stderr=PIPE).stdout 328 + out = ascii(fp.read()).strip() 329 + fp.close() 330 + except: 331 + out = '' 332 + if out: 333 + return out 334 + for path in ['/sbin', '/bin', '/usr/sbin', '/usr/bin', 335 + '/usr/local/sbin', '/usr/local/bin']: 343 336 cmdfull = os.path.join(path, cmd) 344 337 if os.path.exists(cmdfull): 345 338 return cmdfull 346 - return '' 339 + return out 347 340 def setPrecision(self, num): 348 341 if num < 0 or num > 6: 349 342 return ··· 476 455 fp = Popen('dmesg', stdout=PIPE).stdout 477 456 ktime = '0' 478 457 for line in fp: 479 - line = line.replace('\r\n', '') 458 + line = ascii(line).replace('\r\n', '') 480 459 idx = line.find('[') 481 460 if idx > 1: 482 461 line = line[idx:] ··· 490 469 # store all new dmesg lines since initdmesg was called 491 470 fp = Popen('dmesg', stdout=PIPE).stdout 492 471 for line in fp: 493 - line = line.replace('\r\n', '') 472 + line = ascii(line).replace('\r\n', '') 494 473 idx = line.find('[') 495 474 if idx > 1: 496 475 line = line[idx:] ··· 522 501 call('cat '+self.tpath+'available_filter_functions', shell=True) 523 502 return 524 503 master = self.listFromFile(self.tpath+'available_filter_functions') 525 - for i in self.tracefuncs: 504 + for i in sorted(self.tracefuncs): 526 505 if 'func' in self.tracefuncs[i]: 527 506 i = self.tracefuncs[i]['func'] 528 507 if i in master: ··· 649 628 self.fsetVal(kprobeevents, 'kprobe_events') 650 629 if output: 651 630 check = self.fgetVal('kprobe_events') 652 - linesack = (len(check.split('\n')) - 1) / 2 631 + linesack = (len(check.split('\n')) - 1) // 2 653 632 pprint(' kprobe functions enabled: %d/%d' % (linesack, linesout)) 654 633 self.fsetVal('1', 'events/kprobes/enable') 655 634 def testKprobe(self, kname, kprobe): ··· 667 646 if linesack < linesout: 668 647 return False 669 648 return True 670 - def setVal(self, val, file, mode='w'): 649 + def setVal(self, val, file): 671 650 if not os.path.exists(file): 672 651 return False 673 652 try: 674 - fp = open(file, mode, 0) 675 - fp.write(val) 653 + fp = open(file, 'wb', 0) 654 + fp.write(val.encode()) 676 655 fp.flush() 677 656 fp.close() 678 657 except: 679 658 return False 680 659 return True 681 - def fsetVal(self, val, path, mode='w'): 682 - return self.setVal(val, self.tpath+path, mode) 660 + def fsetVal(self, val, path): 661 + return self.setVal(val, self.tpath+path) 683 662 def getVal(self, file): 684 663 res = '' 685 664 if not os.path.exists(file): ··· 740 719 tgtsize = min(self.memfree, bmax) 741 720 else: 742 721 tgtsize = 65536 743 - while not self.fsetVal('%d' % (tgtsize / cpus), 'buffer_size_kb'): 722 + while not self.fsetVal('%d' % (tgtsize // cpus), 'buffer_size_kb'): 744 723 # if the size failed to set, lower it and keep trying 745 724 tgtsize -= 65536 746 725 if tgtsize < 65536: ··· 884 863 isgz = self.gzip 885 864 if mode == 'r': 886 865 try: 887 - with gzip.open(filename, mode+'b') as fp: 866 + with gzip.open(filename, mode+'t') as fp: 888 867 test = fp.read(64) 889 868 isgz = True 890 869 except: 891 870 isgz = False 892 871 if isgz: 893 - return gzip.open(filename, mode+'b') 872 + return gzip.open(filename, mode+'t') 894 873 return open(filename, mode) 874 + def b64unzip(self, data): 875 + try: 876 + out = codecs.decode(base64.b64decode(data), 'zlib').decode() 877 + except: 878 + out = data 879 + return out 880 + def b64zip(self, data): 881 + out = base64.b64encode(codecs.encode(data.encode(), 'zlib')).decode() 882 + return out 895 883 def mcelog(self, clear=False): 896 884 cmd = self.getExec('mcelog') 897 885 if not cmd: ··· 908 878 if clear: 909 879 call(cmd+' > /dev/null 2>&1', shell=True) 910 880 return '' 911 - fp = Popen([cmd], stdout=PIPE, stderr=PIPE).stdout 912 - out = fp.read().strip() 913 - fp.close() 881 + try: 882 + fp = Popen([cmd], stdout=PIPE, stderr=PIPE).stdout 883 + out = ascii(fp.read()).strip() 884 + fp.close() 885 + except: 886 + return '' 914 887 if not out: 915 888 return '' 916 - return base64.b64encode(out.encode('zlib')) 889 + return self.b64zip(out) 890 + def platforminfo(self): 891 + # add platform info on to a completed ftrace file 892 + if not os.path.exists(self.ftracefile): 893 + return False 894 + footer = '#\n' 895 + 896 + # add test command string line if need be 897 + if self.suspendmode == 'command' and self.testcommand: 898 + footer += '# platform-testcmd: %s\n' % (self.testcommand) 899 + 900 + # get a list of target devices from the ftrace file 901 + props = dict() 902 + tp = TestProps() 903 + tf = self.openlog(self.ftracefile, 'r') 904 + for line in tf: 905 + # determine the trace data type (required for further parsing) 906 + m = re.match(tp.tracertypefmt, line) 907 + if(m): 908 + tp.setTracerType(m.group('t')) 909 + continue 910 + # parse only valid lines, if this is not one move on 911 + m = re.match(tp.ftrace_line_fmt, line) 912 + if(not m or 'device_pm_callback_start' not in line): 913 + continue 914 + m = re.match('.*: (?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*', m.group('msg')); 915 + if(not m): 916 + continue 917 + dev = m.group('d') 918 + if dev not in props: 919 + props[dev] = DevProps() 920 + tf.close() 921 + 922 + # now get the syspath for each target device 923 + for dirname, dirnames, filenames in os.walk('/sys/devices'): 924 + if(re.match('.*/power', dirname) and 'async' in filenames): 925 + dev = dirname.split('/')[-2] 926 + if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)): 927 + props[dev].syspath = dirname[:-6] 928 + 929 + # now fill in the properties for our target devices 930 + for dev in sorted(props): 931 + dirname = props[dev].syspath 932 + if not dirname or not os.path.exists(dirname): 933 + continue 934 + with open(dirname+'/power/async') as fp: 935 + text = fp.read() 936 + props[dev].isasync = False 937 + if 'enabled' in text: 938 + props[dev].isasync = True 939 + fields = os.listdir(dirname) 940 + if 'product' in fields: 941 + with open(dirname+'/product', 'rb') as fp: 942 + props[dev].altname = ascii(fp.read()) 943 + elif 'name' in fields: 944 + with open(dirname+'/name', 'rb') as fp: 945 + props[dev].altname = ascii(fp.read()) 946 + elif 'model' in fields: 947 + with open(dirname+'/model', 'rb') as fp: 948 + props[dev].altname = ascii(fp.read()) 949 + elif 'description' in fields: 950 + with open(dirname+'/description', 'rb') as fp: 951 + props[dev].altname = ascii(fp.read()) 952 + elif 'id' in fields: 953 + with open(dirname+'/id', 'rb') as fp: 954 + props[dev].altname = ascii(fp.read()) 955 + elif 'idVendor' in fields and 'idProduct' in fields: 956 + idv, idp = '', '' 957 + with open(dirname+'/idVendor', 'rb') as fp: 958 + idv = ascii(fp.read()).strip() 959 + with open(dirname+'/idProduct', 'rb') as fp: 960 + idp = ascii(fp.read()).strip() 961 + props[dev].altname = '%s:%s' % (idv, idp) 962 + if props[dev].altname: 963 + out = props[dev].altname.strip().replace('\n', ' ')\ 964 + .replace(',', ' ').replace(';', ' ') 965 + props[dev].altname = out 966 + 967 + # add a devinfo line to the bottom of ftrace 968 + out = '' 969 + for dev in sorted(props): 970 + out += props[dev].out(dev) 971 + footer += '# platform-devinfo: %s\n' % self.b64zip(out) 972 + 973 + # add a line for each of these commands with their outputs 974 + cmds = [ 975 + ['pcidevices', 'lspci', '-tv'], 976 + ['interrupts', 'cat', '/proc/interrupts'], 977 + ['gpecounts', 'sh', '-c', 'grep -v invalid /sys/firmware/acpi/interrupts/gpe*'], 978 + ] 979 + for cargs in cmds: 980 + name = cargs[0] 981 + cmdline = ' '.join(cargs[1:]) 982 + cmdpath = self.getExec(cargs[1]) 983 + if not cmdpath: 984 + continue 985 + cmd = [cmdpath] + cargs[2:] 986 + try: 987 + fp = Popen(cmd, stdout=PIPE, stderr=PIPE).stdout 988 + info = ascii(fp.read()).strip() 989 + fp.close() 990 + except: 991 + continue 992 + if not info: 993 + continue 994 + footer += '# platform-%s: %s | %s\n' % (name, cmdline, self.b64zip(info)) 995 + 996 + with self.openlog(self.ftracefile, 'a') as fp: 997 + fp.write(footer) 998 + return True 917 999 def haveTurbostat(self): 918 1000 if not self.tstat: 919 1001 return False ··· 1033 891 if not cmd: 1034 892 return False 1035 893 fp = Popen([cmd, '-v'], stdout=PIPE, stderr=PIPE).stderr 1036 - out = fp.read().strip() 894 + out = ascii(fp.read()).strip() 1037 895 fp.close() 1038 - return re.match('turbostat version [0-9\.]* .*', out) 896 + if re.match('turbostat version [0-9\.]* .*', out): 897 + sysvals.vprint(out) 898 + return True 899 + return False 1039 900 def turbostat(self): 1040 901 cmd = self.getExec('turbostat') 1041 - if not cmd: 1042 - return 'missing turbostat executable' 1043 - text = [] 902 + rawout = keyline = valline = '' 1044 903 fullcmd = '%s -q -S echo freeze > %s' % (cmd, self.powerfile) 1045 904 fp = Popen(['sh', '-c', fullcmd], stdout=PIPE, stderr=PIPE).stderr 1046 905 for line in fp: 1047 - if re.match('[0-9.]* sec', line): 906 + line = ascii(line) 907 + rawout += line 908 + if keyline and valline: 1048 909 continue 1049 - text.append(line.split()) 910 + if re.match('(?i)Avg_MHz.*', line): 911 + keyline = line.strip().split() 912 + elif keyline: 913 + valline = line.strip().split() 1050 914 fp.close() 1051 - if len(text) < 2: 1052 - return 'turbostat output format error' 915 + if not keyline or not valline or len(keyline) != len(valline): 916 + errmsg = 'unrecognized turbostat output:\n'+rawout.strip() 917 + sysvals.vprint(errmsg) 918 + if not sysvals.verbose: 919 + pprint(errmsg) 920 + return '' 921 + if sysvals.verbose: 922 + pprint(rawout.strip()) 1053 923 out = [] 1054 - for key in text[0]: 1055 - values = [] 1056 - idx = text[0].index(key) 1057 - for line in text[1:]: 1058 - if len(line) > idx: 1059 - values.append(line[idx]) 1060 - out.append('%s=%s' % (key, ','.join(values))) 924 + for key in keyline: 925 + idx = keyline.index(key) 926 + val = valline[idx] 927 + out.append('%s=%s' % (key, val)) 1061 928 return '|'.join(out) 1062 929 def checkWifi(self): 1063 930 out = dict() ··· 1075 924 return out 1076 925 fp = Popen(iwcmd, stdout=PIPE, stderr=PIPE).stdout 1077 926 for line in fp: 1078 - m = re.match('(?P<dev>\S*) .* ESSID:(?P<ess>\S*)', line) 927 + m = re.match('(?P<dev>\S*) .* ESSID:(?P<ess>\S*)', ascii(line)) 1079 928 if not m: 1080 929 continue 1081 930 out['device'] = m.group('dev') ··· 1086 935 if 'device' in out: 1087 936 fp = Popen([ifcmd, out['device']], stdout=PIPE, stderr=PIPE).stdout 1088 937 for line in fp: 1089 - m = re.match('.* inet (?P<ip>[0-9\.]*)', line) 938 + m = re.match('.* inet (?P<ip>[0-9\.]*)', ascii(line)) 1090 939 if m: 1091 940 out['ip'] = m.group('ip') 1092 941 break ··· 1141 990 def __init__(self): 1142 991 self.syspath = '' 1143 992 self.altname = '' 1144 - self.async = True 993 + self.isasync = True 1145 994 self.xtraclass = '' 1146 995 self.xtrainfo = '' 1147 996 def out(self, dev): 1148 - return '%s,%s,%d;' % (dev, self.altname, self.async) 997 + return '%s,%s,%d;' % (dev, self.altname, self.isasync) 1149 998 def debug(self, dev): 1150 - pprint('%s:\n\taltname = %s\n\t async = %s' % (dev, self.altname, self.async)) 999 + pprint('%s:\n\taltname = %s\n\t async = %s' % (dev, self.altname, self.isasync)) 1151 1000 def altName(self, dev): 1152 1001 if not self.altname or self.altname == dev: 1153 1002 return dev ··· 1155 1004 def xtraClass(self): 1156 1005 if self.xtraclass: 1157 1006 return ' '+self.xtraclass 1158 - if not self.async: 1007 + if not self.isasync: 1159 1008 return ' sync' 1160 1009 return '' 1161 1010 def xtraInfo(self): 1162 1011 if self.xtraclass: 1163 1012 return ' '+self.xtraclass 1164 - if self.async: 1013 + if self.isasync: 1165 1014 return ' async_device' 1166 1015 return ' sync_device' 1167 1016 ··· 1259 1108 return sorted(self.dmesg, key=lambda k:self.dmesg[k]['order']) 1260 1109 def initDevicegroups(self): 1261 1110 # called when phases are all finished being added 1262 - for phase in self.dmesg.keys(): 1111 + for phase in sorted(self.dmesg.keys()): 1263 1112 if '*' in phase: 1264 1113 p = phase.split('*') 1265 1114 pnew = '%s%d' % (p[0], len(p)) ··· 1581 1430 return phase 1582 1431 def sortedDevices(self, phase): 1583 1432 list = self.dmesg[phase]['list'] 1584 - slist = [] 1585 - tmp = dict() 1586 - for devname in list: 1587 - dev = list[devname] 1588 - if dev['length'] == 0: 1589 - continue 1590 - tmp[dev['start']] = devname 1591 - for t in sorted(tmp): 1592 - slist.append(tmp[t]) 1593 - return slist 1433 + return sorted(list, key=lambda k:list[k]['start']) 1594 1434 def fixupInitcalls(self, phase): 1595 1435 # if any calls never returned, clip them at system resume end 1596 1436 phaselist = self.dmesg[phase]['list'] ··· 1718 1576 maxname = '%d' % self.maxDeviceNameSize(phase) 1719 1577 fmt = '%3d) %'+maxname+'s - %f - %f' 1720 1578 c = 1 1721 - for name in devlist: 1579 + for name in sorted(devlist): 1722 1580 s = devlist[name]['start'] 1723 1581 e = devlist[name]['end'] 1724 1582 sysvals.vprint(fmt % (c, name, s, e)) ··· 1730 1588 devlist = [] 1731 1589 for phase in self.sortedPhases(): 1732 1590 list = self.deviceChildren(devname, phase) 1733 - for dev in list: 1591 + for dev in sorted(list): 1734 1592 if dev not in devlist: 1735 1593 devlist.append(dev) 1736 1594 return devlist ··· 1770 1628 def rootDeviceList(self): 1771 1629 # list of devices graphed 1772 1630 real = [] 1773 - for phase in self.dmesg: 1631 + for phase in self.sortedPhases(): 1774 1632 list = self.dmesg[phase]['list'] 1775 - for dev in list: 1633 + for dev in sorted(list): 1776 1634 if list[dev]['pid'] >= 0 and dev not in real: 1777 1635 real.append(dev) 1778 1636 # list of top-most root devices 1779 1637 rootlist = [] 1780 - for phase in self.dmesg: 1638 + for phase in self.sortedPhases(): 1781 1639 list = self.dmesg[phase]['list'] 1782 - for dev in list: 1640 + for dev in sorted(list): 1783 1641 pdev = list[dev]['par'] 1784 1642 pid = list[dev]['pid'] 1785 1643 if(pid < 0 or re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)): ··· 1860 1718 def createProcessUsageEvents(self): 1861 1719 # get an array of process names 1862 1720 proclist = [] 1863 - for t in self.pstl: 1721 + for t in sorted(self.pstl): 1864 1722 pslist = self.pstl[t] 1865 - for ps in pslist: 1723 + for ps in sorted(pslist): 1866 1724 if ps not in proclist: 1867 1725 proclist.append(ps) 1868 1726 # get a list of data points for suspend and resume ··· 1907 1765 def debugPrint(self): 1908 1766 for p in self.sortedPhases(): 1909 1767 list = self.dmesg[p]['list'] 1910 - for devname in list: 1768 + for devname in sorted(list): 1911 1769 dev = list[devname] 1912 1770 if 'ftrace' in dev: 1913 1771 dev['ftrace'].debugPrint(' [%s]' % devname) ··· 2608 2466 # if there is 1 line per row, draw them the standard way 2609 2467 for t, p in standardphases: 2610 2468 for i in sorted(self.rowheight[t][p]): 2611 - self.rowheight[t][p][i] = self.bodyH/len(self.rowlines[t][p]) 2469 + self.rowheight[t][p][i] = float(self.bodyH)/len(self.rowlines[t][p]) 2612 2470 def createZoomBox(self, mode='command', testcount=1): 2613 2471 # Create bounding box, add buttons 2614 2472 html_zoombox = '<center><button id="zoomin">ZOOM IN +</button><button id="zoomout">ZOOM OUT -</button><button id="zoomdef">ZOOM 1:1</button></center>\n' ··· 2679 2537 cmdlinefmt = '^# command \| (?P<cmd>.*)' 2680 2538 kparamsfmt = '^# kparams \| (?P<kp>.*)' 2681 2539 devpropfmt = '# Device Properties: .*' 2540 + pinfofmt = '# platform-(?P<val>[a-z,A-Z,0-9]*): (?P<info>.*)' 2682 2541 tracertypefmt = '# tracer: (?P<t>.*)' 2683 2542 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$' 2684 2543 procexecfmt = 'ps - (?P<ps>.*)$' ··· 2714 2571 self.ftrace_line_fmt = self.ftrace_line_fmt_nop 2715 2572 else: 2716 2573 doError('Invalid tracer format: [%s]' % tracer) 2717 - def decode(self, data): 2718 - try: 2719 - out = base64.b64decode(data).decode('zlib') 2720 - except: 2721 - out = data 2722 - return out 2723 2574 def stampInfo(self, line): 2724 2575 if re.match(self.stampfmt, line): 2725 2576 self.stamp = line ··· 2797 2660 if len(self.mcelog) > data.testnumber: 2798 2661 m = re.match(self.mcelogfmt, self.mcelog[data.testnumber]) 2799 2662 if m: 2800 - data.mcelog = self.decode(m.group('m')) 2663 + data.mcelog = sv.b64unzip(m.group('m')) 2801 2664 # turbostat data 2802 2665 if len(self.turbostat) > data.testnumber: 2803 2666 m = re.match(self.tstatfmt, self.turbostat[data.testnumber]) ··· 2818 2681 m = re.match(self.testerrfmt, self.testerror[data.testnumber]) 2819 2682 if m: 2820 2683 data.enterfail = m.group('e') 2684 + def devprops(self, data): 2685 + props = dict() 2686 + devlist = data.split(';') 2687 + for dev in devlist: 2688 + f = dev.split(',') 2689 + if len(f) < 3: 2690 + continue 2691 + dev = f[0] 2692 + props[dev] = DevProps() 2693 + props[dev].altname = f[1] 2694 + if int(f[2]): 2695 + props[dev].isasync = True 2696 + else: 2697 + props[dev].isasync = False 2698 + return props 2699 + def parseDevprops(self, line, sv): 2700 + idx = line.index(': ') + 2 2701 + if idx >= len(line): 2702 + return 2703 + props = self.devprops(line[idx:]) 2704 + if sv.suspendmode == 'command' and 'testcommandstring' in props: 2705 + sv.testcommand = props['testcommandstring'].altname 2706 + sv.devprops = props 2707 + def parsePlatformInfo(self, line, sv): 2708 + m = re.match(self.pinfofmt, line) 2709 + if not m: 2710 + return 2711 + name, info = m.group('val'), m.group('info') 2712 + if name == 'devinfo': 2713 + sv.devprops = self.devprops(sv.b64unzip(info)) 2714 + return 2715 + elif name == 'testcmd': 2716 + sv.testcommand = info 2717 + return 2718 + field = info.split('|') 2719 + if len(field) < 2: 2720 + return 2721 + cmdline = field[0].strip() 2722 + output = sv.b64unzip(field[1].strip()) 2723 + sv.platinfo.append([name, cmdline, output]) 2821 2724 2822 2725 # Class: TestRun 2823 2726 # Description: ··· 2878 2701 process = Popen(c, shell=True, stdout=PIPE) 2879 2702 running = dict() 2880 2703 for line in process.stdout: 2881 - data = line.split() 2704 + data = ascii(line).split() 2882 2705 pid = data[0] 2883 2706 name = re.sub('[()]', '', data[1]) 2884 2707 user = int(data[13]) ··· 2982 2805 continue 2983 2806 # device properties line 2984 2807 if(re.match(tp.devpropfmt, line)): 2985 - devProps(line) 2808 + tp.parseDevprops(line, sysvals) 2809 + continue 2810 + # platform info line 2811 + if(re.match(tp.pinfofmt, line)): 2812 + tp.parsePlatformInfo(line, sysvals) 2986 2813 continue 2987 2814 # parse only valid lines, if this is not one move on 2988 2815 m = re.match(tp.ftrace_line_fmt, line) ··· 3083 2902 sysvals.setupAllKprobes() 3084 2903 ksuscalls = ['pm_prepare_console'] 3085 2904 krescalls = ['pm_restore_console'] 3086 - tracewatch = [] 2905 + tracewatch = ['irq_wakeup'] 3087 2906 if sysvals.usekprobes: 3088 2907 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend', 3089 2908 'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON', ··· 3109 2928 continue 3110 2929 # device properties line 3111 2930 if(re.match(tp.devpropfmt, line)): 3112 - devProps(line) 2931 + tp.parseDevprops(line, sysvals) 2932 + continue 2933 + # platform info line 2934 + if(re.match(tp.pinfofmt, line)): 2935 + tp.parsePlatformInfo(line, sysvals) 3113 2936 continue 3114 2937 # ignore all other commented lines 3115 2938 if line[0] == '#': ··· 3186 3001 isbegin = False 3187 3002 else: 3188 3003 continue 3189 - m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name) 3190 - if(m): 3191 - val = m.group('val') 3192 - if val == '0': 3193 - name = m.group('name') 3194 - else: 3195 - name = m.group('name')+'['+val+']' 3004 + if '[' in t.name: 3005 + m = re.match('(?P<name>.*)\[.*', t.name) 3196 3006 else: 3197 3007 m = re.match('(?P<name>.*) .*', t.name) 3198 - name = m.group('name') 3008 + name = m.group('name') 3199 3009 # ignore these events 3200 3010 if(name.split('[')[0] in tracewatch): 3201 3011 continue ··· 3225 3045 elif(re.match('machine_suspend\[.*', t.name)): 3226 3046 if(isbegin): 3227 3047 lp = data.lastPhase() 3048 + if lp == 'resume_machine': 3049 + data.dmesg[lp]['end'] = t.time 3228 3050 phase = data.setPhase('suspend_machine', data.dmesg[lp]['end'], True) 3229 3051 data.setPhase(phase, t.time, False) 3230 3052 if data.tSuspended == 0: ··· 3395 3213 # add the traceevent data to the device hierarchy 3396 3214 if(sysvals.usetraceevents): 3397 3215 # add actual trace funcs 3398 - for name in test.ttemp: 3216 + for name in sorted(test.ttemp): 3399 3217 for event in test.ttemp[name]: 3400 3218 data.newActionGlobal(name, event['begin'], event['end'], event['pid']) 3401 3219 # add the kprobe based virtual tracefuncs as actual devices 3402 - for key in tp.ktemp: 3220 + for key in sorted(tp.ktemp): 3403 3221 name, pid = key 3404 3222 if name not in sysvals.tracefuncs: 3405 3223 continue ··· 3413 3231 data.newActionGlobal(e['name'], kb, ke, pid, color) 3414 3232 # add config base kprobes and dev kprobes 3415 3233 if sysvals.usedevsrc: 3416 - for key in tp.ktemp: 3234 + for key in sorted(tp.ktemp): 3417 3235 name, pid = key 3418 3236 if name in sysvals.tracefuncs or name not in sysvals.dev_tracefuncs: 3419 3237 continue ··· 3426 3244 if sysvals.usecallgraph: 3427 3245 # add the callgraph data to the device hierarchy 3428 3246 sortlist = dict() 3429 - for key in test.ftemp: 3247 + for key in sorted(test.ftemp): 3430 3248 proc, pid = key 3431 3249 for cg in test.ftemp[key]: 3432 3250 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0): ··· 3764 3582 # if trace events are not available, these are better than nothing 3765 3583 if(not sysvals.usetraceevents): 3766 3584 # look for known actions 3767 - for a in at: 3585 + for a in sorted(at): 3768 3586 if(re.match(at[a]['smsg'], msg)): 3769 3587 if(a not in actions): 3770 3588 actions[a] = [] ··· 3823 3641 data.tResumed = data.tSuspended 3824 3642 3825 3643 # fill in any actions we've found 3826 - for name in actions: 3644 + for name in sorted(actions): 3827 3645 for event in actions[name]: 3828 3646 data.newActionGlobal(name, event['begin'], event['end']) 3829 3647 ··· 3943 3761 if lastmode and lastmode != mode and num > 0: 3944 3762 for i in range(2): 3945 3763 s = sorted(tMed[i]) 3946 - list[lastmode]['med'][i] = s[int(len(s)/2)] 3764 + list[lastmode]['med'][i] = s[int(len(s)//2)] 3947 3765 iMed[i] = tMed[i][list[lastmode]['med'][i]] 3948 3766 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num] 3949 3767 list[lastmode]['min'] = tMin ··· 3985 3803 if lastmode and num > 0: 3986 3804 for i in range(2): 3987 3805 s = sorted(tMed[i]) 3988 - list[lastmode]['med'][i] = s[int(len(s)/2)] 3806 + list[lastmode]['med'][i] = s[int(len(s)//2)] 3989 3807 iMed[i] = tMed[i][list[lastmode]['med'][i]] 3990 3808 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num] 3991 3809 list[lastmode]['min'] = tMin ··· 4027 3845 '</tr>\n' 4028 3846 headnone = '<tr class="head"><td>{0}</td><td>{1}</td><td colspan='+\ 4029 3847 colspan+'></td></tr>\n' 4030 - for mode in list: 3848 + for mode in sorted(list): 4031 3849 # header line for each suspend mode 4032 3850 num = 0 4033 3851 tAvg, tMin, tMax, tMed = list[mode]['avg'], list[mode]['min'],\ ··· 4126 3944 th.format('Average Time') + th.format('Count') +\ 4127 3945 th.format('Worst Time') + th.format('Host (worst time)') +\ 4128 3946 th.format('Link (worst time)') + '</tr>\n' 4129 - for name in sorted(devlist, key=lambda k:devlist[k]['worst'], reverse=True): 3947 + for name in sorted(devlist, key=lambda k:(devlist[k]['worst'], \ 3948 + devlist[k]['total'], devlist[k]['name']), reverse=True): 4130 3949 data = devall[type][name] 4131 3950 data['average'] = data['total'] / data['count'] 4132 3951 if data['average'] < limit: ··· 4268 4085 if(tTotal == 0): 4269 4086 doError('No timeline data') 4270 4087 if(len(data.tLow) > 0): 4271 - low_time = '|'.join(data.tLow) 4088 + low_time = '+'.join(data.tLow) 4272 4089 if sysvals.suspendmode == 'command': 4273 4090 run_time = '%.0f'%((data.end-data.start)*1000) 4274 4091 if sysvals.testcommand: ··· 4334 4151 for group in data.devicegroups: 4335 4152 devlist = [] 4336 4153 for phase in group: 4337 - for devname in data.tdevlist[phase]: 4154 + for devname in sorted(data.tdevlist[phase]): 4338 4155 d = DevItem(data.testnumber, phase, data.dmesg[phase]['list'][devname]) 4339 4156 devlist.append(d) 4340 4157 if d.isa('kth'): ··· 4413 4230 for b in phases[dir]: 4414 4231 # draw the devices for this phase 4415 4232 phaselist = data.dmesg[b]['list'] 4416 - for d in data.tdevlist[b]: 4233 + for d in sorted(data.tdevlist[b]): 4417 4234 name = d 4418 4235 drv = '' 4419 4236 dev = phaselist[d] ··· 5154 4971 if mode == 'freeze' and sysvals.haveTurbostat(): 5155 4972 # execution will pause here 5156 4973 turbo = sysvals.turbostat() 5157 - if '|' in turbo: 4974 + if turbo: 5158 4975 tdata['turbo'] = turbo 5159 - else: 5160 - tdata['error'] = turbo 5161 4976 else: 5162 - if sysvals.haveTurbostat(): 5163 - sysvals.vprint('WARNING: ignoring turbostat in mode "%s"' % mode) 5164 4977 pf = open(sysvals.powerfile, 'w') 5165 4978 pf.write(mode) 5166 4979 # execution will pause here ··· 5203 5024 op.write(line) 5204 5025 op.close() 5205 5026 sysvals.fsetVal('', 'trace') 5206 - devProps() 5027 + sysvals.platforminfo() 5207 5028 return testdata 5208 5029 5209 5030 def readFile(file): ··· 5219 5040 # The time string, e.g. "1901m16s" 5220 5041 def ms2nice(val): 5221 5042 val = int(val) 5222 - h = val / 3600000 5223 - m = (val / 60000) % 60 5224 - s = (val / 1000) % 60 5043 + h = val // 3600000 5044 + m = (val // 60000) % 60 5045 + s = (val // 1000) % 60 5225 5046 if h > 0: 5226 5047 return '%d:%02d:%02d' % (h, m, s) 5227 5048 if m > 0: ··· 5293 5114 for i in sorted(lines): 5294 5115 print(lines[i]) 5295 5116 return res 5296 - 5297 - # Function: devProps 5298 - # Description: 5299 - # Retrieve a list of properties for all devices in the trace log 5300 - def devProps(data=0): 5301 - props = dict() 5302 - 5303 - if data: 5304 - idx = data.index(': ') + 2 5305 - if idx >= len(data): 5306 - return 5307 - devlist = data[idx:].split(';') 5308 - for dev in devlist: 5309 - f = dev.split(',') 5310 - if len(f) < 3: 5311 - continue 5312 - dev = f[0] 5313 - props[dev] = DevProps() 5314 - props[dev].altname = f[1] 5315 - if int(f[2]): 5316 - props[dev].async = True 5317 - else: 5318 - props[dev].async = False 5319 - sysvals.devprops = props 5320 - if sysvals.suspendmode == 'command' and 'testcommandstring' in props: 5321 - sysvals.testcommand = props['testcommandstring'].altname 5322 - return 5323 - 5324 - if(os.path.exists(sysvals.ftracefile) == False): 5325 - doError('%s does not exist' % sysvals.ftracefile) 5326 - 5327 - # first get the list of devices we need properties for 5328 - msghead = 'Additional data added by AnalyzeSuspend' 5329 - alreadystamped = False 5330 - tp = TestProps() 5331 - tf = sysvals.openlog(sysvals.ftracefile, 'r') 5332 - for line in tf: 5333 - if msghead in line: 5334 - alreadystamped = True 5335 - continue 5336 - # determine the trace data type (required for further parsing) 5337 - m = re.match(tp.tracertypefmt, line) 5338 - if(m): 5339 - tp.setTracerType(m.group('t')) 5340 - continue 5341 - # parse only valid lines, if this is not one move on 5342 - m = re.match(tp.ftrace_line_fmt, line) 5343 - if(not m or 'device_pm_callback_start' not in line): 5344 - continue 5345 - m = re.match('.*: (?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*', m.group('msg')); 5346 - if(not m): 5347 - continue 5348 - dev = m.group('d') 5349 - if dev not in props: 5350 - props[dev] = DevProps() 5351 - tf.close() 5352 - 5353 - if not alreadystamped and sysvals.suspendmode == 'command': 5354 - out = '#\n# '+msghead+'\n# Device Properties: ' 5355 - out += 'testcommandstring,%s,0;' % (sysvals.testcommand) 5356 - with sysvals.openlog(sysvals.ftracefile, 'a') as fp: 5357 - fp.write(out+'\n') 5358 - sysvals.devprops = props 5359 - return 5360 - 5361 - # now get the syspath for each of our target devices 5362 - for dirname, dirnames, filenames in os.walk('/sys/devices'): 5363 - if(re.match('.*/power', dirname) and 'async' in filenames): 5364 - dev = dirname.split('/')[-2] 5365 - if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)): 5366 - props[dev].syspath = dirname[:-6] 5367 - 5368 - # now fill in the properties for our target devices 5369 - for dev in props: 5370 - dirname = props[dev].syspath 5371 - if not dirname or not os.path.exists(dirname): 5372 - continue 5373 - with open(dirname+'/power/async') as fp: 5374 - text = fp.read() 5375 - props[dev].async = False 5376 - if 'enabled' in text: 5377 - props[dev].async = True 5378 - fields = os.listdir(dirname) 5379 - if 'product' in fields: 5380 - with open(dirname+'/product') as fp: 5381 - props[dev].altname = fp.read() 5382 - elif 'name' in fields: 5383 - with open(dirname+'/name') as fp: 5384 - props[dev].altname = fp.read() 5385 - elif 'model' in fields: 5386 - with open(dirname+'/model') as fp: 5387 - props[dev].altname = fp.read() 5388 - elif 'description' in fields: 5389 - with open(dirname+'/description') as fp: 5390 - props[dev].altname = fp.read() 5391 - elif 'id' in fields: 5392 - with open(dirname+'/id') as fp: 5393 - props[dev].altname = fp.read() 5394 - elif 'idVendor' in fields and 'idProduct' in fields: 5395 - idv, idp = '', '' 5396 - with open(dirname+'/idVendor') as fp: 5397 - idv = fp.read().strip() 5398 - with open(dirname+'/idProduct') as fp: 5399 - idp = fp.read().strip() 5400 - props[dev].altname = '%s:%s' % (idv, idp) 5401 - 5402 - if props[dev].altname: 5403 - out = props[dev].altname.strip().replace('\n', ' ') 5404 - out = out.replace(',', ' ') 5405 - out = out.replace(';', ' ') 5406 - props[dev].altname = out 5407 - 5408 - # and now write the data to the ftrace file 5409 - if not alreadystamped: 5410 - out = '#\n# '+msghead+'\n# Device Properties: ' 5411 - for dev in sorted(props): 5412 - out += props[dev].out(dev) 5413 - with sysvals.openlog(sysvals.ftracefile, 'a') as fp: 5414 - fp.write(out+'\n') 5415 - 5416 - sysvals.devprops = props 5417 5117 5418 5118 # Function: getModes 5419 5119 # Description: ··· 5397 5339 # search for either an SM table or DMI table 5398 5340 i = base = length = num = 0 5399 5341 while(i < memsize): 5400 - if buf[i:i+4] == '_SM_' and i < memsize - 16: 5342 + if buf[i:i+4] == b'_SM_' and i < memsize - 16: 5401 5343 length = struct.unpack('H', buf[i+22:i+24])[0] 5402 5344 base, num = struct.unpack('IH', buf[i+24:i+30]) 5403 5345 break 5404 - elif buf[i:i+5] == '_DMI_': 5346 + elif buf[i:i+5] == b'_DMI_': 5405 5347 length = struct.unpack('H', buf[i+6:i+8])[0] 5406 5348 base, num = struct.unpack('IH', buf[i+8:i+14]) 5407 5349 break ··· 5434 5376 if 0 == struct.unpack('H', buf[n:n+2])[0]: 5435 5377 break 5436 5378 n += 1 5437 - data = buf[i+size:n+2].split('\0') 5379 + data = buf[i+size:n+2].split(b'\0') 5438 5380 for name in info: 5439 5381 itype, idxadr = info[name] 5440 5382 if itype == type: 5441 - idx = struct.unpack('B', buf[i+idxadr])[0] 5383 + idx = struct.unpack('B', buf[i+idxadr:i+idxadr+1])[0] 5442 5384 if idx > 0 and idx < len(data) - 1: 5443 - s = data[idx-1].strip() 5444 - if s and s.lower() != 'to be filled by o.e.m.': 5445 - out[name] = data[idx-1] 5385 + s = data[idx-1].decode('utf-8') 5386 + if s.strip() and s.strip().lower() != 'to be filled by o.e.m.': 5387 + out[name] = s 5446 5388 i = n + 2 5447 5389 count += 1 5448 5390 return out ··· 5467 5409 return (ac, charge) 5468 5410 5469 5411 def displayControl(cmd): 5470 - xset, ret = 'xset -d :0.0 {0}', 0 5412 + xset, ret = 'timeout 10 xset -d :0.0 {0}', 0 5471 5413 if sysvals.sudouser: 5472 5414 xset = 'sudo -u %s %s' % (sysvals.sudouser, xset) 5473 5415 if cmd == 'init': ··· 5491 5433 fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout 5492 5434 ret = 'unknown' 5493 5435 for line in fp: 5494 - m = re.match('[\s]*Monitor is (?P<m>.*)', line) 5436 + m = re.match('[\s]*Monitor is (?P<m>.*)', ascii(line)) 5495 5437 if(m and len(m.group('m')) >= 2): 5496 5438 out = m.group('m').lower() 5497 5439 ret = out[3:] if out[0:2] == 'in' else out ··· 5553 5495 ' OEM Revision : %u\n'\ 5554 5496 ' Creator ID : %s\n'\ 5555 5497 ' Creator Revision : 0x%x\n'\ 5556 - '' % (table[0], table[0], table[1], table[2], table[3], 5557 - table[4], table[5], table[6], table[7], table[8])) 5498 + '' % (ascii(table[0]), ascii(table[0]), table[1], table[2], 5499 + table[3], ascii(table[4]), ascii(table[5]), table[6], 5500 + ascii(table[7]), table[8])) 5558 5501 5559 - if(table[0] != 'FPDT'): 5502 + if(table[0] != b'FPDT'): 5560 5503 if(output): 5561 5504 doError('Invalid FPDT table') 5562 5505 return False ··· 5589 5530 return [0, 0] 5590 5531 rechead = struct.unpack('4sI', first) 5591 5532 recdata = fp.read(rechead[1]-8) 5592 - if(rechead[0] == 'FBPT'): 5593 - record = struct.unpack('HBBIQQQQQ', recdata) 5533 + if(rechead[0] == b'FBPT'): 5534 + record = struct.unpack('HBBIQQQQQ', recdata[:48]) 5594 5535 if(output): 5595 5536 pprint('%s (%s)\n'\ 5596 5537 ' Reset END : %u ns\n'\ ··· 5598 5539 ' OS Loader StartImage Start : %u ns\n'\ 5599 5540 ' ExitBootServices Entry : %u ns\n'\ 5600 5541 ' ExitBootServices Exit : %u ns'\ 5601 - '' % (rectype[header[0]], rechead[0], record[4], record[5], 5542 + '' % (rectype[header[0]], ascii(rechead[0]), record[4], record[5], 5602 5543 record[6], record[7], record[8])) 5603 - elif(rechead[0] == 'S3PT'): 5544 + elif(rechead[0] == b'S3PT'): 5604 5545 if(output): 5605 - pprint('%s (%s)' % (rectype[header[0]], rechead[0])) 5546 + pprint('%s (%s)' % (rectype[header[0]], ascii(rechead[0]))) 5606 5547 j = 0 5607 5548 while(j < len(recdata)): 5608 5549 prechead = struct.unpack('HBB', recdata[j:j+4]) ··· 5748 5689 def getArgInt(name, args, min, max, main=True): 5749 5690 if main: 5750 5691 try: 5751 - arg = args.next() 5692 + arg = next(args) 5752 5693 except: 5753 5694 doError(name+': no argument supplied', True) 5754 5695 else: ··· 5767 5708 def getArgFloat(name, args, min, max, main=True): 5768 5709 if main: 5769 5710 try: 5770 - arg = args.next() 5711 + arg = next(args) 5771 5712 except: 5772 5713 doError(name+': no argument supplied', True) 5773 5714 else: ··· 5796 5737 parseKernelLog(data) 5797 5738 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)): 5798 5739 appendIncompleteTraceLog(testruns) 5740 + shown = ['bios', 'biosdate', 'cpu', 'host', 'kernel', 'man', 'memfr', 5741 + 'memsz', 'mode', 'numcpu', 'plat', 'time'] 5799 5742 sysvals.vprint('System Info:') 5800 5743 for key in sorted(sysvals.stamp): 5801 - sysvals.vprint(' %-8s : %s' % (key.upper(), sysvals.stamp[key])) 5744 + if key in shown: 5745 + sysvals.vprint(' %-8s : %s' % (key.upper(), sysvals.stamp[key])) 5802 5746 if sysvals.kparams: 5803 5747 sysvals.vprint('Kparams:\n %s' % sysvals.kparams) 5804 5748 sysvals.vprint('Command:\n %s' % sysvals.cmdline) ··· 5830 5768 (w[0], w[1]) 5831 5769 sysvals.vprint(s) 5832 5770 data.printDetails() 5771 + if len(sysvals.platinfo) > 0: 5772 + sysvals.vprint('\nPlatform Info:') 5773 + for info in sysvals.platinfo: 5774 + sysvals.vprint(info[0]+' - '+info[1]) 5775 + sysvals.vprint(info[2]) 5776 + sysvals.vprint('') 5833 5777 if sysvals.cgdump: 5834 5778 for data in testruns: 5835 5779 data.debugPrint() ··· 6019 5951 worst[d] = {'name':'', 'time': 0.0} 6020 5952 dev = devices[d] if d in devices else 0 6021 5953 if dev and len(dev.keys()) > 0: 6022 - n = sorted(dev, key=dev.get, reverse=True)[0] 5954 + n = sorted(dev, key=lambda k:(dev[k], k), reverse=True)[0] 6023 5955 worst[d]['name'], worst[d]['time'] = n, dev[n] 6024 5956 data = { 6025 5957 'mode': stmp[2], ··· 6044 5976 data['funclist'] = find_in_html(html, '<div title="', '" class="traceevent"', False) 6045 5977 return data 6046 5978 6047 - def genHtml(subdir): 5979 + def genHtml(subdir, force=False): 6048 5980 for dirname, dirnames, filenames in os.walk(subdir): 6049 5981 sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = '' 6050 5982 for filename in filenames: ··· 6054 5986 sysvals.ftracefile = os.path.join(dirname, filename) 6055 5987 sysvals.setOutputFile() 6056 5988 if sysvals.ftracefile and sysvals.htmlfile and \ 6057 - not os.path.exists(sysvals.htmlfile): 5989 + (force or not os.path.exists(sysvals.htmlfile)): 6058 5990 pprint('FTRACE: %s' % sysvals.ftracefile) 6059 5991 if sysvals.dmesgfile: 6060 5992 pprint('DMESG : %s' % sysvals.dmesgfile) ··· 6110 6042 # Description: 6111 6043 # Configure the script via the info in a config file 6112 6044 def configFromFile(file): 6113 - Config = ConfigParser.ConfigParser() 6045 + Config = configparser.ConfigParser() 6114 6046 6115 6047 Config.read(file) 6116 6048 sections = Config.sections() ··· 6338 6270 ' default: suspend-{date}-{time}\n'\ 6339 6271 ' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)\n'\ 6340 6272 ' -addlogs Add the dmesg and ftrace logs to the html output\n'\ 6341 - ' -turbostat Use turbostat to execute the command in freeze mode (default: disabled)\n'\ 6273 + ' -noturbostat Dont use turbostat in freeze mode (default: disabled)\n'\ 6342 6274 ' -srgap Add a visible gap in the timeline between sus/res (default: disabled)\n'\ 6343 6275 ' -skiphtml Run the test and capture the trace logs, but skip the timeline (default: disabled)\n'\ 6344 6276 ' -result fn Export a results table to a text file for parsing.\n'\ ··· 6408 6340 for arg in args: 6409 6341 if(arg == '-m'): 6410 6342 try: 6411 - val = args.next() 6343 + val = next(args) 6412 6344 except: 6413 6345 doError('No mode supplied', True) 6414 6346 if val == 'command' and not sysvals.testcommand: ··· 6452 6384 sysvals.dmesglog = True 6453 6385 elif(arg == '-addlogftrace'): 6454 6386 sysvals.ftracelog = True 6455 - elif(arg == '-turbostat'): 6456 - sysvals.tstat = True 6457 - if not sysvals.haveTurbostat(): 6458 - doError('Turbostat command not found') 6387 + elif(arg == '-noturbostat'): 6388 + sysvals.tstat = False 6459 6389 elif(arg == '-verbose'): 6460 6390 sysvals.verbose = True 6461 6391 elif(arg == '-proc'): ··· 6466 6400 sysvals.gzip = True 6467 6401 elif(arg == '-rs'): 6468 6402 try: 6469 - val = args.next() 6403 + val = next(args) 6470 6404 except: 6471 6405 doError('-rs requires "enable" or "disable"', True) 6472 6406 if val.lower() in switchvalues: ··· 6478 6412 doError('invalid option: %s, use "enable/disable" or "on/off"' % val, True) 6479 6413 elif(arg == '-display'): 6480 6414 try: 6481 - val = args.next() 6415 + val = next(args) 6482 6416 except: 6483 6417 doError('-display requires an mode value', True) 6484 6418 disopt = ['on', 'off', 'standby', 'suspend'] ··· 6489 6423 sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000) 6490 6424 elif(arg == '-rtcwake'): 6491 6425 try: 6492 - val = args.next() 6426 + val = next(args) 6493 6427 except: 6494 6428 doError('No rtcwake time supplied', True) 6495 6429 if val.lower() in switchoff: ··· 6509 6443 sysvals.cgtest = getArgInt('-cgtest', args, 0, 1) 6510 6444 elif(arg == '-cgphase'): 6511 6445 try: 6512 - val = args.next() 6446 + val = next(args) 6513 6447 except: 6514 6448 doError('No phase name supplied', True) 6515 6449 d = Data(0) ··· 6519 6453 sysvals.cgphase = val 6520 6454 elif(arg == '-cgfilter'): 6521 6455 try: 6522 - val = args.next() 6456 + val = next(args) 6523 6457 except: 6524 6458 doError('No callgraph functions supplied', True) 6525 6459 sysvals.setCallgraphFilter(val) 6526 6460 elif(arg == '-skipkprobe'): 6527 6461 try: 6528 - val = args.next() 6462 + val = next(args) 6529 6463 except: 6530 6464 doError('No kprobe functions supplied', True) 6531 6465 sysvals.skipKprobes(val) 6532 6466 elif(arg == '-cgskip'): 6533 6467 try: 6534 - val = args.next() 6468 + val = next(args) 6535 6469 except: 6536 6470 doError('No file supplied', True) 6537 6471 if val.lower() in switchoff: ··· 6546 6480 sysvals.callloopmaxlen = getArgFloat('-callloop-maxlen', args, 0.0, 1.0) 6547 6481 elif(arg == '-cmd'): 6548 6482 try: 6549 - val = args.next() 6483 + val = next(args) 6550 6484 except: 6551 6485 doError('No command string supplied', True) 6552 6486 sysvals.testcommand = val ··· 6561 6495 sysvals.multitest['delay'] = getArgInt('-multi n d (delay between tests)', args, 0, 3600) 6562 6496 elif(arg == '-o'): 6563 6497 try: 6564 - val = args.next() 6498 + val = next(args) 6565 6499 except: 6566 6500 doError('No subdirectory name supplied', True) 6567 6501 sysvals.outdir = sysvals.setOutputFolder(val) 6568 6502 elif(arg == '-config'): 6569 6503 try: 6570 - val = args.next() 6504 + val = next(args) 6571 6505 except: 6572 6506 doError('No text file supplied', True) 6573 6507 file = sysvals.configFile(val) ··· 6576 6510 configFromFile(file) 6577 6511 elif(arg == '-fadd'): 6578 6512 try: 6579 - val = args.next() 6513 + val = next(args) 6580 6514 except: 6581 6515 doError('No text file supplied', True) 6582 6516 file = sysvals.configFile(val) ··· 6585 6519 sysvals.addFtraceFilterFunctions(file) 6586 6520 elif(arg == '-dmesg'): 6587 6521 try: 6588 - val = args.next() 6522 + val = next(args) 6589 6523 except: 6590 6524 doError('No dmesg file supplied', True) 6591 6525 sysvals.notestrun = True ··· 6594 6528 doError('%s does not exist' % sysvals.dmesgfile) 6595 6529 elif(arg == '-ftrace'): 6596 6530 try: 6597 - val = args.next() 6531 + val = next(args) 6598 6532 except: 6599 6533 doError('No ftrace file supplied', True) 6600 6534 sysvals.notestrun = True ··· 6603 6537 doError('%s does not exist' % sysvals.ftracefile) 6604 6538 elif(arg == '-summary'): 6605 6539 try: 6606 - val = args.next() 6540 + val = next(args) 6607 6541 except: 6608 6542 doError('No directory supplied', True) 6609 6543 cmd = 'summary' ··· 6613 6547 doError('%s is not accesible' % val) 6614 6548 elif(arg == '-filter'): 6615 6549 try: 6616 - val = args.next() 6550 + val = next(args) 6617 6551 except: 6618 6552 doError('No devnames supplied', True) 6619 6553 sysvals.setDeviceFilter(val) 6620 6554 elif(arg == '-result'): 6621 6555 try: 6622 - val = args.next() 6556 + val = next(args) 6623 6557 except: 6624 6558 doError('No result file supplied', True) 6625 6559 sysvals.result = val