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

Pull power management updates from Rafael Wysocki:
"These update cpufreq (core and drivers), cpuidle (polling state
implementation and the PSCI driver), the OPP (operating performance
points) framework, devfreq (core and drivers), the power capping RAPL
(Running Average Power Limit) driver, the Energy Model support, the
generic power domains (genpd) framework, the ACPI device power
management, the core system-wide suspend code and power management
utilities.

Specifics:

- Use local_clock() instead of jiffies in the cpufreq statistics to
improve accuracy (Viresh Kumar).

- Fix up OPP usage in the cpufreq-dt and qcom-cpufreq-nvmem cpufreq
drivers (Viresh Kumar).

- Clean up the cpufreq core, the intel_pstate driver and the
schedutil cpufreq governor (Rafael Wysocki).

- Fix up error code paths in the sti-cpufreq and mediatek cpufreq
drivers (Yangtao Li, Qinglang Miao).

- Fix cpufreq_online() to return error codes instead of success (0)
in all cases when it fails (Wang ShaoBo).

- Add mt8167 support to the mediatek cpufreq driver and blacklist
mt8516 in the cpufreq-dt-platdev driver (Fabien Parent).

- Modify the tegra194 cpufreq driver to always return values from the
frequency table as the current frequency and clean up that driver
(Sumit Gupta, Jon Hunter).

- Modify the arm_scmi cpufreq driver to allow it to discover the
power scale present in the performance protocol and provide this
information to the Energy Model (Lukasz Luba).

- Add missing MODULE_DEVICE_TABLE to several cpufreq drivers (Pali
Rohár).

- Clean up the CPPC cpufreq driver (Ionela Voinescu).

- Fix NVMEM_IMX_OCOTP dependency in the imx cpufreq driver (Arnd
Bergmann).

- Rework the poling interval selection for the polling state in
cpuidle (Mel Gorman).

- Enable suspend-to-idle for PSCI OSI mode in the PSCI cpuidle driver
(Ulf Hansson).

- Modify the OPP framework to support empty (node-less) OPP tables in
DT for passing dependency information (Nicola Mazzucato).

- Fix potential lockdep issue in the OPP core and clean up the OPP
core (Viresh Kumar).

- Modify dev_pm_opp_put_regulators() to accept a NULL argument and
update its users accordingly (Viresh Kumar).

- Add frequency changes tracepoint to devfreq (Matthias Kaehlcke).

- Add support for governor feature flags to devfreq, make devfreq
sysfs file permissions depend on the governor and clean up the
devfreq core (Chanwoo Choi).

- Clean up the tegra20 devfreq driver and deprecate it to allow
another driver based on EMC_STAT to be used instead of it (Dmitry
Osipenko).

- Add interconnect support to the tegra30 devfreq driver, allow it to
take the interconnect and OPP information from DT and clean it up
(Dmitry Osipenko).

- Add interconnect support to the exynos-bus devfreq driver along
with interconnect properties documentation (Sylwester Nawrocki).

- Add suport for AMD Fam17h and Fam19h processors to the RAPL power
capping driver (Victor Ding, Kim Phillips).

- Fix handling of overly long constraint names in the powercap
framework (Lukasz Luba).

- Fix the wakeup configuration handling for bridges in the ACPI
device power management core (Rafael Wysocki).

- Add support for using an abstract scale for power units in the
Energy Model (EM) and document it (Lukasz Luba).

- Add em_cpu_energy() micro-optimization to the EM (Pavankumar
Kondeti).

- Modify the generic power domains (genpd) framwework to support
suspend-to-idle (Ulf Hansson).

- Fix creation of debugfs nodes in genpd (Thierry Strudel).

- Clean up genpd (Lina Iyer).

- Clean up the core system-wide suspend code and make it print driver
flags for devices with debug enabled (Alex Shi, Patrice Chotard,
Chen Yu).

- Modify the ACPI system reboot code to make it prepare for system
power off to avoid confusing the platform firmware (Kai-Heng Feng).

- Update the pm-graph (multiple changes, mostly usability-related)
and cpupower (online and offline CPU information support) PM
utilities (Todd Brandt, Brahadambal Srinivasan)"

* tag 'pm-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (86 commits)
cpufreq: Fix cpufreq_online() return value on errors
cpufreq: Fix up several kerneldoc comments
cpufreq: stats: Use local_clock() instead of jiffies
cpufreq: schedutil: Simplify sugov_update_next_freq()
cpufreq: intel_pstate: Simplify intel_cpufreq_update_pstate()
PM: domains: create debugfs nodes when adding power domains
opp: of: Allow empty opp-table with opp-shared
dt-bindings: opp: Allow empty OPP tables
media: venus: dev_pm_opp_put_*() accepts NULL argument
drm/panfrost: dev_pm_opp_put_*() accepts NULL argument
drm/lima: dev_pm_opp_put_*() accepts NULL argument
PM / devfreq: exynos: dev_pm_opp_put_*() accepts NULL argument
cpufreq: qcom-cpufreq-nvmem: dev_pm_opp_put_*() accepts NULL argument
cpufreq: dt: dev_pm_opp_put_regulators() accepts NULL argument
opp: Allow dev_pm_opp_put_*() APIs to accept NULL opp_table
opp: Don't create an OPP table from dev_pm_opp_get_opp_table()
cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP table
opp: Reduce the size of critical section in _opp_kref_release()
PM / EM: Micro optimization in em_cpu_energy
cpufreq: arm_scmi: Discover the power scale in performance protocol
...

+1694 -1212
+32 -22
Documentation/ABI/testing/sysfs-class-devfreq
··· 37 37 The /sys/class/devfreq/.../target_freq shows the next governor 38 38 predicted target frequency of the corresponding devfreq object. 39 39 40 - What: /sys/class/devfreq/.../polling_interval 41 - Date: September 2011 42 - Contact: MyungJoo Ham <myungjoo.ham@samsung.com> 43 - Description: 44 - The /sys/class/devfreq/.../polling_interval shows and sets 45 - the requested polling interval of the corresponding devfreq 46 - object. The values are represented in ms. If the value is 47 - less than 1 jiffy, it is considered to be 0, which means 48 - no polling. This value is meaningless if the governor is 49 - not polling; thus. If the governor is not using 50 - devfreq-provided central polling 51 - (/sys/class/devfreq/.../central_polling is 0), this value 52 - may be useless. 53 - 54 40 What: /sys/class/devfreq/.../trans_stat 55 41 Date: October 2012 56 42 Contact: MyungJoo Ham <myungjoo.ham@samsung.com> ··· 51 65 as following:: 52 66 53 67 echo 0 > /sys/class/devfreq/.../trans_stat 54 - 55 - What: /sys/class/devfreq/.../userspace/set_freq 56 - Date: September 2011 57 - Contact: MyungJoo Ham <myungjoo.ham@samsung.com> 58 - Description: 59 - The /sys/class/devfreq/.../userspace/set_freq shows and 60 - sets the requested frequency for the devfreq object if 61 - userspace governor is in effect. 62 68 63 69 What: /sys/class/devfreq/.../available_frequencies 64 70 Date: October 2012 ··· 88 110 The max_freq overrides min_freq because max_freq may be 89 111 used to throttle devices to avoid overheating. 90 112 113 + What: /sys/class/devfreq/.../polling_interval 114 + Date: September 2011 115 + Contact: MyungJoo Ham <myungjoo.ham@samsung.com> 116 + Description: 117 + The /sys/class/devfreq/.../polling_interval shows and sets 118 + the requested polling interval of the corresponding devfreq 119 + object. The values are represented in ms. If the value is 120 + less than 1 jiffy, it is considered to be 0, which means 121 + no polling. This value is meaningless if the governor is 122 + not polling; thus. If the governor is not using 123 + devfreq-provided central polling 124 + (/sys/class/devfreq/.../central_polling is 0), this value 125 + may be useless. 126 + 127 + A list of governors that support the node: 128 + - simple_ondmenad 129 + - tegra_actmon 130 + 131 + What: /sys/class/devfreq/.../userspace/set_freq 132 + Date: September 2011 133 + Contact: MyungJoo Ham <myungjoo.ham@samsung.com> 134 + Description: 135 + The /sys/class/devfreq/.../userspace/set_freq shows and 136 + sets the requested frequency for the devfreq object if 137 + userspace governor is in effect. 138 + 139 + A list of governors that support the node: 140 + - userspace 141 + 91 142 What: /sys/class/devfreq/.../timer 92 143 Date: July 2020 93 144 Contact: Chanwoo Choi <cw00.choi@samsung.com> ··· 129 122 130 123 echo deferrable > /sys/class/devfreq/.../timer 131 124 echo delayed > /sys/class/devfreq/.../timer 125 + 126 + A list of governors that support the node: 127 + - simple_ondemand
+69 -2
Documentation/devicetree/bindings/devfreq/exynos-bus.txt
··· 51 51 - exynos,saturation-ratio: the percentage value which is used to calibrate 52 52 the performance count against total cycle count. 53 53 54 + Optional properties for the interconnect functionality (QoS frequency 55 + constraints): 56 + - #interconnect-cells: should be 0. 57 + - interconnects: as documented in ../interconnect.txt, describes a path at the 58 + higher level interconnects used by this interconnect provider. 59 + If this interconnect provider is directly linked to a top level interconnect 60 + provider the property contains only one phandle. The provider extends 61 + the interconnect graph by linking its node to a node registered by provider 62 + pointed to by first phandle in the 'interconnects' property. 63 + 64 + - samsung,data-clock-ratio: ratio of the data throughput in B/s to minimum data 65 + clock frequency in Hz, default value is 8 when this property is missing. 66 + 54 67 Detailed correlation between sub-blocks and power line according to Exynos SoC: 55 68 - In case of Exynos3250, there are two power line as following: 56 69 VDD_MIF |--- DMC ··· 148 135 |--- PERIC (Fixed clock rate) 149 136 |--- FSYS (Fixed clock rate) 150 137 151 - Example1: 138 + Example 1: 152 139 Show the AXI buses of Exynos3250 SoC. Exynos3250 divides the buses to 153 140 power line (regulator). The MIF (Memory Interface) AXI bus is used to 154 141 transfer data between DRAM and CPU and uses the VDD_MIF regulator. ··· 197 184 |L5 |200000 |200000 |400000 |300000 | ||1000000 | 198 185 ---------------------------------------------------------- 199 186 200 - Example2 : 187 + Example 2: 201 188 The bus of DMC (Dynamic Memory Controller) block in exynos3250.dtsi 202 189 is listed below: 203 190 ··· 431 418 &bus_mfc { 432 419 devfreq = <&bus_leftbus>; 433 420 status = "okay"; 421 + }; 422 + 423 + Example 3: 424 + An interconnect path "bus_display -- bus_leftbus -- bus_dmc" on 425 + Exynos4412 SoC with video mixer as an interconnect consumer device. 426 + 427 + soc { 428 + bus_dmc: bus_dmc { 429 + compatible = "samsung,exynos-bus"; 430 + clocks = <&clock CLK_DIV_DMC>; 431 + clock-names = "bus"; 432 + operating-points-v2 = <&bus_dmc_opp_table>; 433 + samsung,data-clock-ratio = <4>; 434 + #interconnect-cells = <0>; 435 + }; 436 + 437 + bus_leftbus: bus_leftbus { 438 + compatible = "samsung,exynos-bus"; 439 + clocks = <&clock CLK_DIV_GDL>; 440 + clock-names = "bus"; 441 + operating-points-v2 = <&bus_leftbus_opp_table>; 442 + #interconnect-cells = <0>; 443 + interconnects = <&bus_dmc>; 444 + }; 445 + 446 + bus_display: bus_display { 447 + compatible = "samsung,exynos-bus"; 448 + clocks = <&clock CLK_ACLK160>; 449 + clock-names = "bus"; 450 + operating-points-v2 = <&bus_display_opp_table>; 451 + #interconnect-cells = <0>; 452 + interconnects = <&bus_leftbus &bus_dmc>; 453 + }; 454 + 455 + bus_dmc_opp_table: opp_table1 { 456 + compatible = "operating-points-v2"; 457 + /* ... */ 458 + } 459 + 460 + bus_leftbus_opp_table: opp_table3 { 461 + compatible = "operating-points-v2"; 462 + /* ... */ 463 + }; 464 + 465 + bus_display_opp_table: opp_table4 { 466 + compatible = "operating-points-v2"; 467 + /* .. */ 468 + }; 469 + 470 + &mixer { 471 + compatible = "samsung,exynos4212-mixer"; 472 + interconnects = <&bus_display &bus_dmc>; 473 + /* ... */ 474 + }; 434 475 };
+53 -1
Documentation/devicetree/bindings/opp/opp.txt
··· 65 65 66 66 - OPP nodes: One or more OPP nodes describing voltage-current-frequency 67 67 combinations. Their name isn't significant but their phandle can be used to 68 - reference an OPP. 68 + reference an OPP. These are mandatory except for the case where the OPP table 69 + is present only to indicate dependency between devices using the opp-shared 70 + property. 69 71 70 72 Optional properties: 71 73 - opp-shared: Indicates that device nodes using this OPP Table Node's phandle ··· 568 566 <965000 960000 975000>; /* Supply vcc1 */ 569 567 opp-microamp = <70000>; /* Will be used for both slow/fast */ 570 568 }; 569 + }; 570 + }; 571 + 572 + Example 7: Single cluster Quad-core ARM cortex A53, OPP points from firmware, 573 + distinct clock controls but two sets of clock/voltage/current lines. 574 + 575 + / { 576 + cpus { 577 + #address-cells = <2>; 578 + #size-cells = <0>; 579 + 580 + cpu@0 { 581 + compatible = "arm,cortex-a53"; 582 + reg = <0x0 0x100>; 583 + next-level-cache = <&A53_L2>; 584 + clocks = <&dvfs_controller 0>; 585 + operating-points-v2 = <&cpu_opp0_table>; 586 + }; 587 + cpu@1 { 588 + compatible = "arm,cortex-a53"; 589 + reg = <0x0 0x101>; 590 + next-level-cache = <&A53_L2>; 591 + clocks = <&dvfs_controller 1>; 592 + operating-points-v2 = <&cpu_opp0_table>; 593 + }; 594 + cpu@2 { 595 + compatible = "arm,cortex-a53"; 596 + reg = <0x0 0x102>; 597 + next-level-cache = <&A53_L2>; 598 + clocks = <&dvfs_controller 2>; 599 + operating-points-v2 = <&cpu_opp1_table>; 600 + }; 601 + cpu@3 { 602 + compatible = "arm,cortex-a53"; 603 + reg = <0x0 0x103>; 604 + next-level-cache = <&A53_L2>; 605 + clocks = <&dvfs_controller 3>; 606 + operating-points-v2 = <&cpu_opp1_table>; 607 + }; 608 + 609 + }; 610 + 611 + cpu_opp0_table: opp0_table { 612 + compatible = "operating-points-v2"; 613 + opp-shared; 614 + }; 615 + 616 + cpu_opp1_table: opp1_table { 617 + compatible = "operating-points-v2"; 618 + opp-shared; 571 619 }; 572 620 };
+11 -1
Documentation/driver-api/thermal/power_allocator.rst
··· 71 71 simply an estimate, and may be tuned to affect the aggressiveness of 72 72 the thermal ramp. For reference, the sustainable power of a 4" phone 73 73 is typically 2000mW, while on a 10" tablet is around 4500mW (may vary 74 - depending on screen size). 74 + depending on screen size). It is possible to have the power value 75 + expressed in an abstract scale. The sustained power should be aligned 76 + to the scale used by the related cooling devices. 75 77 76 78 If you are using device tree, do add it as a property of the 77 79 thermal-zone. For example:: ··· 271 269 governor, step-wise will also misbehave if you call its throttle() 272 270 faster than the normal thermal framework tick (due to interrupts for 273 271 example) as it will overreact. 272 + 273 + Energy Model requirements 274 + ========================= 275 + 276 + Another important thing is the consistent scale of the power values 277 + provided by the cooling devices. All of the cooling devices in a single 278 + thermal zone should have power values reported either in milli-Watts 279 + or scaled to the same 'abstract scale'.
+25 -5
Documentation/power/energy-model.rst
··· 20 20 abstraction layer which standardizes the format of power cost tables in the 21 21 kernel, hence enabling to avoid redundant work. 22 22 23 + The power values might be expressed in milli-Watts or in an 'abstract scale'. 24 + Multiple subsystems might use the EM and it is up to the system integrator to 25 + check that the requirements for the power value scale types are met. An example 26 + can be found in the Energy-Aware Scheduler documentation 27 + Documentation/scheduler/sched-energy.rst. For some subsystems like thermal or 28 + powercap power values expressed in an 'abstract scale' might cause issues. 29 + These subsystems are more interested in estimation of power used in the past, 30 + thus the real milli-Watts might be needed. An example of these requirements can 31 + be found in the Intelligent Power Allocation in 32 + Documentation/driver-api/thermal/power_allocator.rst. 33 + Kernel subsystems might implement automatic detection to check whether EM 34 + registered devices have inconsistent scale (based on EM internal flag). 35 + Important thing to keep in mind is that when the power values are expressed in 36 + an 'abstract scale' deriving real energy in milli-Joules would not be possible. 37 + 23 38 The figure below depicts an example of drivers (Arm-specific here, but the 24 39 approach is applicable to any architecture) providing power costs to the EM 25 40 framework, and interested clients reading the data from it:: ··· 88 73 calling the following API:: 89 74 90 75 int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states, 91 - struct em_data_callback *cb, cpumask_t *cpus); 76 + struct em_data_callback *cb, cpumask_t *cpus, bool milliwatts); 92 77 93 78 Drivers must provide a callback function returning <frequency, power> tuples 94 79 for each performance state. The callback function provided by the driver is free ··· 96 81 deemed necessary. Only for CPU devices, drivers must specify the CPUs of the 97 82 performance domains using cpumask. For other devices than CPUs the last 98 83 argument must be set to NULL. 84 + The last argument 'milliwatts' is important to set with correct value. Kernel 85 + subsystems which use EM might rely on this flag to check if all EM devices use 86 + the same scale. If there are different scales, these subsystems might decide 87 + to: return warning/error, stop working or panic. 99 88 See Section 3. for an example of driver implementing this 100 89 callback, and kernel/power/energy_model.c for further documentation on this 101 90 API. ··· 175 156 37 nr_opp = foo_get_nr_opp(policy); 176 157 38 177 158 39 /* And register the new performance domain */ 178 - 40 em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, policy->cpus); 179 - 41 180 - 42 return 0; 181 - 43 } 159 + 40 em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, policy->cpus, 160 + 41 true); 161 + 42 162 + 43 return 0; 163 + 44 }
+5
Documentation/scheduler/sched-energy.rst
··· 350 350 Please also note that the scheduling domains need to be re-built after the 351 351 EM has been registered in order to start EAS. 352 352 353 + EAS uses the EM to make a forecasting decision on energy usage and thus it is 354 + more focused on the difference when checking possible options for task 355 + placement. For EAS it doesn't matter whether the EM power values are expressed 356 + in milli-Watts or in an 'abstract scale'. 357 + 353 358 354 359 6.3 - Energy Model complexity 355 360 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-1
MAINTAINERS
··· 11438 11438 L: linux-tegra@vger.kernel.org 11439 11439 T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git 11440 11440 S: Maintained 11441 - F: drivers/devfreq/tegra20-devfreq.c 11442 11441 F: drivers/devfreq/tegra30-devfreq.c 11443 11442 11444 11443 MEMORY MANAGEMENT
+2 -1
arch/x86/include/asm/msr-index.h
··· 327 327 #define MSR_PP1_ENERGY_STATUS 0x00000641 328 328 #define MSR_PP1_POLICY 0x00000642 329 329 330 - #define MSR_AMD_PKG_ENERGY_STATUS 0xc001029b 331 330 #define MSR_AMD_RAPL_POWER_UNIT 0xc0010299 331 + #define MSR_AMD_CORE_ENERGY_STATUS 0xc001029a 332 + #define MSR_AMD_PKG_ENERGY_STATUS 0xc001029b 332 333 333 334 /* Config TDP MSRs */ 334 335 #define MSR_CONFIG_TDP_NOMINAL 0x00000648
+29 -33
drivers/acpi/device_pm.c
··· 749 749 static DEFINE_MUTEX(acpi_wakeup_lock); 750 750 751 751 static int __acpi_device_wakeup_enable(struct acpi_device *adev, 752 - u32 target_state, int max_count) 752 + u32 target_state) 753 753 { 754 754 struct acpi_device_wakeup *wakeup = &adev->wakeup; 755 755 acpi_status status; ··· 757 757 758 758 mutex_lock(&acpi_wakeup_lock); 759 759 760 - if (wakeup->enable_count >= max_count) 760 + /* 761 + * If the device wakeup power is already enabled, disable it and enable 762 + * it again in case it depends on the configuration of subordinate 763 + * devices and the conditions have changed since it was enabled last 764 + * time. 765 + */ 766 + if (wakeup->enable_count > 0) 767 + acpi_disable_wakeup_device_power(adev); 768 + 769 + error = acpi_enable_wakeup_device_power(adev, target_state); 770 + if (error) { 771 + if (wakeup->enable_count > 0) { 772 + acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number); 773 + wakeup->enable_count = 0; 774 + } 761 775 goto out; 776 + } 762 777 763 778 if (wakeup->enable_count > 0) 764 779 goto inc; 765 - 766 - error = acpi_enable_wakeup_device_power(adev, target_state); 767 - if (error) 768 - goto out; 769 780 770 781 status = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number); 771 782 if (ACPI_FAILURE(status)) { ··· 789 778 (unsigned int)wakeup->gpe_number); 790 779 791 780 inc: 792 - wakeup->enable_count++; 781 + if (wakeup->enable_count < INT_MAX) 782 + wakeup->enable_count++; 783 + else 784 + acpi_handle_info(adev->handle, "Wakeup enable count out of bounds!\n"); 793 785 794 786 out: 795 787 mutex_unlock(&acpi_wakeup_lock); ··· 813 799 */ 814 800 static int acpi_device_wakeup_enable(struct acpi_device *adev, u32 target_state) 815 801 { 816 - return __acpi_device_wakeup_enable(adev, target_state, 1); 802 + return __acpi_device_wakeup_enable(adev, target_state); 817 803 } 818 804 819 805 /** ··· 843 829 mutex_unlock(&acpi_wakeup_lock); 844 830 } 845 831 846 - static int __acpi_pm_set_device_wakeup(struct device *dev, bool enable, 847 - int max_count) 832 + /** 833 + * acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device. 834 + * @dev: Device to enable/disable to generate wakeup events. 835 + * @enable: Whether to enable or disable the wakeup functionality. 836 + */ 837 + int acpi_pm_set_device_wakeup(struct device *dev, bool enable) 848 838 { 849 839 struct acpi_device *adev; 850 840 int error; ··· 868 850 return 0; 869 851 } 870 852 871 - error = __acpi_device_wakeup_enable(adev, acpi_target_system_state(), 872 - max_count); 853 + error = __acpi_device_wakeup_enable(adev, acpi_target_system_state()); 873 854 if (!error) 874 855 dev_dbg(dev, "Wakeup enabled by ACPI\n"); 875 856 876 857 return error; 877 858 } 878 - 879 - /** 880 - * acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device. 881 - * @dev: Device to enable/disable to generate wakeup events. 882 - * @enable: Whether to enable or disable the wakeup functionality. 883 - */ 884 - int acpi_pm_set_device_wakeup(struct device *dev, bool enable) 885 - { 886 - return __acpi_pm_set_device_wakeup(dev, enable, 1); 887 - } 888 859 EXPORT_SYMBOL_GPL(acpi_pm_set_device_wakeup); 889 - 890 - /** 891 - * acpi_pm_set_bridge_wakeup - Enable/disable remote wakeup for given bridge. 892 - * @dev: Bridge device to enable/disable to generate wakeup events. 893 - * @enable: Whether to enable or disable the wakeup functionality. 894 - */ 895 - int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable) 896 - { 897 - return __acpi_pm_set_device_wakeup(dev, enable, INT_MAX); 898 - } 899 - EXPORT_SYMBOL_GPL(acpi_pm_set_bridge_wakeup); 900 860 901 861 /** 902 862 * acpi_dev_pm_low_power - Put ACPI device into a low-power state.
+83 -47
drivers/base/power/domain.c
··· 21 21 #include <linux/suspend.h> 22 22 #include <linux/export.h> 23 23 #include <linux/cpu.h> 24 + #include <linux/debugfs.h> 24 25 25 26 #include "power.h" 26 27 ··· 211 210 } 212 211 213 212 #ifdef CONFIG_DEBUG_FS 213 + static struct dentry *genpd_debugfs_dir; 214 + 215 + static void genpd_debug_add(struct generic_pm_domain *genpd); 216 + 217 + static void genpd_debug_remove(struct generic_pm_domain *genpd) 218 + { 219 + struct dentry *d; 220 + 221 + d = debugfs_lookup(genpd->name, genpd_debugfs_dir); 222 + debugfs_remove(d); 223 + } 224 + 214 225 static void genpd_update_accounting(struct generic_pm_domain *genpd) 215 226 { 216 227 ktime_t delta, now; ··· 247 234 genpd->accounting_time = now; 248 235 } 249 236 #else 237 + static inline void genpd_debug_add(struct generic_pm_domain *genpd) {} 238 + static inline void genpd_debug_remove(struct generic_pm_domain *genpd) {} 250 239 static inline void genpd_update_accounting(struct generic_pm_domain *genpd) {} 251 240 #endif 252 241 ··· 1157 1142 if (ret) 1158 1143 return ret; 1159 1144 1160 - if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd)) 1145 + if (device_wakeup_path(dev) && genpd_is_active_wakeup(genpd)) 1161 1146 return 0; 1162 1147 1163 1148 if (genpd->dev_ops.stop && genpd->dev_ops.start && ··· 1211 1196 if (IS_ERR(genpd)) 1212 1197 return -EINVAL; 1213 1198 1214 - if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd)) 1199 + if (device_wakeup_path(dev) && genpd_is_active_wakeup(genpd)) 1215 1200 return pm_generic_resume_noirq(dev); 1216 1201 1217 1202 genpd_lock(genpd); ··· 1378 1363 genpd_unlock(genpd); 1379 1364 } 1380 1365 1381 - /** 1382 - * genpd_syscore_switch - Switch power during system core suspend or resume. 1383 - * @dev: Device that normally is marked as "always on" to switch power for. 1384 - * 1385 - * This routine may only be called during the system core (syscore) suspend or 1386 - * resume phase for devices whose "always on" flags are set. 1387 - */ 1388 - static void genpd_syscore_switch(struct device *dev, bool suspend) 1366 + static void genpd_switch_state(struct device *dev, bool suspend) 1389 1367 { 1390 1368 struct generic_pm_domain *genpd; 1369 + bool use_lock; 1391 1370 1392 1371 genpd = dev_to_genpd_safe(dev); 1393 1372 if (!genpd) 1394 1373 return; 1395 1374 1375 + use_lock = genpd_is_irq_safe(genpd); 1376 + 1377 + if (use_lock) 1378 + genpd_lock(genpd); 1379 + 1396 1380 if (suspend) { 1397 1381 genpd->suspended_count++; 1398 - genpd_sync_power_off(genpd, false, 0); 1382 + genpd_sync_power_off(genpd, use_lock, 0); 1399 1383 } else { 1400 - genpd_sync_power_on(genpd, false, 0); 1384 + genpd_sync_power_on(genpd, use_lock, 0); 1401 1385 genpd->suspended_count--; 1402 1386 } 1387 + 1388 + if (use_lock) 1389 + genpd_unlock(genpd); 1403 1390 } 1404 1391 1405 - void pm_genpd_syscore_poweroff(struct device *dev) 1392 + /** 1393 + * dev_pm_genpd_suspend - Synchronously try to suspend the genpd for @dev 1394 + * @dev: The device that is attached to the genpd, that can be suspended. 1395 + * 1396 + * This routine should typically be called for a device that needs to be 1397 + * suspended during the syscore suspend phase. It may also be called during 1398 + * suspend-to-idle to suspend a corresponding CPU device that is attached to a 1399 + * genpd. 1400 + */ 1401 + void dev_pm_genpd_suspend(struct device *dev) 1406 1402 { 1407 - genpd_syscore_switch(dev, true); 1403 + genpd_switch_state(dev, true); 1408 1404 } 1409 - EXPORT_SYMBOL_GPL(pm_genpd_syscore_poweroff); 1405 + EXPORT_SYMBOL_GPL(dev_pm_genpd_suspend); 1410 1406 1411 - void pm_genpd_syscore_poweron(struct device *dev) 1407 + /** 1408 + * dev_pm_genpd_resume - Synchronously try to resume the genpd for @dev 1409 + * @dev: The device that is attached to the genpd, which needs to be resumed. 1410 + * 1411 + * This routine should typically be called for a device that needs to be resumed 1412 + * during the syscore resume phase. It may also be called during suspend-to-idle 1413 + * to resume a corresponding CPU device that is attached to a genpd. 1414 + */ 1415 + void dev_pm_genpd_resume(struct device *dev) 1412 1416 { 1413 - genpd_syscore_switch(dev, false); 1417 + genpd_switch_state(dev, false); 1414 1418 } 1415 - EXPORT_SYMBOL_GPL(pm_genpd_syscore_poweron); 1419 + EXPORT_SYMBOL_GPL(dev_pm_genpd_resume); 1416 1420 1417 1421 #else /* !CONFIG_PM_SLEEP */ 1418 1422 ··· 1988 1954 1989 1955 mutex_lock(&gpd_list_lock); 1990 1956 list_add(&genpd->gpd_list_node, &gpd_list); 1957 + genpd_debug_add(genpd); 1991 1958 mutex_unlock(&gpd_list_lock); 1992 1959 1993 1960 return 0; ··· 2022 1987 kfree(link); 2023 1988 } 2024 1989 1990 + genpd_debug_remove(genpd); 2025 1991 list_del(&genpd->gpd_list_node); 2026 1992 genpd_unlock(genpd); 2027 1993 cancel_work_sync(&genpd->power_off_work); ··· 2285 2249 * Save table for faster processing while setting 2286 2250 * performance state. 2287 2251 */ 2288 - genpd->opp_table = dev_pm_opp_get_opp_table_indexed(&genpd->dev, i); 2252 + genpd->opp_table = dev_pm_opp_get_opp_table(&genpd->dev); 2289 2253 WARN_ON(IS_ERR(genpd->opp_table)); 2290 2254 } 2291 2255 ··· 2929 2893 /*** debugfs support ***/ 2930 2894 2931 2895 #ifdef CONFIG_DEBUG_FS 2932 - #include <linux/pm.h> 2933 - #include <linux/device.h> 2934 - #include <linux/debugfs.h> 2935 - #include <linux/seq_file.h> 2936 - #include <linux/init.h> 2937 - #include <linux/kobject.h> 2938 - static struct dentry *genpd_debugfs_dir; 2939 - 2940 2896 /* 2941 2897 * TODO: This function is a slightly modified version of rtpm_status_show 2942 2898 * from sysfs.c, so generalize it. ··· 3205 3177 DEFINE_SHOW_ATTRIBUTE(devices); 3206 3178 DEFINE_SHOW_ATTRIBUTE(perf_state); 3207 3179 3208 - static int __init genpd_debug_init(void) 3180 + static void genpd_debug_add(struct generic_pm_domain *genpd) 3209 3181 { 3210 3182 struct dentry *d; 3183 + 3184 + if (!genpd_debugfs_dir) 3185 + return; 3186 + 3187 + d = debugfs_create_dir(genpd->name, genpd_debugfs_dir); 3188 + 3189 + debugfs_create_file("current_state", 0444, 3190 + d, genpd, &status_fops); 3191 + debugfs_create_file("sub_domains", 0444, 3192 + d, genpd, &sub_domains_fops); 3193 + debugfs_create_file("idle_states", 0444, 3194 + d, genpd, &idle_states_fops); 3195 + debugfs_create_file("active_time", 0444, 3196 + d, genpd, &active_time_fops); 3197 + debugfs_create_file("total_idle_time", 0444, 3198 + d, genpd, &total_idle_time_fops); 3199 + debugfs_create_file("devices", 0444, 3200 + d, genpd, &devices_fops); 3201 + if (genpd->set_performance_state) 3202 + debugfs_create_file("perf_state", 0444, 3203 + d, genpd, &perf_state_fops); 3204 + } 3205 + 3206 + static int __init genpd_debug_init(void) 3207 + { 3211 3208 struct generic_pm_domain *genpd; 3212 3209 3213 3210 genpd_debugfs_dir = debugfs_create_dir("pm_genpd", NULL); ··· 3240 3187 debugfs_create_file("pm_genpd_summary", S_IRUGO, genpd_debugfs_dir, 3241 3188 NULL, &summary_fops); 3242 3189 3243 - list_for_each_entry(genpd, &gpd_list, gpd_list_node) { 3244 - d = debugfs_create_dir(genpd->name, genpd_debugfs_dir); 3245 - 3246 - debugfs_create_file("current_state", 0444, 3247 - d, genpd, &status_fops); 3248 - debugfs_create_file("sub_domains", 0444, 3249 - d, genpd, &sub_domains_fops); 3250 - debugfs_create_file("idle_states", 0444, 3251 - d, genpd, &idle_states_fops); 3252 - debugfs_create_file("active_time", 0444, 3253 - d, genpd, &active_time_fops); 3254 - debugfs_create_file("total_idle_time", 0444, 3255 - d, genpd, &total_idle_time_fops); 3256 - debugfs_create_file("devices", 0444, 3257 - d, genpd, &devices_fops); 3258 - if (genpd->set_performance_state) 3259 - debugfs_create_file("perf_state", 0444, 3260 - d, genpd, &perf_state_fops); 3261 - } 3190 + list_for_each_entry(genpd, &gpd_list, gpd_list_node) 3191 + genpd_debug_add(genpd); 3262 3192 3263 3193 return 0; 3264 3194 }
+4 -4
drivers/base/power/main.c
··· 441 441 442 442 static void pm_dev_dbg(struct device *dev, pm_message_t state, const char *info) 443 443 { 444 - dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event), 444 + dev_dbg(dev, "%s%s%s driver flags: %x\n", info, pm_verb(state.event), 445 445 ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ? 446 - ", may wakeup" : ""); 446 + ", may wakeup" : "", dev->power.driver_flags); 447 447 } 448 448 449 449 static void pm_dev_err(struct device *dev, pm_message_t state, const char *info, ··· 1359 1359 1360 1360 spin_lock_irq(&parent->power.lock); 1361 1361 1362 - if (dev->power.wakeup_path && !parent->power.ignore_children) 1362 + if (device_wakeup_path(dev) && !parent->power.ignore_children) 1363 1363 parent->power.wakeup_path = true; 1364 1364 1365 1365 spin_unlock_irq(&parent->power.lock); ··· 1627 1627 goto Complete; 1628 1628 1629 1629 /* Avoid direct_complete to let wakeup_path propagate. */ 1630 - if (device_may_wakeup(dev) || dev->power.wakeup_path) 1630 + if (device_may_wakeup(dev) || device_wakeup_path(dev)) 1631 1631 dev->power.direct_complete = false; 1632 1632 1633 1633 if (dev->power.direct_complete) {
+3
drivers/clk/tegra/clk-tegra20-emc.c
··· 13 13 #include <linux/clk-provider.h> 14 14 #include <linux/clk/tegra.h> 15 15 #include <linux/err.h> 16 + #include <linux/export.h> 16 17 #include <linux/io.h> 17 18 #include <linux/kernel.h> 18 19 #include <linux/slab.h> ··· 236 235 emc->cb_arg = cb_arg; 237 236 } 238 237 } 238 + EXPORT_SYMBOL_GPL(tegra20_clk_set_emc_round_callback); 239 239 240 240 bool tegra20_clk_emc_driver_available(struct clk_hw *emc_hw) 241 241 { ··· 293 291 294 292 return 0; 295 293 } 294 + EXPORT_SYMBOL_GPL(tegra20_clk_prepare_emc_mc_same_freq);
+4 -4
drivers/clocksource/sh_cmt.c
··· 668 668 return; 669 669 670 670 sh_cmt_stop(ch, FLAG_CLOCKSOURCE); 671 - pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev); 671 + dev_pm_genpd_suspend(&ch->cmt->pdev->dev); 672 672 } 673 673 674 674 static void sh_cmt_clocksource_resume(struct clocksource *cs) ··· 678 678 if (!ch->cs_enabled) 679 679 return; 680 680 681 - pm_genpd_syscore_poweron(&ch->cmt->pdev->dev); 681 + dev_pm_genpd_resume(&ch->cmt->pdev->dev); 682 682 sh_cmt_start(ch, FLAG_CLOCKSOURCE); 683 683 } 684 684 ··· 770 770 { 771 771 struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); 772 772 773 - pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev); 773 + dev_pm_genpd_suspend(&ch->cmt->pdev->dev); 774 774 clk_unprepare(ch->cmt->clk); 775 775 } 776 776 ··· 779 779 struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); 780 780 781 781 clk_prepare(ch->cmt->clk); 782 - pm_genpd_syscore_poweron(&ch->cmt->pdev->dev); 782 + dev_pm_genpd_resume(&ch->cmt->pdev->dev); 783 783 } 784 784 785 785 static int sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
+2 -2
drivers/clocksource/sh_mtu2.c
··· 297 297 298 298 static void sh_mtu2_clock_event_suspend(struct clock_event_device *ced) 299 299 { 300 - pm_genpd_syscore_poweroff(&ced_to_sh_mtu2(ced)->mtu->pdev->dev); 300 + dev_pm_genpd_suspend(&ced_to_sh_mtu2(ced)->mtu->pdev->dev); 301 301 } 302 302 303 303 static void sh_mtu2_clock_event_resume(struct clock_event_device *ced) 304 304 { 305 - pm_genpd_syscore_poweron(&ced_to_sh_mtu2(ced)->mtu->pdev->dev); 305 + dev_pm_genpd_resume(&ced_to_sh_mtu2(ced)->mtu->pdev->dev); 306 306 } 307 307 308 308 static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
+4 -4
drivers/clocksource/sh_tmu.c
··· 292 292 293 293 if (--ch->enable_count == 0) { 294 294 __sh_tmu_disable(ch); 295 - pm_genpd_syscore_poweroff(&ch->tmu->pdev->dev); 295 + dev_pm_genpd_suspend(&ch->tmu->pdev->dev); 296 296 } 297 297 } 298 298 ··· 304 304 return; 305 305 306 306 if (ch->enable_count++ == 0) { 307 - pm_genpd_syscore_poweron(&ch->tmu->pdev->dev); 307 + dev_pm_genpd_resume(&ch->tmu->pdev->dev); 308 308 __sh_tmu_enable(ch); 309 309 } 310 310 } ··· 394 394 395 395 static void sh_tmu_clock_event_suspend(struct clock_event_device *ced) 396 396 { 397 - pm_genpd_syscore_poweroff(&ced_to_sh_tmu(ced)->tmu->pdev->dev); 397 + dev_pm_genpd_suspend(&ced_to_sh_tmu(ced)->tmu->pdev->dev); 398 398 } 399 399 400 400 static void sh_tmu_clock_event_resume(struct clock_event_device *ced) 401 401 { 402 - pm_genpd_syscore_poweron(&ced_to_sh_tmu(ced)->tmu->pdev->dev); 402 + dev_pm_genpd_resume(&ced_to_sh_tmu(ced)->tmu->pdev->dev); 403 403 } 404 404 405 405 static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
+1 -1
drivers/cpufreq/Kconfig.arm
··· 94 94 tristate "Freescale i.MX6 cpufreq support" 95 95 depends on ARCH_MXC 96 96 depends on REGULATOR_ANATOP 97 - select NVMEM_IMX_OCOTP 97 + depends on NVMEM_IMX_OCOTP || COMPILE_TEST 98 98 select PM_OPP 99 99 help 100 100 This adds cpufreq driver support for Freescale i.MX6 series SoCs.
+6
drivers/cpufreq/armada-8k-cpufreq.c
··· 204 204 } 205 205 module_exit(armada_8k_cpufreq_exit); 206 206 207 + static const struct of_device_id __maybe_unused armada_8k_cpufreq_of_match[] = { 208 + { .compatible = "marvell,ap806-cpu-clock" }, 209 + { }, 210 + }; 211 + MODULE_DEVICE_TABLE(of, armada_8k_cpufreq_of_match); 212 + 207 213 MODULE_AUTHOR("Gregory Clement <gregory.clement@bootlin.com>"); 208 214 MODULE_DESCRIPTION("Armada 8K cpufreq driver"); 209 215 MODULE_LICENSE("GPL");
+82 -81
drivers/cpufreq/cppc_cpufreq.c
··· 26 26 /* Minimum struct length needed for the DMI processor entry we want */ 27 27 #define DMI_ENTRY_PROCESSOR_MIN_LENGTH 48 28 28 29 - /* Offest in the DMI processor structure for the max frequency */ 30 - #define DMI_PROCESSOR_MAX_SPEED 0x14 29 + /* Offset in the DMI processor structure for the max frequency */ 30 + #define DMI_PROCESSOR_MAX_SPEED 0x14 31 31 32 32 /* 33 33 * These structs contain information parsed from per CPU ··· 96 96 * and extrapolate the rest 97 97 * For perf/freq > Nominal, we use the ratio perf:freq at Nominal for conversion 98 98 */ 99 - static unsigned int cppc_cpufreq_perf_to_khz(struct cppc_cpudata *cpu, 100 - unsigned int perf) 99 + static unsigned int cppc_cpufreq_perf_to_khz(struct cppc_cpudata *cpu_data, 100 + unsigned int perf) 101 101 { 102 + struct cppc_perf_caps *caps = &cpu_data->perf_caps; 102 103 static u64 max_khz; 103 - struct cppc_perf_caps *caps = &cpu->perf_caps; 104 104 u64 mul, div; 105 105 106 106 if (caps->lowest_freq && caps->nominal_freq) { ··· 120 120 return (u64)perf * mul / div; 121 121 } 122 122 123 - static unsigned int cppc_cpufreq_khz_to_perf(struct cppc_cpudata *cpu, 124 - unsigned int freq) 123 + static unsigned int cppc_cpufreq_khz_to_perf(struct cppc_cpudata *cpu_data, 124 + unsigned int freq) 125 125 { 126 + struct cppc_perf_caps *caps = &cpu_data->perf_caps; 126 127 static u64 max_khz; 127 - struct cppc_perf_caps *caps = &cpu->perf_caps; 128 128 u64 mul, div; 129 129 130 130 if (caps->lowest_freq && caps->nominal_freq) { ··· 146 146 } 147 147 148 148 static int cppc_cpufreq_set_target(struct cpufreq_policy *policy, 149 - unsigned int target_freq, 150 - unsigned int relation) 149 + unsigned int target_freq, 150 + unsigned int relation) 151 151 { 152 - struct cppc_cpudata *cpu; 152 + struct cppc_cpudata *cpu_data = all_cpu_data[policy->cpu]; 153 153 struct cpufreq_freqs freqs; 154 154 u32 desired_perf; 155 155 int ret = 0; 156 156 157 - cpu = all_cpu_data[policy->cpu]; 158 - 159 - desired_perf = cppc_cpufreq_khz_to_perf(cpu, target_freq); 157 + desired_perf = cppc_cpufreq_khz_to_perf(cpu_data, target_freq); 160 158 /* Return if it is exactly the same perf */ 161 - if (desired_perf == cpu->perf_ctrls.desired_perf) 159 + if (desired_perf == cpu_data->perf_ctrls.desired_perf) 162 160 return ret; 163 161 164 - cpu->perf_ctrls.desired_perf = desired_perf; 162 + cpu_data->perf_ctrls.desired_perf = desired_perf; 165 163 freqs.old = policy->cur; 166 164 freqs.new = target_freq; 167 165 168 166 cpufreq_freq_transition_begin(policy, &freqs); 169 - ret = cppc_set_perf(cpu->cpu, &cpu->perf_ctrls); 167 + ret = cppc_set_perf(cpu_data->cpu, &cpu_data->perf_ctrls); 170 168 cpufreq_freq_transition_end(policy, &freqs, ret != 0); 171 169 172 170 if (ret) 173 171 pr_debug("Failed to set target on CPU:%d. ret:%d\n", 174 - cpu->cpu, ret); 172 + cpu_data->cpu, ret); 175 173 176 174 return ret; 177 175 } ··· 182 184 183 185 static void cppc_cpufreq_stop_cpu(struct cpufreq_policy *policy) 184 186 { 185 - int cpu_num = policy->cpu; 186 - struct cppc_cpudata *cpu = all_cpu_data[cpu_num]; 187 + struct cppc_cpudata *cpu_data = all_cpu_data[policy->cpu]; 188 + struct cppc_perf_caps *caps = &cpu_data->perf_caps; 189 + unsigned int cpu = policy->cpu; 187 190 int ret; 188 191 189 - cpu->perf_ctrls.desired_perf = cpu->perf_caps.lowest_perf; 192 + cpu_data->perf_ctrls.desired_perf = caps->lowest_perf; 190 193 191 - ret = cppc_set_perf(cpu_num, &cpu->perf_ctrls); 194 + ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls); 192 195 if (ret) 193 196 pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n", 194 - cpu->perf_caps.lowest_perf, cpu_num, ret); 197 + caps->lowest_perf, cpu, ret); 195 198 } 196 199 197 200 /* 198 201 * The PCC subspace describes the rate at which platform can accept commands 199 202 * on the shared PCC channel (including READs which do not count towards freq 200 - * trasition requests), so ideally we need to use the PCC values as a fallback 203 + * transition requests), so ideally we need to use the PCC values as a fallback 201 204 * if we don't have a platform specific transition_delay_us 202 205 */ 203 206 #ifdef CONFIG_ARM64 204 207 #include <asm/cputype.h> 205 208 206 - static unsigned int cppc_cpufreq_get_transition_delay_us(int cpu) 209 + static unsigned int cppc_cpufreq_get_transition_delay_us(unsigned int cpu) 207 210 { 208 211 unsigned long implementor = read_cpuid_implementor(); 209 212 unsigned long part_num = read_cpuid_part_number(); ··· 232 233 233 234 #else 234 235 235 - static unsigned int cppc_cpufreq_get_transition_delay_us(int cpu) 236 + static unsigned int cppc_cpufreq_get_transition_delay_us(unsigned int cpu) 236 237 { 237 238 return cppc_get_transition_latency(cpu) / NSEC_PER_USEC; 238 239 } ··· 240 241 241 242 static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) 242 243 { 243 - struct cppc_cpudata *cpu; 244 - unsigned int cpu_num = policy->cpu; 244 + struct cppc_cpudata *cpu_data = all_cpu_data[policy->cpu]; 245 + struct cppc_perf_caps *caps = &cpu_data->perf_caps; 246 + unsigned int cpu = policy->cpu; 245 247 int ret = 0; 246 248 247 - cpu = all_cpu_data[policy->cpu]; 248 - 249 - cpu->cpu = cpu_num; 250 - ret = cppc_get_perf_caps(policy->cpu, &cpu->perf_caps); 249 + cpu_data->cpu = cpu; 250 + ret = cppc_get_perf_caps(cpu, caps); 251 251 252 252 if (ret) { 253 253 pr_debug("Err reading CPU%d perf capabilities. ret:%d\n", 254 - cpu_num, ret); 254 + cpu, ret); 255 255 return ret; 256 256 } 257 257 258 258 /* Convert the lowest and nominal freq from MHz to KHz */ 259 - cpu->perf_caps.lowest_freq *= 1000; 260 - cpu->perf_caps.nominal_freq *= 1000; 259 + caps->lowest_freq *= 1000; 260 + caps->nominal_freq *= 1000; 261 261 262 262 /* 263 263 * Set min to lowest nonlinear perf to avoid any efficiency penalty (see 264 264 * Section 8.4.7.1.1.5 of ACPI 6.1 spec) 265 265 */ 266 - policy->min = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.lowest_nonlinear_perf); 267 - policy->max = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.nominal_perf); 266 + policy->min = cppc_cpufreq_perf_to_khz(cpu_data, 267 + caps->lowest_nonlinear_perf); 268 + policy->max = cppc_cpufreq_perf_to_khz(cpu_data, 269 + caps->nominal_perf); 268 270 269 271 /* 270 272 * Set cpuinfo.min_freq to Lowest to make the full range of performance 271 273 * available if userspace wants to use any perf between lowest & lowest 272 274 * nonlinear perf 273 275 */ 274 - policy->cpuinfo.min_freq = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.lowest_perf); 275 - policy->cpuinfo.max_freq = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.nominal_perf); 276 + policy->cpuinfo.min_freq = cppc_cpufreq_perf_to_khz(cpu_data, 277 + caps->lowest_perf); 278 + policy->cpuinfo.max_freq = cppc_cpufreq_perf_to_khz(cpu_data, 279 + caps->nominal_perf); 276 280 277 - policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu_num); 278 - policy->shared_type = cpu->shared_type; 281 + policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu); 282 + policy->shared_type = cpu_data->shared_type; 279 283 280 284 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { 281 285 int i; 282 286 283 - cpumask_copy(policy->cpus, cpu->shared_cpu_map); 287 + cpumask_copy(policy->cpus, cpu_data->shared_cpu_map); 284 288 285 289 for_each_cpu(i, policy->cpus) { 286 - if (unlikely(i == policy->cpu)) 290 + if (unlikely(i == cpu)) 287 291 continue; 288 292 289 - memcpy(&all_cpu_data[i]->perf_caps, &cpu->perf_caps, 290 - sizeof(cpu->perf_caps)); 293 + memcpy(&all_cpu_data[i]->perf_caps, caps, 294 + sizeof(cpu_data->perf_caps)); 291 295 } 292 296 } else if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL) { 293 297 /* Support only SW_ANY for now. */ ··· 298 296 return -EFAULT; 299 297 } 300 298 301 - cpu->cur_policy = policy; 299 + cpu_data->cur_policy = policy; 302 300 303 301 /* 304 302 * If 'highest_perf' is greater than 'nominal_perf', we assume CPU Boost 305 303 * is supported. 306 304 */ 307 - if (cpu->perf_caps.highest_perf > cpu->perf_caps.nominal_perf) 305 + if (caps->highest_perf > caps->nominal_perf) 308 306 boost_supported = true; 309 307 310 308 /* Set policy->cur to max now. The governors will adjust later. */ 311 - policy->cur = cppc_cpufreq_perf_to_khz(cpu, 312 - cpu->perf_caps.highest_perf); 313 - cpu->perf_ctrls.desired_perf = cpu->perf_caps.highest_perf; 309 + policy->cur = cppc_cpufreq_perf_to_khz(cpu_data, caps->highest_perf); 310 + cpu_data->perf_ctrls.desired_perf = caps->highest_perf; 314 311 315 - ret = cppc_set_perf(cpu_num, &cpu->perf_ctrls); 312 + ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls); 316 313 if (ret) 317 314 pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n", 318 - cpu->perf_caps.highest_perf, cpu_num, ret); 315 + caps->highest_perf, cpu, ret); 319 316 320 317 return ret; 321 318 } ··· 327 326 return (u32)t1 - (u32)t0; 328 327 } 329 328 330 - static int cppc_get_rate_from_fbctrs(struct cppc_cpudata *cpu, 329 + static int cppc_get_rate_from_fbctrs(struct cppc_cpudata *cpu_data, 331 330 struct cppc_perf_fb_ctrs fb_ctrs_t0, 332 331 struct cppc_perf_fb_ctrs fb_ctrs_t1) 333 332 { ··· 346 345 delivered_perf = (reference_perf * delta_delivered) / 347 346 delta_reference; 348 347 else 349 - delivered_perf = cpu->perf_ctrls.desired_perf; 348 + delivered_perf = cpu_data->perf_ctrls.desired_perf; 350 349 351 - return cppc_cpufreq_perf_to_khz(cpu, delivered_perf); 350 + return cppc_cpufreq_perf_to_khz(cpu_data, delivered_perf); 352 351 } 353 352 354 - static unsigned int cppc_cpufreq_get_rate(unsigned int cpunum) 353 + static unsigned int cppc_cpufreq_get_rate(unsigned int cpu) 355 354 { 356 355 struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0}; 357 - struct cppc_cpudata *cpu = all_cpu_data[cpunum]; 356 + struct cppc_cpudata *cpu_data = all_cpu_data[cpu]; 358 357 int ret; 359 358 360 - ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t0); 359 + ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0); 361 360 if (ret) 362 361 return ret; 363 362 364 363 udelay(2); /* 2usec delay between sampling */ 365 364 366 - ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t1); 365 + ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t1); 367 366 if (ret) 368 367 return ret; 369 368 370 - return cppc_get_rate_from_fbctrs(cpu, fb_ctrs_t0, fb_ctrs_t1); 369 + return cppc_get_rate_from_fbctrs(cpu_data, fb_ctrs_t0, fb_ctrs_t1); 371 370 } 372 371 373 372 static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state) 374 373 { 375 - struct cppc_cpudata *cpudata; 374 + struct cppc_cpudata *cpu_data = all_cpu_data[policy->cpu]; 375 + struct cppc_perf_caps *caps = &cpu_data->perf_caps; 376 376 int ret; 377 377 378 378 if (!boost_supported) { ··· 381 379 return -EINVAL; 382 380 } 383 381 384 - cpudata = all_cpu_data[policy->cpu]; 385 382 if (state) 386 - policy->max = cppc_cpufreq_perf_to_khz(cpudata, 387 - cpudata->perf_caps.highest_perf); 383 + policy->max = cppc_cpufreq_perf_to_khz(cpu_data, 384 + caps->highest_perf); 388 385 else 389 - policy->max = cppc_cpufreq_perf_to_khz(cpudata, 390 - cpudata->perf_caps.nominal_perf); 386 + policy->max = cppc_cpufreq_perf_to_khz(cpu_data, 387 + caps->nominal_perf); 391 388 policy->cpuinfo.max_freq = policy->max; 392 389 393 390 ret = freq_qos_update_request(policy->max_freq_req, policy->max); ··· 413 412 * platform specific mechanism. We reuse the desired performance register to 414 413 * store the real performance calculated by the platform. 415 414 */ 416 - static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpunum) 415 + static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu) 417 416 { 418 - struct cppc_cpudata *cpudata = all_cpu_data[cpunum]; 417 + struct cppc_cpudata *cpu_data = all_cpu_data[cpu]; 419 418 u64 desired_perf; 420 419 int ret; 421 420 422 - ret = cppc_get_desired_perf(cpunum, &desired_perf); 421 + ret = cppc_get_desired_perf(cpu, &desired_perf); 423 422 if (ret < 0) 424 423 return -EIO; 425 424 426 - return cppc_cpufreq_perf_to_khz(cpudata, desired_perf); 425 + return cppc_cpufreq_perf_to_khz(cpu_data, desired_perf); 427 426 } 428 427 429 428 static void cppc_check_hisi_workaround(void) ··· 451 450 452 451 static int __init cppc_cpufreq_init(void) 453 452 { 453 + struct cppc_cpudata *cpu_data; 454 454 int i, ret = 0; 455 - struct cppc_cpudata *cpu; 456 455 457 456 if (acpi_disabled) 458 457 return -ENODEV; ··· 467 466 if (!all_cpu_data[i]) 468 467 goto out; 469 468 470 - cpu = all_cpu_data[i]; 471 - if (!zalloc_cpumask_var(&cpu->shared_cpu_map, GFP_KERNEL)) 469 + cpu_data = all_cpu_data[i]; 470 + if (!zalloc_cpumask_var(&cpu_data->shared_cpu_map, GFP_KERNEL)) 472 471 goto out; 473 472 } 474 473 ··· 488 487 489 488 out: 490 489 for_each_possible_cpu(i) { 491 - cpu = all_cpu_data[i]; 492 - if (!cpu) 490 + cpu_data = all_cpu_data[i]; 491 + if (!cpu_data) 493 492 break; 494 - free_cpumask_var(cpu->shared_cpu_map); 495 - kfree(cpu); 493 + free_cpumask_var(cpu_data->shared_cpu_map); 494 + kfree(cpu_data); 496 495 } 497 496 498 497 kfree(all_cpu_data); ··· 501 500 502 501 static void __exit cppc_cpufreq_exit(void) 503 502 { 504 - struct cppc_cpudata *cpu; 503 + struct cppc_cpudata *cpu_data; 505 504 int i; 506 505 507 506 cpufreq_unregister_driver(&cppc_cpufreq_driver); 508 507 509 508 for_each_possible_cpu(i) { 510 - cpu = all_cpu_data[i]; 511 - free_cpumask_var(cpu->shared_cpu_map); 512 - kfree(cpu); 509 + cpu_data = all_cpu_data[i]; 510 + free_cpumask_var(cpu_data->shared_cpu_map); 511 + kfree(cpu_data); 513 512 } 514 513 515 514 kfree(all_cpu_data);
+2
drivers/cpufreq/cpufreq-dt-platdev.c
··· 119 119 { .compatible = "mediatek,mt2712", }, 120 120 { .compatible = "mediatek,mt7622", }, 121 121 { .compatible = "mediatek,mt7623", }, 122 + { .compatible = "mediatek,mt8167", }, 122 123 { .compatible = "mediatek,mt817x", }, 123 124 { .compatible = "mediatek,mt8173", }, 124 125 { .compatible = "mediatek,mt8176", }, 125 126 { .compatible = "mediatek,mt8183", }, 127 + { .compatible = "mediatek,mt8516", }, 126 128 127 129 { .compatible = "nvidia,tegra20", }, 128 130 { .compatible = "nvidia,tegra30", },
+65 -88
drivers/cpufreq/cpufreq-dt.c
··· 30 30 cpumask_var_t cpus; 31 31 struct device *cpu_dev; 32 32 struct opp_table *opp_table; 33 - struct opp_table *reg_opp_table; 33 + struct cpufreq_frequency_table *freq_table; 34 34 bool have_static_opps; 35 35 }; 36 36 ··· 102 102 103 103 static int cpufreq_init(struct cpufreq_policy *policy) 104 104 { 105 - struct cpufreq_frequency_table *freq_table; 106 105 struct private_data *priv; 107 106 struct device *cpu_dev; 108 107 struct clk *cpu_clk; ··· 113 114 pr_err("failed to find data for cpu%d\n", policy->cpu); 114 115 return -ENODEV; 115 116 } 116 - 117 117 cpu_dev = priv->cpu_dev; 118 - cpumask_copy(policy->cpus, priv->cpus); 119 118 120 119 cpu_clk = clk_get(cpu_dev, NULL); 121 120 if (IS_ERR(cpu_clk)) { ··· 122 125 return ret; 123 126 } 124 127 125 - /* 126 - * Initialize OPP tables for all policy->cpus. They will be shared by 127 - * all CPUs which have marked their CPUs shared with OPP bindings. 128 - * 129 - * For platforms not using operating-points-v2 bindings, we do this 130 - * before updating policy->cpus. Otherwise, we will end up creating 131 - * duplicate OPPs for policy->cpus. 132 - * 133 - * OPPs might be populated at runtime, don't check for error here 134 - */ 135 - if (!dev_pm_opp_of_cpumask_add_table(policy->cpus)) 136 - priv->have_static_opps = true; 128 + transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev); 129 + if (!transition_latency) 130 + transition_latency = CPUFREQ_ETERNAL; 137 131 138 - /* 139 - * But we need OPP table to function so if it is not there let's 140 - * give platform code chance to provide it for us. 141 - */ 142 - ret = dev_pm_opp_get_opp_count(cpu_dev); 143 - if (ret <= 0) { 144 - dev_err(cpu_dev, "OPP table can't be empty\n"); 145 - ret = -ENODEV; 146 - goto out_free_opp; 147 - } 148 - 149 - ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); 150 - if (ret) { 151 - dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); 152 - goto out_free_opp; 153 - } 154 - 132 + cpumask_copy(policy->cpus, priv->cpus); 155 133 policy->driver_data = priv; 156 134 policy->clk = cpu_clk; 157 - policy->freq_table = freq_table; 158 - 135 + policy->freq_table = priv->freq_table; 159 136 policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000; 137 + policy->cpuinfo.transition_latency = transition_latency; 138 + policy->dvfs_possible_from_any_cpu = true; 160 139 161 140 /* Support turbo/boost mode */ 162 141 if (policy_has_boost_freq(policy)) { 163 142 /* This gets disabled by core on driver unregister */ 164 143 ret = cpufreq_enable_boost_support(); 165 144 if (ret) 166 - goto out_free_cpufreq_table; 145 + goto out_clk_put; 167 146 cpufreq_dt_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs; 168 147 } 169 - 170 - transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev); 171 - if (!transition_latency) 172 - transition_latency = CPUFREQ_ETERNAL; 173 - 174 - policy->cpuinfo.transition_latency = transition_latency; 175 - policy->dvfs_possible_from_any_cpu = true; 176 148 177 149 dev_pm_opp_of_register_em(cpu_dev, policy->cpus); 178 150 179 151 return 0; 180 152 181 - out_free_cpufreq_table: 182 - dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); 183 - out_free_opp: 184 - if (priv->have_static_opps) 185 - dev_pm_opp_of_cpumask_remove_table(policy->cpus); 153 + out_clk_put: 186 154 clk_put(cpu_clk); 187 155 188 156 return ret; ··· 170 208 171 209 static int cpufreq_exit(struct cpufreq_policy *policy) 172 210 { 173 - struct private_data *priv = policy->driver_data; 174 - 175 - dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); 176 - if (priv->have_static_opps) 177 - dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); 178 211 clk_put(policy->clk); 179 212 return 0; 180 213 } ··· 193 236 { 194 237 struct private_data *priv; 195 238 struct device *cpu_dev; 239 + bool fallback = false; 196 240 const char *reg_name; 197 241 int ret; 198 242 ··· 212 254 if (!alloc_cpumask_var(&priv->cpus, GFP_KERNEL)) 213 255 return -ENOMEM; 214 256 257 + cpumask_set_cpu(cpu, priv->cpus); 215 258 priv->cpu_dev = cpu_dev; 216 - 217 - /* Try to get OPP table early to ensure resources are available */ 218 - priv->opp_table = dev_pm_opp_get_opp_table(cpu_dev); 219 - if (IS_ERR(priv->opp_table)) { 220 - ret = PTR_ERR(priv->opp_table); 221 - if (ret != -EPROBE_DEFER) 222 - dev_err(cpu_dev, "failed to get OPP table: %d\n", ret); 223 - goto free_cpumask; 224 - } 225 259 226 260 /* 227 261 * OPP layer will be taking care of regulators now, but it needs to know ··· 221 271 */ 222 272 reg_name = find_supply_name(cpu_dev); 223 273 if (reg_name) { 224 - priv->reg_opp_table = dev_pm_opp_set_regulators(cpu_dev, 225 - &reg_name, 1); 226 - if (IS_ERR(priv->reg_opp_table)) { 227 - ret = PTR_ERR(priv->reg_opp_table); 274 + priv->opp_table = dev_pm_opp_set_regulators(cpu_dev, &reg_name, 275 + 1); 276 + if (IS_ERR(priv->opp_table)) { 277 + ret = PTR_ERR(priv->opp_table); 228 278 if (ret != -EPROBE_DEFER) 229 279 dev_err(cpu_dev, "failed to set regulators: %d\n", 230 280 ret); 231 - goto put_table; 281 + goto free_cpumask; 232 282 } 233 283 } 234 284 235 - /* Find OPP sharing information so we can fill pri->cpus here */ 236 285 /* Get OPP-sharing information from "operating-points-v2" bindings */ 237 286 ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, priv->cpus); 238 287 if (ret) { 239 288 if (ret != -ENOENT) 240 - goto put_reg; 289 + goto out; 241 290 242 291 /* 243 292 * operating-points-v2 not supported, fallback to all CPUs share 244 293 * OPP for backward compatibility if the platform hasn't set 245 294 * sharing CPUs. 246 295 */ 247 - if (dev_pm_opp_get_sharing_cpus(cpu_dev, priv->cpus)) { 248 - cpumask_setall(priv->cpus); 296 + if (dev_pm_opp_get_sharing_cpus(cpu_dev, priv->cpus)) 297 + fallback = true; 298 + } 249 299 250 - /* 251 - * OPP tables are initialized only for cpu, do it for 252 - * others as well. 253 - */ 254 - ret = dev_pm_opp_set_sharing_cpus(cpu_dev, priv->cpus); 255 - if (ret) 256 - dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n", 257 - __func__, ret); 258 - } 300 + /* 301 + * Initialize OPP tables for all priv->cpus. They will be shared by 302 + * all CPUs which have marked their CPUs shared with OPP bindings. 303 + * 304 + * For platforms not using operating-points-v2 bindings, we do this 305 + * before updating priv->cpus. Otherwise, we will end up creating 306 + * duplicate OPPs for the CPUs. 307 + * 308 + * OPPs might be populated at runtime, don't check for error here. 309 + */ 310 + if (!dev_pm_opp_of_cpumask_add_table(priv->cpus)) 311 + priv->have_static_opps = true; 312 + 313 + /* 314 + * The OPP table must be initialized, statically or dynamically, by this 315 + * point. 316 + */ 317 + ret = dev_pm_opp_get_opp_count(cpu_dev); 318 + if (ret <= 0) { 319 + dev_err(cpu_dev, "OPP table can't be empty\n"); 320 + ret = -ENODEV; 321 + goto out; 322 + } 323 + 324 + if (fallback) { 325 + cpumask_setall(priv->cpus); 326 + ret = dev_pm_opp_set_sharing_cpus(cpu_dev, priv->cpus); 327 + if (ret) 328 + dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n", 329 + __func__, ret); 330 + } 331 + 332 + ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &priv->freq_table); 333 + if (ret) { 334 + dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); 335 + goto out; 259 336 } 260 337 261 338 list_add(&priv->node, &priv_list); 262 339 return 0; 263 340 264 - put_reg: 265 - if (priv->reg_opp_table) 266 - dev_pm_opp_put_regulators(priv->reg_opp_table); 267 - put_table: 268 - dev_pm_opp_put_opp_table(priv->opp_table); 341 + out: 342 + if (priv->have_static_opps) 343 + dev_pm_opp_of_cpumask_remove_table(priv->cpus); 344 + dev_pm_opp_put_regulators(priv->opp_table); 269 345 free_cpumask: 270 346 free_cpumask_var(priv->cpus); 271 347 return ret; ··· 302 326 struct private_data *priv, *tmp; 303 327 304 328 list_for_each_entry_safe(priv, tmp, &priv_list, node) { 305 - if (priv->reg_opp_table) 306 - dev_pm_opp_put_regulators(priv->reg_opp_table); 307 - dev_pm_opp_put_opp_table(priv->opp_table); 329 + dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &priv->freq_table); 330 + if (priv->have_static_opps) 331 + dev_pm_opp_of_cpumask_remove_table(priv->cpus); 332 + dev_pm_opp_put_regulators(priv->opp_table); 308 333 free_cpumask_var(priv->cpus); 309 334 list_del(&priv->node); 310 335 }
+44 -41
drivers/cpufreq/cpufreq.c
··· 298 298 * EXTERNALLY AFFECTING FREQUENCY CHANGES * 299 299 *********************************************************************/ 300 300 301 - /* 302 - * adjust_jiffies - adjust the system "loops_per_jiffy" 301 + /** 302 + * adjust_jiffies - Adjust the system "loops_per_jiffy". 303 + * @val: CPUFREQ_PRECHANGE or CPUFREQ_POSTCHANGE. 304 + * @ci: Frequency change information. 303 305 * 304 306 * This function alters the system "loops_per_jiffy" for the clock 305 307 * speed change. Note that loops_per_jiffy cannot be updated on SMP ··· 333 331 } 334 332 335 333 /** 336 - * cpufreq_notify_transition - Notify frequency transition and adjust_jiffies. 334 + * cpufreq_notify_transition - Notify frequency transition and adjust jiffies. 337 335 * @policy: cpufreq policy to enable fast frequency switching for. 338 336 * @freqs: contain details of the frequency update. 339 337 * @state: set to CPUFREQ_PRECHANGE or CPUFREQ_POSTCHANGE. 340 338 * 341 - * This function calls the transition notifiers and the "adjust_jiffies" 342 - * function. It is called twice on all CPU frequency changes that have 343 - * external effects. 339 + * This function calls the transition notifiers and adjust_jiffies(). 340 + * 341 + * It is called twice on all CPU frequency changes that have external effects. 344 342 */ 345 343 static void cpufreq_notify_transition(struct cpufreq_policy *policy, 346 344 struct cpufreq_freqs *freqs, ··· 1393 1391 1394 1392 policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req), 1395 1393 GFP_KERNEL); 1396 - if (!policy->min_freq_req) 1394 + if (!policy->min_freq_req) { 1395 + ret = -ENOMEM; 1397 1396 goto out_destroy_policy; 1397 + } 1398 1398 1399 1399 ret = freq_qos_add_request(&policy->constraints, 1400 1400 policy->min_freq_req, FREQ_QOS_MIN, ··· 1433 1429 if (cpufreq_driver->get && has_target()) { 1434 1430 policy->cur = cpufreq_driver->get(policy->cpu); 1435 1431 if (!policy->cur) { 1432 + ret = -EIO; 1436 1433 pr_err("%s: ->get() failed\n", __func__); 1437 1434 goto out_destroy_policy; 1438 1435 } ··· 1651 1646 } 1652 1647 1653 1648 /** 1654 - * cpufreq_out_of_sync - If actual and saved CPU frequency differs, we're 1655 - * in deep trouble. 1656 - * @policy: policy managing CPUs 1657 - * @new_freq: CPU frequency the CPU actually runs at 1649 + * cpufreq_out_of_sync - Fix up actual and saved CPU frequency difference. 1650 + * @policy: Policy managing CPUs. 1651 + * @new_freq: New CPU frequency. 1658 1652 * 1659 - * We adjust to current frequency first, and need to clean up later. 1660 - * So either call to cpufreq_update_policy() or schedule handle_update()). 1653 + * Adjust to the current frequency first and clean up later by either calling 1654 + * cpufreq_update_policy(), or scheduling handle_update(). 1661 1655 */ 1662 1656 static void cpufreq_out_of_sync(struct cpufreq_policy *policy, 1663 1657 unsigned int new_freq) ··· 1836 1832 EXPORT_SYMBOL(cpufreq_generic_suspend); 1837 1833 1838 1834 /** 1839 - * cpufreq_suspend() - Suspend CPUFreq governors 1835 + * cpufreq_suspend() - Suspend CPUFreq governors. 1840 1836 * 1841 1837 * Called during system wide Suspend/Hibernate cycles for suspending governors 1842 1838 * as some platforms can't change frequency after this point in suspend cycle. ··· 1872 1868 } 1873 1869 1874 1870 /** 1875 - * cpufreq_resume() - Resume CPUFreq governors 1871 + * cpufreq_resume() - Resume CPUFreq governors. 1876 1872 * 1877 1873 * Called during system wide Suspend/Hibernate cycle for resuming governors that 1878 1874 * are suspended with cpufreq_suspend(). ··· 1924 1920 } 1925 1921 1926 1922 /** 1927 - * cpufreq_get_current_driver - return current driver's name 1923 + * cpufreq_get_current_driver - Return the current driver's name. 1928 1924 * 1929 - * Return the name string of the currently loaded cpufreq driver 1930 - * or NULL, if none. 1925 + * Return the name string of the currently registered cpufreq driver or NULL if 1926 + * none. 1931 1927 */ 1932 1928 const char *cpufreq_get_current_driver(void) 1933 1929 { ··· 1939 1935 EXPORT_SYMBOL_GPL(cpufreq_get_current_driver); 1940 1936 1941 1937 /** 1942 - * cpufreq_get_driver_data - return current driver data 1938 + * cpufreq_get_driver_data - Return current driver data. 1943 1939 * 1944 - * Return the private data of the currently loaded cpufreq 1945 - * driver, or NULL if no cpufreq driver is loaded. 1940 + * Return the private data of the currently registered cpufreq driver, or NULL 1941 + * if no cpufreq driver has been registered. 1946 1942 */ 1947 1943 void *cpufreq_get_driver_data(void) 1948 1944 { ··· 1958 1954 *********************************************************************/ 1959 1955 1960 1956 /** 1961 - * cpufreq_register_notifier - register a driver with cpufreq 1962 - * @nb: notifier function to register 1963 - * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER 1957 + * cpufreq_register_notifier - Register a notifier with cpufreq. 1958 + * @nb: notifier function to register. 1959 + * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER. 1964 1960 * 1965 - * Add a driver to one of two lists: either a list of drivers that 1966 - * are notified about clock rate changes (once before and once after 1967 - * the transition), or a list of drivers that are notified about 1968 - * changes in cpufreq policy. 1961 + * Add a notifier to one of two lists: either a list of notifiers that run on 1962 + * clock rate changes (once before and once after every transition), or a list 1963 + * of notifiers that ron on cpufreq policy changes. 1969 1964 * 1970 - * This function may sleep, and has the same return conditions as 1971 - * blocking_notifier_chain_register. 1965 + * This function may sleep and it has the same return values as 1966 + * blocking_notifier_chain_register(). 1972 1967 */ 1973 1968 int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) 1974 1969 { ··· 2004 2001 EXPORT_SYMBOL(cpufreq_register_notifier); 2005 2002 2006 2003 /** 2007 - * cpufreq_unregister_notifier - unregister a driver with cpufreq 2008 - * @nb: notifier block to be unregistered 2009 - * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER 2004 + * cpufreq_unregister_notifier - Unregister a notifier from cpufreq. 2005 + * @nb: notifier block to be unregistered. 2006 + * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER. 2010 2007 * 2011 - * Remove a driver from the CPU frequency notifier list. 2008 + * Remove a notifier from one of the cpufreq notifier lists. 2012 2009 * 2013 - * This function may sleep, and has the same return conditions as 2014 - * blocking_notifier_chain_unregister. 2010 + * This function may sleep and it has the same return values as 2011 + * blocking_notifier_chain_unregister(). 2015 2012 */ 2016 2013 int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) 2017 2014 { ··· 2126 2123 static int __target_index(struct cpufreq_policy *policy, int index) 2127 2124 { 2128 2125 struct cpufreq_freqs freqs = {.old = policy->cur, .flags = 0}; 2129 - unsigned int intermediate_freq = 0; 2126 + unsigned int restore_freq, intermediate_freq = 0; 2130 2127 unsigned int newfreq = policy->freq_table[index].frequency; 2131 2128 int retval = -EINVAL; 2132 2129 bool notify; 2133 2130 2134 2131 if (newfreq == policy->cur) 2135 2132 return 0; 2133 + 2134 + /* Save last value to restore later on errors */ 2135 + restore_freq = policy->cur; 2136 2136 2137 2137 notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION); 2138 2138 if (notify) { ··· 2174 2168 */ 2175 2169 if (unlikely(retval && intermediate_freq)) { 2176 2170 freqs.old = intermediate_freq; 2177 - freqs.new = policy->restore_freq; 2171 + freqs.new = restore_freq; 2178 2172 cpufreq_freq_transition_begin(policy, &freqs); 2179 2173 cpufreq_freq_transition_end(policy, &freqs, 0); 2180 2174 } ··· 2208 2202 if (target_freq == policy->cur && 2209 2203 !(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS)) 2210 2204 return 0; 2211 - 2212 - /* Save last value to restore later on errors */ 2213 - policy->restore_freq = policy->cur; 2214 2205 2215 2206 if (cpufreq_driver->target) 2216 2207 return cpufreq_driver->target(policy, target_freq, relation);
+8 -8
drivers/cpufreq/cpufreq_stats.c
··· 9 9 #include <linux/cpu.h> 10 10 #include <linux/cpufreq.h> 11 11 #include <linux/module.h> 12 + #include <linux/sched/clock.h> 12 13 #include <linux/slab.h> 13 - 14 14 15 15 struct cpufreq_stats { 16 16 unsigned int total_trans; ··· 30 30 static void cpufreq_stats_update(struct cpufreq_stats *stats, 31 31 unsigned long long time) 32 32 { 33 - unsigned long long cur_time = get_jiffies_64(); 33 + unsigned long long cur_time = local_clock(); 34 34 35 35 stats->time_in_state[stats->last_index] += cur_time - time; 36 36 stats->last_time = cur_time; ··· 42 42 43 43 memset(stats->time_in_state, 0, count * sizeof(u64)); 44 44 memset(stats->trans_table, 0, count * count * sizeof(int)); 45 - stats->last_time = get_jiffies_64(); 45 + stats->last_time = local_clock(); 46 46 stats->total_trans = 0; 47 47 48 48 /* Adjust for the time elapsed since reset was requested */ ··· 82 82 * before the reset_pending read above. 83 83 */ 84 84 smp_rmb(); 85 - time = get_jiffies_64() - READ_ONCE(stats->reset_time); 85 + time = local_clock() - READ_ONCE(stats->reset_time); 86 86 } else { 87 87 time = 0; 88 88 } 89 89 } else { 90 90 time = stats->time_in_state[i]; 91 91 if (i == stats->last_index) 92 - time += get_jiffies_64() - stats->last_time; 92 + time += local_clock() - stats->last_time; 93 93 } 94 94 95 95 len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i], 96 - jiffies_64_to_clock_t(time)); 96 + nsec_to_clock_t(time)); 97 97 } 98 98 return len; 99 99 } ··· 109 109 * Defer resetting of stats to cpufreq_stats_record_transition() to 110 110 * avoid races. 111 111 */ 112 - WRITE_ONCE(stats->reset_time, get_jiffies_64()); 112 + WRITE_ONCE(stats->reset_time, local_clock()); 113 113 /* 114 114 * The memory barrier below is to prevent the readers of reset_time from 115 115 * seeing a stale or partially updated value. ··· 249 249 stats->freq_table[i++] = pos->frequency; 250 250 251 251 stats->state_num = i; 252 - stats->last_time = get_jiffies_64(); 252 + stats->last_time = local_clock(); 253 253 stats->last_index = freq_table_get_index(stats, policy->cur); 254 254 255 255 policy->stats = stats;
+7
drivers/cpufreq/highbank-cpufreq.c
··· 101 101 } 102 102 module_init(hb_cpufreq_driver_init); 103 103 104 + static const struct of_device_id __maybe_unused hb_cpufreq_of_match[] = { 105 + { .compatible = "calxeda,highbank" }, 106 + { .compatible = "calxeda,ecx-2000" }, 107 + { }, 108 + }; 109 + MODULE_DEVICE_TABLE(of, hb_cpufreq_of_match); 110 + 104 111 MODULE_AUTHOR("Mark Langsdorf <mark.langsdorf@calxeda.com>"); 105 112 MODULE_DESCRIPTION("Calxeda Highbank cpufreq driver"); 106 113 MODULE_LICENSE("GPL");
+4 -5
drivers/cpufreq/intel_pstate.c
··· 2569 2569 int old_pstate = cpu->pstate.current_pstate; 2570 2570 2571 2571 target_pstate = intel_pstate_prepare_request(cpu, target_pstate); 2572 - if (hwp_active) { 2572 + if (hwp_active) 2573 2573 intel_cpufreq_adjust_hwp(cpu, target_pstate, 2574 2574 policy->strict_target, fast_switch); 2575 - cpu->pstate.current_pstate = target_pstate; 2576 - } else if (target_pstate != old_pstate) { 2575 + else if (target_pstate != old_pstate) 2577 2576 intel_cpufreq_adjust_perf_ctl(cpu, target_pstate, fast_switch); 2578 - cpu->pstate.current_pstate = target_pstate; 2579 - } 2577 + 2578 + cpu->pstate.current_pstate = target_pstate; 2580 2579 2581 2580 intel_cpufreq_trace(cpu, fast_switch ? INTEL_PSTATE_TRACE_FAST_SWITCH : 2582 2581 INTEL_PSTATE_TRACE_TARGET, old_pstate);
+1
drivers/cpufreq/loongson1-cpufreq.c
··· 216 216 217 217 module_platform_driver(ls1x_cpufreq_platdrv); 218 218 219 + MODULE_ALIAS("platform:ls1x-cpufreq"); 219 220 MODULE_AUTHOR("Kelvin Cheung <keguang.zhang@gmail.com>"); 220 221 MODULE_DESCRIPTION("Loongson1 CPUFreq driver"); 221 222 MODULE_LICENSE("GPL");
+3
drivers/cpufreq/mediatek-cpufreq.c
··· 532 532 { .compatible = "mediatek,mt2712", }, 533 533 { .compatible = "mediatek,mt7622", }, 534 534 { .compatible = "mediatek,mt7623", }, 535 + { .compatible = "mediatek,mt8167", }, 535 536 { .compatible = "mediatek,mt817x", }, 536 537 { .compatible = "mediatek,mt8173", }, 537 538 { .compatible = "mediatek,mt8176", }, ··· 541 540 542 541 { } 543 542 }; 543 + MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines); 544 544 545 545 static int __init mtk_cpufreq_driver_init(void) 546 546 { ··· 574 572 pdev = platform_device_register_simple("mtk-cpufreq", -1, NULL, 0); 575 573 if (IS_ERR(pdev)) { 576 574 pr_err("failed to register mtk-cpufreq platform device\n"); 575 + platform_driver_unregister(&mtk_cpufreq_platdrv); 577 576 return PTR_ERR(pdev); 578 577 } 579 578
+7 -9
drivers/cpufreq/qcom-cpufreq-nvmem.c
··· 397 397 398 398 free_genpd_opp: 399 399 for_each_possible_cpu(cpu) { 400 - if (IS_ERR_OR_NULL(drv->genpd_opp_tables[cpu])) 400 + if (IS_ERR(drv->genpd_opp_tables[cpu])) 401 401 break; 402 402 dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]); 403 403 } 404 404 kfree(drv->genpd_opp_tables); 405 405 free_opp: 406 406 for_each_possible_cpu(cpu) { 407 - if (IS_ERR_OR_NULL(drv->names_opp_tables[cpu])) 407 + if (IS_ERR(drv->names_opp_tables[cpu])) 408 408 break; 409 409 dev_pm_opp_put_prop_name(drv->names_opp_tables[cpu]); 410 410 } 411 411 for_each_possible_cpu(cpu) { 412 - if (IS_ERR_OR_NULL(drv->hw_opp_tables[cpu])) 412 + if (IS_ERR(drv->hw_opp_tables[cpu])) 413 413 break; 414 414 dev_pm_opp_put_supported_hw(drv->hw_opp_tables[cpu]); 415 415 } ··· 430 430 platform_device_unregister(cpufreq_dt_pdev); 431 431 432 432 for_each_possible_cpu(cpu) { 433 - if (drv->names_opp_tables[cpu]) 434 - dev_pm_opp_put_supported_hw(drv->names_opp_tables[cpu]); 435 - if (drv->hw_opp_tables[cpu]) 436 - dev_pm_opp_put_supported_hw(drv->hw_opp_tables[cpu]); 437 - if (drv->genpd_opp_tables[cpu]) 438 - dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]); 433 + dev_pm_opp_put_supported_hw(drv->names_opp_tables[cpu]); 434 + dev_pm_opp_put_supported_hw(drv->hw_opp_tables[cpu]); 435 + dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]); 439 436 } 440 437 441 438 kfree(drv->names_opp_tables); ··· 461 464 { .compatible = "qcom,msm8960", .data = &match_data_krait }, 462 465 {}, 463 466 }; 467 + MODULE_DEVICE_TABLE(of, qcom_cpufreq_match_list); 464 468 465 469 /* 466 470 * Since the driver depends on smem and nvmem drivers, which may
+4 -1
drivers/cpufreq/scmi-cpufreq.c
··· 126 126 struct scmi_data *priv; 127 127 struct cpufreq_frequency_table *freq_table; 128 128 struct em_data_callback em_cb = EM_DATA_CB(scmi_get_cpu_power); 129 + bool power_scale_mw; 129 130 130 131 cpu_dev = get_cpu_device(policy->cpu); 131 132 if (!cpu_dev) { ··· 190 189 policy->fast_switch_possible = 191 190 handle->perf_ops->fast_switch_possible(handle, cpu_dev); 192 191 193 - em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, policy->cpus); 192 + power_scale_mw = handle->perf_ops->power_scale_mw_get(handle); 193 + em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, policy->cpus, 194 + power_scale_mw); 194 195 195 196 return 0; 196 197
+1
drivers/cpufreq/scpi-cpufreq.c
··· 233 233 }; 234 234 module_platform_driver(scpi_cpufreq_platdrv); 235 235 236 + MODULE_ALIAS("platform:scpi-cpufreq"); 236 237 MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>"); 237 238 MODULE_DESCRIPTION("ARM SCPI CPUFreq interface driver"); 238 239 MODULE_LICENSE("GPL v2");
+13 -1
drivers/cpufreq/sti-cpufreq.c
··· 223 223 opp_table = dev_pm_opp_set_supported_hw(dev, version, VERSION_ELEMENTS); 224 224 if (IS_ERR(opp_table)) { 225 225 dev_err(dev, "Failed to set supported hardware\n"); 226 - return PTR_ERR(opp_table); 226 + ret = PTR_ERR(opp_table); 227 + goto err_put_prop_name; 227 228 } 228 229 229 230 dev_dbg(dev, "pcode: %d major: %d minor: %d substrate: %d\n", ··· 233 232 version[0], version[1], version[2]); 234 233 235 234 return 0; 235 + 236 + err_put_prop_name: 237 + dev_pm_opp_put_prop_name(opp_table); 238 + return ret; 236 239 } 237 240 238 241 static int sti_cpufreq_fetch_syscon_registers(void) ··· 296 291 return 0; 297 292 } 298 293 module_init(sti_cpufreq_init); 294 + 295 + static const struct of_device_id __maybe_unused sti_cpufreq_of_match[] = { 296 + { .compatible = "st,stih407" }, 297 + { .compatible = "st,stih410" }, 298 + { }, 299 + }; 300 + MODULE_DEVICE_TABLE(of, sti_cpufreq_of_match); 299 301 300 302 MODULE_DESCRIPTION("STMicroelectronics CPUFreq/OPP driver"); 301 303 MODULE_AUTHOR("Ajitpal Singh <ajitpal.singh@st.com>");
+1
drivers/cpufreq/sun50i-cpufreq-nvmem.c
··· 167 167 { .compatible = "allwinner,sun50i-h6" }, 168 168 {} 169 169 }; 170 + MODULE_DEVICE_TABLE(of, sun50i_cpufreq_match_list); 170 171 171 172 static const struct of_device_id *sun50i_cpufreq_match_node(void) 172 173 {
+56 -70
drivers/cpufreq/tegra186-cpufreq.c
··· 12 12 #include <soc/tegra/bpmp.h> 13 13 #include <soc/tegra/bpmp-abi.h> 14 14 15 - #define EDVD_CORE_VOLT_FREQ(core) (0x20 + (core) * 0x4) 16 - #define EDVD_CORE_VOLT_FREQ_F_SHIFT 0 17 - #define EDVD_CORE_VOLT_FREQ_F_MASK 0xffff 18 - #define EDVD_CORE_VOLT_FREQ_V_SHIFT 16 15 + #define TEGRA186_NUM_CLUSTERS 2 16 + #define EDVD_OFFSET_A57(core) ((SZ_64K * 6) + (0x20 + (core) * 0x4)) 17 + #define EDVD_OFFSET_DENVER(core) ((SZ_64K * 7) + (0x20 + (core) * 0x4)) 18 + #define EDVD_CORE_VOLT_FREQ_F_SHIFT 0 19 + #define EDVD_CORE_VOLT_FREQ_F_MASK 0xffff 20 + #define EDVD_CORE_VOLT_FREQ_V_SHIFT 16 19 21 20 - struct tegra186_cpufreq_cluster_info { 21 - unsigned long offset; 22 - int cpus[4]; 22 + struct tegra186_cpufreq_cpu { 23 23 unsigned int bpmp_cluster_id; 24 + unsigned int edvd_offset; 24 25 }; 25 26 26 - #define NO_CPU -1 27 - static const struct tegra186_cpufreq_cluster_info tegra186_clusters[] = { 28 - /* Denver cluster */ 27 + static const struct tegra186_cpufreq_cpu tegra186_cpus[] = { 28 + /* CPU0 - A57 Cluster */ 29 29 { 30 - .offset = SZ_64K * 7, 31 - .cpus = { 1, 2, NO_CPU, NO_CPU }, 32 - .bpmp_cluster_id = 0, 33 - }, 34 - /* A57 cluster */ 35 - { 36 - .offset = SZ_64K * 6, 37 - .cpus = { 0, 3, 4, 5 }, 38 30 .bpmp_cluster_id = 1, 31 + .edvd_offset = EDVD_OFFSET_A57(0) 32 + }, 33 + /* CPU1 - Denver Cluster */ 34 + { 35 + .bpmp_cluster_id = 0, 36 + .edvd_offset = EDVD_OFFSET_DENVER(0) 37 + }, 38 + /* CPU2 - Denver Cluster */ 39 + { 40 + .bpmp_cluster_id = 0, 41 + .edvd_offset = EDVD_OFFSET_DENVER(1) 42 + }, 43 + /* CPU3 - A57 Cluster */ 44 + { 45 + .bpmp_cluster_id = 1, 46 + .edvd_offset = EDVD_OFFSET_A57(1) 47 + }, 48 + /* CPU4 - A57 Cluster */ 49 + { 50 + .bpmp_cluster_id = 1, 51 + .edvd_offset = EDVD_OFFSET_A57(2) 52 + }, 53 + /* CPU5 - A57 Cluster */ 54 + { 55 + .bpmp_cluster_id = 1, 56 + .edvd_offset = EDVD_OFFSET_A57(3) 39 57 }, 40 58 }; 41 59 42 60 struct tegra186_cpufreq_cluster { 43 - const struct tegra186_cpufreq_cluster_info *info; 44 61 struct cpufreq_frequency_table *table; 45 62 u32 ref_clk_khz; 46 63 u32 div; ··· 65 48 66 49 struct tegra186_cpufreq_data { 67 50 void __iomem *regs; 68 - 69 - size_t num_clusters; 70 51 struct tegra186_cpufreq_cluster *clusters; 52 + const struct tegra186_cpufreq_cpu *cpus; 71 53 }; 72 54 73 55 static int tegra186_cpufreq_init(struct cpufreq_policy *policy) 74 56 { 75 57 struct tegra186_cpufreq_data *data = cpufreq_get_driver_data(); 76 - unsigned int i; 58 + unsigned int cluster = data->cpus[policy->cpu].bpmp_cluster_id; 77 59 78 - for (i = 0; i < data->num_clusters; i++) { 79 - struct tegra186_cpufreq_cluster *cluster = &data->clusters[i]; 80 - const struct tegra186_cpufreq_cluster_info *info = 81 - cluster->info; 82 - int core; 83 - 84 - for (core = 0; core < ARRAY_SIZE(info->cpus); core++) { 85 - if (info->cpus[core] == policy->cpu) 86 - break; 87 - } 88 - if (core == ARRAY_SIZE(info->cpus)) 89 - continue; 90 - 91 - policy->driver_data = 92 - data->regs + info->offset + EDVD_CORE_VOLT_FREQ(core); 93 - policy->freq_table = cluster->table; 94 - break; 95 - } 96 - 60 + policy->freq_table = data->clusters[cluster].table; 97 61 policy->cpuinfo.transition_latency = 300 * 1000; 62 + policy->driver_data = NULL; 98 63 99 64 return 0; 100 65 } ··· 84 85 static int tegra186_cpufreq_set_target(struct cpufreq_policy *policy, 85 86 unsigned int index) 86 87 { 88 + struct tegra186_cpufreq_data *data = cpufreq_get_driver_data(); 87 89 struct cpufreq_frequency_table *tbl = policy->freq_table + index; 88 - void __iomem *edvd_reg = policy->driver_data; 90 + unsigned int edvd_offset = data->cpus[policy->cpu].edvd_offset; 89 91 u32 edvd_val = tbl->driver_data; 90 92 91 - writel(edvd_val, edvd_reg); 93 + writel(edvd_val, data->regs + edvd_offset); 92 94 93 95 return 0; 94 96 } ··· 97 97 static unsigned int tegra186_cpufreq_get(unsigned int cpu) 98 98 { 99 99 struct tegra186_cpufreq_data *data = cpufreq_get_driver_data(); 100 + struct tegra186_cpufreq_cluster *cluster; 100 101 struct cpufreq_policy *policy; 101 - void __iomem *edvd_reg; 102 - unsigned int i, freq = 0; 102 + unsigned int edvd_offset, cluster_id; 103 103 u32 ndiv; 104 104 105 105 policy = cpufreq_cpu_get(cpu); 106 106 if (!policy) 107 107 return 0; 108 108 109 - edvd_reg = policy->driver_data; 110 - ndiv = readl(edvd_reg) & EDVD_CORE_VOLT_FREQ_F_MASK; 111 - 112 - for (i = 0; i < data->num_clusters; i++) { 113 - struct tegra186_cpufreq_cluster *cluster = &data->clusters[i]; 114 - int core; 115 - 116 - for (core = 0; core < ARRAY_SIZE(cluster->info->cpus); core++) { 117 - if (cluster->info->cpus[core] != policy->cpu) 118 - continue; 119 - 120 - freq = (cluster->ref_clk_khz * ndiv) / cluster->div; 121 - goto out; 122 - } 123 - } 124 - 125 - out: 109 + edvd_offset = data->cpus[policy->cpu].edvd_offset; 110 + ndiv = readl(data->regs + edvd_offset) & EDVD_CORE_VOLT_FREQ_F_MASK; 111 + cluster_id = data->cpus[policy->cpu].bpmp_cluster_id; 112 + cluster = &data->clusters[cluster_id]; 126 113 cpufreq_cpu_put(policy); 127 114 128 - return freq; 115 + return (cluster->ref_clk_khz * ndiv) / cluster->div; 129 116 } 130 117 131 118 static struct cpufreq_driver tegra186_cpufreq_driver = { ··· 128 141 129 142 static struct cpufreq_frequency_table *init_vhint_table( 130 143 struct platform_device *pdev, struct tegra_bpmp *bpmp, 131 - struct tegra186_cpufreq_cluster *cluster) 144 + struct tegra186_cpufreq_cluster *cluster, unsigned int cluster_id) 132 145 { 133 146 struct cpufreq_frequency_table *table; 134 147 struct mrq_cpu_vhint_request req; ··· 147 160 148 161 memset(&req, 0, sizeof(req)); 149 162 req.addr = phys; 150 - req.cluster_id = cluster->info->bpmp_cluster_id; 163 + req.cluster_id = cluster_id; 151 164 152 165 memset(&msg, 0, sizeof(msg)); 153 166 msg.mrq = MRQ_CPU_VHINT; ··· 221 234 if (!data) 222 235 return -ENOMEM; 223 236 224 - data->clusters = devm_kcalloc(&pdev->dev, ARRAY_SIZE(tegra186_clusters), 237 + data->clusters = devm_kcalloc(&pdev->dev, TEGRA186_NUM_CLUSTERS, 225 238 sizeof(*data->clusters), GFP_KERNEL); 226 239 if (!data->clusters) 227 240 return -ENOMEM; 228 241 229 - data->num_clusters = ARRAY_SIZE(tegra186_clusters); 242 + data->cpus = tegra186_cpus; 230 243 231 244 bpmp = tegra_bpmp_get(&pdev->dev); 232 245 if (IS_ERR(bpmp)) ··· 238 251 goto put_bpmp; 239 252 } 240 253 241 - for (i = 0; i < data->num_clusters; i++) { 254 + for (i = 0; i < TEGRA186_NUM_CLUSTERS; i++) { 242 255 struct tegra186_cpufreq_cluster *cluster = &data->clusters[i]; 243 256 244 - cluster->info = &tegra186_clusters[i]; 245 - cluster->table = init_vhint_table(pdev, bpmp, cluster); 257 + cluster->table = init_vhint_table(pdev, bpmp, cluster, i); 246 258 if (IS_ERR(cluster->table)) { 247 259 err = PTR_ERR(cluster->table); 248 260 goto put_bpmp;
+55 -17
drivers/cpufreq/tegra194-cpufreq.c
··· 21 21 #define KHZ 1000 22 22 #define REF_CLK_MHZ 408 /* 408 MHz */ 23 23 #define US_DELAY 500 24 - #define US_DELAY_MIN 2 25 24 #define CPUFREQ_TBL_STEP_HZ (50 * KHZ * KHZ) 26 25 #define MAX_CNT ~0U 27 26 ··· 43 44 44 45 struct tegra_cpu_ctr { 45 46 u32 cpu; 46 - u32 delay; 47 47 u32 coreclk_cnt, last_coreclk_cnt; 48 48 u32 refclk_cnt, last_refclk_cnt; 49 49 }; ··· 110 112 val = read_freq_feedback(); 111 113 c->last_refclk_cnt = lower_32_bits(val); 112 114 c->last_coreclk_cnt = upper_32_bits(val); 113 - udelay(c->delay); 115 + udelay(US_DELAY); 114 116 val = read_freq_feedback(); 115 117 c->refclk_cnt = lower_32_bits(val); 116 118 c->coreclk_cnt = upper_32_bits(val); ··· 137 139 * @cpu - logical cpu whose freq to be updated 138 140 * Returns freq in KHz on success, 0 if cpu is offline 139 141 */ 140 - static unsigned int tegra194_get_speed_common(u32 cpu, u32 delay) 142 + static unsigned int tegra194_calculate_speed(u32 cpu) 141 143 { 142 144 struct read_counters_work read_counters_work; 143 145 struct tegra_cpu_ctr c; ··· 151 153 * interrupts enabled. 152 154 */ 153 155 read_counters_work.c.cpu = cpu; 154 - read_counters_work.c.delay = delay; 155 156 INIT_WORK_ONSTACK(&read_counters_work.work, tegra_read_counters); 156 157 queue_work_on(cpu, read_counters_wq, &read_counters_work.work); 157 158 flush_work(&read_counters_work.work); ··· 177 180 return (rate_mhz * KHZ); /* in KHz */ 178 181 } 179 182 183 + static void get_cpu_ndiv(void *ndiv) 184 + { 185 + u64 ndiv_val; 186 + 187 + asm volatile("mrs %0, s3_0_c15_c0_4" : "=r" (ndiv_val) : ); 188 + 189 + *(u64 *)ndiv = ndiv_val; 190 + } 191 + 192 + static void set_cpu_ndiv(void *data) 193 + { 194 + struct cpufreq_frequency_table *tbl = data; 195 + u64 ndiv_val = (u64)tbl->driver_data; 196 + 197 + asm volatile("msr s3_0_c15_c0_4, %0" : : "r" (ndiv_val)); 198 + } 199 + 180 200 static unsigned int tegra194_get_speed(u32 cpu) 181 201 { 182 - return tegra194_get_speed_common(cpu, US_DELAY); 202 + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); 203 + struct cpufreq_frequency_table *pos; 204 + unsigned int rate; 205 + u64 ndiv; 206 + int ret; 207 + u32 cl; 208 + 209 + smp_call_function_single(cpu, get_cpu_cluster, &cl, true); 210 + 211 + /* reconstruct actual cpu freq using counters */ 212 + rate = tegra194_calculate_speed(cpu); 213 + 214 + /* get last written ndiv value */ 215 + ret = smp_call_function_single(cpu, get_cpu_ndiv, &ndiv, true); 216 + if (WARN_ON_ONCE(ret)) 217 + return rate; 218 + 219 + /* 220 + * If the reconstructed frequency has acceptable delta from 221 + * the last written value, then return freq corresponding 222 + * to the last written ndiv value from freq_table. This is 223 + * done to return consistent value. 224 + */ 225 + cpufreq_for_each_valid_entry(pos, data->tables[cl]) { 226 + if (pos->driver_data != ndiv) 227 + continue; 228 + 229 + if (abs(pos->frequency - rate) > 115200) { 230 + pr_warn("cpufreq: cpu%d,cur:%u,set:%u,set ndiv:%llu\n", 231 + cpu, rate, pos->frequency, ndiv); 232 + } else { 233 + rate = pos->frequency; 234 + } 235 + break; 236 + } 237 + return rate; 183 238 } 184 239 185 240 static int tegra194_cpufreq_init(struct cpufreq_policy *policy) ··· 245 196 if (cl >= data->num_clusters) 246 197 return -EINVAL; 247 198 248 - /* boot freq */ 249 - policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY_MIN); 250 - 251 199 /* set same policy for all cpus in a cluster */ 252 200 for (cpu = (cl * 2); cpu < ((cl + 1) * 2); cpu++) 253 201 cpumask_set_cpu(cpu, policy->cpus); ··· 253 207 policy->cpuinfo.transition_latency = TEGRA_CPUFREQ_TRANSITION_LATENCY; 254 208 255 209 return 0; 256 - } 257 - 258 - static void set_cpu_ndiv(void *data) 259 - { 260 - struct cpufreq_frequency_table *tbl = data; 261 - u64 ndiv_val = (u64)tbl->driver_data; 262 - 263 - asm volatile("msr s3_0_c15_c0_4, %0" : : "r" (ndiv_val)); 264 210 } 265 211 266 212 static int tegra194_cpufreq_set_target(struct cpufreq_policy *policy,
+1
drivers/cpufreq/vexpress-spc-cpufreq.c
··· 591 591 }; 592 592 module_platform_driver(ve_spc_cpufreq_platdrv); 593 593 594 + MODULE_ALIAS("platform:vexpress-spc-cpufreq"); 594 595 MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>"); 595 596 MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>"); 596 597 MODULE_DESCRIPTION("Vexpress SPC ARM big LITTLE cpufreq driver");
+2
drivers/cpuidle/cpuidle-psci-domain.c
··· 327 327 if (cpu_online(cpu)) 328 328 pm_runtime_get_sync(dev); 329 329 330 + dev_pm_syscore_device(dev, true); 331 + 330 332 return dev; 331 333 } 332 334
+30 -4
drivers/cpuidle/cpuidle-psci.c
··· 19 19 #include <linux/of_device.h> 20 20 #include <linux/platform_device.h> 21 21 #include <linux/psci.h> 22 + #include <linux/pm_domain.h> 22 23 #include <linux/pm_runtime.h> 23 24 #include <linux/slab.h> 24 25 #include <linux/string.h> ··· 53 52 return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter, idx, state); 54 53 } 55 54 56 - static int psci_enter_domain_idle_state(struct cpuidle_device *dev, 57 - struct cpuidle_driver *drv, int idx) 55 + static int __psci_enter_domain_idle_state(struct cpuidle_device *dev, 56 + struct cpuidle_driver *drv, int idx, 57 + bool s2idle) 58 58 { 59 59 struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data); 60 60 u32 *states = data->psci_states; ··· 68 66 return -1; 69 67 70 68 /* Do runtime PM to manage a hierarchical CPU toplogy. */ 71 - RCU_NONIDLE(pm_runtime_put_sync_suspend(pd_dev)); 69 + rcu_irq_enter_irqson(); 70 + if (s2idle) 71 + dev_pm_genpd_suspend(pd_dev); 72 + else 73 + pm_runtime_put_sync_suspend(pd_dev); 74 + rcu_irq_exit_irqson(); 72 75 73 76 state = psci_get_domain_state(); 74 77 if (!state) ··· 81 74 82 75 ret = psci_cpu_suspend_enter(state) ? -1 : idx; 83 76 84 - RCU_NONIDLE(pm_runtime_get_sync(pd_dev)); 77 + rcu_irq_enter_irqson(); 78 + if (s2idle) 79 + dev_pm_genpd_resume(pd_dev); 80 + else 81 + pm_runtime_get_sync(pd_dev); 82 + rcu_irq_exit_irqson(); 85 83 86 84 cpu_pm_exit(); 87 85 88 86 /* Clear the domain state to start fresh when back from idle. */ 89 87 psci_set_domain_state(0); 90 88 return ret; 89 + } 90 + 91 + static int psci_enter_domain_idle_state(struct cpuidle_device *dev, 92 + struct cpuidle_driver *drv, int idx) 93 + { 94 + return __psci_enter_domain_idle_state(dev, drv, idx, false); 95 + } 96 + 97 + static int psci_enter_s2idle_domain_idle_state(struct cpuidle_device *dev, 98 + struct cpuidle_driver *drv, 99 + int idx) 100 + { 101 + return __psci_enter_domain_idle_state(dev, drv, idx, true); 91 102 } 92 103 93 104 static int psci_idle_cpuhp_up(unsigned int cpu) ··· 195 170 * deeper states. 196 171 */ 197 172 drv->states[state_count - 1].enter = psci_enter_domain_idle_state; 173 + drv->states[state_count - 1].enter_s2idle = psci_enter_s2idle_domain_idle_state; 198 174 psci_cpuidle_use_cpuhp = true; 199 175 200 176 return 0;
+23 -2
drivers/cpuidle/cpuidle.c
··· 368 368 cpuidle_curr_governor->reflect(dev, index); 369 369 } 370 370 371 + /* 372 + * Min polling interval of 10usec is a guess. It is assuming that 373 + * for most users, the time for a single ping-pong workload like 374 + * perf bench pipe would generally complete within 10usec but 375 + * this is hardware dependant. Actual time can be estimated with 376 + * 377 + * perf bench sched pipe -l 10000 378 + * 379 + * Run multiple times to avoid cpufreq effects. 380 + */ 381 + #define CPUIDLE_POLL_MIN 10000 382 + #define CPUIDLE_POLL_MAX (TICK_NSEC / 16) 383 + 371 384 /** 372 385 * cpuidle_poll_time - return amount of time to poll for, 373 386 * governors can override dev->poll_limit_ns if necessary ··· 395 382 int i; 396 383 u64 limit_ns; 397 384 385 + BUILD_BUG_ON(CPUIDLE_POLL_MIN > CPUIDLE_POLL_MAX); 386 + 398 387 if (dev->poll_limit_ns) 399 388 return dev->poll_limit_ns; 400 389 401 - limit_ns = TICK_NSEC; 390 + limit_ns = CPUIDLE_POLL_MAX; 402 391 for (i = 1; i < drv->state_count; i++) { 392 + u64 state_limit; 393 + 403 394 if (dev->states_usage[i].disable) 404 395 continue; 405 396 406 - limit_ns = drv->states[i].target_residency_ns; 397 + state_limit = drv->states[i].target_residency_ns; 398 + if (state_limit < CPUIDLE_POLL_MIN) 399 + continue; 400 + 401 + limit_ns = min_t(u64, state_limit, CPUIDLE_POLL_MAX); 407 402 break; 408 403 } 409 404
-10
drivers/devfreq/Kconfig
··· 121 121 It reads ACTMON counters of memory controllers and adjusts the 122 122 operating frequencies and voltages with OPP support. 123 123 124 - config ARM_TEGRA20_DEVFREQ 125 - tristate "NVIDIA Tegra20 DEVFREQ Driver" 126 - depends on (TEGRA_MC && TEGRA20_EMC) || COMPILE_TEST 127 - depends on COMMON_CLK 128 - select DEVFREQ_GOV_SIMPLE_ONDEMAND 129 - help 130 - This adds the DEVFREQ driver for the Tegra20 family of SoCs. 131 - It reads Memory Controller counters and adjusts the operating 132 - frequencies and voltages with OPP support. 133 - 134 124 config ARM_RK3399_DMC_DEVFREQ 135 125 tristate "ARM RK3399 DMC DEVFREQ Driver" 136 126 depends on (ARCH_ROCKCHIP && HAVE_ARM_SMCCC) || \
-1
drivers/devfreq/Makefile
··· 13 13 obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o 14 14 obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o 15 15 obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o 16 - obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o 17 16 18 17 # DEVFREQ Event Drivers 19 18 obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/
+163 -79
drivers/devfreq/devfreq.c
··· 31 31 #define CREATE_TRACE_POINTS 32 32 #include <trace/events/devfreq.h> 33 33 34 + #define IS_SUPPORTED_FLAG(f, name) ((f & DEVFREQ_GOV_FLAG_##name) ? true : false) 35 + #define IS_SUPPORTED_ATTR(f, name) ((f & DEVFREQ_GOV_ATTR_##name) ? true : false) 34 36 #define HZ_PER_KHZ 1000 35 37 36 38 static struct class *devfreq_class; ··· 369 367 return err; 370 368 } 371 369 370 + /* 371 + * Print devfreq_frequency trace information between DEVFREQ_PRECHANGE 372 + * and DEVFREQ_POSTCHANGE because for showing the correct frequency 373 + * change order of between devfreq device and passive devfreq device. 374 + */ 375 + if (trace_devfreq_frequency_enabled() && new_freq != cur_freq) 376 + trace_devfreq_frequency(devfreq, new_freq, cur_freq); 377 + 372 378 freqs.new = new_freq; 373 379 devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE); 374 380 ··· 392 382 return err; 393 383 } 394 384 395 - /* Load monitoring helper functions for governors use */ 396 - 397 385 /** 398 - * update_devfreq() - Reevaluate the device and configure frequency. 386 + * devfreq_update_target() - Reevaluate the device and configure frequency 387 + * on the final stage. 399 388 * @devfreq: the devfreq instance. 389 + * @freq: the new frequency of parent device. This argument 390 + * is only used for devfreq device using passive governor. 400 391 * 401 - * Note: Lock devfreq->lock before calling update_devfreq 402 - * This function is exported for governors. 392 + * Note: Lock devfreq->lock before calling devfreq_update_target. This function 393 + * should be only used by both update_devfreq() and devfreq governors. 403 394 */ 404 - int update_devfreq(struct devfreq *devfreq) 395 + int devfreq_update_target(struct devfreq *devfreq, unsigned long freq) 405 396 { 406 - unsigned long freq, min_freq, max_freq; 397 + unsigned long min_freq, max_freq; 407 398 int err = 0; 408 399 u32 flags = 0; 409 400 ··· 429 418 } 430 419 431 420 return devfreq_set_target(devfreq, freq, flags); 421 + } 422 + EXPORT_SYMBOL(devfreq_update_target); 432 423 424 + /* Load monitoring helper functions for governors use */ 425 + 426 + /** 427 + * update_devfreq() - Reevaluate the device and configure frequency. 428 + * @devfreq: the devfreq instance. 429 + * 430 + * Note: Lock devfreq->lock before calling update_devfreq 431 + * This function is exported for governors. 432 + */ 433 + int update_devfreq(struct devfreq *devfreq) 434 + { 435 + return devfreq_update_target(devfreq, 0L); 433 436 } 434 437 EXPORT_SYMBOL(update_devfreq); 435 438 ··· 481 456 */ 482 457 void devfreq_monitor_start(struct devfreq *devfreq) 483 458 { 484 - if (devfreq->governor->interrupt_driven) 459 + if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN)) 485 460 return; 486 461 487 462 switch (devfreq->profile->timer) { ··· 511 486 */ 512 487 void devfreq_monitor_stop(struct devfreq *devfreq) 513 488 { 514 - if (devfreq->governor->interrupt_driven) 489 + if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN)) 515 490 return; 516 491 517 492 cancel_delayed_work_sync(&devfreq->work); ··· 542 517 devfreq->stop_polling = true; 543 518 mutex_unlock(&devfreq->lock); 544 519 545 - if (devfreq->governor->interrupt_driven) 520 + if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN)) 546 521 return; 547 522 548 523 cancel_delayed_work_sync(&devfreq->work); ··· 562 537 unsigned long freq; 563 538 564 539 mutex_lock(&devfreq->lock); 540 + 541 + if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN)) 542 + goto out_update; 543 + 565 544 if (!devfreq->stop_polling) 566 545 goto out; 567 - 568 - if (devfreq->governor->interrupt_driven) 569 - goto out_update; 570 546 571 547 if (!delayed_work_pending(&devfreq->work) && 572 548 devfreq->profile->polling_ms) ··· 603 577 mutex_lock(&devfreq->lock); 604 578 devfreq->profile->polling_ms = new_delay; 605 579 606 - if (devfreq->stop_polling) 580 + if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN)) 607 581 goto out; 608 582 609 - if (devfreq->governor->interrupt_driven) 583 + if (devfreq->stop_polling) 610 584 goto out; 611 585 612 586 /* if new delay is zero, stop polling */ ··· 761 735 kfree(devfreq); 762 736 } 763 737 738 + static void create_sysfs_files(struct devfreq *devfreq, 739 + const struct devfreq_governor *gov); 740 + static void remove_sysfs_files(struct devfreq *devfreq, 741 + const struct devfreq_governor *gov); 742 + 764 743 /** 765 744 * devfreq_add_device() - Add devfreq feature to the device 766 745 * @dev: the device to add devfreq feature. ··· 811 780 devfreq->dev.release = devfreq_dev_release; 812 781 INIT_LIST_HEAD(&devfreq->node); 813 782 devfreq->profile = profile; 814 - strscpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN); 815 783 devfreq->previous_freq = profile->initial_freq; 816 784 devfreq->last_status.current_frequency = profile->initial_freq; 817 785 devfreq->data = data; ··· 906 876 907 877 mutex_lock(&devfreq_list_lock); 908 878 909 - governor = try_then_request_governor(devfreq->governor_name); 879 + governor = try_then_request_governor(governor_name); 910 880 if (IS_ERR(governor)) { 911 881 dev_err(dev, "%s: Unable to find governor for the device\n", 912 882 __func__); ··· 922 892 __func__); 923 893 goto err_init; 924 894 } 895 + create_sysfs_files(devfreq, devfreq->governor); 925 896 926 897 list_add(&devfreq->node, &devfreq_list); 927 898 ··· 953 922 if (!devfreq) 954 923 return -EINVAL; 955 924 956 - if (devfreq->governor) 925 + if (devfreq->governor) { 957 926 devfreq->governor->event_handler(devfreq, 958 927 DEVFREQ_GOV_STOP, NULL); 928 + remove_sysfs_files(devfreq, devfreq->governor); 929 + } 930 + 959 931 device_unregister(&devfreq->dev); 960 932 961 933 return 0; ··· 1248 1214 int ret = 0; 1249 1215 struct device *dev = devfreq->dev.parent; 1250 1216 1251 - if (!strncmp(devfreq->governor_name, governor->name, 1217 + if (!strncmp(devfreq->governor->name, governor->name, 1252 1218 DEVFREQ_NAME_LEN)) { 1253 1219 /* The following should never occur */ 1254 1220 if (devfreq->governor) { ··· 1310 1276 int ret; 1311 1277 struct device *dev = devfreq->dev.parent; 1312 1278 1313 - if (!strncmp(devfreq->governor_name, governor->name, 1279 + if (!strncmp(devfreq->governor->name, governor->name, 1314 1280 DEVFREQ_NAME_LEN)) { 1315 1281 /* we should have a devfreq governor! */ 1316 1282 if (!devfreq->governor) { ··· 1381 1347 if (df->governor == governor) { 1382 1348 ret = 0; 1383 1349 goto out; 1384 - } else if (df->governor->immutable || governor->immutable) { 1350 + } else if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE) 1351 + || IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE)) { 1385 1352 ret = -EINVAL; 1386 1353 goto out; 1387 1354 } 1388 1355 1356 + /* 1357 + * Stop the current governor and remove the specific sysfs files 1358 + * which depend on current governor. 1359 + */ 1389 1360 ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL); 1390 1361 if (ret) { 1391 1362 dev_warn(dev, "%s: Governor %s not stopped(%d)\n", 1392 1363 __func__, df->governor->name, ret); 1393 1364 goto out; 1394 1365 } 1366 + remove_sysfs_files(df, df->governor); 1395 1367 1368 + /* 1369 + * Start the new governor and create the specific sysfs files 1370 + * which depend on the new governor. 1371 + */ 1396 1372 prev_governor = df->governor; 1397 1373 df->governor = governor; 1398 - strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN); 1399 1374 ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL); 1400 1375 if (ret) { 1401 1376 dev_warn(dev, "%s: Governor %s not started(%d)\n", 1402 1377 __func__, df->governor->name, ret); 1378 + 1379 + /* Restore previous governor */ 1403 1380 df->governor = prev_governor; 1404 - strncpy(df->governor_name, prev_governor->name, 1405 - DEVFREQ_NAME_LEN); 1406 1381 ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL); 1407 1382 if (ret) { 1408 1383 dev_err(dev, 1409 1384 "%s: reverting to Governor %s failed (%d)\n", 1410 - __func__, df->governor_name, ret); 1385 + __func__, prev_governor->name, ret); 1411 1386 df->governor = NULL; 1387 + goto out; 1412 1388 } 1413 1389 } 1390 + 1391 + /* 1392 + * Create the sysfs files for the new governor. But if failed to start 1393 + * the new governor, restore the sysfs files of previous governor. 1394 + */ 1395 + create_sysfs_files(df, df->governor); 1396 + 1414 1397 out: 1415 1398 mutex_unlock(&devfreq_list_lock); 1416 1399 ··· 1453 1402 * The devfreq with immutable governor (e.g., passive) shows 1454 1403 * only own governor. 1455 1404 */ 1456 - if (df->governor->immutable) { 1405 + if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE)) { 1457 1406 count = scnprintf(&buf[count], DEVFREQ_NAME_LEN, 1458 - "%s ", df->governor_name); 1407 + "%s ", df->governor->name); 1459 1408 /* 1460 1409 * The devfreq device shows the registered governor except for 1461 1410 * immutable governors such as passive governor . ··· 1464 1413 struct devfreq_governor *governor; 1465 1414 1466 1415 list_for_each_entry(governor, &devfreq_governor_list, node) { 1467 - if (governor->immutable) 1416 + if (IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE)) 1468 1417 continue; 1469 1418 count += scnprintf(&buf[count], (PAGE_SIZE - count - 2), 1470 1419 "%s ", governor->name); ··· 1508 1457 return sprintf(buf, "%lu\n", df->previous_freq); 1509 1458 } 1510 1459 static DEVICE_ATTR_RO(target_freq); 1511 - 1512 - static ssize_t polling_interval_show(struct device *dev, 1513 - struct device_attribute *attr, char *buf) 1514 - { 1515 - struct devfreq *df = to_devfreq(dev); 1516 - 1517 - if (!df->profile) 1518 - return -EINVAL; 1519 - 1520 - return sprintf(buf, "%d\n", df->profile->polling_ms); 1521 - } 1522 - 1523 - static ssize_t polling_interval_store(struct device *dev, 1524 - struct device_attribute *attr, 1525 - const char *buf, size_t count) 1526 - { 1527 - struct devfreq *df = to_devfreq(dev); 1528 - unsigned int value; 1529 - int ret; 1530 - 1531 - if (!df->governor) 1532 - return -EINVAL; 1533 - 1534 - ret = sscanf(buf, "%u", &value); 1535 - if (ret != 1) 1536 - return -EINVAL; 1537 - 1538 - df->governor->event_handler(df, DEVFREQ_GOV_UPDATE_INTERVAL, &value); 1539 - ret = count; 1540 - 1541 - return ret; 1542 - } 1543 - static DEVICE_ATTR_RW(polling_interval); 1544 1460 1545 1461 static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr, 1546 1462 const char *buf, size_t count) ··· 1716 1698 } 1717 1699 static DEVICE_ATTR_RW(trans_stat); 1718 1700 1701 + static struct attribute *devfreq_attrs[] = { 1702 + &dev_attr_name.attr, 1703 + &dev_attr_governor.attr, 1704 + &dev_attr_available_governors.attr, 1705 + &dev_attr_cur_freq.attr, 1706 + &dev_attr_available_frequencies.attr, 1707 + &dev_attr_target_freq.attr, 1708 + &dev_attr_min_freq.attr, 1709 + &dev_attr_max_freq.attr, 1710 + &dev_attr_trans_stat.attr, 1711 + NULL, 1712 + }; 1713 + ATTRIBUTE_GROUPS(devfreq); 1714 + 1715 + static ssize_t polling_interval_show(struct device *dev, 1716 + struct device_attribute *attr, char *buf) 1717 + { 1718 + struct devfreq *df = to_devfreq(dev); 1719 + 1720 + if (!df->profile) 1721 + return -EINVAL; 1722 + 1723 + return sprintf(buf, "%d\n", df->profile->polling_ms); 1724 + } 1725 + 1726 + static ssize_t polling_interval_store(struct device *dev, 1727 + struct device_attribute *attr, 1728 + const char *buf, size_t count) 1729 + { 1730 + struct devfreq *df = to_devfreq(dev); 1731 + unsigned int value; 1732 + int ret; 1733 + 1734 + if (!df->governor) 1735 + return -EINVAL; 1736 + 1737 + ret = sscanf(buf, "%u", &value); 1738 + if (ret != 1) 1739 + return -EINVAL; 1740 + 1741 + df->governor->event_handler(df, DEVFREQ_GOV_UPDATE_INTERVAL, &value); 1742 + ret = count; 1743 + 1744 + return ret; 1745 + } 1746 + static DEVICE_ATTR_RW(polling_interval); 1747 + 1719 1748 static ssize_t timer_show(struct device *dev, 1720 1749 struct device_attribute *attr, char *buf) 1721 1750 { ··· 1826 1761 } 1827 1762 static DEVICE_ATTR_RW(timer); 1828 1763 1829 - static struct attribute *devfreq_attrs[] = { 1830 - &dev_attr_name.attr, 1831 - &dev_attr_governor.attr, 1832 - &dev_attr_available_governors.attr, 1833 - &dev_attr_cur_freq.attr, 1834 - &dev_attr_available_frequencies.attr, 1835 - &dev_attr_target_freq.attr, 1836 - &dev_attr_polling_interval.attr, 1837 - &dev_attr_min_freq.attr, 1838 - &dev_attr_max_freq.attr, 1839 - &dev_attr_trans_stat.attr, 1840 - &dev_attr_timer.attr, 1841 - NULL, 1842 - }; 1843 - ATTRIBUTE_GROUPS(devfreq); 1764 + #define CREATE_SYSFS_FILE(df, name) \ 1765 + { \ 1766 + int ret; \ 1767 + ret = sysfs_create_file(&df->dev.kobj, &dev_attr_##name.attr); \ 1768 + if (ret < 0) { \ 1769 + dev_warn(&df->dev, \ 1770 + "Unable to create attr(%s)\n", "##name"); \ 1771 + } \ 1772 + } \ 1773 + 1774 + /* Create the specific sysfs files which depend on each governor. */ 1775 + static void create_sysfs_files(struct devfreq *devfreq, 1776 + const struct devfreq_governor *gov) 1777 + { 1778 + if (IS_SUPPORTED_ATTR(gov->attrs, POLLING_INTERVAL)) 1779 + CREATE_SYSFS_FILE(devfreq, polling_interval); 1780 + if (IS_SUPPORTED_ATTR(gov->attrs, TIMER)) 1781 + CREATE_SYSFS_FILE(devfreq, timer); 1782 + } 1783 + 1784 + /* Remove the specific sysfs files which depend on each governor. */ 1785 + static void remove_sysfs_files(struct devfreq *devfreq, 1786 + const struct devfreq_governor *gov) 1787 + { 1788 + if (IS_SUPPORTED_ATTR(gov->attrs, POLLING_INTERVAL)) 1789 + sysfs_remove_file(&devfreq->dev.kobj, 1790 + &dev_attr_polling_interval.attr); 1791 + if (IS_SUPPORTED_ATTR(gov->attrs, TIMER)) 1792 + sysfs_remove_file(&devfreq->dev.kobj, &dev_attr_timer.attr); 1793 + } 1844 1794 1845 1795 /** 1846 1796 * devfreq_summary_show() - Show the summary of the devfreq devices ··· 1898 1818 1899 1819 list_for_each_entry_reverse(devfreq, &devfreq_list, node) { 1900 1820 #if IS_ENABLED(CONFIG_DEVFREQ_GOV_PASSIVE) 1901 - if (!strncmp(devfreq->governor_name, DEVFREQ_GOV_PASSIVE, 1821 + if (!strncmp(devfreq->governor->name, DEVFREQ_GOV_PASSIVE, 1902 1822 DEVFREQ_NAME_LEN)) { 1903 1823 struct devfreq_passive_data *data = devfreq->data; 1904 1824 ··· 1912 1832 mutex_lock(&devfreq->lock); 1913 1833 cur_freq = devfreq->previous_freq; 1914 1834 get_freq_range(devfreq, &min_freq, &max_freq); 1915 - polling_ms = devfreq->profile->polling_ms; 1916 1835 timer = devfreq->profile->timer; 1836 + 1837 + if (IS_SUPPORTED_ATTR(devfreq->governor->attrs, POLLING_INTERVAL)) 1838 + polling_ms = devfreq->profile->polling_ms; 1839 + else 1840 + polling_ms = 0; 1917 1841 mutex_unlock(&devfreq->lock); 1918 1842 1919 1843 seq_printf(s, 1920 1844 "%-30s %-30s %-15s %-10s %10d %12ld %12ld %12ld\n", 1921 1845 dev_name(&devfreq->dev), 1922 1846 p_devfreq ? dev_name(&p_devfreq->dev) : "null", 1923 - devfreq->governor_name, 1847 + devfreq->governor->name, 1924 1848 polling_ms ? timer_name[timer] : "null", 1925 1849 polling_ms, 1926 1850 cur_freq,
+21 -8
drivers/devfreq/exynos-bus.c
··· 24 24 25 25 struct exynos_bus { 26 26 struct device *dev; 27 + struct platform_device *icc_pdev; 27 28 28 29 struct devfreq *devfreq; 29 30 struct devfreq_event_dev **edev; ··· 157 156 if (ret < 0) 158 157 dev_warn(dev, "failed to disable the devfreq-event devices\n"); 159 158 159 + platform_device_unregister(bus->icc_pdev); 160 + 160 161 dev_pm_opp_of_remove_table(dev); 161 162 clk_disable_unprepare(bus->clk); 162 - if (bus->opp_table) { 163 - dev_pm_opp_put_regulators(bus->opp_table); 164 - bus->opp_table = NULL; 165 - } 163 + dev_pm_opp_put_regulators(bus->opp_table); 164 + bus->opp_table = NULL; 166 165 } 167 166 168 167 static void exynos_bus_passive_exit(struct device *dev) 169 168 { 170 169 struct exynos_bus *bus = dev_get_drvdata(dev); 170 + 171 + platform_device_unregister(bus->icc_pdev); 171 172 172 173 dev_pm_opp_of_remove_table(dev); 173 174 clk_disable_unprepare(bus->clk); ··· 435 432 if (ret < 0) 436 433 goto err; 437 434 435 + /* Create child platform device for the interconnect provider */ 436 + if (of_get_property(dev->of_node, "#interconnect-cells", NULL)) { 437 + bus->icc_pdev = platform_device_register_data( 438 + dev, "exynos-generic-icc", 439 + PLATFORM_DEVID_AUTO, NULL, 0); 440 + 441 + if (IS_ERR(bus->icc_pdev)) { 442 + ret = PTR_ERR(bus->icc_pdev); 443 + goto err; 444 + } 445 + } 446 + 438 447 max_state = bus->devfreq->profile->max_state; 439 448 min_freq = (bus->devfreq->profile->freq_table[0] / 1000); 440 449 max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000); ··· 459 444 dev_pm_opp_of_remove_table(dev); 460 445 clk_disable_unprepare(bus->clk); 461 446 err_reg: 462 - if (!passive) { 463 - dev_pm_opp_put_regulators(bus->opp_table); 464 - bus->opp_table = NULL; 465 - } 447 + dev_pm_opp_put_regulators(bus->opp_table); 448 + bus->opp_table = NULL; 466 449 467 450 return ret; 468 451 }
+27 -6
drivers/devfreq/governor.h
··· 13 13 14 14 #include <linux/devfreq.h> 15 15 16 + #define DEVFREQ_NAME_LEN 16 17 + 16 18 #define to_devfreq(DEV) container_of((DEV), struct devfreq, dev) 17 19 18 20 /* Devfreq events */ ··· 27 25 #define DEVFREQ_MIN_FREQ 0 28 26 #define DEVFREQ_MAX_FREQ ULONG_MAX 29 27 28 + /* 29 + * Definition of the governor feature flags 30 + * - DEVFREQ_GOV_FLAG_IMMUTABLE 31 + * : This governor is never changeable to other governors. 32 + * - DEVFREQ_GOV_FLAG_IRQ_DRIVEN 33 + * : The devfreq won't schedule the work for this governor. 34 + */ 35 + #define DEVFREQ_GOV_FLAG_IMMUTABLE BIT(0) 36 + #define DEVFREQ_GOV_FLAG_IRQ_DRIVEN BIT(1) 37 + 38 + /* 39 + * Definition of governor attribute flags except for common sysfs attributes 40 + * - DEVFREQ_GOV_ATTR_POLLING_INTERVAL 41 + * : Indicate polling_interal sysfs attribute 42 + * - DEVFREQ_GOV_ATTR_TIMER 43 + * : Indicate timer sysfs attribute 44 + */ 45 + #define DEVFREQ_GOV_ATTR_POLLING_INTERVAL BIT(0) 46 + #define DEVFREQ_GOV_ATTR_TIMER BIT(1) 47 + 30 48 /** 31 49 * struct devfreq_governor - Devfreq policy governor 32 50 * @node: list node - contains registered devfreq governors 33 51 * @name: Governor's name 34 - * @immutable: Immutable flag for governor. If the value is 1, 35 - * this governor is never changeable to other governor. 36 - * @interrupt_driven: Devfreq core won't schedule polling work for this 37 - * governor if value is set to 1. 52 + * @attrs: Governor's sysfs attribute flags 53 + * @flags: Governor's feature flags 38 54 * @get_target_freq: Returns desired operating frequency for the device. 39 55 * Basically, get_target_freq will run 40 56 * devfreq_dev_profile.get_dev_status() to get the ··· 70 50 struct list_head node; 71 51 72 52 const char name[DEVFREQ_NAME_LEN]; 73 - const unsigned int immutable; 74 - const unsigned int interrupt_driven; 53 + const u64 attrs; 54 + const u64 flags; 75 55 int (*get_target_freq)(struct devfreq *this, unsigned long *freq); 76 56 int (*event_handler)(struct devfreq *devfreq, 77 57 unsigned int event, void *data); ··· 87 67 int devfreq_remove_governor(struct devfreq_governor *governor); 88 68 89 69 int devfreq_update_status(struct devfreq *devfreq, unsigned long freq); 70 + int devfreq_update_target(struct devfreq *devfreq, unsigned long freq); 90 71 91 72 static inline int devfreq_update_stats(struct devfreq *df) 92 73 {
+11 -33
drivers/devfreq/governor_passive.c
··· 92 92 return ret; 93 93 } 94 94 95 - static int update_devfreq_passive(struct devfreq *devfreq, unsigned long freq) 96 - { 97 - int ret; 98 - 99 - if (!devfreq->governor) 100 - return -EINVAL; 101 - 102 - mutex_lock_nested(&devfreq->lock, SINGLE_DEPTH_NESTING); 103 - 104 - ret = devfreq->governor->get_target_freq(devfreq, &freq); 105 - if (ret < 0) 106 - goto out; 107 - 108 - ret = devfreq->profile->target(devfreq->dev.parent, &freq, 0); 109 - if (ret < 0) 110 - goto out; 111 - 112 - if (devfreq->profile->freq_table 113 - && (devfreq_update_status(devfreq, freq))) 114 - dev_err(&devfreq->dev, 115 - "Couldn't update frequency transition information.\n"); 116 - 117 - devfreq->previous_freq = freq; 118 - 119 - out: 120 - mutex_unlock(&devfreq->lock); 121 - 122 - return 0; 123 - } 124 - 125 95 static int devfreq_passive_notifier_call(struct notifier_block *nb, 126 96 unsigned long event, void *ptr) 127 97 { ··· 101 131 struct devfreq *parent = (struct devfreq *)data->parent; 102 132 struct devfreq_freqs *freqs = (struct devfreq_freqs *)ptr; 103 133 unsigned long freq = freqs->new; 134 + int ret = 0; 104 135 136 + mutex_lock_nested(&devfreq->lock, SINGLE_DEPTH_NESTING); 105 137 switch (event) { 106 138 case DEVFREQ_PRECHANGE: 107 139 if (parent->previous_freq > freq) 108 - update_devfreq_passive(devfreq, freq); 140 + ret = devfreq_update_target(devfreq, freq); 141 + 109 142 break; 110 143 case DEVFREQ_POSTCHANGE: 111 144 if (parent->previous_freq < freq) 112 - update_devfreq_passive(devfreq, freq); 145 + ret = devfreq_update_target(devfreq, freq); 113 146 break; 114 147 } 148 + mutex_unlock(&devfreq->lock); 149 + 150 + if (ret < 0) 151 + dev_warn(&devfreq->dev, 152 + "failed to update devfreq using passive governor\n"); 115 153 116 154 return NOTIFY_DONE; 117 155 } ··· 158 180 159 181 static struct devfreq_governor devfreq_passive = { 160 182 .name = DEVFREQ_GOV_PASSIVE, 161 - .immutable = 1, 183 + .flags = DEVFREQ_GOV_FLAG_IMMUTABLE, 162 184 .get_target_freq = devfreq_passive_get_target_freq, 163 185 .event_handler = devfreq_passive_event_handler, 164 186 };
+2
drivers/devfreq/governor_simpleondemand.c
··· 117 117 118 118 static struct devfreq_governor devfreq_simple_ondemand = { 119 119 .name = DEVFREQ_GOV_SIMPLE_ONDEMAND, 120 + .attrs = DEVFREQ_GOV_ATTR_POLLING_INTERVAL 121 + | DEVFREQ_GOV_ATTR_TIMER, 120 122 .get_target_freq = devfreq_simple_ondemand_func, 121 123 .event_handler = devfreq_simple_ondemand_handler, 122 124 };
-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");
+97 -62
drivers/devfreq/tegra30-devfreq.c
··· 19 19 #include <linux/reset.h> 20 20 #include <linux/workqueue.h> 21 21 22 + #include <soc/tegra/fuse.h> 23 + 22 24 #include "governor.h" 23 25 24 26 #define ACTMON_GLB_STATUS 0x0 ··· 56 54 #define ACTMON_ABOVE_WMARK_WINDOW 1 57 55 #define ACTMON_BELOW_WMARK_WINDOW 3 58 56 #define ACTMON_BOOST_FREQ_STEP 16000 59 - 60 - /* 61 - * Activity counter is incremented every 256 memory transactions, and each 62 - * transaction takes 4 EMC clocks for Tegra124; So the COUNT_WEIGHT is 63 - * 4 * 256 = 1024. 64 - */ 65 - #define ACTMON_COUNT_WEIGHT 0x400 66 57 67 58 /* 68 59 * ACTMON_AVERAGE_WINDOW_LOG2: default value for @DEV_CTRL_K_VAL, which ··· 104 109 MCCPU, 105 110 }; 106 111 107 - static const struct tegra_devfreq_device_config actmon_device_configs[] = { 112 + static const struct tegra_devfreq_device_config tegra124_device_configs[] = { 108 113 { 109 114 /* MCALL: All memory accesses (including from the CPUs) */ 110 115 .offset = 0x1c0, ··· 113 118 .boost_down_coeff = 50, 114 119 .boost_up_threshold = 60, 115 120 .boost_down_threshold = 40, 121 + }, 122 + { 123 + /* MCCPU: memory accesses from the CPUs */ 124 + .offset = 0x200, 125 + .irq_mask = 1 << 25, 126 + .boost_up_coeff = 800, 127 + .boost_down_coeff = 40, 128 + .boost_up_threshold = 27, 129 + .boost_down_threshold = 10, 130 + .avg_dependency_threshold = 16000, /* 16MHz in kHz units */ 131 + }, 132 + }; 133 + 134 + static const struct tegra_devfreq_device_config tegra30_device_configs[] = { 135 + { 136 + /* MCALL: All memory accesses (including from the CPUs) */ 137 + .offset = 0x1c0, 138 + .irq_mask = 1 << 26, 139 + .boost_up_coeff = 200, 140 + .boost_down_coeff = 50, 141 + .boost_up_threshold = 20, 142 + .boost_down_threshold = 10, 116 143 }, 117 144 { 118 145 /* MCCPU: memory accesses from the CPUs */ ··· 170 153 unsigned long target_freq; 171 154 }; 172 155 156 + struct tegra_devfreq_soc_data { 157 + const struct tegra_devfreq_device_config *configs; 158 + /* Weight value for count measurements */ 159 + unsigned int count_weight; 160 + }; 161 + 173 162 struct tegra_devfreq { 174 163 struct devfreq *devfreq; 164 + struct opp_table *opp_table; 175 165 176 166 struct reset_control *reset; 177 167 struct clk *clock; ··· 192 168 struct delayed_work cpufreq_update_work; 193 169 struct notifier_block cpu_rate_change_nb; 194 170 195 - struct tegra_devfreq_device devices[ARRAY_SIZE(actmon_device_configs)]; 171 + struct tegra_devfreq_device devices[2]; 196 172 197 173 unsigned int irq; 198 174 199 175 bool started; 176 + 177 + const struct tegra_devfreq_soc_data *soc; 200 178 }; 201 179 202 180 struct tegra_actmon_emc_ratio { ··· 511 485 tegra_devfreq_update_avg_wmark(tegra, dev); 512 486 tegra_devfreq_update_wmark(tegra, dev); 513 487 514 - device_writel(dev, ACTMON_COUNT_WEIGHT, ACTMON_DEV_COUNT_WEIGHT); 488 + device_writel(dev, tegra->soc->count_weight, ACTMON_DEV_COUNT_WEIGHT); 515 489 device_writel(dev, ACTMON_INTR_STATUS_CLEAR, ACTMON_DEV_INTR_STATUS); 516 490 517 491 val |= ACTMON_DEV_CTRL_ENB_PERIODIC; ··· 638 612 static int tegra_devfreq_target(struct device *dev, unsigned long *freq, 639 613 u32 flags) 640 614 { 641 - struct tegra_devfreq *tegra = dev_get_drvdata(dev); 642 - struct devfreq *devfreq = tegra->devfreq; 643 615 struct dev_pm_opp *opp; 644 - unsigned long rate; 645 - int err; 616 + int ret; 646 617 647 618 opp = devfreq_recommended_opp(dev, freq, flags); 648 619 if (IS_ERR(opp)) { 649 620 dev_err(dev, "Failed to find opp for %lu Hz\n", *freq); 650 621 return PTR_ERR(opp); 651 622 } 652 - rate = dev_pm_opp_get_freq(opp); 623 + 624 + ret = dev_pm_opp_set_bw(dev, opp); 653 625 dev_pm_opp_put(opp); 654 626 655 - err = clk_set_min_rate(tegra->emc_clock, rate * KHZ); 656 - if (err) 657 - return err; 658 - 659 - err = clk_set_rate(tegra->emc_clock, 0); 660 - if (err) 661 - goto restore_min_rate; 662 - 663 - return 0; 664 - 665 - restore_min_rate: 666 - clk_set_min_rate(tegra->emc_clock, devfreq->previous_freq); 667 - 668 - return err; 627 + return ret; 669 628 } 670 629 671 630 static int tegra_devfreq_get_dev_status(struct device *dev, ··· 666 655 stat->private_data = tegra; 667 656 668 657 /* The below are to be used by the other governors */ 669 - stat->current_frequency = cur_freq; 658 + stat->current_frequency = cur_freq * KHZ; 670 659 671 660 actmon_dev = &tegra->devices[MCALL]; 672 661 ··· 716 705 target_freq = max(target_freq, dev->target_freq); 717 706 } 718 707 719 - *freq = target_freq; 708 + /* 709 + * tegra-devfreq driver operates with KHz units, while OPP table 710 + * entries use Hz units. Hence we need to convert the units for the 711 + * devfreq core. 712 + */ 713 + *freq = target_freq * KHZ; 720 714 721 715 return 0; 722 716 } ··· 781 765 782 766 static struct devfreq_governor tegra_devfreq_governor = { 783 767 .name = "tegra_actmon", 768 + .attrs = DEVFREQ_GOV_ATTR_POLLING_INTERVAL, 769 + .flags = DEVFREQ_GOV_FLAG_IMMUTABLE 770 + | DEVFREQ_GOV_FLAG_IRQ_DRIVEN, 784 771 .get_target_freq = tegra_governor_get_target, 785 772 .event_handler = tegra_governor_event_handler, 786 - .immutable = true, 787 - .interrupt_driven = true, 788 773 }; 789 774 790 775 static int tegra_devfreq_probe(struct platform_device *pdev) 791 776 { 777 + u32 hw_version = BIT(tegra_sku_info.soc_speedo_id); 792 778 struct tegra_devfreq_device *dev; 793 779 struct tegra_devfreq *tegra; 794 780 struct devfreq *devfreq; ··· 801 783 tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL); 802 784 if (!tegra) 803 785 return -ENOMEM; 786 + 787 + tegra->soc = of_device_get_match_data(&pdev->dev); 804 788 805 789 tegra->regs = devm_platform_ioremap_resource(pdev, 0); 806 790 if (IS_ERR(tegra->regs)) ··· 821 801 } 822 802 823 803 tegra->emc_clock = devm_clk_get(&pdev->dev, "emc"); 824 - if (IS_ERR(tegra->emc_clock)) { 825 - dev_err(&pdev->dev, "Failed to get emc clock\n"); 826 - return PTR_ERR(tegra->emc_clock); 827 - } 804 + if (IS_ERR(tegra->emc_clock)) 805 + return dev_err_probe(&pdev->dev, PTR_ERR(tegra->emc_clock), 806 + "Failed to get emc clock\n"); 828 807 829 808 err = platform_get_irq(pdev, 0); 830 809 if (err < 0) ··· 841 822 return err; 842 823 } 843 824 825 + tegra->opp_table = dev_pm_opp_set_supported_hw(&pdev->dev, 826 + &hw_version, 1); 827 + err = PTR_ERR_OR_ZERO(tegra->opp_table); 828 + if (err) { 829 + dev_err(&pdev->dev, "Failed to set supported HW: %d\n", err); 830 + return err; 831 + } 832 + 833 + err = dev_pm_opp_of_add_table(&pdev->dev); 834 + if (err) { 835 + dev_err(&pdev->dev, "Failed to add OPP table: %d\n", err); 836 + goto put_hw; 837 + } 838 + 844 839 err = clk_prepare_enable(tegra->clock); 845 840 if (err) { 846 841 dev_err(&pdev->dev, 847 842 "Failed to prepare and enable ACTMON clock\n"); 848 - return err; 843 + goto remove_table; 849 844 } 850 845 851 846 err = reset_control_reset(tegra->reset); ··· 877 844 878 845 tegra->max_freq = rate / KHZ; 879 846 880 - for (i = 0; i < ARRAY_SIZE(actmon_device_configs); i++) { 847 + for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 881 848 dev = tegra->devices + i; 882 - dev->config = actmon_device_configs + i; 849 + dev->config = tegra->soc->configs + i; 883 850 dev->regs = tegra->regs + dev->config->offset; 884 - } 885 - 886 - for (rate = 0; rate <= tegra->max_freq * KHZ; rate++) { 887 - rate = clk_round_rate(tegra->emc_clock, rate); 888 - 889 - if (rate < 0) { 890 - dev_err(&pdev->dev, 891 - "Failed to round clock rate: %ld\n", rate); 892 - err = rate; 893 - goto remove_opps; 894 - } 895 - 896 - err = dev_pm_opp_add(&pdev->dev, rate / KHZ, 0); 897 - if (err) { 898 - dev_err(&pdev->dev, "Failed to add OPP: %d\n", err); 899 - goto remove_opps; 900 - } 901 851 } 902 852 903 853 platform_set_drvdata(pdev, tegra); ··· 898 882 } 899 883 900 884 tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock); 901 - tegra_devfreq_profile.initial_freq /= KHZ; 902 885 903 886 devfreq = devfreq_add_device(&pdev->dev, &tegra_devfreq_profile, 904 887 "tegra_actmon", NULL); ··· 917 902 reset_control_reset(tegra->reset); 918 903 disable_clk: 919 904 clk_disable_unprepare(tegra->clock); 905 + remove_table: 906 + dev_pm_opp_of_remove_table(&pdev->dev); 907 + put_hw: 908 + dev_pm_opp_put_supported_hw(tegra->opp_table); 920 909 921 910 return err; 922 911 } ··· 932 913 devfreq_remove_device(tegra->devfreq); 933 914 devfreq_remove_governor(&tegra_devfreq_governor); 934 915 935 - dev_pm_opp_remove_all_dynamic(&pdev->dev); 936 - 937 916 reset_control_reset(tegra->reset); 938 917 clk_disable_unprepare(tegra->clock); 918 + 919 + dev_pm_opp_of_remove_table(&pdev->dev); 920 + dev_pm_opp_put_supported_hw(tegra->opp_table); 939 921 940 922 return 0; 941 923 } 942 924 925 + static const struct tegra_devfreq_soc_data tegra124_soc = { 926 + .configs = tegra124_device_configs, 927 + 928 + /* 929 + * Activity counter is incremented every 256 memory transactions, 930 + * and each transaction takes 4 EMC clocks. 931 + */ 932 + .count_weight = 4 * 256, 933 + }; 934 + 935 + static const struct tegra_devfreq_soc_data tegra30_soc = { 936 + .configs = tegra30_device_configs, 937 + .count_weight = 2 * 256, 938 + }; 939 + 943 940 static const struct of_device_id tegra_devfreq_of_match[] = { 944 - { .compatible = "nvidia,tegra30-actmon" }, 945 - { .compatible = "nvidia,tegra124-actmon" }, 941 + { .compatible = "nvidia,tegra30-actmon", .data = &tegra30_soc, }, 942 + { .compatible = "nvidia,tegra124-actmon", .data = &tegra124_soc, }, 946 943 { }, 947 944 }; 948 945
+8
drivers/firmware/arm_scmi/perf.c
··· 750 750 return dom->fc_info && dom->fc_info->level_set_addr; 751 751 } 752 752 753 + static bool scmi_power_scale_mw_get(const struct scmi_handle *handle) 754 + { 755 + struct scmi_perf_info *pi = handle->perf_priv; 756 + 757 + return pi->power_scale_mw; 758 + } 759 + 753 760 static const struct scmi_perf_ops perf_ops = { 754 761 .limits_set = scmi_perf_limits_set, 755 762 .limits_get = scmi_perf_limits_get, ··· 769 762 .freq_get = scmi_dvfs_freq_get, 770 763 .est_power_get = scmi_dvfs_est_power_get, 771 764 .fast_switch_possible = scmi_fast_switch_possible, 765 + .power_scale_mw_get = scmi_power_scale_mw_get, 772 766 }; 773 767 774 768 static int scmi_perf_set_notify_enabled(const struct scmi_handle *handle,
+4 -9
drivers/gpu/drm/lima/lima_devfreq.c
··· 102 102 103 103 dev_pm_opp_of_remove_table(ldev->dev); 104 104 105 - if (devfreq->regulators_opp_table) { 106 - dev_pm_opp_put_regulators(devfreq->regulators_opp_table); 107 - devfreq->regulators_opp_table = NULL; 108 - } 109 - 110 - if (devfreq->clkname_opp_table) { 111 - dev_pm_opp_put_clkname(devfreq->clkname_opp_table); 112 - devfreq->clkname_opp_table = NULL; 113 - } 105 + dev_pm_opp_put_regulators(devfreq->regulators_opp_table); 106 + dev_pm_opp_put_clkname(devfreq->clkname_opp_table); 107 + devfreq->regulators_opp_table = NULL; 108 + devfreq->clkname_opp_table = NULL; 114 109 } 115 110 116 111 int lima_devfreq_init(struct lima_device *ldev)
+2 -4
drivers/gpu/drm/panfrost/panfrost_devfreq.c
··· 165 165 pfdevfreq->opp_of_table_added = false; 166 166 } 167 167 168 - if (pfdevfreq->regulators_opp_table) { 169 - dev_pm_opp_put_regulators(pfdevfreq->regulators_opp_table); 170 - pfdevfreq->regulators_opp_table = NULL; 171 - } 168 + dev_pm_opp_put_regulators(pfdevfreq->regulators_opp_table); 169 + pfdevfreq->regulators_opp_table = NULL; 172 170 } 173 171 174 172 void panfrost_devfreq_resume(struct panfrost_device *pfdev)
+2 -2
drivers/i2c/busses/i2c-stm32f7.c
··· 2322 2322 2323 2323 i2c_mark_adapter_suspended(&i2c_dev->adap); 2324 2324 2325 - if (!device_may_wakeup(dev) && !dev->power.wakeup_path) { 2325 + if (!device_may_wakeup(dev) && !device_wakeup_path(dev)) { 2326 2326 ret = stm32f7_i2c_regs_backup(i2c_dev); 2327 2327 if (ret < 0) { 2328 2328 i2c_mark_adapter_resumed(&i2c_dev->adap); ··· 2341 2341 struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); 2342 2342 int ret; 2343 2343 2344 - if (!device_may_wakeup(dev) && !dev->power.wakeup_path) { 2344 + if (!device_may_wakeup(dev) && !device_wakeup_path(dev)) { 2345 2345 ret = pm_runtime_force_resume(dev); 2346 2346 if (ret < 0) 2347 2347 return ret;
+1 -2
drivers/media/platform/qcom/venus/pm_helpers.c
··· 908 908 909 909 if (core->has_opp_table) 910 910 dev_pm_opp_of_remove_table(dev); 911 - if (core->opp_table) 912 - dev_pm_opp_put_clkname(core->opp_table); 911 + dev_pm_opp_put_clkname(core->opp_table); 913 912 914 913 } 915 914
+136 -94
drivers/opp/core.c
··· 29 29 LIST_HEAD(opp_tables); 30 30 /* Lock to allow exclusive modification to the device and opp lists */ 31 31 DEFINE_MUTEX(opp_table_lock); 32 + /* Flag indicating that opp_tables list is being updated at the moment */ 33 + static bool opp_tables_busy; 32 34 33 - static struct opp_device *_find_opp_dev(const struct device *dev, 34 - struct opp_table *opp_table) 35 + static bool _find_opp_dev(const struct device *dev, struct opp_table *opp_table) 35 36 { 36 37 struct opp_device *opp_dev; 38 + bool found = false; 37 39 40 + mutex_lock(&opp_table->lock); 38 41 list_for_each_entry(opp_dev, &opp_table->dev_list, node) 39 - if (opp_dev->dev == dev) 40 - return opp_dev; 42 + if (opp_dev->dev == dev) { 43 + found = true; 44 + break; 45 + } 41 46 42 - return NULL; 47 + mutex_unlock(&opp_table->lock); 48 + return found; 43 49 } 44 50 45 51 static struct opp_table *_find_opp_table_unlocked(struct device *dev) 46 52 { 47 53 struct opp_table *opp_table; 48 - bool found; 49 54 50 55 list_for_each_entry(opp_table, &opp_tables, node) { 51 - mutex_lock(&opp_table->lock); 52 - found = !!_find_opp_dev(dev, opp_table); 53 - mutex_unlock(&opp_table->lock); 54 - 55 - if (found) { 56 + if (_find_opp_dev(dev, opp_table)) { 56 57 _get_opp_table_kref(opp_table); 57 - 58 58 return opp_table; 59 59 } 60 60 } ··· 1036 1036 kfree(opp_dev); 1037 1037 } 1038 1038 1039 - static struct opp_device *_add_opp_dev_unlocked(const struct device *dev, 1040 - struct opp_table *opp_table) 1039 + struct opp_device *_add_opp_dev(const struct device *dev, 1040 + struct opp_table *opp_table) 1041 1041 { 1042 1042 struct opp_device *opp_dev; 1043 1043 ··· 1048 1048 /* Initialize opp-dev */ 1049 1049 opp_dev->dev = dev; 1050 1050 1051 + mutex_lock(&opp_table->lock); 1051 1052 list_add(&opp_dev->node, &opp_table->dev_list); 1053 + mutex_unlock(&opp_table->lock); 1052 1054 1053 1055 /* Create debugfs entries for the opp_table */ 1054 1056 opp_debug_register(opp_dev, opp_table); 1055 - 1056 - return opp_dev; 1057 - } 1058 - 1059 - struct opp_device *_add_opp_dev(const struct device *dev, 1060 - struct opp_table *opp_table) 1061 - { 1062 - struct opp_device *opp_dev; 1063 - 1064 - mutex_lock(&opp_table->lock); 1065 - opp_dev = _add_opp_dev_unlocked(dev, opp_table); 1066 - mutex_unlock(&opp_table->lock); 1067 1057 1068 1058 return opp_dev; 1069 1059 } ··· 1111 1121 INIT_LIST_HEAD(&opp_table->opp_list); 1112 1122 kref_init(&opp_table->kref); 1113 1123 1114 - /* Secure the device table modification */ 1115 - list_add(&opp_table->node, &opp_tables); 1116 1124 return opp_table; 1117 1125 1118 1126 err: ··· 1123 1135 kref_get(&opp_table->kref); 1124 1136 } 1125 1137 1126 - static struct opp_table *_opp_get_opp_table(struct device *dev, int index) 1138 + /* 1139 + * We need to make sure that the OPP table for a device doesn't get added twice, 1140 + * if this routine gets called in parallel with the same device pointer. 1141 + * 1142 + * The simplest way to enforce that is to perform everything (find existing 1143 + * table and if not found, create a new one) under the opp_table_lock, so only 1144 + * one creator gets access to the same. But that expands the critical section 1145 + * under the lock and may end up causing circular dependencies with frameworks 1146 + * like debugfs, interconnect or clock framework as they may be direct or 1147 + * indirect users of OPP core. 1148 + * 1149 + * And for that reason we have to go for a bit tricky implementation here, which 1150 + * uses the opp_tables_busy flag to indicate if another creator is in the middle 1151 + * of adding an OPP table and others should wait for it to finish. 1152 + */ 1153 + struct opp_table *_add_opp_table_indexed(struct device *dev, int index) 1127 1154 { 1128 1155 struct opp_table *opp_table; 1129 1156 1130 - /* Hold our table modification lock here */ 1157 + again: 1131 1158 mutex_lock(&opp_table_lock); 1132 1159 1133 1160 opp_table = _find_opp_table_unlocked(dev); 1134 1161 if (!IS_ERR(opp_table)) 1135 1162 goto unlock; 1136 1163 1164 + /* 1165 + * The opp_tables list or an OPP table's dev_list is getting updated by 1166 + * another user, wait for it to finish. 1167 + */ 1168 + if (unlikely(opp_tables_busy)) { 1169 + mutex_unlock(&opp_table_lock); 1170 + cpu_relax(); 1171 + goto again; 1172 + } 1173 + 1174 + opp_tables_busy = true; 1137 1175 opp_table = _managed_opp(dev, index); 1176 + 1177 + /* Drop the lock to reduce the size of critical section */ 1178 + mutex_unlock(&opp_table_lock); 1179 + 1138 1180 if (opp_table) { 1139 - if (!_add_opp_dev_unlocked(dev, opp_table)) { 1181 + if (!_add_opp_dev(dev, opp_table)) { 1140 1182 dev_pm_opp_put_opp_table(opp_table); 1141 1183 opp_table = ERR_PTR(-ENOMEM); 1142 1184 } 1143 - goto unlock; 1185 + 1186 + mutex_lock(&opp_table_lock); 1187 + } else { 1188 + opp_table = _allocate_opp_table(dev, index); 1189 + 1190 + mutex_lock(&opp_table_lock); 1191 + if (!IS_ERR(opp_table)) 1192 + list_add(&opp_table->node, &opp_tables); 1144 1193 } 1145 1194 1146 - opp_table = _allocate_opp_table(dev, index); 1195 + opp_tables_busy = false; 1147 1196 1148 1197 unlock: 1149 1198 mutex_unlock(&opp_table_lock); ··· 1188 1163 return opp_table; 1189 1164 } 1190 1165 1166 + struct opp_table *_add_opp_table(struct device *dev) 1167 + { 1168 + return _add_opp_table_indexed(dev, 0); 1169 + } 1170 + 1191 1171 struct opp_table *dev_pm_opp_get_opp_table(struct device *dev) 1192 1172 { 1193 - return _opp_get_opp_table(dev, 0); 1173 + return _find_opp_table(dev); 1194 1174 } 1195 1175 EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table); 1196 - 1197 - struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev, 1198 - int index) 1199 - { 1200 - return _opp_get_opp_table(dev, index); 1201 - } 1202 1176 1203 1177 static void _opp_table_kref_release(struct kref *kref) 1204 1178 { ··· 1251 1227 kfree(opp); 1252 1228 } 1253 1229 1254 - static void _opp_kref_release(struct dev_pm_opp *opp, 1255 - struct opp_table *opp_table) 1230 + static void _opp_kref_release(struct kref *kref) 1256 1231 { 1232 + struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref); 1233 + struct opp_table *opp_table = opp->opp_table; 1234 + 1235 + list_del(&opp->node); 1236 + mutex_unlock(&opp_table->lock); 1237 + 1257 1238 /* 1258 1239 * Notify the changes in the availability of the operable 1259 1240 * frequency/voltage list. ··· 1266 1237 blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_REMOVE, opp); 1267 1238 _of_opp_free_required_opps(opp_table, opp); 1268 1239 opp_debug_remove_one(opp); 1269 - list_del(&opp->node); 1270 1240 kfree(opp); 1271 - } 1272 - 1273 - static void _opp_kref_release_unlocked(struct kref *kref) 1274 - { 1275 - struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref); 1276 - struct opp_table *opp_table = opp->opp_table; 1277 - 1278 - _opp_kref_release(opp, opp_table); 1279 - } 1280 - 1281 - static void _opp_kref_release_locked(struct kref *kref) 1282 - { 1283 - struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref); 1284 - struct opp_table *opp_table = opp->opp_table; 1285 - 1286 - _opp_kref_release(opp, opp_table); 1287 - mutex_unlock(&opp_table->lock); 1288 1241 } 1289 1242 1290 1243 void dev_pm_opp_get(struct dev_pm_opp *opp) ··· 1276 1265 1277 1266 void dev_pm_opp_put(struct dev_pm_opp *opp) 1278 1267 { 1279 - kref_put_mutex(&opp->kref, _opp_kref_release_locked, 1280 - &opp->opp_table->lock); 1268 + kref_put_mutex(&opp->kref, _opp_kref_release, &opp->opp_table->lock); 1281 1269 } 1282 1270 EXPORT_SYMBOL_GPL(dev_pm_opp_put); 1283 - 1284 - static void dev_pm_opp_put_unlocked(struct dev_pm_opp *opp) 1285 - { 1286 - kref_put(&opp->kref, _opp_kref_release_unlocked); 1287 - } 1288 1271 1289 1272 /** 1290 1273 * dev_pm_opp_remove() - Remove an OPP from OPP table ··· 1323 1318 } 1324 1319 EXPORT_SYMBOL_GPL(dev_pm_opp_remove); 1325 1320 1321 + static struct dev_pm_opp *_opp_get_next(struct opp_table *opp_table, 1322 + bool dynamic) 1323 + { 1324 + struct dev_pm_opp *opp = NULL, *temp; 1325 + 1326 + mutex_lock(&opp_table->lock); 1327 + list_for_each_entry(temp, &opp_table->opp_list, node) { 1328 + if (dynamic == temp->dynamic) { 1329 + opp = temp; 1330 + break; 1331 + } 1332 + } 1333 + 1334 + mutex_unlock(&opp_table->lock); 1335 + return opp; 1336 + } 1337 + 1326 1338 bool _opp_remove_all_static(struct opp_table *opp_table) 1327 1339 { 1328 - struct dev_pm_opp *opp, *tmp; 1329 - bool ret = true; 1340 + struct dev_pm_opp *opp; 1330 1341 1331 1342 mutex_lock(&opp_table->lock); 1332 1343 1333 1344 if (!opp_table->parsed_static_opps) { 1334 - ret = false; 1335 - goto unlock; 1345 + mutex_unlock(&opp_table->lock); 1346 + return false; 1336 1347 } 1337 1348 1338 - if (--opp_table->parsed_static_opps) 1339 - goto unlock; 1340 - 1341 - list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) { 1342 - if (!opp->dynamic) 1343 - dev_pm_opp_put_unlocked(opp); 1349 + if (--opp_table->parsed_static_opps) { 1350 + mutex_unlock(&opp_table->lock); 1351 + return true; 1344 1352 } 1345 1353 1346 - unlock: 1347 1354 mutex_unlock(&opp_table->lock); 1348 1355 1349 - return ret; 1356 + /* 1357 + * Can't remove the OPP from under the lock, debugfs removal needs to 1358 + * happen lock less to avoid circular dependency issues. 1359 + */ 1360 + while ((opp = _opp_get_next(opp_table, false))) 1361 + dev_pm_opp_put(opp); 1362 + 1363 + return true; 1350 1364 } 1351 1365 1352 1366 /** ··· 1377 1353 void dev_pm_opp_remove_all_dynamic(struct device *dev) 1378 1354 { 1379 1355 struct opp_table *opp_table; 1380 - struct dev_pm_opp *opp, *temp; 1356 + struct dev_pm_opp *opp; 1381 1357 int count = 0; 1382 1358 1383 1359 opp_table = _find_opp_table(dev); 1384 1360 if (IS_ERR(opp_table)) 1385 1361 return; 1386 1362 1387 - mutex_lock(&opp_table->lock); 1388 - list_for_each_entry_safe(opp, temp, &opp_table->opp_list, node) { 1389 - if (opp->dynamic) { 1390 - dev_pm_opp_put_unlocked(opp); 1391 - count++; 1392 - } 1363 + /* 1364 + * Can't remove the OPP from under the lock, debugfs removal needs to 1365 + * happen lock less to avoid circular dependency issues. 1366 + */ 1367 + while ((opp = _opp_get_next(opp_table, true))) { 1368 + dev_pm_opp_put(opp); 1369 + count++; 1393 1370 } 1394 - mutex_unlock(&opp_table->lock); 1395 1371 1396 1372 /* Drop the references taken by dev_pm_opp_add() */ 1397 1373 while (count--) ··· 1626 1602 { 1627 1603 struct opp_table *opp_table; 1628 1604 1629 - opp_table = dev_pm_opp_get_opp_table(dev); 1605 + opp_table = _add_opp_table(dev); 1630 1606 if (IS_ERR(opp_table)) 1631 1607 return opp_table; 1632 1608 ··· 1660 1636 */ 1661 1637 void dev_pm_opp_put_supported_hw(struct opp_table *opp_table) 1662 1638 { 1639 + if (unlikely(!opp_table)) 1640 + return; 1641 + 1663 1642 /* Make sure there are no concurrent readers while updating opp_table */ 1664 1643 WARN_ON(!list_empty(&opp_table->opp_list)); 1665 1644 ··· 1688 1661 { 1689 1662 struct opp_table *opp_table; 1690 1663 1691 - opp_table = dev_pm_opp_get_opp_table(dev); 1664 + opp_table = _add_opp_table(dev); 1692 1665 if (IS_ERR(opp_table)) 1693 1666 return opp_table; 1694 1667 ··· 1719 1692 */ 1720 1693 void dev_pm_opp_put_prop_name(struct opp_table *opp_table) 1721 1694 { 1695 + if (unlikely(!opp_table)) 1696 + return; 1697 + 1722 1698 /* Make sure there are no concurrent readers while updating opp_table */ 1723 1699 WARN_ON(!list_empty(&opp_table->opp_list)); 1724 1700 ··· 1784 1754 struct regulator *reg; 1785 1755 int ret, i; 1786 1756 1787 - opp_table = dev_pm_opp_get_opp_table(dev); 1757 + opp_table = _add_opp_table(dev); 1788 1758 if (IS_ERR(opp_table)) 1789 1759 return opp_table; 1790 1760 ··· 1850 1820 { 1851 1821 int i; 1852 1822 1823 + if (unlikely(!opp_table)) 1824 + return; 1825 + 1853 1826 if (!opp_table->regulators) 1854 1827 goto put_opp_table; 1855 1828 ··· 1895 1862 struct opp_table *opp_table; 1896 1863 int ret; 1897 1864 1898 - opp_table = dev_pm_opp_get_opp_table(dev); 1865 + opp_table = _add_opp_table(dev); 1899 1866 if (IS_ERR(opp_table)) 1900 1867 return opp_table; 1901 1868 ··· 1935 1902 */ 1936 1903 void dev_pm_opp_put_clkname(struct opp_table *opp_table) 1937 1904 { 1905 + if (unlikely(!opp_table)) 1906 + return; 1907 + 1938 1908 /* Make sure there are no concurrent readers while updating opp_table */ 1939 1909 WARN_ON(!list_empty(&opp_table->opp_list)); 1940 1910 ··· 1966 1930 if (!set_opp) 1967 1931 return ERR_PTR(-EINVAL); 1968 1932 1969 - opp_table = dev_pm_opp_get_opp_table(dev); 1933 + opp_table = _add_opp_table(dev); 1970 1934 if (IS_ERR(opp_table)) 1971 1935 return opp_table; 1972 1936 ··· 1993 1957 */ 1994 1958 void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table) 1995 1959 { 1960 + if (unlikely(!opp_table)) 1961 + return; 1962 + 1996 1963 /* Make sure there are no concurrent readers while updating opp_table */ 1997 1964 WARN_ON(!list_empty(&opp_table->opp_list)); 1998 1965 ··· 2053 2014 int index = 0, ret = -EINVAL; 2054 2015 const char **name = names; 2055 2016 2056 - opp_table = dev_pm_opp_get_opp_table(dev); 2017 + opp_table = _add_opp_table(dev); 2057 2018 if (IS_ERR(opp_table)) 2058 2019 return opp_table; 2059 2020 ··· 2124 2085 */ 2125 2086 void dev_pm_opp_detach_genpd(struct opp_table *opp_table) 2126 2087 { 2088 + if (unlikely(!opp_table)) 2089 + return; 2090 + 2127 2091 /* 2128 2092 * Acquire genpd_virt_dev_lock to make sure virt_dev isn't getting 2129 2093 * used in parallel. ··· 2221 2179 struct opp_table *opp_table; 2222 2180 int ret; 2223 2181 2224 - opp_table = dev_pm_opp_get_opp_table(dev); 2182 + opp_table = _add_opp_table(dev); 2225 2183 if (IS_ERR(opp_table)) 2226 2184 return PTR_ERR(opp_table); 2227 2185
+11 -7
drivers/opp/of.c
··· 112 112 struct opp_table *opp_table; 113 113 struct device_node *opp_table_np; 114 114 115 - lockdep_assert_held(&opp_table_lock); 116 - 117 115 opp_table_np = of_get_parent(opp_np); 118 116 if (!opp_table_np) 119 117 goto err; ··· 119 121 /* It is safe to put the node now as all we need now is its address */ 120 122 of_node_put(opp_table_np); 121 123 124 + mutex_lock(&opp_table_lock); 122 125 list_for_each_entry(opp_table, &opp_tables, node) { 123 126 if (opp_table_np == opp_table->np) { 124 127 _get_opp_table_kref(opp_table); 128 + mutex_unlock(&opp_table_lock); 125 129 return opp_table; 126 130 } 127 131 } 132 + mutex_unlock(&opp_table_lock); 128 133 129 134 err: 130 135 return ERR_PTR(-ENODEV); ··· 170 169 /* Traversing the first OPP node is all we need */ 171 170 np = of_get_next_available_child(opp_np, NULL); 172 171 if (!np) { 173 - dev_err(dev, "Empty OPP table\n"); 172 + dev_warn(dev, "Empty OPP table\n"); 173 + 174 174 return; 175 175 } 176 176 ··· 379 377 struct icc_path **paths; 380 378 381 379 ret = _bandwidth_supported(dev, opp_table); 382 - if (ret <= 0) 380 + if (ret == -EINVAL) 381 + return 0; /* Empty OPP table is a valid corner-case, let's not fail */ 382 + else if (ret <= 0) 383 383 return ret; 384 384 385 385 ret = 0; ··· 978 974 struct opp_table *opp_table; 979 975 int ret; 980 976 981 - opp_table = dev_pm_opp_get_opp_table_indexed(dev, 0); 977 + opp_table = _add_opp_table_indexed(dev, 0); 982 978 if (IS_ERR(opp_table)) 983 979 return PTR_ERR(opp_table); 984 980 ··· 1033 1029 index = 0; 1034 1030 } 1035 1031 1036 - opp_table = dev_pm_opp_get_opp_table_indexed(dev, index); 1032 + opp_table = _add_opp_table_indexed(dev, index); 1037 1033 if (IS_ERR(opp_table)) 1038 1034 return PTR_ERR(opp_table); 1039 1035 ··· 1339 1335 goto failed; 1340 1336 } 1341 1337 1342 - ret = em_dev_register_perf_domain(dev, nr_opp, &em_cb, cpus); 1338 + ret = em_dev_register_perf_domain(dev, nr_opp, &em_cb, cpus, true); 1343 1339 if (ret) 1344 1340 goto failed; 1345 1341
+1
drivers/opp/opp.h
··· 224 224 int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic); 225 225 void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu); 226 226 struct opp_table *_add_opp_table(struct device *dev); 227 + struct opp_table *_add_opp_table_indexed(struct device *dev, int index); 227 228 void _put_opp_list_kref(struct opp_table *opp_table); 228 229 229 230 #ifdef CONFIG_OF
+2 -2
drivers/pci/pci-acpi.c
··· 1060 1060 { 1061 1061 while (bus->parent) { 1062 1062 if (acpi_pm_device_can_wakeup(&bus->self->dev)) 1063 - return acpi_pm_set_bridge_wakeup(&bus->self->dev, enable); 1063 + return acpi_pm_set_device_wakeup(&bus->self->dev, enable); 1064 1064 1065 1065 bus = bus->parent; 1066 1066 } ··· 1068 1068 /* We have reached the root bus. */ 1069 1069 if (bus->bridge) { 1070 1070 if (acpi_pm_device_can_wakeup(bus->bridge)) 1071 - return acpi_pm_set_bridge_wakeup(bus->bridge, enable); 1071 + return acpi_pm_set_device_wakeup(bus->bridge, enable); 1072 1072 } 1073 1073 return 0; 1074 1074 }
+7
drivers/powercap/intel_rapl_common.c
··· 1011 1011 .compute_time_window = rapl_compute_time_window_atom, 1012 1012 }; 1013 1013 1014 + static const struct rapl_defaults rapl_defaults_amd = { 1015 + .check_unit = rapl_check_unit_core, 1016 + }; 1017 + 1014 1018 static const struct x86_cpu_id rapl_ids[] __initconst = { 1015 1019 X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE, &rapl_defaults_core), 1016 1020 X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X, &rapl_defaults_core), ··· 1065 1061 1066 1062 X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &rapl_defaults_hsw_server), 1067 1063 X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &rapl_defaults_hsw_server), 1064 + 1065 + X86_MATCH_VENDOR_FAM(AMD, 0x17, &rapl_defaults_amd), 1066 + X86_MATCH_VENDOR_FAM(AMD, 0x19, &rapl_defaults_amd), 1068 1067 {} 1069 1068 }; 1070 1069 MODULE_DEVICE_TABLE(x86cpu, rapl_ids);
+36 -15
drivers/powercap/intel_rapl_msr.c
··· 31 31 #define MSR_VR_CURRENT_CONFIG 0x00000601 32 32 33 33 /* private data for RAPL MSR Interface */ 34 - static struct rapl_if_priv rapl_msr_priv = { 34 + static struct rapl_if_priv *rapl_msr_priv; 35 + 36 + static struct rapl_if_priv rapl_msr_priv_intel = { 35 37 .reg_unit = MSR_RAPL_POWER_UNIT, 36 38 .regs[RAPL_DOMAIN_PACKAGE] = { 37 39 MSR_PKG_POWER_LIMIT, MSR_PKG_ENERGY_STATUS, MSR_PKG_PERF_STATUS, 0, MSR_PKG_POWER_INFO }, ··· 49 47 .limits[RAPL_DOMAIN_PLATFORM] = 2, 50 48 }; 51 49 50 + static struct rapl_if_priv rapl_msr_priv_amd = { 51 + .reg_unit = MSR_AMD_RAPL_POWER_UNIT, 52 + .regs[RAPL_DOMAIN_PACKAGE] = { 53 + 0, MSR_AMD_PKG_ENERGY_STATUS, 0, 0, 0 }, 54 + .regs[RAPL_DOMAIN_PP0] = { 55 + 0, MSR_AMD_CORE_ENERGY_STATUS, 0, 0, 0 }, 56 + }; 57 + 52 58 /* Handles CPU hotplug on multi-socket systems. 53 59 * If a CPU goes online as the first CPU of the physical package 54 60 * we add the RAPL package to the system. Similarly, when the last ··· 68 58 { 69 59 struct rapl_package *rp; 70 60 71 - rp = rapl_find_package_domain(cpu, &rapl_msr_priv); 61 + rp = rapl_find_package_domain(cpu, rapl_msr_priv); 72 62 if (!rp) { 73 - rp = rapl_add_package(cpu, &rapl_msr_priv); 63 + rp = rapl_add_package(cpu, rapl_msr_priv); 74 64 if (IS_ERR(rp)) 75 65 return PTR_ERR(rp); 76 66 } ··· 83 73 struct rapl_package *rp; 84 74 int lead_cpu; 85 75 86 - rp = rapl_find_package_domain(cpu, &rapl_msr_priv); 76 + rp = rapl_find_package_domain(cpu, rapl_msr_priv); 87 77 if (!rp) 88 78 return 0; 89 79 ··· 146 136 const struct x86_cpu_id *id = x86_match_cpu(pl4_support_ids); 147 137 int ret; 148 138 149 - rapl_msr_priv.read_raw = rapl_msr_read_raw; 150 - rapl_msr_priv.write_raw = rapl_msr_write_raw; 139 + switch (boot_cpu_data.x86_vendor) { 140 + case X86_VENDOR_INTEL: 141 + rapl_msr_priv = &rapl_msr_priv_intel; 142 + break; 143 + case X86_VENDOR_AMD: 144 + rapl_msr_priv = &rapl_msr_priv_amd; 145 + break; 146 + default: 147 + pr_err("intel-rapl does not support CPU vendor %d\n", boot_cpu_data.x86_vendor); 148 + return -ENODEV; 149 + } 150 + rapl_msr_priv->read_raw = rapl_msr_read_raw; 151 + rapl_msr_priv->write_raw = rapl_msr_write_raw; 151 152 152 153 if (id) { 153 - rapl_msr_priv.limits[RAPL_DOMAIN_PACKAGE] = 3; 154 - rapl_msr_priv.regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4] = 154 + rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] = 3; 155 + rapl_msr_priv->regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4] = 155 156 MSR_VR_CURRENT_CONFIG; 156 157 pr_info("PL4 support detected.\n"); 157 158 } 158 159 159 - rapl_msr_priv.control_type = powercap_register_control_type(NULL, "intel-rapl", NULL); 160 - if (IS_ERR(rapl_msr_priv.control_type)) { 160 + rapl_msr_priv->control_type = powercap_register_control_type(NULL, "intel-rapl", NULL); 161 + if (IS_ERR(rapl_msr_priv->control_type)) { 161 162 pr_debug("failed to register powercap control_type.\n"); 162 - return PTR_ERR(rapl_msr_priv.control_type); 163 + return PTR_ERR(rapl_msr_priv->control_type); 163 164 } 164 165 165 166 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online", 166 167 rapl_cpu_online, rapl_cpu_down_prep); 167 168 if (ret < 0) 168 169 goto out; 169 - rapl_msr_priv.pcap_rapl_online = ret; 170 + rapl_msr_priv->pcap_rapl_online = ret; 170 171 171 172 return 0; 172 173 173 174 out: 174 175 if (ret) 175 - powercap_unregister_control_type(rapl_msr_priv.control_type); 176 + powercap_unregister_control_type(rapl_msr_priv->control_type); 176 177 return ret; 177 178 } 178 179 179 180 static int rapl_msr_remove(struct platform_device *pdev) 180 181 { 181 - cpuhp_remove_state(rapl_msr_priv.pcap_rapl_online); 182 - powercap_unregister_control_type(rapl_msr_priv.control_type); 182 + cpuhp_remove_state(rapl_msr_priv->pcap_rapl_online); 183 + powercap_unregister_control_type(rapl_msr_priv->control_type); 183 184 return 0; 184 185 } 185 186
+2 -3
drivers/powercap/powercap_sys.c
··· 170 170 if (pconst && pconst->ops && pconst->ops->get_name) { 171 171 name = pconst->ops->get_name(power_zone, id); 172 172 if (name) { 173 - snprintf(buf, POWERCAP_CONSTRAINT_NAME_LEN, 174 - "%s\n", name); 175 - buf[POWERCAP_CONSTRAINT_NAME_LEN] = '\0'; 173 + sprintf(buf, "%.*s\n", POWERCAP_CONSTRAINT_NAME_LEN - 1, 174 + name); 176 175 len = strlen(buf); 177 176 } 178 177 }
+2
drivers/soc/tegra/fuse/tegra-apbmisc.c
··· 3 3 * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 4 4 */ 5 5 6 + #include <linux/export.h> 6 7 #include <linux/kernel.h> 7 8 #include <linux/of.h> 8 9 #include <linux/of_address.h> ··· 91 90 92 91 return straps >> PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT; 93 92 } 93 + EXPORT_SYMBOL_GPL(tegra_read_ram_code); 94 94 95 95 static const struct of_device_id apbmisc_match[] __initconst = { 96 96 { .compatible = "nvidia,tegra20-apbmisc", },
-5
include/acpi/acpi_bus.h
··· 620 620 bool acpi_pm_device_can_wakeup(struct device *dev); 621 621 int acpi_pm_device_sleep_state(struct device *, int *, int); 622 622 int acpi_pm_set_device_wakeup(struct device *dev, bool enable); 623 - int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable); 624 623 #else 625 624 static inline void acpi_pm_wakeup_event(struct device *dev) 626 625 { ··· 647 648 m : ACPI_STATE_D0; 648 649 } 649 650 static inline int acpi_pm_set_device_wakeup(struct device *dev, bool enable) 650 - { 651 - return -ENODEV; 652 - } 653 - static inline int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable) 654 651 { 655 652 return -ENODEV; 656 653 }
-5
include/linux/cpufreq.h
··· 65 65 unsigned int max; /* in kHz */ 66 66 unsigned int cur; /* in kHz, only needed if cpufreq 67 67 * governors are used */ 68 - unsigned int restore_freq; /* = policy->cur before transition */ 69 68 unsigned int suspend_freq; /* freq to set during suspend */ 70 69 71 70 unsigned int policy; /* see above */ ··· 313 314 /* define one out of two */ 314 315 int (*setpolicy)(struct cpufreq_policy *policy); 315 316 316 - /* 317 - * On failure, should always restore frequency to policy->restore_freq 318 - * (i.e. old freq). 319 - */ 320 317 int (*target)(struct cpufreq_policy *policy, 321 318 unsigned int target_freq, 322 319 unsigned int relation); /* Deprecated */
-4
include/linux/devfreq.h
··· 15 15 #include <linux/pm_opp.h> 16 16 #include <linux/pm_qos.h> 17 17 18 - #define DEVFREQ_NAME_LEN 16 19 - 20 18 /* DEVFREQ governor name */ 21 19 #define DEVFREQ_GOV_SIMPLE_ONDEMAND "simple_ondemand" 22 20 #define DEVFREQ_GOV_PERFORMANCE "performance" ··· 137 139 * using devfreq. 138 140 * @profile: device-specific devfreq profile 139 141 * @governor: method how to choose frequency based on the usage. 140 - * @governor_name: devfreq governor name for use with this devfreq 141 142 * @nb: notifier block used to notify devfreq object that it should 142 143 * reevaluate operable frequencies. Devfreq users may use 143 144 * devfreq.nb to the corresponding register notifier call chain. ··· 173 176 struct device dev; 174 177 struct devfreq_dev_profile *profile; 175 178 const struct devfreq_governor *governor; 176 - char governor_name[DEVFREQ_NAME_LEN]; 177 179 struct notifier_block nb; 178 180 struct delayed_work work; 179 181
+15 -8
include/linux/energy_model.h
··· 13 13 /** 14 14 * em_perf_state - Performance state of a performance domain 15 15 * @frequency: The frequency in KHz, for consistency with CPUFreq 16 - * @power: The power consumed at this level, in milli-watts (by 1 CPU or 17 - by a registered device). It can be a total power: static and 18 - dynamic. 16 + * @power: The power consumed at this level (by 1 CPU or by a registered 17 + * device). It can be a total power: static and dynamic. 19 18 * @cost: The cost coefficient associated with this level, used during 20 19 * energy calculation. Equal to: power * max_frequency / frequency 21 20 */ ··· 28 29 * em_perf_domain - Performance domain 29 30 * @table: List of performance states, in ascending order 30 31 * @nr_perf_states: Number of performance states 32 + * @milliwatts: Flag indicating the power values are in milli-Watts 33 + * or some other scale. 31 34 * @cpus: Cpumask covering the CPUs of the domain. It's here 32 35 * for performance reasons to avoid potential cache 33 36 * misses during energy calculations in the scheduler ··· 44 43 struct em_perf_domain { 45 44 struct em_perf_state *table; 46 45 int nr_perf_states; 46 + int milliwatts; 47 47 unsigned long cpus[]; 48 48 }; 49 49 ··· 57 55 /** 58 56 * active_power() - Provide power at the next performance state of 59 57 * a device 60 - * @power : Active power at the performance state in mW 58 + * @power : Active power at the performance state 61 59 * (modified) 62 60 * @freq : Frequency at the performance state in kHz 63 61 * (modified) ··· 68 66 * and frequency. 69 67 * 70 68 * In case of CPUs, the power is the one of a single CPU in the domain, 71 - * expressed in milli-watts. It is expected to fit in the 72 - * [0, EM_MAX_POWER] range. 69 + * expressed in milli-Watts or an abstract scale. It is expected to 70 + * fit in the [0, EM_MAX_POWER] range. 73 71 * 74 72 * Return 0 on success. 75 73 */ ··· 81 79 struct em_perf_domain *em_cpu_get(int cpu); 82 80 struct em_perf_domain *em_pd_get(struct device *dev); 83 81 int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states, 84 - struct em_data_callback *cb, cpumask_t *span); 82 + struct em_data_callback *cb, cpumask_t *span, 83 + bool milliwatts); 85 84 void em_dev_unregister_perf_domain(struct device *dev); 86 85 87 86 /** ··· 105 102 unsigned long freq, scale_cpu; 106 103 struct em_perf_state *ps; 107 104 int i, cpu; 105 + 106 + if (!sum_util) 107 + return 0; 108 108 109 109 /* 110 110 * In order to predict the performance state, map the utilization of ··· 192 186 193 187 static inline 194 188 int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states, 195 - struct em_data_callback *cb, cpumask_t *span) 189 + struct em_data_callback *cb, cpumask_t *span, 190 + bool milliwatts) 196 191 { 197 192 return -EINVAL; 198 193 }
+11 -11
include/linux/pm_domain.h
··· 255 255 } 256 256 static inline int pm_genpd_remove(struct generic_pm_domain *genpd) 257 257 { 258 - return -ENOTSUPP; 258 + return -EOPNOTSUPP; 259 259 } 260 260 261 261 static inline int dev_pm_genpd_set_performance_state(struct device *dev, 262 262 unsigned int state) 263 263 { 264 - return -ENOTSUPP; 264 + return -EOPNOTSUPP; 265 265 } 266 266 267 267 static inline int dev_pm_genpd_add_notifier(struct device *dev, 268 268 struct notifier_block *nb) 269 269 { 270 - return -ENOTSUPP; 270 + return -EOPNOTSUPP; 271 271 } 272 272 273 273 static inline int dev_pm_genpd_remove_notifier(struct device *dev) 274 274 { 275 - return -ENOTSUPP; 275 + return -EOPNOTSUPP; 276 276 } 277 277 278 278 #define simple_qos_governor (*(struct dev_power_governor *)(NULL)) ··· 280 280 #endif 281 281 282 282 #ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP 283 - void pm_genpd_syscore_poweroff(struct device *dev); 284 - void pm_genpd_syscore_poweron(struct device *dev); 283 + void dev_pm_genpd_suspend(struct device *dev); 284 + void dev_pm_genpd_resume(struct device *dev); 285 285 #else 286 - static inline void pm_genpd_syscore_poweroff(struct device *dev) {} 287 - static inline void pm_genpd_syscore_poweron(struct device *dev) {} 286 + static inline void dev_pm_genpd_suspend(struct device *dev) {} 287 + static inline void dev_pm_genpd_resume(struct device *dev) {} 288 288 #endif 289 289 290 290 /* OF PM domain providers */ ··· 325 325 static inline int of_genpd_add_provider_simple(struct device_node *np, 326 326 struct generic_pm_domain *genpd) 327 327 { 328 - return -ENOTSUPP; 328 + return -EOPNOTSUPP; 329 329 } 330 330 331 331 static inline int of_genpd_add_provider_onecell(struct device_node *np, 332 332 struct genpd_onecell_data *data) 333 333 { 334 - return -ENOTSUPP; 334 + return -EOPNOTSUPP; 335 335 } 336 336 337 337 static inline void of_genpd_del_provider(struct device_node *np) {} ··· 387 387 static inline 388 388 struct generic_pm_domain *of_genpd_remove_last(struct device_node *np) 389 389 { 390 - return ERR_PTR(-ENOTSUPP); 390 + return ERR_PTR(-EOPNOTSUPP); 391 391 } 392 392 #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */ 393 393
-1
include/linux/pm_opp.h
··· 90 90 #if defined(CONFIG_PM_OPP) 91 91 92 92 struct opp_table *dev_pm_opp_get_opp_table(struct device *dev); 93 - struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev, int index); 94 93 void dev_pm_opp_put_opp_table(struct opp_table *opp_table); 95 94 96 95 unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
+10
include/linux/pm_wakeup.h
··· 84 84 return dev->power.can_wakeup && !!dev->power.wakeup; 85 85 } 86 86 87 + static inline bool device_wakeup_path(struct device *dev) 88 + { 89 + return dev->power.wakeup_path; 90 + } 91 + 87 92 static inline void device_set_wakeup_path(struct device *dev) 88 93 { 89 94 dev->power.wakeup_path = true; ··· 177 172 static inline bool device_may_wakeup(struct device *dev) 178 173 { 179 174 return dev->power.can_wakeup && dev->power.should_wakeup; 175 + } 176 + 177 + static inline bool device_wakeup_path(struct device *dev) 178 + { 179 + return false; 180 180 } 181 181 182 182 static inline void device_set_wakeup_path(struct device *dev) {}
+1
include/linux/scmi_protocol.h
··· 121 121 unsigned long *rate, unsigned long *power); 122 122 bool (*fast_switch_possible)(const struct scmi_handle *handle, 123 123 struct device *dev); 124 + bool (*power_scale_mw_get)(const struct scmi_handle *handle); 124 125 }; 125 126 126 127 /**
+4
include/soc/tegra/fuse.h
··· 56 56 u32 tegra_read_ram_code(void); 57 57 int tegra_fuse_readl(unsigned long offset, u32 *value); 58 58 59 + #ifdef CONFIG_ARCH_TEGRA 59 60 extern struct tegra_sku_info tegra_sku_info; 61 + #else 62 + static struct tegra_sku_info tegra_sku_info __maybe_unused; 63 + #endif 60 64 61 65 struct device *tegra_soc_device_register(void); 62 66
+29 -1
include/trace/events/devfreq.h
··· 8 8 #include <linux/devfreq.h> 9 9 #include <linux/tracepoint.h> 10 10 11 + TRACE_EVENT(devfreq_frequency, 12 + TP_PROTO(struct devfreq *devfreq, unsigned long freq, 13 + unsigned long prev_freq), 14 + 15 + TP_ARGS(devfreq, freq, prev_freq), 16 + 17 + TP_STRUCT__entry( 18 + __string(dev_name, dev_name(&devfreq->dev)) 19 + __field(unsigned long, freq) 20 + __field(unsigned long, prev_freq) 21 + __field(unsigned long, busy_time) 22 + __field(unsigned long, total_time) 23 + ), 24 + 25 + TP_fast_assign( 26 + __assign_str(dev_name, dev_name(&devfreq->dev)); 27 + __entry->freq = freq; 28 + __entry->prev_freq = prev_freq; 29 + __entry->busy_time = devfreq->last_status.busy_time; 30 + __entry->total_time = devfreq->last_status.total_time; 31 + ), 32 + 33 + TP_printk("dev_name=%-30s freq=%-12lu prev_freq=%-12lu load=%-2lu", 34 + __get_str(dev_name), __entry->freq, __entry->prev_freq, 35 + __entry->total_time == 0 ? 0 : 36 + (100 * __entry->busy_time) / __entry->total_time) 37 + ); 38 + 11 39 TRACE_EVENT(devfreq_monitor, 12 40 TP_PROTO(struct devfreq *devfreq), 13 41 ··· 57 29 __assign_str(dev_name, dev_name(&devfreq->dev)); 58 30 ), 59 31 60 - TP_printk("dev_name=%s freq=%lu polling_ms=%u load=%lu", 32 + TP_printk("dev_name=%-30s freq=%-12lu polling_ms=%-3u load=%-2lu", 61 33 __get_str(dev_name), __entry->freq, __entry->polling_ms, 62 34 __entry->total_time == 0 ? 0 : 63 35 (100 * __entry->busy_time) / __entry->total_time)
+24 -2
kernel/power/energy_model.c
··· 52 52 } 53 53 DEFINE_SHOW_ATTRIBUTE(em_debug_cpus); 54 54 55 + static int em_debug_units_show(struct seq_file *s, void *unused) 56 + { 57 + struct em_perf_domain *pd = s->private; 58 + char *units = pd->milliwatts ? "milliWatts" : "bogoWatts"; 59 + 60 + seq_printf(s, "%s\n", units); 61 + 62 + return 0; 63 + } 64 + DEFINE_SHOW_ATTRIBUTE(em_debug_units); 65 + 55 66 static void em_debug_create_pd(struct device *dev) 56 67 { 57 68 struct dentry *d; ··· 74 63 if (_is_cpu_device(dev)) 75 64 debugfs_create_file("cpus", 0444, d, dev->em_pd->cpus, 76 65 &em_debug_cpus_fops); 66 + 67 + debugfs_create_file("units", 0444, d, dev->em_pd, &em_debug_units_fops); 77 68 78 69 /* Create a sub-directory for each performance state */ 79 70 for (i = 0; i < dev->em_pd->nr_perf_states; i++) ··· 143 130 144 131 /* 145 132 * The power returned by active_state() is expected to be 146 - * positive, in milli-watts and to fit into 16 bits. 133 + * positive and to fit into 16 bits. 147 134 */ 148 135 if (!power || power > EM_MAX_POWER) { 149 136 dev_err(dev, "EM: invalid power: %lu\n", ··· 263 250 * @cpus : Pointer to cpumask_t, which in case of a CPU device is 264 251 * obligatory. It can be taken from i.e. 'policy->cpus'. For other 265 252 * type of devices this should be set to NULL. 253 + * @milliwatts : Flag indicating that the power values are in milliWatts or 254 + * in some other scale. It must be set properly. 266 255 * 267 256 * Create Energy Model tables for a performance domain using the callbacks 268 257 * defined in cb. 258 + * 259 + * The @milliwatts is important to set with correct value. Some kernel 260 + * sub-systems might rely on this flag and check if all devices in the EM are 261 + * using the same scale. 269 262 * 270 263 * If multiple clients register the same performance domain, all but the first 271 264 * registration will be ignored. ··· 279 260 * Return 0 on success 280 261 */ 281 262 int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states, 282 - struct em_data_callback *cb, cpumask_t *cpus) 263 + struct em_data_callback *cb, cpumask_t *cpus, 264 + bool milliwatts) 283 265 { 284 266 unsigned long cap, prev_cap = 0; 285 267 int cpu, ret; ··· 332 312 ret = em_create_pd(dev, nr_states, cb, cpus); 333 313 if (ret) 334 314 goto unlock; 315 + 316 + dev->em_pd->milliwatts = milliwatts; 335 317 336 318 em_debug_create_pd(dev); 337 319 dev_info(dev, "EM: created perf domain\n");
+2
kernel/power/suspend.c
··· 224 224 225 225 /** 226 226 * suspend_valid_only_mem - Generic memory-only valid callback. 227 + * @state: Target system sleep state. 227 228 * 228 229 * Platform drivers that implement mem suspend only and only need to check for 229 230 * that in their .valid() callback can use this instead of rolling their own ··· 336 335 337 336 /** 338 337 * suspend_prepare - Prepare for entering system sleep state. 338 + * @state: Target system sleep state. 339 339 * 340 340 * Common code run for every system sleep state that can be entered (except for 341 341 * hibernation). Run suspend notifiers, allocate the "suspend" console and
+2
kernel/reboot.c
··· 244 244 void kernel_restart(char *cmd) 245 245 { 246 246 kernel_restart_prepare(cmd); 247 + if (pm_power_off_prepare) 248 + pm_power_off_prepare(); 247 249 migrate_to_reboot_cpu(); 248 250 syscore_shutdown(); 249 251 if (!cmd)
+3 -5
kernel/sched/cpufreq_schedutil.c
··· 102 102 static bool sugov_update_next_freq(struct sugov_policy *sg_policy, u64 time, 103 103 unsigned int next_freq) 104 104 { 105 - if (!sg_policy->need_freq_update) { 106 - if (sg_policy->next_freq == next_freq) 107 - return false; 108 - } else { 105 + if (sg_policy->need_freq_update) 109 106 sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS); 110 - } 107 + else if (sg_policy->next_freq == next_freq) 108 + return false; 111 109 112 110 sg_policy->next_freq = next_freq; 113 111 sg_policy->last_freq_update_time = time;
+3
tools/power/cpupower/utils/cpufreq-set.c
··· 315 315 } 316 316 } 317 317 318 + get_cpustate(); 318 319 319 320 /* loop over CPUs */ 320 321 for (cpu = bitmask_first(cpus_chosen); ··· 332 331 return ret; 333 332 } 334 333 } 334 + 335 + print_offline_cpus(); 335 336 336 337 return 0; 337 338 }
+4
tools/power/cpupower/utils/cpuidle-set.c
··· 95 95 exit(EXIT_FAILURE); 96 96 } 97 97 98 + get_cpustate(); 99 + 98 100 /* Default is: set all CPUs */ 99 101 if (bitmask_isallclear(cpus_chosen)) 100 102 bitmask_setall(cpus_chosen); ··· 183 181 break; 184 182 } 185 183 } 184 + 185 + print_offline_cpus(); 186 186 return EXIT_SUCCESS; 187 187 }
+8
tools/power/cpupower/utils/cpupower.c
··· 34 34 int base_cpu; 35 35 /* Affected cpus chosen by -c/--cpu param */ 36 36 struct bitmask *cpus_chosen; 37 + struct bitmask *online_cpus; 38 + struct bitmask *offline_cpus; 37 39 38 40 #ifdef DEBUG 39 41 int be_verbose; ··· 180 178 char pathname[32]; 181 179 182 180 cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF)); 181 + online_cpus = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF)); 182 + offline_cpus = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF)); 183 183 184 184 argc--; 185 185 argv += 1; ··· 234 230 ret = p->main(argc, argv); 235 231 if (cpus_chosen) 236 232 bitmask_free(cpus_chosen); 233 + if (online_cpus) 234 + bitmask_free(online_cpus); 235 + if (offline_cpus) 236 + bitmask_free(offline_cpus); 237 237 return ret; 238 238 } 239 239 print_help();
+12
tools/power/cpupower/utils/helpers/helpers.h
··· 94 94 */ 95 95 extern int get_cpu_info(struct cpupower_cpu_info *cpu_info); 96 96 extern struct cpupower_cpu_info cpupower_cpu_info; 97 + 98 + 97 99 /* cpuid and cpuinfo helpers **************************/ 98 100 99 101 /* X86 ONLY ****************************************/ ··· 172 170 static inline unsigned int cpuid_ecx(unsigned int op) { return 0; }; 173 171 static inline unsigned int cpuid_edx(unsigned int op) { return 0; }; 174 172 #endif /* defined(__i386__) || defined(__x86_64__) */ 173 + 174 + /* 175 + * CPU State related functions 176 + */ 177 + extern struct bitmask *online_cpus; 178 + extern struct bitmask *offline_cpus; 179 + 180 + void get_cpustate(void); 181 + void print_online_cpus(void); 182 + void print_offline_cpus(void); 175 183 176 184 #endif /* __CPUPOWERUTILS_HELPERS__ */
+62 -2
tools/power/cpupower/utils/helpers/misc.c
··· 4 4 #include <errno.h> 5 5 #include <stdlib.h> 6 6 7 - #if defined(__i386__) || defined(__x86_64__) 8 - 9 7 #include "helpers/helpers.h" 10 8 #include "helpers/sysfs.h" 9 + 10 + #if defined(__i386__) || defined(__x86_64__) 11 11 12 12 #include "cpupower_intern.h" 13 13 ··· 89 89 } 90 90 91 91 #endif /* #if defined(__i386__) || defined(__x86_64__) */ 92 + 93 + /* get_cpustate 94 + * 95 + * Gather the information of all online CPUs into bitmask struct 96 + */ 97 + void get_cpustate(void) 98 + { 99 + unsigned int cpu = 0; 100 + 101 + bitmask_clearall(online_cpus); 102 + bitmask_clearall(offline_cpus); 103 + 104 + for (cpu = bitmask_first(cpus_chosen); 105 + cpu <= bitmask_last(cpus_chosen); cpu++) { 106 + 107 + if (cpupower_is_cpu_online(cpu) == 1) 108 + bitmask_setbit(online_cpus, cpu); 109 + else 110 + bitmask_setbit(offline_cpus, cpu); 111 + 112 + continue; 113 + } 114 + } 115 + 116 + /* print_online_cpus 117 + * 118 + * Print the CPU numbers of all CPUs that are online currently 119 + */ 120 + void print_online_cpus(void) 121 + { 122 + int str_len = 0; 123 + char *online_cpus_str = NULL; 124 + 125 + str_len = online_cpus->size * 5; 126 + online_cpus_str = (void *)malloc(sizeof(char) * str_len); 127 + 128 + if (!bitmask_isallclear(online_cpus)) { 129 + bitmask_displaylist(online_cpus_str, str_len, online_cpus); 130 + printf(_("Following CPUs are online:\n%s\n"), online_cpus_str); 131 + } 132 + } 133 + 134 + /* print_offline_cpus 135 + * 136 + * Print the CPU numbers of all CPUs that are offline currently 137 + */ 138 + void print_offline_cpus(void) 139 + { 140 + int str_len = 0; 141 + char *offline_cpus_str = NULL; 142 + 143 + str_len = offline_cpus->size * 5; 144 + offline_cpus_str = (void *)malloc(sizeof(char) * str_len); 145 + 146 + if (!bitmask_isallclear(offline_cpus)) { 147 + bitmask_displaylist(offline_cpus_str, str_len, offline_cpus); 148 + printf(_("Following CPUs are offline:\n%s\n"), offline_cpus_str); 149 + printf(_("cpupower set operation was not performed on them\n")); 150 + } 151 + }
+2 -2
tools/power/pm-graph/README
··· 6 6 |_| |___/ |_| 7 7 8 8 pm-graph: suspend/resume/boot timing analysis tools 9 - Version: 5.7 9 + Version: 5.8 10 10 Author: Todd Brandt <todd.e.brandt@intel.com> 11 11 Home Page: https://01.org/pm-graph 12 12 ··· 61 61 - runs with python2 or python3, choice is made by /usr/bin/python link 62 62 - python 63 63 - python-configparser (for python2 sleepgraph) 64 - - python-requests (for googlesheet.py) 64 + - python-requests (for stresstester.py) 65 65 - linux-tools-common (for turbostat usage in sleepgraph) 66 66 67 67 Ubuntu:
+225 -162
tools/power/pm-graph/sleepgraph.py
··· 81 81 # store system values and test parameters 82 82 class SystemValues: 83 83 title = 'SleepGraph' 84 - version = '5.7' 84 + version = '5.8' 85 85 ansi = False 86 86 rs = 0 87 87 display = '' ··· 92 92 testlog = True 93 93 dmesglog = True 94 94 ftracelog = False 95 + acpidebug = True 95 96 tstat = True 96 - mindevlen = 0.0 97 + mindevlen = 0.0001 97 98 mincglen = 0.0 98 99 cgphase = '' 99 100 cgtest = -1 ··· 116 115 fpdtpath = '/sys/firmware/acpi/tables/FPDT' 117 116 epath = '/sys/kernel/debug/tracing/events/power/' 118 117 pmdpath = '/sys/power/pm_debug_messages' 118 + acpipath='/sys/module/acpi/parameters/debug_level' 119 119 traceevents = [ 120 120 'suspend_resume', 121 121 'wakeup_source_activate', ··· 164 162 devdump = False 165 163 mixedphaseheight = True 166 164 devprops = dict() 165 + cfgdef = dict() 167 166 platinfo = [] 168 167 predelay = 0 169 168 postdelay = 0 170 - pmdebug = '' 171 169 tmstart = 'SUSPEND START %Y%m%d-%H:%M:%S.%f' 172 170 tmend = 'RESUME COMPLETE %Y%m%d-%H:%M:%S.%f' 173 171 tracefuncs = { 174 172 'sys_sync': {}, 175 173 'ksys_sync': {}, 176 - 'pm_notifier_call_chain_robust': {}, 174 + '__pm_notifier_call_chain': {}, 177 175 'pm_prepare_console': {}, 178 176 'pm_notifier_call_chain': {}, 179 177 'freeze_processes': {}, ··· 492 490 call('echo 0 > %s/wakealarm' % self.rtcpath, shell=True) 493 491 def initdmesg(self): 494 492 # get the latest time stamp from the dmesg log 495 - fp = Popen('dmesg', stdout=PIPE).stdout 493 + lines = Popen('dmesg', stdout=PIPE).stdout.readlines() 496 494 ktime = '0' 497 - for line in fp: 495 + for line in reversed(lines): 498 496 line = ascii(line).replace('\r\n', '') 499 497 idx = line.find('[') 500 498 if idx > 1: ··· 502 500 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 503 501 if(m): 504 502 ktime = m.group('ktime') 505 - fp.close() 503 + break 506 504 self.dmesgstart = float(ktime) 507 505 def getdmesg(self, testdata): 508 506 op = self.writeDatafileHeader(self.dmesgfile, testdata) ··· 717 715 self.fsetVal('0', 'events/kprobes/enable') 718 716 self.fsetVal('', 'kprobe_events') 719 717 self.fsetVal('1024', 'buffer_size_kb') 720 - if self.pmdebug: 721 - self.setVal(self.pmdebug, self.pmdpath) 722 718 def setupAllKprobes(self): 723 719 for name in self.tracefuncs: 724 720 self.defaultKprobe(name, self.tracefuncs[name]) ··· 740 740 # turn trace off 741 741 self.fsetVal('0', 'tracing_on') 742 742 self.cleanupFtrace() 743 - # pm debug messages 744 - pv = self.getVal(self.pmdpath) 745 - if pv != '1': 746 - self.setVal('1', self.pmdpath) 747 - self.pmdebug = pv 743 + self.testVal(self.pmdpath, 'basic', '1') 748 744 # set the trace clock to global 749 745 self.fsetVal('global', 'trace_clock') 750 746 self.fsetVal('nop', 'current_tracer') ··· 896 900 if isgz: 897 901 return gzip.open(filename, mode+'t') 898 902 return open(filename, mode) 903 + def putlog(self, filename, text): 904 + with self.openlog(filename, 'a') as fp: 905 + fp.write(text) 906 + fp.close() 907 + def dlog(self, text): 908 + self.putlog(self.dmesgfile, '# %s\n' % text) 909 + def flog(self, text): 910 + self.putlog(self.ftracefile, text) 899 911 def b64unzip(self, data): 900 912 try: 901 913 out = codecs.decode(base64.b64decode(data), 'zlib').decode() ··· 996 992 # add a line for each of these commands with their outputs 997 993 for name, cmdline, info in cmdafter: 998 994 footer += '# platform-%s: %s | %s\n' % (name, cmdline, self.b64zip(info)) 999 - 1000 - with self.openlog(self.ftracefile, 'a') as fp: 1001 - fp.write(footer) 995 + self.flog(footer) 1002 996 return True 1003 997 def commonPrefix(self, list): 1004 998 if len(list) < 2: ··· 1036 1034 cmdline, cmdpath = ' '.join(cargs[2:]), self.getExec(cargs[2]) 1037 1035 if not cmdpath or (begin and not delta): 1038 1036 continue 1037 + self.dlog('[%s]' % cmdline) 1039 1038 try: 1040 1039 fp = Popen([cmdpath]+cargs[3:], stdout=PIPE, stderr=PIPE).stdout 1041 1040 info = ascii(fp.read()).strip() ··· 1063 1060 else: 1064 1061 out.append((name, cmdline, '\tnothing' if not info else info)) 1065 1062 return out 1063 + def testVal(self, file, fmt='basic', value=''): 1064 + if file == 'restoreall': 1065 + for f in self.cfgdef: 1066 + if os.path.exists(f): 1067 + fp = open(f, 'w') 1068 + fp.write(self.cfgdef[f]) 1069 + fp.close() 1070 + self.cfgdef = dict() 1071 + elif value and os.path.exists(file): 1072 + fp = open(file, 'r+') 1073 + if fmt == 'radio': 1074 + m = re.match('.*\[(?P<v>.*)\].*', fp.read()) 1075 + if m: 1076 + self.cfgdef[file] = m.group('v') 1077 + elif fmt == 'acpi': 1078 + line = fp.read().strip().split('\n')[-1] 1079 + m = re.match('.* (?P<v>[0-9A-Fx]*) .*', line) 1080 + if m: 1081 + self.cfgdef[file] = m.group('v') 1082 + else: 1083 + self.cfgdef[file] = fp.read().strip() 1084 + fp.write(value) 1085 + fp.close() 1066 1086 def haveTurbostat(self): 1067 1087 if not self.tstat: 1068 1088 return False ··· 1227 1201 self.multitest[sz] *= 1440 1228 1202 elif unit == 'h': 1229 1203 self.multitest[sz] *= 60 1204 + def displayControl(self, cmd): 1205 + xset, ret = 'timeout 10 xset -d :0.0 {0}', 0 1206 + if self.sudouser: 1207 + xset = 'sudo -u %s %s' % (self.sudouser, xset) 1208 + if cmd == 'init': 1209 + ret = call(xset.format('dpms 0 0 0'), shell=True) 1210 + if not ret: 1211 + ret = call(xset.format('s off'), shell=True) 1212 + elif cmd == 'reset': 1213 + ret = call(xset.format('s reset'), shell=True) 1214 + elif cmd in ['on', 'off', 'standby', 'suspend']: 1215 + b4 = self.displayControl('stat') 1216 + ret = call(xset.format('dpms force %s' % cmd), shell=True) 1217 + if not ret: 1218 + curr = self.displayControl('stat') 1219 + self.vprint('Display Switched: %s -> %s' % (b4, curr)) 1220 + if curr != cmd: 1221 + self.vprint('WARNING: Display failed to change to %s' % cmd) 1222 + if ret: 1223 + self.vprint('WARNING: Display failed to change to %s with xset' % cmd) 1224 + return ret 1225 + elif cmd == 'stat': 1226 + fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout 1227 + ret = 'unknown' 1228 + for line in fp: 1229 + m = re.match('[\s]*Monitor is (?P<m>.*)', ascii(line)) 1230 + if(m and len(m.group('m')) >= 2): 1231 + out = m.group('m').lower() 1232 + ret = out[3:] if out[0:2] == 'in' else out 1233 + break 1234 + fp.close() 1235 + return ret 1236 + def setRuntimeSuspend(self, before=True): 1237 + if before: 1238 + # runtime suspend disable or enable 1239 + if self.rs > 0: 1240 + self.rstgt, self.rsval, self.rsdir = 'on', 'auto', 'enabled' 1241 + else: 1242 + self.rstgt, self.rsval, self.rsdir = 'auto', 'on', 'disabled' 1243 + pprint('CONFIGURING RUNTIME SUSPEND...') 1244 + self.rslist = deviceInfo(self.rstgt) 1245 + for i in self.rslist: 1246 + self.setVal(self.rsval, i) 1247 + pprint('runtime suspend %s on all devices (%d changed)' % (self.rsdir, len(self.rslist))) 1248 + pprint('waiting 5 seconds...') 1249 + time.sleep(5) 1250 + else: 1251 + # runtime suspend re-enable or re-disable 1252 + for i in self.rslist: 1253 + self.setVal(self.rstgt, i) 1254 + pprint('runtime suspend settings restored on %d devices' % len(self.rslist)) 1230 1255 1231 1256 sysvals = SystemValues() 1232 1257 switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0'] ··· 1717 1640 if 'resume_machine' in phase and 'suspend_machine' in lp: 1718 1641 tS, tR = self.dmesg[lp]['end'], self.dmesg[phase]['start'] 1719 1642 tL = tR - tS 1720 - if tL > 0: 1721 - left = True if tR > tZero else False 1722 - self.trimTime(tS, tL, left) 1723 - if 'trying' in self.dmesg[lp] and self.dmesg[lp]['trying'] >= 0.001: 1724 - tTry = round(self.dmesg[lp]['trying'] * 1000) 1725 - text = '%.0f (-%.0f waking)' % (tL * 1000, tTry) 1643 + if tL <= 0: 1644 + continue 1645 + left = True if tR > tZero else False 1646 + self.trimTime(tS, tL, left) 1647 + if 'waking' in self.dmesg[lp]: 1648 + tCnt = self.dmesg[lp]['waking'][0] 1649 + if self.dmesg[lp]['waking'][1] >= 0.001: 1650 + tTry = '-%.0f' % (round(self.dmesg[lp]['waking'][1] * 1000)) 1726 1651 else: 1727 - text = '%.0f' % (tL * 1000) 1728 - self.tLow.append(text) 1652 + tTry = '-%.3f' % (self.dmesg[lp]['waking'][1] * 1000) 1653 + text = '%.0f (%s ms waking %d times)' % (tL * 1000, tTry, tCnt) 1654 + else: 1655 + text = '%.0f' % (tL * 1000) 1656 + self.tLow.append(text) 1729 1657 lp = phase 1730 1658 def getMemTime(self): 1731 1659 if not self.hwstart or not self.hwend: ··· 2003 1921 for dev in list: 2004 1922 length = (list[dev]['end'] - list[dev]['start']) * 1000 2005 1923 width = widfmt % (((list[dev]['end']-list[dev]['start'])*100)/tTotal) 2006 - if width != '0.000000' and length >= mindevlen: 1924 + if length >= mindevlen: 2007 1925 devlist.append(dev) 2008 1926 self.tdevlist[phase] = devlist 2009 1927 def addHorizontalDivider(self, devname, devend): ··· 3398 3316 # trim out s2idle loops, track time trying to freeze 3399 3317 llp = data.lastPhase(2) 3400 3318 if llp.startswith('suspend_machine'): 3401 - if 'trying' not in data.dmesg[llp]: 3402 - data.dmesg[llp]['trying'] = 0 3403 - data.dmesg[llp]['trying'] += \ 3319 + if 'waking' not in data.dmesg[llp]: 3320 + data.dmesg[llp]['waking'] = [0, 0.0] 3321 + data.dmesg[llp]['waking'][0] += 1 3322 + data.dmesg[llp]['waking'][1] += \ 3404 3323 t.time - data.dmesg[lp]['start'] 3405 3324 data.currphase = '' 3406 3325 del data.dmesg[lp] ··· 4638 4555 # draw the devices for this phase 4639 4556 phaselist = data.dmesg[b]['list'] 4640 4557 for d in sorted(data.tdevlist[b]): 4641 - dname = d if '[' not in d else d.split('[')[0] 4558 + dname = d if ('[' not in d or 'CPU' in d) else d.split('[')[0] 4642 4559 name, dev = dname, phaselist[d] 4643 4560 drv = xtraclass = xtrainfo = xtrastyle = '' 4644 4561 if 'htmlclass' in dev: ··· 5277 5194 '</script>\n' 5278 5195 hf.write(script_code); 5279 5196 5280 - def setRuntimeSuspend(before=True): 5281 - global sysvals 5282 - sv = sysvals 5283 - if sv.rs == 0: 5284 - return 5285 - if before: 5286 - # runtime suspend disable or enable 5287 - if sv.rs > 0: 5288 - sv.rstgt, sv.rsval, sv.rsdir = 'on', 'auto', 'enabled' 5289 - else: 5290 - sv.rstgt, sv.rsval, sv.rsdir = 'auto', 'on', 'disabled' 5291 - pprint('CONFIGURING RUNTIME SUSPEND...') 5292 - sv.rslist = deviceInfo(sv.rstgt) 5293 - for i in sv.rslist: 5294 - sv.setVal(sv.rsval, i) 5295 - pprint('runtime suspend %s on all devices (%d changed)' % (sv.rsdir, len(sv.rslist))) 5296 - pprint('waiting 5 seconds...') 5297 - time.sleep(5) 5298 - else: 5299 - # runtime suspend re-enable or re-disable 5300 - for i in sv.rslist: 5301 - sv.setVal(sv.rstgt, i) 5302 - pprint('runtime suspend settings restored on %d devices' % len(sv.rslist)) 5303 - 5304 5197 # Function: executeSuspend 5305 5198 # Description: 5306 5199 # Execute system suspend through the sysfs interface, then copy the output 5307 5200 # dmesg and ftrace files to the test output directory. 5308 5201 def executeSuspend(quiet=False): 5309 - pm = ProcessMonitor() 5310 - tp = sysvals.tpath 5311 - if sysvals.wifi: 5312 - wifi = sysvals.checkWifi() 5202 + sv, tp, pm = sysvals, sysvals.tpath, ProcessMonitor() 5203 + if sv.wifi: 5204 + wifi = sv.checkWifi() 5205 + sv.dlog('wifi check, connected device is "%s"' % wifi) 5313 5206 testdata = [] 5314 5207 # run these commands to prepare the system for suspend 5315 - if sysvals.display: 5208 + if sv.display: 5316 5209 if not quiet: 5317 - pprint('SET DISPLAY TO %s' % sysvals.display.upper()) 5318 - displayControl(sysvals.display) 5210 + pprint('SET DISPLAY TO %s' % sv.display.upper()) 5211 + ret = sv.displayControl(sv.display) 5212 + sv.dlog('xset display %s, ret = %d' % (sv.display, ret)) 5319 5213 time.sleep(1) 5320 - if sysvals.sync: 5214 + if sv.sync: 5321 5215 if not quiet: 5322 5216 pprint('SYNCING FILESYSTEMS') 5217 + sv.dlog('syncing filesystems') 5323 5218 call('sync', shell=True) 5324 - # mark the start point in the kernel ring buffer just as we start 5325 - sysvals.initdmesg() 5219 + sv.dlog('read dmesg') 5220 + sv.initdmesg() 5326 5221 # start ftrace 5327 - if(sysvals.usecallgraph or sysvals.usetraceevents): 5222 + if(sv.usecallgraph or sv.usetraceevents): 5328 5223 if not quiet: 5329 5224 pprint('START TRACING') 5330 - sysvals.fsetVal('1', 'tracing_on') 5331 - if sysvals.useprocmon: 5225 + sv.dlog('start ftrace tracing') 5226 + sv.fsetVal('1', 'tracing_on') 5227 + if sv.useprocmon: 5228 + sv.dlog('start the process monitor') 5332 5229 pm.start() 5333 - sysvals.cmdinfo(True) 5230 + sv.dlog('run the cmdinfo list before') 5231 + sv.cmdinfo(True) 5334 5232 # execute however many s/r runs requested 5335 - for count in range(1,sysvals.execcount+1): 5233 + for count in range(1,sv.execcount+1): 5336 5234 # x2delay in between test runs 5337 - if(count > 1 and sysvals.x2delay > 0): 5338 - sysvals.fsetVal('WAIT %d' % sysvals.x2delay, 'trace_marker') 5339 - time.sleep(sysvals.x2delay/1000.0) 5340 - sysvals.fsetVal('WAIT END', 'trace_marker') 5235 + if(count > 1 and sv.x2delay > 0): 5236 + sv.fsetVal('WAIT %d' % sv.x2delay, 'trace_marker') 5237 + time.sleep(sv.x2delay/1000.0) 5238 + sv.fsetVal('WAIT END', 'trace_marker') 5341 5239 # start message 5342 - if sysvals.testcommand != '': 5240 + if sv.testcommand != '': 5343 5241 pprint('COMMAND START') 5344 5242 else: 5345 - if(sysvals.rtcwake): 5243 + if(sv.rtcwake): 5346 5244 pprint('SUSPEND START') 5347 5245 else: 5348 5246 pprint('SUSPEND START (press a key to resume)') 5349 5247 # set rtcwake 5350 - if(sysvals.rtcwake): 5248 + if(sv.rtcwake): 5351 5249 if not quiet: 5352 - pprint('will issue an rtcwake in %d seconds' % sysvals.rtcwaketime) 5353 - sysvals.rtcWakeAlarmOn() 5250 + pprint('will issue an rtcwake in %d seconds' % sv.rtcwaketime) 5251 + sv.dlog('enable RTC wake alarm') 5252 + sv.rtcWakeAlarmOn() 5354 5253 # start of suspend trace marker 5355 - if(sysvals.usecallgraph or sysvals.usetraceevents): 5356 - sysvals.fsetVal(datetime.now().strftime(sysvals.tmstart), 'trace_marker') 5254 + if(sv.usecallgraph or sv.usetraceevents): 5255 + sv.fsetVal(datetime.now().strftime(sv.tmstart), 'trace_marker') 5357 5256 # predelay delay 5358 - if(count == 1 and sysvals.predelay > 0): 5359 - sysvals.fsetVal('WAIT %d' % sysvals.predelay, 'trace_marker') 5360 - time.sleep(sysvals.predelay/1000.0) 5361 - sysvals.fsetVal('WAIT END', 'trace_marker') 5257 + if(count == 1 and sv.predelay > 0): 5258 + sv.fsetVal('WAIT %d' % sv.predelay, 'trace_marker') 5259 + time.sleep(sv.predelay/1000.0) 5260 + sv.fsetVal('WAIT END', 'trace_marker') 5362 5261 # initiate suspend or command 5262 + sv.dlog('system executing a suspend') 5363 5263 tdata = {'error': ''} 5364 - if sysvals.testcommand != '': 5365 - res = call(sysvals.testcommand+' 2>&1', shell=True); 5264 + if sv.testcommand != '': 5265 + res = call(sv.testcommand+' 2>&1', shell=True); 5366 5266 if res != 0: 5367 5267 tdata['error'] = 'cmd returned %d' % res 5368 5268 else: 5369 - mode = sysvals.suspendmode 5370 - if sysvals.memmode and os.path.exists(sysvals.mempowerfile): 5269 + mode = sv.suspendmode 5270 + if sv.memmode and os.path.exists(sv.mempowerfile): 5371 5271 mode = 'mem' 5372 - pf = open(sysvals.mempowerfile, 'w') 5373 - pf.write(sysvals.memmode) 5374 - pf.close() 5375 - if sysvals.diskmode and os.path.exists(sysvals.diskpowerfile): 5272 + sv.testVal(sv.mempowerfile, 'radio', sv.memmode) 5273 + if sv.diskmode and os.path.exists(sv.diskpowerfile): 5376 5274 mode = 'disk' 5377 - pf = open(sysvals.diskpowerfile, 'w') 5378 - pf.write(sysvals.diskmode) 5379 - pf.close() 5380 - if mode == 'freeze' and sysvals.haveTurbostat(): 5275 + sv.testVal(sv.diskpowerfile, 'radio', sv.diskmode) 5276 + if sv.acpidebug: 5277 + sv.testVal(sv.acpipath, 'acpi', '0xe') 5278 + if mode == 'freeze' and sv.haveTurbostat(): 5381 5279 # execution will pause here 5382 - turbo = sysvals.turbostat() 5280 + turbo = sv.turbostat() 5383 5281 if turbo: 5384 5282 tdata['turbo'] = turbo 5385 5283 else: 5386 - pf = open(sysvals.powerfile, 'w') 5284 + pf = open(sv.powerfile, 'w') 5387 5285 pf.write(mode) 5388 5286 # execution will pause here 5389 5287 try: 5390 5288 pf.close() 5391 5289 except Exception as e: 5392 5290 tdata['error'] = str(e) 5393 - if(sysvals.rtcwake): 5394 - sysvals.rtcWakeAlarmOff() 5291 + sv.dlog('system returned from resume') 5292 + # reset everything 5293 + sv.testVal('restoreall') 5294 + if(sv.rtcwake): 5295 + sv.dlog('disable RTC wake alarm') 5296 + sv.rtcWakeAlarmOff() 5395 5297 # postdelay delay 5396 - if(count == sysvals.execcount and sysvals.postdelay > 0): 5397 - sysvals.fsetVal('WAIT %d' % sysvals.postdelay, 'trace_marker') 5398 - time.sleep(sysvals.postdelay/1000.0) 5399 - sysvals.fsetVal('WAIT END', 'trace_marker') 5298 + if(count == sv.execcount and sv.postdelay > 0): 5299 + sv.fsetVal('WAIT %d' % sv.postdelay, 'trace_marker') 5300 + time.sleep(sv.postdelay/1000.0) 5301 + sv.fsetVal('WAIT END', 'trace_marker') 5400 5302 # return from suspend 5401 5303 pprint('RESUME COMPLETE') 5402 - if(sysvals.usecallgraph or sysvals.usetraceevents): 5403 - sysvals.fsetVal(datetime.now().strftime(sysvals.tmend), 'trace_marker') 5404 - if sysvals.wifi and wifi: 5405 - tdata['wifi'] = sysvals.pollWifi(wifi) 5406 - if(sysvals.suspendmode == 'mem' or sysvals.suspendmode == 'command'): 5304 + if(sv.usecallgraph or sv.usetraceevents): 5305 + sv.fsetVal(datetime.now().strftime(sv.tmend), 'trace_marker') 5306 + if sv.wifi and wifi: 5307 + tdata['wifi'] = sv.pollWifi(wifi) 5308 + sv.dlog('wifi check, %s' % tdata['wifi']) 5309 + if(sv.suspendmode == 'mem' or sv.suspendmode == 'command'): 5310 + sv.dlog('read the ACPI FPDT') 5407 5311 tdata['fw'] = getFPDT(False) 5408 5312 testdata.append(tdata) 5409 - cmdafter = sysvals.cmdinfo(False) 5313 + sv.dlog('run the cmdinfo list after') 5314 + cmdafter = sv.cmdinfo(False) 5410 5315 # stop ftrace 5411 - if(sysvals.usecallgraph or sysvals.usetraceevents): 5412 - if sysvals.useprocmon: 5316 + if(sv.usecallgraph or sv.usetraceevents): 5317 + if sv.useprocmon: 5318 + sv.dlog('stop the process monitor') 5413 5319 pm.stop() 5414 - sysvals.fsetVal('0', 'tracing_on') 5320 + sv.fsetVal('0', 'tracing_on') 5415 5321 # grab a copy of the dmesg output 5416 5322 if not quiet: 5417 5323 pprint('CAPTURING DMESG') 5418 - sysvals.getdmesg(testdata) 5324 + sysvals.dlog('EXECUTION TRACE END') 5325 + sv.getdmesg(testdata) 5419 5326 # grab a copy of the ftrace output 5420 - if(sysvals.usecallgraph or sysvals.usetraceevents): 5327 + if(sv.usecallgraph or sv.usetraceevents): 5421 5328 if not quiet: 5422 5329 pprint('CAPTURING TRACE') 5423 - op = sysvals.writeDatafileHeader(sysvals.ftracefile, testdata) 5330 + op = sv.writeDatafileHeader(sv.ftracefile, testdata) 5424 5331 fp = open(tp+'trace', 'r') 5425 5332 for line in fp: 5426 5333 op.write(line) 5427 5334 op.close() 5428 - sysvals.fsetVal('', 'trace') 5429 - sysvals.platforminfo(cmdafter) 5335 + sv.fsetVal('', 'trace') 5336 + sv.platforminfo(cmdafter) 5430 5337 5431 5338 def readFile(file): 5432 5339 if os.path.islink(file): ··· 5658 5585 i = n + 2 5659 5586 count += 1 5660 5587 return out 5661 - 5662 - def displayControl(cmd): 5663 - xset, ret = 'timeout 10 xset -d :0.0 {0}', 0 5664 - if sysvals.sudouser: 5665 - xset = 'sudo -u %s %s' % (sysvals.sudouser, xset) 5666 - if cmd == 'init': 5667 - ret = call(xset.format('dpms 0 0 0'), shell=True) 5668 - if not ret: 5669 - ret = call(xset.format('s off'), shell=True) 5670 - elif cmd == 'reset': 5671 - ret = call(xset.format('s reset'), shell=True) 5672 - elif cmd in ['on', 'off', 'standby', 'suspend']: 5673 - b4 = displayControl('stat') 5674 - ret = call(xset.format('dpms force %s' % cmd), shell=True) 5675 - if not ret: 5676 - curr = displayControl('stat') 5677 - sysvals.vprint('Display Switched: %s -> %s' % (b4, curr)) 5678 - if curr != cmd: 5679 - sysvals.vprint('WARNING: Display failed to change to %s' % cmd) 5680 - if ret: 5681 - sysvals.vprint('WARNING: Display failed to change to %s with xset' % cmd) 5682 - return ret 5683 - elif cmd == 'stat': 5684 - fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout 5685 - ret = 'unknown' 5686 - for line in fp: 5687 - m = re.match('[\s]*Monitor is (?P<m>.*)', ascii(line)) 5688 - if(m and len(m.group('m')) >= 2): 5689 - out = m.group('m').lower() 5690 - ret = out[3:] if out[0:2] == 'in' else out 5691 - break 5692 - fp.close() 5693 - return ret 5694 5588 5695 5589 # Function: getFPDT 5696 5590 # Description: ··· 6041 6001 # execute a suspend/resume, gather the logs, and generate the output 6042 6002 def runTest(n=0, quiet=False): 6043 6003 # prepare for the test 6044 - sysvals.initFtrace(quiet) 6045 6004 sysvals.initTestOutput('suspend') 6005 + op = sysvals.writeDatafileHeader(sysvals.dmesgfile, []) 6006 + op.write('# EXECUTION TRACE START\n') 6007 + op.close() 6008 + if n <= 1: 6009 + if sysvals.rs != 0: 6010 + sysvals.dlog('%sabling runtime suspend' % ('en' if sysvals.rs > 0 else 'dis')) 6011 + sysvals.setRuntimeSuspend(True) 6012 + if sysvals.display: 6013 + ret = sysvals.displayControl('init') 6014 + sysvals.dlog('xset display init, ret = %d' % ret) 6015 + sysvals.dlog('initialize ftrace') 6016 + sysvals.initFtrace(quiet) 6046 6017 6047 6018 # execute the test 6048 6019 executeSuspend(quiet) ··· 6149 6098 if wifi: 6150 6099 extra['wifi'] = wifi 6151 6100 low = find_in_html(html, 'freeze time: <b>', ' ms</b>') 6152 - if low and 'waking' in low: 6153 - issue = 'FREEZEWAKE' 6101 + for lowstr in ['waking', '+']: 6102 + if not low: 6103 + break 6104 + if lowstr not in low: 6105 + continue 6106 + if lowstr == '+': 6107 + issue = 'S2LOOPx%d' % len(low.split('+')) 6108 + else: 6109 + m = re.match('.*waking *(?P<n>[0-9]*) *times.*', low) 6110 + issue = 'S2WAKEx%s' % m.group('n') if m else 'S2WAKExNaN' 6154 6111 match = [i for i in issues if i['match'] == issue] 6155 6112 if len(match) > 0: 6156 6113 match[0]['count'] += 1 ··· 6664 6605 val = next(args) 6665 6606 except: 6666 6607 doError('-info requires one string argument', True) 6608 + elif(arg == '-desc'): 6609 + try: 6610 + val = next(args) 6611 + except: 6612 + doError('-desc requires one string argument', True) 6667 6613 elif(arg == '-rs'): 6668 6614 try: 6669 6615 val = next(args) ··· 6878 6814 runSummary(sysvals.outdir, True, genhtml) 6879 6815 elif(cmd in ['xon', 'xoff', 'xstandby', 'xsuspend', 'xinit', 'xreset']): 6880 6816 sysvals.verbose = True 6881 - ret = displayControl(cmd[1:]) 6817 + ret = sysvals.displayControl(cmd[1:]) 6882 6818 elif(cmd == 'xstat'): 6883 - pprint('Display Status: %s' % displayControl('stat').upper()) 6819 + pprint('Display Status: %s' % sysvals.displayControl('stat').upper()) 6884 6820 elif(cmd == 'wificheck'): 6885 6821 dev = sysvals.checkWifi() 6886 6822 if dev: ··· 6918 6854 if mode.startswith('disk-'): 6919 6855 sysvals.diskmode = mode.split('-', 1)[-1] 6920 6856 sysvals.suspendmode = 'disk' 6921 - 6922 6857 sysvals.systemInfo(dmidecode(sysvals.mempath)) 6923 6858 6924 - setRuntimeSuspend(True) 6925 - if sysvals.display: 6926 - displayControl('init') 6927 6859 failcnt, ret = 0, 0 6928 6860 if sysvals.multitest['run']: 6929 6861 # run multiple tests in a separate subdirectory ··· 6960 6900 sysvals.testdir = sysvals.outdir 6961 6901 # run the test in the current directory 6962 6902 ret = runTest() 6903 + 6904 + # reset to default values after testing 6963 6905 if sysvals.display: 6964 - displayControl('reset') 6965 - setRuntimeSuspend(False) 6906 + sysvals.displayControl('reset') 6907 + if sysvals.rs != 0: 6908 + sysvals.setRuntimeSuspend(False) 6966 6909 sys.exit(ret)