aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-03 13:45:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-03 13:45:39 -0400
commitf2d285669aae656dfeafa0bf25e86bbbc5d22329 (patch)
tree4391c45051429c09199d7fd2ca6ca0dd142a5ed6
parentbe5537542743f72c7cedddd145c17cf7706baa23 (diff)
parent103cf0e5799ce024fd28dfab716d7111afe4b117 (diff)
Merge tag 'pm-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael Wysocki: "These update the cpuidle poll state definition to reduce excessive energy usage related to it, add new CPU ID to the RAPL power capping driver, update the ACPI system suspend code to handle some special cases better, extend the PM core's device links code slightly, add new sysfs attribute for better suspend-to-idle diagnostics and easier hibernation handling, update power management tools and clean up cpufreq quite a bit. Specifics: - Modify the cpuidle poll state implementation to prevent CPUs from staying in the loop in there for excessive times (Rafael Wysocki). - Add Intel Cannon Lake chips support to the RAPL power capping driver (Joe Konno). - Add reference counting to the device links handling code in the PM core (Lukas Wunner). - Avoid reconfiguring GPEs on suspend-to-idle in the ACPI system suspend code (Rafael Wysocki). - Allow devices to be put into deeper low-power states via ACPI if both _SxD and _SxW are missing (Daniel Drake). - Reorganize the core ACPI suspend-to-idle wakeup code to avoid a keyboard wakeup issue on Asus UX331UA (Chris Chiu). - Prevent the PCMCIA library code from aborting suspend-to-idle due to noirq suspend failures resulting from incorrect assumptions (Rafael Wysocki). - Add coupled cpuidle supprt to the Exynos3250 platform (Marek Szyprowski). - Add new sysfs file to make it easier to specify the image storage location during hibernation (Mario Limonciello). - Add sysfs files for collecting suspend-to-idle usage and time statistics for CPU idle states (Rafael Wysocki). - Update the pm-graph utilities (Todd Brandt). - Reduce the kernel log noise related to reporting Low-power Idle constraings by the ACPI system suspend code (Rafael Wysocki). - Make it easier to distinguish dedicated wakeup IRQs in the /proc/interrupts output (Tony Lindgren). - Add the frequency table validation in cpufreq to the core and drop it from a number of cpufreq drivers (Viresh Kumar). - Drop "cooling-{min|max}-level" for CPU nodes from a couple of DT bindings (Viresh Kumar). - Clean up the CPU online error code path in the cpufreq core (Viresh Kumar). - Fix assorted issues in the SCPI, CPPC, mediatek and tegra186 cpufreq drivers (Arnd Bergmann, Chunyu Hu, George Cherian, Viresh Kumar). - Drop memory allocation error messages from a few places in cpufreq and cpuildle drivers (Markus Elfring)" * tag 'pm-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (56 commits) ACPI / PM: Fix keyboard wakeup from suspend-to-idle on ASUS UX331UA cpufreq: CPPC: Use transition_delay_us depending transition_latency PM / hibernate: Change message when writing to /sys/power/resume PM / hibernate: Make passing hibernate offsets more friendly cpuidle: poll_state: Avoid invoking local_clock() too often PM: cpuidle/suspend: Add s2idle usage and time state attributes cpuidle: Enable coupled cpuidle support on Exynos3250 platform cpuidle: poll_state: Add time limit to poll_idle() cpufreq: tegra186: Don't validate the frequency table twice cpufreq: speedstep: Don't validate the frequency table twice cpufreq: sparc: Don't validate the frequency table twice cpufreq: sh: Don't validate the frequency table twice cpufreq: sfi: Don't validate the frequency table twice cpufreq: scpi: Don't validate the frequency table twice cpufreq: sc520: Don't validate the frequency table twice cpufreq: s3c24xx: Don't validate the frequency table twice cpufreq: qoirq: Don't validate the frequency table twice cpufreq: pxa: Don't validate the frequency table twice cpufreq: ppc_cbe: Don't validate the frequency table twice cpufreq: powernow: Don't validate the frequency table twice ...
-rw-r--r--Documentation/ABI/testing/sysfs-devices-system-cpu25
-rw-r--r--Documentation/ABI/testing/sysfs-power14
-rw-r--r--Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt4
-rw-r--r--Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt4
-rw-r--r--Documentation/power/swsusp.txt10
-rw-r--r--arch/arm/boot/dts/mt7623.dtsi2
-rw-r--r--drivers/acpi/device_pm.c11
-rw-r--r--drivers/acpi/sleep.c24
-rw-r--r--drivers/base/core.c25
-rw-r--r--drivers/base/power/power.h1
-rw-r--r--drivers/base/power/wakeirq.c13
-rw-r--r--drivers/cpufreq/Kconfig.arm1
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c20
-rw-r--r--drivers/cpufreq/arm_big_little.c9
-rw-r--r--drivers/cpufreq/brcmstb-avs-cpufreq.c6
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c12
-rw-r--r--drivers/cpufreq/cpufreq-dt.c8
-rw-r--r--drivers/cpufreq/cpufreq.c28
-rw-r--r--drivers/cpufreq/e_powersaver.c8
-rw-r--r--drivers/cpufreq/elanfreq.c3
-rw-r--r--drivers/cpufreq/freq_table.c16
-rw-r--r--drivers/cpufreq/ia64-acpi-cpufreq.c7
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c7
-rw-r--r--drivers/cpufreq/longhaul.c3
-rw-r--r--drivers/cpufreq/mediatek-cpufreq.c13
-rw-r--r--drivers/cpufreq/p4-clockmod.c3
-rw-r--r--drivers/cpufreq/powernow-k6.c3
-rw-r--r--drivers/cpufreq/powernow-k7.c3
-rw-r--r--drivers/cpufreq/powernow-k8.c24
-rw-r--r--drivers/cpufreq/powernv-cpufreq.c11
-rw-r--r--drivers/cpufreq/ppc_cbe_cpufreq.c5
-rw-r--r--drivers/cpufreq/pxa2xx-cpufreq.c4
-rw-r--r--drivers/cpufreq/pxa3xx-cpufreq.c4
-rw-r--r--drivers/cpufreq/qoriq-cpufreq.c21
-rw-r--r--drivers/cpufreq/s3c24xx-cpufreq.c13
-rw-r--r--drivers/cpufreq/sc520_freq.c3
-rw-r--r--drivers/cpufreq/scpi-cpufreq.c10
-rw-r--r--drivers/cpufreq/sfi-cpufreq.c3
-rw-r--r--drivers/cpufreq/sh-cpufreq.c22
-rw-r--r--drivers/cpufreq/sparc-us2e-cpufreq.c3
-rw-r--r--drivers/cpufreq/sparc-us3-cpufreq.c3
-rw-r--r--drivers/cpufreq/speedstep-centrino.c4
-rw-r--r--drivers/cpufreq/speedstep-ich.c4
-rw-r--r--drivers/cpufreq/speedstep-smi.c4
-rw-r--r--drivers/cpufreq/tegra186-cpufreq.c3
-rw-r--r--drivers/cpuidle/cpuidle-arm.c1
-rw-r--r--drivers/cpuidle/cpuidle-exynos.c3
-rw-r--r--drivers/cpuidle/cpuidle.c9
-rw-r--r--drivers/cpuidle/poll_state.c17
-rw-r--r--drivers/cpuidle/sysfs.c54
-rw-r--r--drivers/pcmcia/cs.c10
-rw-r--r--drivers/pcmcia/cs_internal.h1
-rw-r--r--drivers/powercap/intel_rapl.c1
-rw-r--r--include/linux/cpufreq.h1
-rw-r--r--include/linux/cpuidle.h4
-rw-r--r--include/linux/device.h2
-rw-r--r--kernel/power/hibernate.c26
-rw-r--r--tools/power/pm-graph/Makefile29
-rw-r--r--tools/power/pm-graph/bootgraph.818
-rwxr-xr-xtools/power/pm-graph/bootgraph.py (renamed from tools/power/pm-graph/analyze_boot.py)219
-rw-r--r--tools/power/pm-graph/config/cgskip.txt65
-rw-r--r--tools/power/pm-graph/config/custom-timeline-functions.cfg205
-rw-r--r--tools/power/pm-graph/config/example.cfg133
-rw-r--r--tools/power/pm-graph/config/freeze-callgraph.cfg94
-rw-r--r--tools/power/pm-graph/config/freeze-dev.cfg93
-rw-r--r--tools/power/pm-graph/config/freeze.cfg93
-rw-r--r--tools/power/pm-graph/config/standby-callgraph.cfg94
-rw-r--r--tools/power/pm-graph/config/standby-dev.cfg93
-rw-r--r--tools/power/pm-graph/config/standby.cfg93
-rw-r--r--tools/power/pm-graph/config/suspend-callgraph.cfg98
-rw-r--r--tools/power/pm-graph/config/suspend-dev.cfg93
-rw-r--r--tools/power/pm-graph/config/suspend-x2-proc.cfg93
-rw-r--r--tools/power/pm-graph/config/suspend.cfg93
-rw-r--r--tools/power/pm-graph/sleepgraph.847
-rwxr-xr-xtools/power/pm-graph/sleepgraph.py (renamed from tools/power/pm-graph/analyze_suspend.py)1625
75 files changed, 2916 insertions, 915 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 4ed63b6cfb15..025b7cf3768d 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -198,6 +198,31 @@ Description:
198 time (in microseconds) this cpu should spend in this idle state 198 time (in microseconds) this cpu should spend in this idle state
199 to make the transition worth the effort. 199 to make the transition worth the effort.
200 200
201What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/s2idle/
202Date: March 2018
203KernelVersion: v4.17
204Contact: Linux power management list <linux-pm@vger.kernel.org>
205Description:
206 Idle state usage statistics related to suspend-to-idle.
207
208 This attribute group is only present for states that can be
209 used in suspend-to-idle with suspended timekeeping.
210
211What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/s2idle/time
212Date: March 2018
213KernelVersion: v4.17
214Contact: Linux power management list <linux-pm@vger.kernel.org>
215Description:
216 Total time spent by the CPU in suspend-to-idle (with scheduler
217 tick suspended) after requesting this state.
218
219What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/s2idle/usage
220Date: March 2018
221KernelVersion: v4.17
222Contact: Linux power management list <linux-pm@vger.kernel.org>
223Description:
224 Total number of times this state has been requested by the CPU
225 while entering suspend-to-idle.
201 226
202What: /sys/devices/system/cpu/cpu#/cpufreq/* 227What: /sys/devices/system/cpu/cpu#/cpufreq/*
203Date: pre-git history 228Date: pre-git history
diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index 1e0d1dac706b..2f813d644c69 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -287,3 +287,17 @@ Description:
287 Writing a "1" to this file enables the debug messages and 287 Writing a "1" to this file enables the debug messages and
288 writing a "0" (default) to it disables them. Reads from 288 writing a "0" (default) to it disables them. Reads from
289 this file return the current value. 289 this file return the current value.
290
291What: /sys/power/resume_offset
292Date: April 2018
293Contact: Mario Limonciello <mario.limonciello@dell.com>
294Description:
295 This file is used for telling the kernel an offset into a disk
296 to use when hibernating the system such as with a swap file.
297
298 Reads from this file will display the current offset
299 the kernel will be using on the next hibernation
300 attempt.
301
302 Using this sysfs file will override any values that were
303 set using the kernel command line for disk offset. \ No newline at end of file
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt
index dd3929e85dec..332aed8f4597 100644
--- a/Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt
@@ -18,8 +18,6 @@ Optional properties:
18 in unit of nanoseconds. 18 in unit of nanoseconds.
19- voltage-tolerance: Specify the CPU voltage tolerance in percentage. 19- voltage-tolerance: Specify the CPU voltage tolerance in percentage.
20- #cooling-cells: 20- #cooling-cells:
21- cooling-min-level:
22- cooling-max-level:
23 Please refer to Documentation/devicetree/bindings/thermal/thermal.txt. 21 Please refer to Documentation/devicetree/bindings/thermal/thermal.txt.
24 22
25Examples: 23Examples:
@@ -40,8 +38,6 @@ cpus {
40 >; 38 >;
41 clock-latency = <61036>; /* two CLK32 periods */ 39 clock-latency = <61036>; /* two CLK32 periods */
42 #cooling-cells = <2>; 40 #cooling-cells = <2>;
43 cooling-min-level = <0>;
44 cooling-max-level = <2>;
45 }; 41 };
46 42
47 cpu@1 { 43 cpu@1 {
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt
index f6403089edcf..d36f07e0a2bb 100644
--- a/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt
@@ -21,8 +21,6 @@ Optional properties:
21 flow is handled by hardware, hence no software "voltage tracking" is 21 flow is handled by hardware, hence no software "voltage tracking" is
22 needed. 22 needed.
23- #cooling-cells: 23- #cooling-cells:
24- cooling-min-level:
25- cooling-max-level:
26 Please refer to Documentation/devicetree/bindings/thermal/thermal.txt 24 Please refer to Documentation/devicetree/bindings/thermal/thermal.txt
27 for detail. 25 for detail.
28 26
@@ -67,8 +65,6 @@ Example 1 (MT7623 SoC):
67 clock-names = "cpu", "intermediate"; 65 clock-names = "cpu", "intermediate";
68 operating-points-v2 = <&cpu_opp_table>; 66 operating-points-v2 = <&cpu_opp_table>;
69 #cooling-cells = <2>; 67 #cooling-cells = <2>;
70 cooling-min-level = <0>;
71 cooling-max-level = <7>;
72 }; 68 };
73 cpu@1 { 69 cpu@1 {
74 device_type = "cpu"; 70 device_type = "cpu";
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 9f2f942a01cf..cc87adf44c0a 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -24,8 +24,16 @@ Some warnings, first.
24 * see the FAQ below for details. (This is not true for more traditional 24 * see the FAQ below for details. (This is not true for more traditional
25 * power states like "standby", which normally don't turn USB off.) 25 * power states like "standby", which normally don't turn USB off.)
26 26
27Swap partition:
27You need to append resume=/dev/your_swap_partition to kernel command 28You need to append resume=/dev/your_swap_partition to kernel command
28line. Then you suspend by 29line or specify it using /sys/power/resume.
30
31Swap file:
32If using a swapfile you can also specify a resume offset using
33resume_offset=<number> on the kernel command line or specify it
34in /sys/power/resume_offset.
35
36After preparing then you suspend by
29 37
30echo shutdown > /sys/power/disk; echo disk > /sys/power/state 38echo shutdown > /sys/power/disk; echo disk > /sys/power/state
31 39
diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi
index b750da5362f7..8e7c65464c9d 100644
--- a/arch/arm/boot/dts/mt7623.dtsi
+++ b/arch/arm/boot/dts/mt7623.dtsi
@@ -87,8 +87,6 @@
87 clock-names = "cpu", "intermediate"; 87 clock-names = "cpu", "intermediate";
88 operating-points-v2 = <&cpu_opp_table>; 88 operating-points-v2 = <&cpu_opp_table>;
89 #cooling-cells = <2>; 89 #cooling-cells = <2>;
90 cooling-min-level = <0>;
91 cooling-max-level = <7>;
92 clock-frequency = <1300000000>; 90 clock-frequency = <1300000000>;
93 }; 91 };
94 92
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index c4d0a1c912f0..3d96e4da2d98 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -543,6 +543,7 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
543 unsigned long long ret; 543 unsigned long long ret;
544 int d_min, d_max; 544 int d_min, d_max;
545 bool wakeup = false; 545 bool wakeup = false;
546 bool has_sxd = false;
546 acpi_status status; 547 acpi_status status;
547 548
548 /* 549 /*
@@ -581,6 +582,10 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
581 else 582 else
582 return -ENODATA; 583 return -ENODATA;
583 } 584 }
585
586 if (status == AE_OK)
587 has_sxd = true;
588
584 d_min = ret; 589 d_min = ret;
585 wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid 590 wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid
586 && adev->wakeup.sleep_state >= target_state; 591 && adev->wakeup.sleep_state >= target_state;
@@ -599,7 +604,11 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
599 method[3] = 'W'; 604 method[3] = 'W';
600 status = acpi_evaluate_integer(handle, method, NULL, &ret); 605 status = acpi_evaluate_integer(handle, method, NULL, &ret);
601 if (status == AE_NOT_FOUND) { 606 if (status == AE_NOT_FOUND) {
602 if (target_state > ACPI_STATE_S0) 607 /* No _SxW. In this case, the ACPI spec says that we
608 * must not go into any power state deeper than the
609 * value returned from _SxD.
610 */
611 if (has_sxd && target_state > ACPI_STATE_S0)
603 d_max = d_min; 612 d_max = d_min;
604 } else if (ACPI_SUCCESS(status) && ret <= ACPI_STATE_D3_COLD) { 613 } else if (ACPI_SUCCESS(status) && ret <= ACPI_STATE_D3_COLD) {
605 /* Fall back to D3cold if ret is not a valid state. */ 614 /* Fall back to D3cold if ret is not a valid state. */
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index b35923e3a926..99a1a650326d 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -849,23 +849,25 @@ static void lpi_check_constraints(void)
849 int i; 849 int i;
850 850
851 for (i = 0; i < lpi_constraints_table_size; ++i) { 851 for (i = 0; i < lpi_constraints_table_size; ++i) {
852 acpi_handle handle = lpi_constraints_table[i].handle;
852 struct acpi_device *adev; 853 struct acpi_device *adev;
853 854
854 if (acpi_bus_get_device(lpi_constraints_table[i].handle, &adev)) 855 if (!handle || acpi_bus_get_device(handle, &adev))
855 continue; 856 continue;
856 857
857 acpi_handle_debug(adev->handle, 858 acpi_handle_debug(handle,
858 "LPI: required min power state:%s current power state:%s\n", 859 "LPI: required min power state:%s current power state:%s\n",
859 acpi_power_state_string(lpi_constraints_table[i].min_dstate), 860 acpi_power_state_string(lpi_constraints_table[i].min_dstate),
860 acpi_power_state_string(adev->power.state)); 861 acpi_power_state_string(adev->power.state));
861 862
862 if (!adev->flags.power_manageable) { 863 if (!adev->flags.power_manageable) {
863 acpi_handle_info(adev->handle, "LPI: Device not power manageble\n"); 864 acpi_handle_info(handle, "LPI: Device not power manageable\n");
865 lpi_constraints_table[i].handle = NULL;
864 continue; 866 continue;
865 } 867 }
866 868
867 if (adev->power.state < lpi_constraints_table[i].min_dstate) 869 if (adev->power.state < lpi_constraints_table[i].min_dstate)
868 acpi_handle_info(adev->handle, 870 acpi_handle_info(handle,
869 "LPI: Constraint not met; min power state:%s current power state:%s\n", 871 "LPI: Constraint not met; min power state:%s current power state:%s\n",
870 acpi_power_state_string(lpi_constraints_table[i].min_dstate), 872 acpi_power_state_string(lpi_constraints_table[i].min_dstate),
871 acpi_power_state_string(adev->power.state)); 873 acpi_power_state_string(adev->power.state));
@@ -951,15 +953,8 @@ static int acpi_s2idle_prepare(void)
951 if (lps0_device_handle) { 953 if (lps0_device_handle) {
952 acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); 954 acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF);
953 acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); 955 acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY);
954 } else {
955 /*
956 * The configuration of GPEs is changed here to avoid spurious
957 * wakeups, but that should not be necessary if this is a
958 * "low-power S0" platform and the low-power S0 _DSM is present.
959 */
960 acpi_enable_all_wakeup_gpes();
961 acpi_os_wait_events_complete();
962 } 956 }
957
963 if (acpi_sci_irq_valid()) 958 if (acpi_sci_irq_valid())
964 enable_irq_wake(acpi_sci_irq); 959 enable_irq_wake(acpi_sci_irq);
965 960
@@ -992,8 +987,9 @@ static void acpi_s2idle_sync(void)
992 * The EC driver uses the system workqueue and an additional special 987 * The EC driver uses the system workqueue and an additional special
993 * one, so those need to be flushed too. 988 * one, so those need to be flushed too.
994 */ 989 */
990 acpi_os_wait_events_complete(); /* synchronize SCI IRQ handling */
995 acpi_ec_flush_work(); 991 acpi_ec_flush_work();
996 acpi_os_wait_events_complete(); 992 acpi_os_wait_events_complete(); /* synchronize Notify handling */
997 s2idle_wakeup = false; 993 s2idle_wakeup = false;
998} 994}
999 995
@@ -1005,8 +1001,6 @@ static void acpi_s2idle_restore(void)
1005 if (lps0_device_handle) { 1001 if (lps0_device_handle) {
1006 acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); 1002 acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT);
1007 acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); 1003 acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON);
1008 } else {
1009 acpi_enable_all_runtime_gpes();
1010 } 1004 }
1011} 1005}
1012 1006
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 5847364f25d9..b610816eb887 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -196,8 +196,10 @@ struct device_link *device_link_add(struct device *consumer,
196 } 196 }
197 197
198 list_for_each_entry(link, &supplier->links.consumers, s_node) 198 list_for_each_entry(link, &supplier->links.consumers, s_node)
199 if (link->consumer == consumer) 199 if (link->consumer == consumer) {
200 kref_get(&link->kref);
200 goto out; 201 goto out;
202 }
201 203
202 link = kzalloc(sizeof(*link), GFP_KERNEL); 204 link = kzalloc(sizeof(*link), GFP_KERNEL);
203 if (!link) 205 if (!link)
@@ -222,6 +224,7 @@ struct device_link *device_link_add(struct device *consumer,
222 link->consumer = consumer; 224 link->consumer = consumer;
223 INIT_LIST_HEAD(&link->c_node); 225 INIT_LIST_HEAD(&link->c_node);
224 link->flags = flags; 226 link->flags = flags;
227 kref_init(&link->kref);
225 228
226 /* Determine the initial link state. */ 229 /* Determine the initial link state. */
227 if (flags & DL_FLAG_STATELESS) { 230 if (flags & DL_FLAG_STATELESS) {
@@ -292,8 +295,10 @@ static void __device_link_free_srcu(struct rcu_head *rhead)
292 device_link_free(container_of(rhead, struct device_link, rcu_head)); 295 device_link_free(container_of(rhead, struct device_link, rcu_head));
293} 296}
294 297
295static void __device_link_del(struct device_link *link) 298static void __device_link_del(struct kref *kref)
296{ 299{
300 struct device_link *link = container_of(kref, struct device_link, kref);
301
297 dev_info(link->consumer, "Dropping the link to %s\n", 302 dev_info(link->consumer, "Dropping the link to %s\n",
298 dev_name(link->supplier)); 303 dev_name(link->supplier));
299 304
@@ -305,8 +310,10 @@ static void __device_link_del(struct device_link *link)
305 call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu); 310 call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);
306} 311}
307#else /* !CONFIG_SRCU */ 312#else /* !CONFIG_SRCU */
308static void __device_link_del(struct device_link *link) 313static void __device_link_del(struct kref *kref)
309{ 314{
315 struct device_link *link = container_of(kref, struct device_link, kref);
316
310 dev_info(link->consumer, "Dropping the link to %s\n", 317 dev_info(link->consumer, "Dropping the link to %s\n",
311 dev_name(link->supplier)); 318 dev_name(link->supplier));
312 319
@@ -324,13 +331,15 @@ static void __device_link_del(struct device_link *link)
324 * @link: Device link to delete. 331 * @link: Device link to delete.
325 * 332 *
326 * The caller must ensure proper synchronization of this function with runtime 333 * The caller must ensure proper synchronization of this function with runtime
327 * PM. 334 * PM. If the link was added multiple times, it needs to be deleted as often.
335 * Care is required for hotplugged devices: Their links are purged on removal
336 * and calling device_link_del() is then no longer allowed.
328 */ 337 */
329void device_link_del(struct device_link *link) 338void device_link_del(struct device_link *link)
330{ 339{
331 device_links_write_lock(); 340 device_links_write_lock();
332 device_pm_lock(); 341 device_pm_lock();
333 __device_link_del(link); 342 kref_put(&link->kref, __device_link_del);
334 device_pm_unlock(); 343 device_pm_unlock();
335 device_links_write_unlock(); 344 device_links_write_unlock();
336} 345}
@@ -444,7 +453,7 @@ static void __device_links_no_driver(struct device *dev)
444 continue; 453 continue;
445 454
446 if (link->flags & DL_FLAG_AUTOREMOVE) 455 if (link->flags & DL_FLAG_AUTOREMOVE)
447 __device_link_del(link); 456 kref_put(&link->kref, __device_link_del);
448 else if (link->status != DL_STATE_SUPPLIER_UNBIND) 457 else if (link->status != DL_STATE_SUPPLIER_UNBIND)
449 WRITE_ONCE(link->status, DL_STATE_AVAILABLE); 458 WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
450 } 459 }
@@ -597,13 +606,13 @@ static void device_links_purge(struct device *dev)
597 606
598 list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) { 607 list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) {
599 WARN_ON(link->status == DL_STATE_ACTIVE); 608 WARN_ON(link->status == DL_STATE_ACTIVE);
600 __device_link_del(link); 609 __device_link_del(&link->kref);
601 } 610 }
602 611
603 list_for_each_entry_safe_reverse(link, ln, &dev->links.consumers, s_node) { 612 list_for_each_entry_safe_reverse(link, ln, &dev->links.consumers, s_node) {
604 WARN_ON(link->status != DL_STATE_DORMANT && 613 WARN_ON(link->status != DL_STATE_DORMANT &&
605 link->status != DL_STATE_NONE); 614 link->status != DL_STATE_NONE);
606 __device_link_del(link); 615 __device_link_del(&link->kref);
607 } 616 }
608 617
609 device_links_write_unlock(); 618 device_links_write_unlock();
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 21244c53e377..86e67e70b509 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -31,6 +31,7 @@ struct wake_irq {
31 struct device *dev; 31 struct device *dev;
32 unsigned int status; 32 unsigned int status;
33 int irq; 33 int irq;
34 const char *name;
34}; 35};
35 36
36extern void dev_pm_arm_wake_irq(struct wake_irq *wirq); 37extern void dev_pm_arm_wake_irq(struct wake_irq *wirq);
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
index 6637fc319269..b8fa5c0f2d13 100644
--- a/drivers/base/power/wakeirq.c
+++ b/drivers/base/power/wakeirq.c
@@ -112,6 +112,7 @@ void dev_pm_clear_wake_irq(struct device *dev)
112 free_irq(wirq->irq, wirq); 112 free_irq(wirq->irq, wirq);
113 wirq->status &= ~WAKE_IRQ_DEDICATED_MASK; 113 wirq->status &= ~WAKE_IRQ_DEDICATED_MASK;
114 } 114 }
115 kfree(wirq->name);
115 kfree(wirq); 116 kfree(wirq);
116} 117}
117EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq); 118EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq);
@@ -184,6 +185,12 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
184 if (!wirq) 185 if (!wirq)
185 return -ENOMEM; 186 return -ENOMEM;
186 187
188 wirq->name = kasprintf(GFP_KERNEL, "%s:wakeup", dev_name(dev));
189 if (!wirq->name) {
190 err = -ENOMEM;
191 goto err_free;
192 }
193
187 wirq->dev = dev; 194 wirq->dev = dev;
188 wirq->irq = irq; 195 wirq->irq = irq;
189 irq_set_status_flags(irq, IRQ_NOAUTOEN); 196 irq_set_status_flags(irq, IRQ_NOAUTOEN);
@@ -196,9 +203,9 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
196 * so we use a threaded irq. 203 * so we use a threaded irq.
197 */ 204 */
198 err = request_threaded_irq(irq, NULL, handle_threaded_wake_irq, 205 err = request_threaded_irq(irq, NULL, handle_threaded_wake_irq,
199 IRQF_ONESHOT, dev_name(dev), wirq); 206 IRQF_ONESHOT, wirq->name, wirq);
200 if (err) 207 if (err)
201 goto err_free; 208 goto err_free_name;
202 209
203 err = dev_pm_attach_wake_irq(dev, irq, wirq); 210 err = dev_pm_attach_wake_irq(dev, irq, wirq);
204 if (err) 211 if (err)
@@ -210,6 +217,8 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
210 217
211err_free_irq: 218err_free_irq:
212 free_irq(irq, wirq); 219 free_irq(irq, wirq);
220err_free_name:
221 kfree(wirq->name);
213err_free: 222err_free:
214 kfree(wirq); 223 kfree(wirq);
215 224
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index fb586e09682d..833b5f41f596 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -45,6 +45,7 @@ config ARM_DT_BL_CPUFREQ
45config ARM_SCPI_CPUFREQ 45config ARM_SCPI_CPUFREQ
46 tristate "SCPI based CPUfreq driver" 46 tristate "SCPI based CPUfreq driver"
47 depends on ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI 47 depends on ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
48 depends on !CPU_THERMAL || THERMAL
48 help 49 help
49 This adds the CPUfreq driver support for ARM platforms using SCPI 50 This adds the CPUfreq driver support for ARM platforms using SCPI
50 protocol for CPU power management. 51 protocol for CPU power management.
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index d0c34df0529c..9449657d72f0 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -794,15 +794,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
794 valid_states++; 794 valid_states++;
795 } 795 }
796 freq_table[valid_states].frequency = CPUFREQ_TABLE_END; 796 freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
797 policy->freq_table = freq_table;
797 perf->state = 0; 798 perf->state = 0;
798 799
799 result = cpufreq_table_validate_and_show(policy, freq_table);
800 if (result)
801 goto err_freqfree;
802
803 if (perf->states[0].core_frequency * 1000 != policy->cpuinfo.max_freq)
804 pr_warn(FW_WARN "P-state 0 is not max freq\n");
805
806 switch (perf->control_register.space_id) { 800 switch (perf->control_register.space_id) {
807 case ACPI_ADR_SPACE_SYSTEM_IO: 801 case ACPI_ADR_SPACE_SYSTEM_IO:
808 /* 802 /*
@@ -842,8 +836,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
842 836
843 return result; 837 return result;
844 838
845err_freqfree:
846 kfree(freq_table);
847err_unreg: 839err_unreg:
848 acpi_processor_unregister_performance(cpu); 840 acpi_processor_unregister_performance(cpu);
849err_free_mask: 841err_free_mask:
@@ -871,6 +863,15 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
871 return 0; 863 return 0;
872} 864}
873 865
866static void acpi_cpufreq_cpu_ready(struct cpufreq_policy *policy)
867{
868 struct acpi_processor_performance *perf = per_cpu_ptr(acpi_perf_data,
869 policy->cpu);
870
871 if (perf->states[0].core_frequency * 1000 != policy->cpuinfo.max_freq)
872 pr_warn(FW_WARN "P-state 0 is not max freq\n");
873}
874
874static int acpi_cpufreq_resume(struct cpufreq_policy *policy) 875static int acpi_cpufreq_resume(struct cpufreq_policy *policy)
875{ 876{
876 struct acpi_cpufreq_data *data = policy->driver_data; 877 struct acpi_cpufreq_data *data = policy->driver_data;
@@ -898,6 +899,7 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
898 .bios_limit = acpi_processor_get_bios_limit, 899 .bios_limit = acpi_processor_get_bios_limit,
899 .init = acpi_cpufreq_cpu_init, 900 .init = acpi_cpufreq_cpu_init,
900 .exit = acpi_cpufreq_cpu_exit, 901 .exit = acpi_cpufreq_cpu_exit,
902 .ready = acpi_cpufreq_cpu_ready,
901 .resume = acpi_cpufreq_resume, 903 .resume = acpi_cpufreq_resume,
902 .name = "acpi-cpufreq", 904 .name = "acpi-cpufreq",
903 .attr = acpi_cpufreq_attr, 905 .attr = acpi_cpufreq_attr,
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index c56b57dcfda5..1d7ef5fc1977 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -483,14 +483,7 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
483 if (ret) 483 if (ret)
484 return ret; 484 return ret;
485 485
486 ret = cpufreq_table_validate_and_show(policy, freq_table[cur_cluster]); 486 policy->freq_table = freq_table[cur_cluster];
487 if (ret) {
488 dev_err(cpu_dev, "CPU %d, cluster: %d invalid freq table\n",
489 policy->cpu, cur_cluster);
490 put_cluster_clk_and_freq_table(cpu_dev, policy->cpus);
491 return ret;
492 }
493
494 policy->cpuinfo.transition_latency = 487 policy->cpuinfo.transition_latency =
495 arm_bL_ops->get_transition_latency(cpu_dev); 488 arm_bL_ops->get_transition_latency(cpu_dev);
496 489
diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c
index 7281a2c19c36..6cdac1aaf23c 100644
--- a/drivers/cpufreq/brcmstb-avs-cpufreq.c
+++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c
@@ -902,11 +902,7 @@ static int brcm_avs_cpufreq_init(struct cpufreq_policy *policy)
902 return ret; 902 return ret;
903 } 903 }
904 904
905 ret = cpufreq_table_validate_and_show(policy, freq_table); 905 policy->freq_table = freq_table;
906 if (ret) {
907 dev_err(dev, "invalid frequency table: %d\n", ret);
908 return ret;
909 }
910 906
911 /* All cores share the same clock and thus the same policy. */ 907 /* All cores share the same clock and thus the same policy. */
912 cpumask_setall(policy->cpus); 908 cpumask_setall(policy->cpus);
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index a1c3025f9df7..8300a9fcb80c 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -20,6 +20,7 @@
20#include <linux/cpu.h> 20#include <linux/cpu.h>
21#include <linux/cpufreq.h> 21#include <linux/cpufreq.h>
22#include <linux/dmi.h> 22#include <linux/dmi.h>
23#include <linux/time.h>
23#include <linux/vmalloc.h> 24#include <linux/vmalloc.h>
24 25
25#include <asm/unaligned.h> 26#include <asm/unaligned.h>
@@ -162,6 +163,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
162 policy->cpuinfo.max_freq = cppc_dmi_max_khz; 163 policy->cpuinfo.max_freq = cppc_dmi_max_khz;
163 164
164 policy->cpuinfo.transition_latency = cppc_get_transition_latency(cpu_num); 165 policy->cpuinfo.transition_latency = cppc_get_transition_latency(cpu_num);
166 policy->transition_delay_us = cppc_get_transition_latency(cpu_num) /
167 NSEC_PER_USEC;
165 policy->shared_type = cpu->shared_type; 168 policy->shared_type = cpu->shared_type;
166 169
167 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) 170 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
@@ -230,8 +233,13 @@ static int __init cppc_cpufreq_init(void)
230 return ret; 233 return ret;
231 234
232out: 235out:
233 for_each_possible_cpu(i) 236 for_each_possible_cpu(i) {
234 kfree(all_cpu_data[i]); 237 cpu = all_cpu_data[i];
238 if (!cpu)
239 break;
240 free_cpumask_var(cpu->shared_cpu_map);
241 kfree(cpu);
242 }
235 243
236 kfree(all_cpu_data); 244 kfree(all_cpu_data);
237 return -ENODEV; 245 return -ENODEV;
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index de3d104c25d7..190ea0dccb79 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -258,16 +258,10 @@ static int cpufreq_init(struct cpufreq_policy *policy)
258 priv->cpu_dev = cpu_dev; 258 priv->cpu_dev = cpu_dev;
259 policy->driver_data = priv; 259 policy->driver_data = priv;
260 policy->clk = cpu_clk; 260 policy->clk = cpu_clk;
261 policy->freq_table = freq_table;
261 262
262 policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000; 263 policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000;
263 264
264 ret = cpufreq_table_validate_and_show(policy, freq_table);
265 if (ret) {
266 dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__,
267 ret);
268 goto out_free_cpufreq_table;
269 }
270
271 /* Support turbo/boost mode */ 265 /* Support turbo/boost mode */
272 if (policy_has_boost_freq(policy)) { 266 if (policy_has_boost_freq(policy)) {
273 /* This gets disabled by core on driver unregister */ 267 /* This gets disabled by core on driver unregister */
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index de33ebf008ad..075d18f6ba7a 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -178,14 +178,7 @@ int cpufreq_generic_init(struct cpufreq_policy *policy,
178 struct cpufreq_frequency_table *table, 178 struct cpufreq_frequency_table *table,
179 unsigned int transition_latency) 179 unsigned int transition_latency)
180{ 180{
181 int ret; 181 policy->freq_table = table;
182
183 ret = cpufreq_table_validate_and_show(policy, table);
184 if (ret) {
185 pr_err("%s: invalid frequency table: %d\n", __func__, ret);
186 return ret;
187 }
188
189 policy->cpuinfo.transition_latency = transition_latency; 182 policy->cpuinfo.transition_latency = transition_latency;
190 183
191 /* 184 /*
@@ -1219,6 +1212,10 @@ static int cpufreq_online(unsigned int cpu)
1219 goto out_free_policy; 1212 goto out_free_policy;
1220 } 1213 }
1221 1214
1215 ret = cpufreq_table_validate_and_sort(policy);
1216 if (ret)
1217 goto out_exit_policy;
1218
1222 down_write(&policy->rwsem); 1219 down_write(&policy->rwsem);
1223 1220
1224 if (new_policy) { 1221 if (new_policy) {
@@ -1249,7 +1246,7 @@ static int cpufreq_online(unsigned int cpu)
1249 policy->cur = cpufreq_driver->get(policy->cpu); 1246 policy->cur = cpufreq_driver->get(policy->cpu);
1250 if (!policy->cur) { 1247 if (!policy->cur) {
1251 pr_err("%s: ->get() failed\n", __func__); 1248 pr_err("%s: ->get() failed\n", __func__);
1252 goto out_exit_policy; 1249 goto out_destroy_policy;
1253 } 1250 }
1254 } 1251 }
1255 1252
@@ -1296,7 +1293,7 @@ static int cpufreq_online(unsigned int cpu)
1296 if (new_policy) { 1293 if (new_policy) {
1297 ret = cpufreq_add_dev_interface(policy); 1294 ret = cpufreq_add_dev_interface(policy);
1298 if (ret) 1295 if (ret)
1299 goto out_exit_policy; 1296 goto out_destroy_policy;
1300 1297
1301 cpufreq_stats_create_table(policy); 1298 cpufreq_stats_create_table(policy);
1302 1299
@@ -1311,7 +1308,7 @@ static int cpufreq_online(unsigned int cpu)
1311 __func__, cpu, ret); 1308 __func__, cpu, ret);
1312 /* cpufreq_policy_free() will notify based on this */ 1309 /* cpufreq_policy_free() will notify based on this */
1313 new_policy = false; 1310 new_policy = false;
1314 goto out_exit_policy; 1311 goto out_destroy_policy;
1315 } 1312 }
1316 1313
1317 up_write(&policy->rwsem); 1314 up_write(&policy->rwsem);
@@ -1326,15 +1323,16 @@ static int cpufreq_online(unsigned int cpu)
1326 1323
1327 return 0; 1324 return 0;
1328 1325
1329out_exit_policy: 1326out_destroy_policy:
1327 for_each_cpu(j, policy->real_cpus)
1328 remove_cpu_dev_symlink(policy, get_cpu_device(j));
1329
1330 up_write(&policy->rwsem); 1330 up_write(&policy->rwsem);
1331 1331
1332out_exit_policy:
1332 if (cpufreq_driver->exit) 1333 if (cpufreq_driver->exit)
1333 cpufreq_driver->exit(policy); 1334 cpufreq_driver->exit(policy);
1334 1335
1335 for_each_cpu(j, policy->real_cpus)
1336 remove_cpu_dev_symlink(policy, get_cpu_device(j));
1337
1338out_free_policy: 1336out_free_policy:
1339 cpufreq_policy_free(policy); 1337 cpufreq_policy_free(policy);
1340 return ret; 1338 return ret;
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
index cdf097b29862..60bea302abbe 100644
--- a/drivers/cpufreq/e_powersaver.c
+++ b/drivers/cpufreq/e_powersaver.c
@@ -184,7 +184,6 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
184 struct cpuinfo_x86 *c = &cpu_data(0); 184 struct cpuinfo_x86 *c = &cpu_data(0);
185 struct cpufreq_frequency_table *f_table; 185 struct cpufreq_frequency_table *f_table;
186 int k, step, voltage; 186 int k, step, voltage;
187 int ret;
188 int states; 187 int states;
189#if IS_ENABLED(CONFIG_ACPI_PROCESSOR) 188#if IS_ENABLED(CONFIG_ACPI_PROCESSOR)
190 unsigned int limit; 189 unsigned int limit;
@@ -359,12 +358,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
359 } 358 }
360 359
361 policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */ 360 policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */
362 361 policy->freq_table = &centaur->freq_table[0];
363 ret = cpufreq_table_validate_and_show(policy, &centaur->freq_table[0]);
364 if (ret) {
365 kfree(centaur);
366 return ret;
367 }
368 362
369 return 0; 363 return 0;
370} 364}
diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c
index 45e2ca62515e..03419f064752 100644
--- a/drivers/cpufreq/elanfreq.c
+++ b/drivers/cpufreq/elanfreq.c
@@ -165,7 +165,8 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
165 if (pos->frequency > max_freq) 165 if (pos->frequency > max_freq)
166 pos->frequency = CPUFREQ_ENTRY_INVALID; 166 pos->frequency = CPUFREQ_ENTRY_INVALID;
167 167
168 return cpufreq_table_validate_and_show(policy, elanfreq_table); 168 policy->freq_table = elanfreq_table;
169 return 0;
169} 170}
170 171
171 172
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 6d007f824ca7..10e119ae66dd 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -362,10 +362,24 @@ int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
362 return ret; 362 return ret;
363 363
364 policy->freq_table = table; 364 policy->freq_table = table;
365 return set_freq_table_sorted(policy); 365 return 0;
366} 366}
367EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show); 367EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
368 368
369int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy)
370{
371 int ret;
372
373 if (!policy->freq_table)
374 return 0;
375
376 ret = cpufreq_frequency_table_cpuinfo(policy, policy->freq_table);
377 if (ret)
378 return ret;
379
380 return set_freq_table_sorted(policy);
381}
382
369MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); 383MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
370MODULE_DESCRIPTION("CPUfreq frequency table helpers"); 384MODULE_DESCRIPTION("CPUfreq frequency table helpers");
371MODULE_LICENSE("GPL"); 385MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c
index a757c0a1e7b5..7974a2fdb760 100644
--- a/drivers/cpufreq/ia64-acpi-cpufreq.c
+++ b/drivers/cpufreq/ia64-acpi-cpufreq.c
@@ -270,10 +270,7 @@ acpi_cpufreq_cpu_init (
270 } 270 }
271 } 271 }
272 272
273 result = cpufreq_table_validate_and_show(policy, freq_table); 273 policy->freq_table = freq_table;
274 if (result) {
275 goto err_freqfree;
276 }
277 274
278 /* notify BIOS that we exist */ 275 /* notify BIOS that we exist */
279 acpi_processor_notify_smm(THIS_MODULE); 276 acpi_processor_notify_smm(THIS_MODULE);
@@ -296,8 +293,6 @@ acpi_cpufreq_cpu_init (
296 293
297 return (result); 294 return (result);
298 295
299 err_freqfree:
300 kfree(freq_table);
301 err_unreg: 296 err_unreg:
302 acpi_processor_unregister_performance(cpu); 297 acpi_processor_unregister_performance(cpu);
303 err_free: 298 err_free:
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index ff67859948b3..83cf631fc9bc 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -52,6 +52,7 @@ static struct clk_bulk_data clks[] = {
52static struct device *cpu_dev; 52static struct device *cpu_dev;
53static bool free_opp; 53static bool free_opp;
54static struct cpufreq_frequency_table *freq_table; 54static struct cpufreq_frequency_table *freq_table;
55static unsigned int max_freq;
55static unsigned int transition_latency; 56static unsigned int transition_latency;
56 57
57static u32 *imx6_soc_volt; 58static u32 *imx6_soc_volt;
@@ -196,7 +197,7 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
196 197
197 policy->clk = clks[ARM].clk; 198 policy->clk = clks[ARM].clk;
198 ret = cpufreq_generic_init(policy, freq_table, transition_latency); 199 ret = cpufreq_generic_init(policy, freq_table, transition_latency);
199 policy->suspend_freq = policy->max; 200 policy->suspend_freq = max_freq;
200 201
201 return ret; 202 return ret;
202} 203}
@@ -437,12 +438,12 @@ soc_opp_out:
437 * freq_table initialised from OPP is therefore sorted in the 438 * freq_table initialised from OPP is therefore sorted in the
438 * same order. 439 * same order.
439 */ 440 */
441 max_freq = freq_table[--num].frequency;
440 opp = dev_pm_opp_find_freq_exact(cpu_dev, 442 opp = dev_pm_opp_find_freq_exact(cpu_dev,
441 freq_table[0].frequency * 1000, true); 443 freq_table[0].frequency * 1000, true);
442 min_volt = dev_pm_opp_get_voltage(opp); 444 min_volt = dev_pm_opp_get_voltage(opp);
443 dev_pm_opp_put(opp); 445 dev_pm_opp_put(opp);
444 opp = dev_pm_opp_find_freq_exact(cpu_dev, 446 opp = dev_pm_opp_find_freq_exact(cpu_dev, max_freq * 1000, true);
445 freq_table[--num].frequency * 1000, true);
446 max_volt = dev_pm_opp_get_voltage(opp); 447 max_volt = dev_pm_opp_get_voltage(opp);
447 dev_pm_opp_put(opp); 448 dev_pm_opp_put(opp);
448 449
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index f730b6528c18..61a4c5b08219 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -895,8 +895,9 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy)
895 longhaul_setup_voltagescaling(); 895 longhaul_setup_voltagescaling();
896 896
897 policy->transition_delay_us = 200000; /* usec */ 897 policy->transition_delay_us = 200000; /* usec */
898 policy->freq_table = longhaul_table;
898 899
899 return cpufreq_table_validate_and_show(policy, longhaul_table); 900 return 0;
900} 901}
901 902
902static struct cpufreq_driver longhaul_driver = { 903static struct cpufreq_driver longhaul_driver = {
diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
index 8c04dddd3c28..eb8920d39818 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -460,21 +460,12 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
460 return ret; 460 return ret;
461 } 461 }
462 462
463 ret = cpufreq_table_validate_and_show(policy, freq_table);
464 if (ret) {
465 pr_err("%s: invalid frequency table: %d\n", __func__, ret);
466 goto out_free_cpufreq_table;
467 }
468
469 cpumask_copy(policy->cpus, &info->cpus); 463 cpumask_copy(policy->cpus, &info->cpus);
464 policy->freq_table = freq_table;
470 policy->driver_data = info; 465 policy->driver_data = info;
471 policy->clk = info->cpu_clk; 466 policy->clk = info->cpu_clk;
472 467
473 return 0; 468 return 0;
474
475out_free_cpufreq_table:
476 dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table);
477 return ret;
478} 469}
479 470
480static int mtk_cpufreq_exit(struct cpufreq_policy *policy) 471static int mtk_cpufreq_exit(struct cpufreq_policy *policy)
@@ -578,7 +569,7 @@ static int __init mtk_cpufreq_driver_init(void)
578 match = of_match_node(mtk_cpufreq_machines, np); 569 match = of_match_node(mtk_cpufreq_machines, np);
579 of_node_put(np); 570 of_node_put(np);
580 if (!match) { 571 if (!match) {
581 pr_warn("Machine is not compatible with mtk-cpufreq\n"); 572 pr_debug("Machine is not compatible with mtk-cpufreq\n");
582 return -ENODEV; 573 return -ENODEV;
583 } 574 }
584 575
diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c
index a25741b1281b..911206243050 100644
--- a/drivers/cpufreq/p4-clockmod.c
+++ b/drivers/cpufreq/p4-clockmod.c
@@ -202,8 +202,9 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
202 /* the transition latency is set to be 1 higher than the maximum 202 /* the transition latency is set to be 1 higher than the maximum
203 * transition latency of the ondemand governor */ 203 * transition latency of the ondemand governor */
204 policy->cpuinfo.transition_latency = 10000001; 204 policy->cpuinfo.transition_latency = 10000001;
205 policy->freq_table = &p4clockmod_table[0];
205 206
206 return cpufreq_table_validate_and_show(policy, &p4clockmod_table[0]); 207 return 0;
207} 208}
208 209
209 210
diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c
index dedd2568e852..8a8ea68611a8 100644
--- a/drivers/cpufreq/powernow-k6.c
+++ b/drivers/cpufreq/powernow-k6.c
@@ -214,8 +214,9 @@ have_busfreq:
214 214
215 /* cpuinfo and default policy values */ 215 /* cpuinfo and default policy values */
216 policy->cpuinfo.transition_latency = 500000; 216 policy->cpuinfo.transition_latency = 500000;
217 policy->freq_table = clock_ratio;
217 218
218 return cpufreq_table_validate_and_show(policy, clock_ratio); 219 return 0;
219} 220}
220 221
221 222
diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c
index 302e9ce793a0..d6cb052b0a75 100644
--- a/drivers/cpufreq/powernow-k7.c
+++ b/drivers/cpufreq/powernow-k7.c
@@ -639,8 +639,9 @@ static int powernow_cpu_init(struct cpufreq_policy *policy)
639 639
640 policy->cpuinfo.transition_latency = 640 policy->cpuinfo.transition_latency =
641 cpufreq_scale(2000000UL, fsb, latency); 641 cpufreq_scale(2000000UL, fsb, latency);
642 policy->freq_table = powernow_table;
642 643
643 return cpufreq_table_validate_and_show(policy, powernow_table); 644 return 0;
644} 645}
645 646
646static int powernow_cpu_exit(struct cpufreq_policy *policy) 647static int powernow_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index b01e31db5f83..fb77b39a4ce3 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -122,14 +122,12 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data)
122static void count_off_irt(struct powernow_k8_data *data) 122static void count_off_irt(struct powernow_k8_data *data)
123{ 123{
124 udelay((1 << data->irt) * 10); 124 udelay((1 << data->irt) * 10);
125 return;
126} 125}
127 126
128/* the voltage stabilization time */ 127/* the voltage stabilization time */
129static void count_off_vst(struct powernow_k8_data *data) 128static void count_off_vst(struct powernow_k8_data *data)
130{ 129{
131 udelay(data->vstable * VST_UNITS_20US); 130 udelay(data->vstable * VST_UNITS_20US);
132 return;
133} 131}
134 132
135/* need to init the control msr to a safe value (for each cpu) */ 133/* need to init the control msr to a safe value (for each cpu) */
@@ -591,10 +589,8 @@ static int fill_powernow_table(struct powernow_k8_data *data,
591 589
592 powernow_table = kzalloc((sizeof(*powernow_table) 590 powernow_table = kzalloc((sizeof(*powernow_table)
593 * (data->numps + 1)), GFP_KERNEL); 591 * (data->numps + 1)), GFP_KERNEL);
594 if (!powernow_table) { 592 if (!powernow_table)
595 pr_err("powernow_table memory alloc failure\n");
596 return -ENOMEM; 593 return -ENOMEM;
597 }
598 594
599 for (j = 0; j < data->numps; j++) { 595 for (j = 0; j < data->numps; j++) {
600 int freq; 596 int freq;
@@ -760,10 +756,8 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
760 /* fill in data->powernow_table */ 756 /* fill in data->powernow_table */
761 powernow_table = kzalloc((sizeof(*powernow_table) 757 powernow_table = kzalloc((sizeof(*powernow_table)
762 * (data->acpi_data.state_count + 1)), GFP_KERNEL); 758 * (data->acpi_data.state_count + 1)), GFP_KERNEL);
763 if (!powernow_table) { 759 if (!powernow_table)
764 pr_debug("powernow_table memory alloc failure\n");
765 goto err_out; 760 goto err_out;
766 }
767 761
768 /* fill in data */ 762 /* fill in data */
769 data->numps = data->acpi_data.state_count; 763 data->numps = data->acpi_data.state_count;
@@ -1042,10 +1036,8 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
1042 return -ENODEV; 1036 return -ENODEV;
1043 1037
1044 data = kzalloc(sizeof(*data), GFP_KERNEL); 1038 data = kzalloc(sizeof(*data), GFP_KERNEL);
1045 if (!data) { 1039 if (!data)
1046 pr_err("unable to alloc powernow_k8_data\n");
1047 return -ENOMEM; 1040 return -ENOMEM;
1048 }
1049 1041
1050 data->cpu = pol->cpu; 1042 data->cpu = pol->cpu;
1051 1043
@@ -1084,15 +1076,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
1084 1076
1085 cpumask_copy(pol->cpus, topology_core_cpumask(pol->cpu)); 1077 cpumask_copy(pol->cpus, topology_core_cpumask(pol->cpu));
1086 data->available_cores = pol->cpus; 1078 data->available_cores = pol->cpus;
1087 1079 pol->freq_table = data->powernow_table;
1088 /* min/max the cpu is capable of */
1089 if (cpufreq_table_validate_and_show(pol, data->powernow_table)) {
1090 pr_err(FW_BUG "invalid powernow_table\n");
1091 powernow_k8_cpu_exit_acpi(data);
1092 kfree(data->powernow_table);
1093 kfree(data);
1094 return -EINVAL;
1095 }
1096 1080
1097 pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n", 1081 pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
1098 data->currfid, data->currvid); 1082 data->currfid, data->currvid);
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 29cdec198657..0591874856d3 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -812,7 +812,7 @@ gpstates_done:
812 812
813static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy) 813static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
814{ 814{
815 int base, i, ret; 815 int base, i;
816 struct kernfs_node *kn; 816 struct kernfs_node *kn;
817 struct global_pstate_info *gpstates; 817 struct global_pstate_info *gpstates;
818 818
@@ -848,15 +848,10 @@ static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
848 gpstates->timer.expires = jiffies + 848 gpstates->timer.expires = jiffies +
849 msecs_to_jiffies(GPSTATE_TIMER_INTERVAL); 849 msecs_to_jiffies(GPSTATE_TIMER_INTERVAL);
850 spin_lock_init(&gpstates->gpstate_lock); 850 spin_lock_init(&gpstates->gpstate_lock);
851 ret = cpufreq_table_validate_and_show(policy, powernv_freqs);
852
853 if (ret < 0) {
854 kfree(policy->driver_data);
855 return ret;
856 }
857 851
852 policy->freq_table = powernv_freqs;
858 policy->fast_switch_possible = true; 853 policy->fast_switch_possible = true;
859 return ret; 854 return 0;
860} 855}
861 856
862static int powernv_cpufreq_cpu_exit(struct cpufreq_policy *policy) 857static int powernv_cpufreq_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c
index 5a4c5a639f61..41a0f0be3f9f 100644
--- a/drivers/cpufreq/ppc_cbe_cpufreq.c
+++ b/drivers/cpufreq/ppc_cbe_cpufreq.c
@@ -121,9 +121,8 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
121 cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu)); 121 cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu));
122#endif 122#endif
123 123
124 /* this ensures that policy->cpuinfo_min 124 policy->freq_table = cbe_freqs;
125 * and policy->cpuinfo_max are set correctly */ 125 return 0;
126 return cpufreq_table_validate_and_show(policy, cbe_freqs);
127} 126}
128 127
129static int cbe_cpufreq_target(struct cpufreq_policy *policy, 128static int cbe_cpufreq_target(struct cpufreq_policy *policy,
diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c
index 06b024a3e474..46254e583982 100644
--- a/drivers/cpufreq/pxa2xx-cpufreq.c
+++ b/drivers/cpufreq/pxa2xx-cpufreq.c
@@ -292,10 +292,10 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy)
292 pr_info("using %s frequency table\n", 292 pr_info("using %s frequency table\n",
293 pxa255_turbo_table ? "turbo" : "run"); 293 pxa255_turbo_table ? "turbo" : "run");
294 294
295 cpufreq_table_validate_and_show(policy, pxa255_freq_table); 295 policy->freq_table = pxa255_freq_table;
296 } 296 }
297 else if (cpu_is_pxa27x()) { 297 else if (cpu_is_pxa27x()) {
298 cpufreq_table_validate_and_show(policy, pxa27x_freq_table); 298 policy->freq_table = pxa27x_freq_table;
299 } 299 }
300 300
301 pr_info("frequency change support initialized\n"); 301 pr_info("frequency change support initialized\n");
diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c
index a01275900389..7acc7fa4536d 100644
--- a/drivers/cpufreq/pxa3xx-cpufreq.c
+++ b/drivers/cpufreq/pxa3xx-cpufreq.c
@@ -108,7 +108,9 @@ static int setup_freqs_table(struct cpufreq_policy *policy,
108 pxa3xx_freqs_num = num; 108 pxa3xx_freqs_num = num;
109 pxa3xx_freqs_table = table; 109 pxa3xx_freqs_table = table;
110 110
111 return cpufreq_table_validate_and_show(policy, table); 111 policy->freq_table = table;
112
113 return 0;
112} 114}
113 115
114static void __update_core_freq(struct pxa3xx_freq_info *info) 116static void __update_core_freq(struct pxa3xx_freq_info *info)
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 0562761a3dec..3d773f64b4df 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -165,7 +165,7 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table,
165static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) 165static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
166{ 166{
167 struct device_node *np; 167 struct device_node *np;
168 int i, count, ret; 168 int i, count;
169 u32 freq; 169 u32 freq;
170 struct clk *clk; 170 struct clk *clk;
171 const struct clk_hw *hwclk; 171 const struct clk_hw *hwclk;
@@ -192,16 +192,12 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
192 count = clk_hw_get_num_parents(hwclk); 192 count = clk_hw_get_num_parents(hwclk);
193 193
194 data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL); 194 data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
195 if (!data->pclk) { 195 if (!data->pclk)
196 pr_err("%s: no memory\n", __func__);
197 goto err_nomem2; 196 goto err_nomem2;
198 }
199 197
200 table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL); 198 table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
201 if (!table) { 199 if (!table)
202 pr_err("%s: no memory\n", __func__);
203 goto err_pclk; 200 goto err_pclk;
204 }
205 201
206 for (i = 0; i < count; i++) { 202 for (i = 0; i < count; i++) {
207 clk = clk_hw_get_parent_by_index(hwclk, i)->clk; 203 clk = clk_hw_get_parent_by_index(hwclk, i)->clk;
@@ -213,14 +209,7 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
213 freq_table_redup(table, count); 209 freq_table_redup(table, count);
214 freq_table_sort(table, count); 210 freq_table_sort(table, count);
215 table[i].frequency = CPUFREQ_TABLE_END; 211 table[i].frequency = CPUFREQ_TABLE_END;
216 212 policy->freq_table = table;
217 /* set the min and max frequency properly */
218 ret = cpufreq_table_validate_and_show(policy, table);
219 if (ret) {
220 pr_err("invalid frequency table: %d\n", ret);
221 goto err_nomem1;
222 }
223
224 data->table = table; 213 data->table = table;
225 214
226 /* update ->cpus if we have cluster, no harm if not */ 215 /* update ->cpus if we have cluster, no harm if not */
@@ -236,8 +225,6 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
236 225
237 return 0; 226 return 0;
238 227
239err_nomem1:
240 kfree(table);
241err_pclk: 228err_pclk:
242 kfree(data->pclk); 229 kfree(data->pclk);
243err_nomem2: 230err_nomem2:
diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c
index 6bebc1f9f55a..909bd6e27639 100644
--- a/drivers/cpufreq/s3c24xx-cpufreq.c
+++ b/drivers/cpufreq/s3c24xx-cpufreq.c
@@ -351,11 +351,8 @@ struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name)
351static int s3c_cpufreq_init(struct cpufreq_policy *policy) 351static int s3c_cpufreq_init(struct cpufreq_policy *policy)
352{ 352{
353 policy->clk = clk_arm; 353 policy->clk = clk_arm;
354
355 policy->cpuinfo.transition_latency = cpu_cur.info->latency; 354 policy->cpuinfo.transition_latency = cpu_cur.info->latency;
356 355 policy->freq_table = ftab;
357 if (ftab)
358 return cpufreq_table_validate_and_show(policy, ftab);
359 356
360 return 0; 357 return 0;
361} 358}
@@ -479,10 +476,8 @@ int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board)
479 * initdata. */ 476 * initdata. */
480 477
481 ours = kzalloc(sizeof(*ours), GFP_KERNEL); 478 ours = kzalloc(sizeof(*ours), GFP_KERNEL);
482 if (ours == NULL) { 479 if (!ours)
483 pr_err("%s: no memory\n", __func__);
484 return -ENOMEM; 480 return -ENOMEM;
485 }
486 481
487 *ours = *board; 482 *ours = *board;
488 cpu_cur.board = ours; 483 cpu_cur.board = ours;
@@ -568,10 +563,8 @@ static int s3c_cpufreq_build_freq(void)
568 size++; 563 size++;
569 564
570 ftab = kzalloc(sizeof(*ftab) * size, GFP_KERNEL); 565 ftab = kzalloc(sizeof(*ftab) * size, GFP_KERNEL);
571 if (!ftab) { 566 if (!ftab)
572 pr_err("%s: no memory for tables\n", __func__);
573 return -ENOMEM; 567 return -ENOMEM;
574 }
575 568
576 ftab_size = size; 569 ftab_size = size;
577 570
diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c
index 4225501a4b78..abaa75e86148 100644
--- a/drivers/cpufreq/sc520_freq.c
+++ b/drivers/cpufreq/sc520_freq.c
@@ -83,8 +83,9 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
83 83
84 /* cpuinfo and default policy values */ 84 /* cpuinfo and default policy values */
85 policy->cpuinfo.transition_latency = 1000000; /* 1ms */ 85 policy->cpuinfo.transition_latency = 1000000; /* 1ms */
86 policy->freq_table = sc520_freq_table;
86 87
87 return cpufreq_table_validate_and_show(policy, sc520_freq_table); 88 return 0;
88} 89}
89 90
90 91
diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
index d300a163945f..87a98ec77773 100644
--- a/drivers/cpufreq/scpi-cpufreq.c
+++ b/drivers/cpufreq/scpi-cpufreq.c
@@ -158,13 +158,7 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy)
158 } 158 }
159 159
160 policy->driver_data = priv; 160 policy->driver_data = priv;
161 161 policy->freq_table = freq_table;
162 ret = cpufreq_table_validate_and_show(policy, freq_table);
163 if (ret) {
164 dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__,
165 ret);
166 goto out_put_clk;
167 }
168 162
169 /* scpi allows DVFS request for any domain from any CPU */ 163 /* scpi allows DVFS request for any domain from any CPU */
170 policy->dvfs_possible_from_any_cpu = true; 164 policy->dvfs_possible_from_any_cpu = true;
@@ -178,8 +172,6 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy)
178 policy->fast_switch_possible = false; 172 policy->fast_switch_possible = false;
179 return 0; 173 return 0;
180 174
181out_put_clk:
182 clk_put(priv->clk);
183out_free_cpufreq_table: 175out_free_cpufreq_table:
184 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); 176 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
185out_free_priv: 177out_free_priv:
diff --git a/drivers/cpufreq/sfi-cpufreq.c b/drivers/cpufreq/sfi-cpufreq.c
index 3779742f86e3..9767afe05da2 100644
--- a/drivers/cpufreq/sfi-cpufreq.c
+++ b/drivers/cpufreq/sfi-cpufreq.c
@@ -72,8 +72,9 @@ static int sfi_cpufreq_cpu_init(struct cpufreq_policy *policy)
72{ 72{
73 policy->shared_type = CPUFREQ_SHARED_TYPE_HW; 73 policy->shared_type = CPUFREQ_SHARED_TYPE_HW;
74 policy->cpuinfo.transition_latency = 100000; /* 100us */ 74 policy->cpuinfo.transition_latency = 100000; /* 100us */
75 policy->freq_table = freq_table;
75 76
76 return cpufreq_table_validate_and_show(policy, freq_table); 77 return 0;
77} 78}
78 79
79static struct cpufreq_driver sfi_cpufreq_driver = { 80static struct cpufreq_driver sfi_cpufreq_driver = {
diff --git a/drivers/cpufreq/sh-cpufreq.c b/drivers/cpufreq/sh-cpufreq.c
index 28893d435cf5..5096c0ab781b 100644
--- a/drivers/cpufreq/sh-cpufreq.c
+++ b/drivers/cpufreq/sh-cpufreq.c
@@ -122,11 +122,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
122 122
123 freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL; 123 freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL;
124 if (freq_table) { 124 if (freq_table) {
125 int result; 125 policy->freq_table = freq_table;
126
127 result = cpufreq_table_validate_and_show(policy, freq_table);
128 if (result)
129 return result;
130 } else { 126 } else {
131 dev_notice(dev, "no frequency table found, falling back " 127 dev_notice(dev, "no frequency table found, falling back "
132 "to rate rounding.\n"); 128 "to rate rounding.\n");
@@ -137,11 +133,6 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
137 (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; 133 (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
138 } 134 }
139 135
140 dev_info(dev, "CPU Frequencies - Minimum %u.%03u MHz, "
141 "Maximum %u.%03u MHz.\n",
142 policy->min / 1000, policy->min % 1000,
143 policy->max / 1000, policy->max % 1000);
144
145 return 0; 136 return 0;
146} 137}
147 138
@@ -155,6 +146,16 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy)
155 return 0; 146 return 0;
156} 147}
157 148
149static void sh_cpufreq_cpu_ready(struct cpufreq_policy *policy)
150{
151 struct device *dev = get_cpu_device(policy->cpu);
152
153 dev_info(dev, "CPU Frequencies - Minimum %u.%03u MHz, "
154 "Maximum %u.%03u MHz.\n",
155 policy->min / 1000, policy->min % 1000,
156 policy->max / 1000, policy->max % 1000);
157}
158
158static struct cpufreq_driver sh_cpufreq_driver = { 159static struct cpufreq_driver sh_cpufreq_driver = {
159 .name = "sh", 160 .name = "sh",
160 .flags = CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING, 161 .flags = CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING,
@@ -163,6 +164,7 @@ static struct cpufreq_driver sh_cpufreq_driver = {
163 .verify = sh_cpufreq_verify, 164 .verify = sh_cpufreq_verify,
164 .init = sh_cpufreq_cpu_init, 165 .init = sh_cpufreq_cpu_init,
165 .exit = sh_cpufreq_cpu_exit, 166 .exit = sh_cpufreq_cpu_exit,
167 .ready = sh_cpufreq_cpu_ready,
166 .attr = cpufreq_generic_attr, 168 .attr = cpufreq_generic_attr,
167}; 169};
168 170
diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c
index 90f33efee5fc..bbd1d1e166b8 100644
--- a/drivers/cpufreq/sparc-us2e-cpufreq.c
+++ b/drivers/cpufreq/sparc-us2e-cpufreq.c
@@ -292,8 +292,9 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
292 292
293 policy->cpuinfo.transition_latency = 0; 293 policy->cpuinfo.transition_latency = 0;
294 policy->cur = clock_tick; 294 policy->cur = clock_tick;
295 policy->freq_table = table;
295 296
296 return cpufreq_table_validate_and_show(policy, table); 297 return 0;
297} 298}
298 299
299static int us2e_freq_cpu_exit(struct cpufreq_policy *policy) 300static int us2e_freq_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c
index 30645b0118f9..51e3c6018e74 100644
--- a/drivers/cpufreq/sparc-us3-cpufreq.c
+++ b/drivers/cpufreq/sparc-us3-cpufreq.c
@@ -136,8 +136,9 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
136 136
137 policy->cpuinfo.transition_latency = 0; 137 policy->cpuinfo.transition_latency = 0;
138 policy->cur = clock_tick; 138 policy->cur = clock_tick;
139 policy->freq_table = table;
139 140
140 return cpufreq_table_validate_and_show(policy, table); 141 return 0;
141} 142}
142 143
143static int us3_freq_cpu_exit(struct cpufreq_policy *policy) 144static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c
index 4fa5adf16c70..a1fb735685db 100644
--- a/drivers/cpufreq/speedstep-centrino.c
+++ b/drivers/cpufreq/speedstep-centrino.c
@@ -394,9 +394,9 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
394 394
395 policy->cpuinfo.transition_latency = 10000; 395 policy->cpuinfo.transition_latency = 10000;
396 /* 10uS transition latency */ 396 /* 10uS transition latency */
397 policy->freq_table = per_cpu(centrino_model, policy->cpu)->op_points;
397 398
398 return cpufreq_table_validate_and_show(policy, 399 return 0;
399 per_cpu(centrino_model, policy->cpu)->op_points);
400} 400}
401 401
402static int centrino_cpu_exit(struct cpufreq_policy *policy) 402static int centrino_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c
index 0412a246a785..fbbcb88db061 100644
--- a/drivers/cpufreq/speedstep-ich.c
+++ b/drivers/cpufreq/speedstep-ich.c
@@ -304,7 +304,9 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
304 if (gf.ret) 304 if (gf.ret)
305 return gf.ret; 305 return gf.ret;
306 306
307 return cpufreq_table_validate_and_show(policy, speedstep_freqs); 307 policy->freq_table = speedstep_freqs;
308
309 return 0;
308} 310}
309 311
310 312
diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c
index d23f24ccff38..01fe70dae20b 100644
--- a/drivers/cpufreq/speedstep-smi.c
+++ b/drivers/cpufreq/speedstep-smi.c
@@ -266,7 +266,9 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
266 pr_debug("workaround worked.\n"); 266 pr_debug("workaround worked.\n");
267 } 267 }
268 268
269 return cpufreq_table_validate_and_show(policy, speedstep_freqs); 269 policy->freq_table = speedstep_freqs;
270
271 return 0;
270} 272}
271 273
272static unsigned int speedstep_get(unsigned int cpu) 274static unsigned int speedstep_get(unsigned int cpu)
diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c
index fe7875311d62..1f59966573aa 100644
--- a/drivers/cpufreq/tegra186-cpufreq.c
+++ b/drivers/cpufreq/tegra186-cpufreq.c
@@ -78,7 +78,8 @@ static int tegra186_cpufreq_init(struct cpufreq_policy *policy)
78 78
79 policy->driver_data = 79 policy->driver_data =
80 data->regs + info->offset + EDVD_CORE_VOLT_FREQ(core); 80 data->regs + info->offset + EDVD_CORE_VOLT_FREQ(core);
81 cpufreq_table_validate_and_show(policy, cluster->table); 81 policy->freq_table = cluster->table;
82 break;
82 } 83 }
83 84
84 policy->cpuinfo.transition_latency = 300 * 1000; 85 policy->cpuinfo.transition_latency = 300 * 1000;
diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c
index ddee1b601b89..e07bc7ace774 100644
--- a/drivers/cpuidle/cpuidle-arm.c
+++ b/drivers/cpuidle/cpuidle-arm.c
@@ -129,7 +129,6 @@ static int __init arm_idle_init_cpu(int cpu)
129 129
130 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 130 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
131 if (!dev) { 131 if (!dev) {
132 pr_err("Failed to allocate cpuidle device\n");
133 ret = -ENOMEM; 132 ret = -ENOMEM;
134 goto out_unregister_drv; 133 goto out_unregister_drv;
135 } 134 }
diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c
index 00cd129b10a4..0171a6e190d7 100644
--- a/drivers/cpuidle/cpuidle-exynos.c
+++ b/drivers/cpuidle/cpuidle-exynos.c
@@ -117,7 +117,8 @@ static int exynos_cpuidle_probe(struct platform_device *pdev)
117 int ret; 117 int ret;
118 118
119 if (IS_ENABLED(CONFIG_SMP) && 119 if (IS_ENABLED(CONFIG_SMP) &&
120 of_machine_is_compatible("samsung,exynos4210")) { 120 (of_machine_is_compatible("samsung,exynos4210") ||
121 of_machine_is_compatible("samsung,exynos3250"))) {
121 exynos_cpuidle_pdata = pdev->dev.platform_data; 122 exynos_cpuidle_pdata = pdev->dev.platform_data;
122 123
123 ret = cpuidle_register(&exynos_coupled_idle_driver, 124 ret = cpuidle_register(&exynos_coupled_idle_driver,
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 68a16827f45f..0003e9a02637 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -131,6 +131,10 @@ int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
131static void enter_s2idle_proper(struct cpuidle_driver *drv, 131static void enter_s2idle_proper(struct cpuidle_driver *drv,
132 struct cpuidle_device *dev, int index) 132 struct cpuidle_device *dev, int index)
133{ 133{
134 ktime_t time_start, time_end;
135
136 time_start = ns_to_ktime(local_clock());
137
134 /* 138 /*
135 * trace_suspend_resume() called by tick_freeze() for the last CPU 139 * trace_suspend_resume() called by tick_freeze() for the last CPU
136 * executing it contains RCU usage regarded as invalid in the idle 140 * executing it contains RCU usage regarded as invalid in the idle
@@ -152,6 +156,11 @@ static void enter_s2idle_proper(struct cpuidle_driver *drv,
152 */ 156 */
153 RCU_NONIDLE(tick_unfreeze()); 157 RCU_NONIDLE(tick_unfreeze());
154 start_critical_timings(); 158 start_critical_timings();
159
160 time_end = ns_to_ktime(local_clock());
161
162 dev->states_usage[index].s2idle_time += ktime_us_delta(time_end, time_start);
163 dev->states_usage[index].s2idle_usage++;
155} 164}
156 165
157/** 166/**
diff --git a/drivers/cpuidle/poll_state.c b/drivers/cpuidle/poll_state.c
index 7416b16287de..3f86d23c592e 100644
--- a/drivers/cpuidle/poll_state.c
+++ b/drivers/cpuidle/poll_state.c
@@ -6,15 +6,30 @@
6 6
7#include <linux/cpuidle.h> 7#include <linux/cpuidle.h>
8#include <linux/sched.h> 8#include <linux/sched.h>
9#include <linux/sched/clock.h>
9#include <linux/sched/idle.h> 10#include <linux/sched/idle.h>
10 11
12#define POLL_IDLE_TIME_LIMIT (TICK_NSEC / 16)
13#define POLL_IDLE_RELAX_COUNT 200
14
11static int __cpuidle poll_idle(struct cpuidle_device *dev, 15static int __cpuidle poll_idle(struct cpuidle_device *dev,
12 struct cpuidle_driver *drv, int index) 16 struct cpuidle_driver *drv, int index)
13{ 17{
18 u64 time_start = local_clock();
19
14 local_irq_enable(); 20 local_irq_enable();
15 if (!current_set_polling_and_test()) { 21 if (!current_set_polling_and_test()) {
16 while (!need_resched()) 22 unsigned int loop_count = 0;
23
24 while (!need_resched()) {
17 cpu_relax(); 25 cpu_relax();
26 if (loop_count++ < POLL_IDLE_RELAX_COUNT)
27 continue;
28
29 loop_count = 0;
30 if (local_clock() - time_start > POLL_IDLE_TIME_LIMIT)
31 break;
32 }
18 } 33 }
19 current_clr_polling(); 34 current_clr_polling();
20 35
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index ae948b1da93a..e754c7aae7f7 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -330,6 +330,58 @@ struct cpuidle_state_kobj {
330 struct kobject kobj; 330 struct kobject kobj;
331}; 331};
332 332
333#ifdef CONFIG_SUSPEND
334#define define_show_state_s2idle_ull_function(_name) \
335static ssize_t show_state_s2idle_##_name(struct cpuidle_state *state, \
336 struct cpuidle_state_usage *state_usage, \
337 char *buf) \
338{ \
339 return sprintf(buf, "%llu\n", state_usage->s2idle_##_name);\
340}
341
342define_show_state_s2idle_ull_function(usage);
343define_show_state_s2idle_ull_function(time);
344
345#define define_one_state_s2idle_ro(_name, show) \
346static struct cpuidle_state_attr attr_s2idle_##_name = \
347 __ATTR(_name, 0444, show, NULL)
348
349define_one_state_s2idle_ro(usage, show_state_s2idle_usage);
350define_one_state_s2idle_ro(time, show_state_s2idle_time);
351
352static struct attribute *cpuidle_state_s2idle_attrs[] = {
353 &attr_s2idle_usage.attr,
354 &attr_s2idle_time.attr,
355 NULL
356};
357
358static const struct attribute_group cpuidle_state_s2idle_group = {
359 .name = "s2idle",
360 .attrs = cpuidle_state_s2idle_attrs,
361};
362
363static void cpuidle_add_s2idle_attr_group(struct cpuidle_state_kobj *kobj)
364{
365 int ret;
366
367 if (!kobj->state->enter_s2idle)
368 return;
369
370 ret = sysfs_create_group(&kobj->kobj, &cpuidle_state_s2idle_group);
371 if (ret)
372 pr_debug("%s: sysfs attribute group not created\n", __func__);
373}
374
375static void cpuidle_remove_s2idle_attr_group(struct cpuidle_state_kobj *kobj)
376{
377 if (kobj->state->enter_s2idle)
378 sysfs_remove_group(&kobj->kobj, &cpuidle_state_s2idle_group);
379}
380#else
381static inline void cpuidle_add_s2idle_attr_group(struct cpuidle_state_kobj *kobj) { }
382static inline void cpuidle_remove_s2idle_attr_group(struct cpuidle_state_kobj *kobj) { }
383#endif /* CONFIG_SUSPEND */
384
333#define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj) 385#define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
334#define kobj_to_state(k) (kobj_to_state_obj(k)->state) 386#define kobj_to_state(k) (kobj_to_state_obj(k)->state)
335#define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage) 387#define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
@@ -383,6 +435,7 @@ static struct kobj_type ktype_state_cpuidle = {
383 435
384static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i) 436static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
385{ 437{
438 cpuidle_remove_s2idle_attr_group(device->kobjs[i]);
386 kobject_put(&device->kobjs[i]->kobj); 439 kobject_put(&device->kobjs[i]->kobj);
387 wait_for_completion(&device->kobjs[i]->kobj_unregister); 440 wait_for_completion(&device->kobjs[i]->kobj_unregister);
388 kfree(device->kobjs[i]); 441 kfree(device->kobjs[i]);
@@ -417,6 +470,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
417 kfree(kobj); 470 kfree(kobj);
418 goto error_state; 471 goto error_state;
419 } 472 }
473 cpuidle_add_s2idle_attr_group(kobj);
420 kobject_uevent(&kobj->kobj, KOBJ_ADD); 474 kobject_uevent(&kobj->kobj, KOBJ_ADD);
421 device->kobjs[i] = kobj; 475 device->kobjs[i] = kobj;
422 } 476 }
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index c3b615c94b4b..8c8caec3a72c 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -452,17 +452,20 @@ static int socket_insert(struct pcmcia_socket *skt)
452 452
453static int socket_suspend(struct pcmcia_socket *skt) 453static int socket_suspend(struct pcmcia_socket *skt)
454{ 454{
455 if (skt->state & SOCKET_SUSPEND) 455 if ((skt->state & SOCKET_SUSPEND) && !(skt->state & SOCKET_IN_RESUME))
456 return -EBUSY; 456 return -EBUSY;
457 457
458 mutex_lock(&skt->ops_mutex); 458 mutex_lock(&skt->ops_mutex);
459 skt->suspended_state = skt->state; 459 /* store state on first suspend, but not after spurious wakeups */
460 if (!(skt->state & SOCKET_IN_RESUME))
461 skt->suspended_state = skt->state;
460 462
461 skt->socket = dead_socket; 463 skt->socket = dead_socket;
462 skt->ops->set_socket(skt, &skt->socket); 464 skt->ops->set_socket(skt, &skt->socket);
463 if (skt->ops->suspend) 465 if (skt->ops->suspend)
464 skt->ops->suspend(skt); 466 skt->ops->suspend(skt);
465 skt->state |= SOCKET_SUSPEND; 467 skt->state |= SOCKET_SUSPEND;
468 skt->state &= ~SOCKET_IN_RESUME;
466 mutex_unlock(&skt->ops_mutex); 469 mutex_unlock(&skt->ops_mutex);
467 return 0; 470 return 0;
468} 471}
@@ -475,6 +478,7 @@ static int socket_early_resume(struct pcmcia_socket *skt)
475 skt->ops->set_socket(skt, &skt->socket); 478 skt->ops->set_socket(skt, &skt->socket);
476 if (skt->state & SOCKET_PRESENT) 479 if (skt->state & SOCKET_PRESENT)
477 skt->resume_status = socket_setup(skt, resume_delay); 480 skt->resume_status = socket_setup(skt, resume_delay);
481 skt->state |= SOCKET_IN_RESUME;
478 mutex_unlock(&skt->ops_mutex); 482 mutex_unlock(&skt->ops_mutex);
479 return 0; 483 return 0;
480} 484}
@@ -484,7 +488,7 @@ static int socket_late_resume(struct pcmcia_socket *skt)
484 int ret = 0; 488 int ret = 0;
485 489
486 mutex_lock(&skt->ops_mutex); 490 mutex_lock(&skt->ops_mutex);
487 skt->state &= ~SOCKET_SUSPEND; 491 skt->state &= ~(SOCKET_SUSPEND | SOCKET_IN_RESUME);
488 mutex_unlock(&skt->ops_mutex); 492 mutex_unlock(&skt->ops_mutex);
489 493
490 if (!(skt->state & SOCKET_PRESENT)) { 494 if (!(skt->state & SOCKET_PRESENT)) {
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 6765beadea95..03ec43802909 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -70,6 +70,7 @@ struct pccard_resource_ops {
70/* Flags in socket state */ 70/* Flags in socket state */
71#define SOCKET_PRESENT 0x0008 71#define SOCKET_PRESENT 0x0008
72#define SOCKET_INUSE 0x0010 72#define SOCKET_INUSE 0x0010
73#define SOCKET_IN_RESUME 0x0040
73#define SOCKET_SUSPEND 0x0080 74#define SOCKET_SUSPEND 0x0080
74#define SOCKET_WIN_REQ(i) (0x0100<<(i)) 75#define SOCKET_WIN_REQ(i) (0x0100<<(i))
75#define SOCKET_CARDBUS 0x8000 76#define SOCKET_CARDBUS 0x8000
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
index 35636e1d8a3d..295d8dcba48c 100644
--- a/drivers/powercap/intel_rapl.c
+++ b/drivers/powercap/intel_rapl.c
@@ -1162,6 +1162,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
1162 RAPL_CPU(INTEL_FAM6_SKYLAKE_X, rapl_defaults_hsw_server), 1162 RAPL_CPU(INTEL_FAM6_SKYLAKE_X, rapl_defaults_hsw_server),
1163 RAPL_CPU(INTEL_FAM6_KABYLAKE_MOBILE, rapl_defaults_core), 1163 RAPL_CPU(INTEL_FAM6_KABYLAKE_MOBILE, rapl_defaults_core),
1164 RAPL_CPU(INTEL_FAM6_KABYLAKE_DESKTOP, rapl_defaults_core), 1164 RAPL_CPU(INTEL_FAM6_KABYLAKE_DESKTOP, rapl_defaults_core),
1165 RAPL_CPU(INTEL_FAM6_CANNONLAKE_MOBILE, rapl_defaults_core),
1165 1166
1166 RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT1, rapl_defaults_byt), 1167 RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT1, rapl_defaults_byt),
1167 RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT, rapl_defaults_cht), 1168 RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT, rapl_defaults_cht),
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 21e8d248d956..1fe49724da9e 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -962,6 +962,7 @@ extern struct freq_attr cpufreq_freq_attr_scaling_boost_freqs;
962extern struct freq_attr *cpufreq_generic_attr[]; 962extern struct freq_attr *cpufreq_generic_attr[];
963int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, 963int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
964 struct cpufreq_frequency_table *table); 964 struct cpufreq_frequency_table *table);
965int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy);
965 966
966unsigned int cpufreq_generic_get(unsigned int cpu); 967unsigned int cpufreq_generic_get(unsigned int cpu);
967int cpufreq_generic_init(struct cpufreq_policy *policy, 968int cpufreq_generic_init(struct cpufreq_policy *policy,
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 0b3fc229086c..a806e94c482f 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -33,6 +33,10 @@ struct cpuidle_state_usage {
33 unsigned long long disable; 33 unsigned long long disable;
34 unsigned long long usage; 34 unsigned long long usage;
35 unsigned long long time; /* in US */ 35 unsigned long long time; /* in US */
36#ifdef CONFIG_SUSPEND
37 unsigned long long s2idle_usage;
38 unsigned long long s2idle_time; /* in US */
39#endif
36}; 40};
37 41
38struct cpuidle_state { 42struct cpuidle_state {
diff --git a/include/linux/device.h b/include/linux/device.h
index b093405ed525..abf952c82c6d 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -769,6 +769,7 @@ enum device_link_state {
769 * @status: The state of the link (with respect to the presence of drivers). 769 * @status: The state of the link (with respect to the presence of drivers).
770 * @flags: Link flags. 770 * @flags: Link flags.
771 * @rpm_active: Whether or not the consumer device is runtime-PM-active. 771 * @rpm_active: Whether or not the consumer device is runtime-PM-active.
772 * @kref: Count repeated addition of the same link.
772 * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks. 773 * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks.
773 */ 774 */
774struct device_link { 775struct device_link {
@@ -779,6 +780,7 @@ struct device_link {
779 enum device_link_state status; 780 enum device_link_state status;
780 u32 flags; 781 u32 flags;
781 bool rpm_active; 782 bool rpm_active;
783 struct kref kref;
782#ifdef CONFIG_SRCU 784#ifdef CONFIG_SRCU
783 struct rcu_head rcu_head; 785 struct rcu_head rcu_head;
784#endif 786#endif
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 4710f1b142fc..5454cc639a8d 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -1053,7 +1053,7 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
1053 lock_system_sleep(); 1053 lock_system_sleep();
1054 swsusp_resume_device = res; 1054 swsusp_resume_device = res;
1055 unlock_system_sleep(); 1055 unlock_system_sleep();
1056 pr_info("Starting manual resume from disk\n"); 1056 pm_pr_dbg("Configured resume from disk to %u\n", swsusp_resume_device);
1057 noresume = 0; 1057 noresume = 0;
1058 software_resume(); 1058 software_resume();
1059 return n; 1059 return n;
@@ -1061,6 +1061,29 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
1061 1061
1062power_attr(resume); 1062power_attr(resume);
1063 1063
1064static ssize_t resume_offset_show(struct kobject *kobj,
1065 struct kobj_attribute *attr, char *buf)
1066{
1067 return sprintf(buf, "%llu\n", (unsigned long long)swsusp_resume_block);
1068}
1069
1070static ssize_t resume_offset_store(struct kobject *kobj,
1071 struct kobj_attribute *attr, const char *buf,
1072 size_t n)
1073{
1074 unsigned long long offset;
1075 int rc;
1076
1077 rc = kstrtoull(buf, 0, &offset);
1078 if (rc)
1079 return rc;
1080 swsusp_resume_block = offset;
1081
1082 return n;
1083}
1084
1085power_attr(resume_offset);
1086
1064static ssize_t image_size_show(struct kobject *kobj, struct kobj_attribute *attr, 1087static ssize_t image_size_show(struct kobject *kobj, struct kobj_attribute *attr,
1065 char *buf) 1088 char *buf)
1066{ 1089{
@@ -1106,6 +1129,7 @@ power_attr(reserved_size);
1106 1129
1107static struct attribute * g[] = { 1130static struct attribute * g[] = {
1108 &disk_attr.attr, 1131 &disk_attr.attr,
1132 &resume_offset_attr.attr,
1109 &resume_attr.attr, 1133 &resume_attr.attr,
1110 &image_size_attr.attr, 1134 &image_size_attr.attr,
1111 &reserved_size_attr.attr, 1135 &reserved_size_attr.attr,
diff --git a/tools/power/pm-graph/Makefile b/tools/power/pm-graph/Makefile
index 4e1e999e7b05..c1899cd72c80 100644
--- a/tools/power/pm-graph/Makefile
+++ b/tools/power/pm-graph/Makefile
@@ -7,11 +7,24 @@ all:
7 7
8install : uninstall 8install : uninstall
9 install -d $(DESTDIR)$(PREFIX)/lib/pm-graph 9 install -d $(DESTDIR)$(PREFIX)/lib/pm-graph
10 install analyze_suspend.py $(DESTDIR)$(PREFIX)/lib/pm-graph 10 install sleepgraph.py $(DESTDIR)$(PREFIX)/lib/pm-graph
11 install analyze_boot.py $(DESTDIR)$(PREFIX)/lib/pm-graph 11 install bootgraph.py $(DESTDIR)$(PREFIX)/lib/pm-graph
12 install -d $(DESTDIR)$(PREFIX)/lib/pm-graph/config
13 install -m 644 config/cgskip.txt $(DESTDIR)$(PREFIX)/lib/pm-graph/config
14 install -m 644 config/freeze-callgraph.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
15 install -m 644 config/freeze.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
16 install -m 644 config/freeze-dev.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
17 install -m 644 config/standby-callgraph.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
18 install -m 644 config/standby.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
19 install -m 644 config/standby-dev.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
20 install -m 644 config/suspend-callgraph.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
21 install -m 644 config/suspend.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
22 install -m 644 config/suspend-dev.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
23 install -m 644 config/suspend-x2-proc.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
12 24
13 ln -s $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_boot.py $(DESTDIR)$(PREFIX)/bin/bootgraph 25 install -d $(DESTDIR)$(PREFIX)/bin
14 ln -s $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_suspend.py $(DESTDIR)$(PREFIX)/bin/sleepgraph 26 ln -s $(DESTDIR)$(PREFIX)/lib/pm-graph/bootgraph.py $(DESTDIR)$(PREFIX)/bin/bootgraph
27 ln -s $(DESTDIR)$(PREFIX)/lib/pm-graph/sleepgraph.py $(DESTDIR)$(PREFIX)/bin/sleepgraph
15 28
16 install -d $(DESTDIR)$(PREFIX)/share/man/man8 29 install -d $(DESTDIR)$(PREFIX)/share/man/man8
17 install bootgraph.8 $(DESTDIR)$(PREFIX)/share/man/man8 30 install bootgraph.8 $(DESTDIR)$(PREFIX)/share/man/man8
@@ -24,9 +37,11 @@ uninstall :
24 rm -f $(DESTDIR)$(PREFIX)/bin/bootgraph 37 rm -f $(DESTDIR)$(PREFIX)/bin/bootgraph
25 rm -f $(DESTDIR)$(PREFIX)/bin/sleepgraph 38 rm -f $(DESTDIR)$(PREFIX)/bin/sleepgraph
26 39
27 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_boot.py 40 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/config/*
28 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_suspend.py 41 if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph/config ] ; then \
29 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/*.pyc 42 rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph/config; \
43 fi;
44 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/*
30 if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph ] ; then \ 45 if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph ] ; then \
31 rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph; \ 46 rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph; \
32 fi; 47 fi;
diff --git a/tools/power/pm-graph/bootgraph.8 b/tools/power/pm-graph/bootgraph.8
index dbdafcf546df..64d513f80a2a 100644
--- a/tools/power/pm-graph/bootgraph.8
+++ b/tools/power/pm-graph/bootgraph.8
@@ -37,6 +37,9 @@ Print the current tool version
37Add the dmesg log to the html output. It will be viewable by 37Add the dmesg log to the html output. It will be viewable by
38clicking a button in the timeline. 38clicking a button in the timeline.
39.TP 39.TP
40\fB-result \fIfile\fR
41Export a results table to a text file for parsing.
42.TP
40\fB-o \fIname\fR 43\fB-o \fIname\fR
41Overrides the output subdirectory name when running a new test. 44Overrides the output subdirectory name when running a new test.
42Use {date}, {time}, {hostname} for current values. 45Use {date}, {time}, {hostname} for current values.
@@ -44,14 +47,14 @@ Use {date}, {time}, {hostname} for current values.
44e.g. boot-{hostname}-{date}-{time} 47e.g. boot-{hostname}-{date}-{time}
45.SS "advanced" 48.SS "advanced"
46.TP 49.TP
47\fB-f\fR 50\fB-f or -callgraph\fR
48Use ftrace to add function detail (default: disabled)
49.TP
50\fB-callgraph\fR
51Use ftrace to create initcall callgraphs (default: disabled). If -func 51Use ftrace to create initcall callgraphs (default: disabled). If -func
52is not used there will be one callgraph per initcall. This can produce 52is not used there will be one callgraph per initcall. This can produce
53very large outputs, i.e. 10MB - 100MB. 53very large outputs, i.e. 10MB - 100MB.
54.TP 54.TP
55\fB-fstat\fR
56Use ftrace to add function detail (default: disabled)
57.TP
55\fB-maxdepth \fIlevel\fR 58\fB-maxdepth \fIlevel\fR
56limit the callgraph trace depth to \fIlevel\fR (default: 2). This is 59limit the callgraph trace depth to \fIlevel\fR (default: 2). This is
57the best way to limit the output size when using -callgraph. 60the best way to limit the output size when using -callgraph.
@@ -67,6 +70,13 @@ Reduce callgraph output in the timeline by limiting it to a list of calls. The
67argument can be a single function name or a comma delimited list. 70argument can be a single function name or a comma delimited list.
68(default: none) 71(default: none)
69.TP 72.TP
73\fB-cgskip \fIfile\fR
74Reduce callgraph output in the timeline by skipping over uninteresting
75functions in the trace, e.g. printk or console_unlock. The functions listed
76in this file will show up as empty leaves in the callgraph with only the start/end
77times displayed.
78(default: none)
79.TP
70\fB-timeprec \fIn\fR 80\fB-timeprec \fIn\fR
71Number of significant digits in timestamps (0:S, 3:ms, [6:us]) 81Number of significant digits in timestamps (0:S, 3:ms, [6:us])
72.TP 82.TP
diff --git a/tools/power/pm-graph/analyze_boot.py b/tools/power/pm-graph/bootgraph.py
index e83df141a597..abb4c38f029b 100755
--- a/tools/power/pm-graph/analyze_boot.py
+++ b/tools/power/pm-graph/bootgraph.py
@@ -32,7 +32,7 @@ import platform
32import shutil 32import shutil
33from datetime import datetime, timedelta 33from datetime import datetime, timedelta
34from subprocess import call, Popen, PIPE 34from subprocess import call, Popen, PIPE
35import analyze_suspend as aslib 35import sleepgraph as aslib
36 36
37# ----------------- CLASSES -------------------- 37# ----------------- CLASSES --------------------
38 38
@@ -42,23 +42,18 @@ import analyze_suspend as aslib
42# store system values and test parameters 42# store system values and test parameters
43class SystemValues(aslib.SystemValues): 43class SystemValues(aslib.SystemValues):
44 title = 'BootGraph' 44 title = 'BootGraph'
45 version = '2.1' 45 version = '2.2'
46 hostname = 'localhost' 46 hostname = 'localhost'
47 testtime = '' 47 testtime = ''
48 kernel = '' 48 kernel = ''
49 dmesgfile = '' 49 dmesgfile = ''
50 ftracefile = '' 50 ftracefile = ''
51 htmlfile = 'bootgraph.html' 51 htmlfile = 'bootgraph.html'
52 outfile = ''
53 testdir = '' 52 testdir = ''
54 testdirprefix = 'boot' 53 kparams = ''
55 embedded = False 54 result = ''
56 testlog = False
57 dmesglog = False
58 ftracelog = False
59 useftrace = False 55 useftrace = False
60 usecallgraph = False 56 usecallgraph = False
61 usedevsrc = True
62 suspendmode = 'boot' 57 suspendmode = 'boot'
63 max_graph_depth = 2 58 max_graph_depth = 2
64 graph_filter = 'do_one_initcall' 59 graph_filter = 'do_one_initcall'
@@ -69,11 +64,6 @@ class SystemValues(aslib.SystemValues):
69 bootloader = 'grub' 64 bootloader = 'grub'
70 blexec = [] 65 blexec = []
71 def __init__(self): 66 def __init__(self):
72 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ):
73 self.embedded = True
74 self.dmesglog = True
75 self.outfile = os.environ['LOG_FILE']
76 self.htmlfile = os.environ['LOG_FILE']
77 self.hostname = platform.node() 67 self.hostname = platform.node()
78 self.testtime = datetime.now().strftime('%Y-%m-%d_%H:%M:%S') 68 self.testtime = datetime.now().strftime('%Y-%m-%d_%H:%M:%S')
79 if os.path.exists('/proc/version'): 69 if os.path.exists('/proc/version'):
@@ -148,11 +138,18 @@ class SystemValues(aslib.SystemValues):
148 cmdline = '%s -cronjob' % os.path.abspath(sys.argv[0]) 138 cmdline = '%s -cronjob' % os.path.abspath(sys.argv[0])
149 args = iter(sys.argv[1:]) 139 args = iter(sys.argv[1:])
150 for arg in args: 140 for arg in args:
151 if arg in ['-h', '-v', '-cronjob', '-reboot']: 141 if arg in ['-h', '-v', '-cronjob', '-reboot', '-verbose']:
152 continue 142 continue
153 elif arg in ['-o', '-dmesg', '-ftrace', '-func']: 143 elif arg in ['-o', '-dmesg', '-ftrace', '-func']:
154 args.next() 144 args.next()
155 continue 145 continue
146 elif arg == '-result':
147 cmdline += ' %s "%s"' % (arg, os.path.abspath(args.next()))
148 continue
149 elif arg == '-cgskip':
150 file = self.configFile(args.next())
151 cmdline += ' %s "%s"' % (arg, os.path.abspath(file))
152 continue
156 cmdline += ' '+arg 153 cmdline += ' '+arg
157 if self.graph_filter != 'do_one_initcall': 154 if self.graph_filter != 'do_one_initcall':
158 cmdline += ' -func "%s"' % self.graph_filter 155 cmdline += ' -func "%s"' % self.graph_filter
@@ -166,14 +163,6 @@ class SystemValues(aslib.SystemValues):
166 print '3. After reboot, re-run this tool with the same arguments but no command (w/o -reboot or -manual).\n' 163 print '3. After reboot, re-run this tool with the same arguments but no command (w/o -reboot or -manual).\n'
167 print 'CMDLINE="%s"' % cmdline 164 print 'CMDLINE="%s"' % cmdline
168 sys.exit() 165 sys.exit()
169 def getExec(self, cmd):
170 dirlist = ['/sbin', '/bin', '/usr/sbin', '/usr/bin',
171 '/usr/local/sbin', '/usr/local/bin']
172 for path in dirlist:
173 cmdfull = os.path.join(path, cmd)
174 if os.path.exists(cmdfull):
175 return cmdfull
176 return ''
177 def blGrub(self): 166 def blGrub(self):
178 blcmd = '' 167 blcmd = ''
179 for cmd in ['update-grub', 'grub-mkconfig', 'grub2-mkconfig']: 168 for cmd in ['update-grub', 'grub-mkconfig', 'grub2-mkconfig']:
@@ -199,6 +188,14 @@ class SystemValues(aslib.SystemValues):
199 self.blGrub() 188 self.blGrub()
200 else: 189 else:
201 doError('unknown boot loader: %s' % self.bootloader) 190 doError('unknown boot loader: %s' % self.bootloader)
191 def writeDatafileHeader(self, filename):
192 self.kparams = open('/proc/cmdline', 'r').read().strip()
193 fp = open(filename, 'w')
194 fp.write(self.teststamp+'\n')
195 fp.write(self.sysstamp+'\n')
196 fp.write('# command | %s\n' % self.cmdline)
197 fp.write('# kparams | %s\n' % self.kparams)
198 fp.close()
202 199
203sysvals = SystemValues() 200sysvals = SystemValues()
204 201
@@ -249,7 +246,7 @@ class Data(aslib.Data):
249 return name 246 return name
250 def deviceMatch(self, pid, cg): 247 def deviceMatch(self, pid, cg):
251 if cg.end - cg.start == 0: 248 if cg.end - cg.start == 0:
252 return True 249 return ''
253 for p in data.phases: 250 for p in data.phases:
254 list = self.dmesg[p]['list'] 251 list = self.dmesg[p]['list']
255 for devname in list: 252 for devname in list:
@@ -260,14 +257,25 @@ class Data(aslib.Data):
260 if(cg.start <= dev['start'] and cg.end >= dev['end'] and dev['length'] > 0): 257 if(cg.start <= dev['start'] and cg.end >= dev['end'] and dev['length'] > 0):
261 dev['ftrace'] = cg 258 dev['ftrace'] = cg
262 self.do_one_initcall = True 259 self.do_one_initcall = True
263 return True 260 return devname
264 else: 261 else:
265 if(cg.start > dev['start'] and cg.end < dev['end']): 262 if(cg.start > dev['start'] and cg.end < dev['end']):
266 if 'ftraces' not in dev: 263 if 'ftraces' not in dev:
267 dev['ftraces'] = [] 264 dev['ftraces'] = []
268 dev['ftraces'].append(cg) 265 dev['ftraces'].append(cg)
269 return True 266 return devname
270 return False 267 return ''
268 def printDetails(self):
269 sysvals.vprint('Timeline Details:')
270 sysvals.vprint(' Host: %s' % sysvals.hostname)
271 sysvals.vprint(' Kernel: %s' % sysvals.kernel)
272 sysvals.vprint(' Test time: %s' % sysvals.testtime)
273 sysvals.vprint(' Boot time: %s' % self.boottime)
274 for phase in self.phases:
275 dc = len(self.dmesg[phase]['list'])
276 sysvals.vprint('%9s mode: %.3f - %.3f (%d initcalls)' % (phase,
277 self.dmesg[phase]['start']*1000,
278 self.dmesg[phase]['end']*1000, dc))
271 279
272# ----------------- FUNCTIONS -------------------- 280# ----------------- FUNCTIONS --------------------
273 281
@@ -275,6 +283,8 @@ class Data(aslib.Data):
275# Description: 283# Description:
276# parse a kernel log for boot data 284# parse a kernel log for boot data
277def parseKernelLog(): 285def parseKernelLog():
286 sysvals.vprint('Analyzing the dmesg data (%s)...' % \
287 os.path.basename(sysvals.dmesgfile))
278 phase = 'kernel' 288 phase = 'kernel'
279 data = Data(0) 289 data = Data(0)
280 data.dmesg['kernel']['start'] = data.start = ktime = 0.0 290 data.dmesg['kernel']['start'] = data.start = ktime = 0.0
@@ -298,6 +308,12 @@ def parseKernelLog():
298 elif re.match(tp.sysinfofmt, line): 308 elif re.match(tp.sysinfofmt, line):
299 tp.sysinfo = line 309 tp.sysinfo = line
300 continue 310 continue
311 elif re.match(tp.cmdlinefmt, line):
312 tp.cmdline = line
313 continue
314 elif re.match(tp.kparamsfmt, line):
315 tp.kparams = line
316 continue
301 idx = line.find('[') 317 idx = line.find('[')
302 if idx > 1: 318 if idx > 1:
303 line = line[idx:] 319 line = line[idx:]
@@ -353,6 +369,17 @@ def parseKernelLog():
353# Description: 369# Description:
354# Check if trace is available and copy to a temp file 370# Check if trace is available and copy to a temp file
355def parseTraceLog(data): 371def parseTraceLog(data):
372 sysvals.vprint('Analyzing the ftrace data (%s)...' % \
373 os.path.basename(sysvals.ftracefile))
374 # if available, calculate cgfilter allowable ranges
375 cgfilter = []
376 if len(sysvals.cgfilter) > 0:
377 for p in data.phases:
378 list = data.dmesg[p]['list']
379 for i in sysvals.cgfilter:
380 if i in list:
381 cgfilter.append([list[i]['start']-0.0001,
382 list[i]['end']+0.0001])
356 # parse the trace log 383 # parse the trace log
357 ftemp = dict() 384 ftemp = dict()
358 tp = aslib.TestProps() 385 tp = aslib.TestProps()
@@ -366,7 +393,16 @@ def parseTraceLog(data):
366 continue 393 continue
367 m_time, m_proc, m_pid, m_msg, m_dur = \ 394 m_time, m_proc, m_pid, m_msg, m_dur = \
368 m.group('time', 'proc', 'pid', 'msg', 'dur') 395 m.group('time', 'proc', 'pid', 'msg', 'dur')
369 if float(m_time) > data.end: 396 t = float(m_time)
397 if len(cgfilter) > 0:
398 allow = False
399 for r in cgfilter:
400 if t >= r[0] and t < r[1]:
401 allow = True
402 break
403 if not allow:
404 continue
405 if t > data.end:
370 break 406 break
371 if(m_time and m_pid and m_msg): 407 if(m_time and m_pid and m_msg):
372 t = aslib.FTraceLine(m_time, m_msg, m_dur) 408 t = aslib.FTraceLine(m_time, m_msg, m_dur)
@@ -378,24 +414,36 @@ def parseTraceLog(data):
378 key = (m_proc, pid) 414 key = (m_proc, pid)
379 if(key not in ftemp): 415 if(key not in ftemp):
380 ftemp[key] = [] 416 ftemp[key] = []
381 ftemp[key].append(aslib.FTraceCallGraph(pid)) 417 ftemp[key].append(aslib.FTraceCallGraph(pid, sysvals))
382 cg = ftemp[key][-1] 418 cg = ftemp[key][-1]
383 if(cg.addLine(t)): 419 res = cg.addLine(t)
384 ftemp[key].append(aslib.FTraceCallGraph(pid)) 420 if(res != 0):
421 ftemp[key].append(aslib.FTraceCallGraph(pid, sysvals))
422 if(res == -1):
423 ftemp[key][-1].addLine(t)
424
385 tf.close() 425 tf.close()
386 426
387 # add the callgraph data to the device hierarchy 427 # add the callgraph data to the device hierarchy
388 for key in ftemp: 428 for key in ftemp:
389 proc, pid = key 429 proc, pid = key
390 for cg in ftemp[key]: 430 for cg in ftemp[key]:
391 if len(cg.list) < 1 or cg.invalid: 431 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0):
392 continue 432 continue
393 if(not cg.postProcess()): 433 if(not cg.postProcess()):
394 print('Sanity check failed for %s-%d' % (proc, pid)) 434 print('Sanity check failed for %s-%d' % (proc, pid))
395 continue 435 continue
396 # match cg data to devices 436 # match cg data to devices
397 if not data.deviceMatch(pid, cg): 437 devname = data.deviceMatch(pid, cg)
398 print ' BAD: %s %s-%d [%f - %f]' % (cg.name, proc, pid, cg.start, cg.end) 438 if not devname:
439 kind = 'Orphan'
440 if cg.partial:
441 kind = 'Partial'
442 sysvals.vprint('%s callgraph found for %s %s-%d [%f - %f]' %\
443 (kind, cg.name, proc, pid, cg.start, cg.end))
444 elif len(cg.list) > 1000000:
445 print 'WARNING: the callgraph found for %s is massive! (%d lines)' %\
446 (devname, len(cg.list))
399 447
400# Function: retrieveLogs 448# Function: retrieveLogs
401# Description: 449# Description:
@@ -473,7 +521,7 @@ def createBootGraph(data):
473 devtl = aslib.Timeline(100, 20) 521 devtl = aslib.Timeline(100, 20)
474 522
475 # write the test title and general info header 523 # write the test title and general info header
476 devtl.createHeader(sysvals) 524 devtl.createHeader(sysvals, sysvals.stamp)
477 525
478 # Generate the header for this timeline 526 # Generate the header for this timeline
479 t0 = data.start 527 t0 = data.start
@@ -574,12 +622,9 @@ def createBootGraph(data):
574 data.dmesg[phase]['color'], phase+'_mode', phase[0]) 622 data.dmesg[phase]['color'], phase+'_mode', phase[0])
575 devtl.html += '</div>\n' 623 devtl.html += '</div>\n'
576 624
577 if(sysvals.outfile == sysvals.htmlfile): 625 hf = open(sysvals.htmlfile, 'w')
578 hf = open(sysvals.htmlfile, 'a')
579 else:
580 hf = open(sysvals.htmlfile, 'w')
581 626
582 # add the css if this is not an embedded run 627 # add the css
583 extra = '\ 628 extra = '\
584 .c1 {background:rgba(209,0,0,0.4);}\n\ 629 .c1 {background:rgba(209,0,0,0.4);}\n\
585 .c2 {background:rgba(255,102,34,0.4);}\n\ 630 .c2 {background:rgba(255,102,34,0.4);}\n\
@@ -597,8 +642,7 @@ def createBootGraph(data):
597 .fstat td {text-align:left;width:35px;}\n\ 642 .fstat td {text-align:left;width:35px;}\n\
598 .srccall {position:absolute;font-size:10px;z-index:7;overflow:hidden;color:black;text-align:center;white-space:nowrap;border-radius:5px;border:1px solid black;background:linear-gradient(to bottom right,#CCC,#969696);}\n\ 643 .srccall {position:absolute;font-size:10px;z-index:7;overflow:hidden;color:black;text-align:center;white-space:nowrap;border-radius:5px;border:1px solid black;background:linear-gradient(to bottom right,#CCC,#969696);}\n\
599 .srccall:hover {color:white;font-weight:bold;border:1px solid white;}\n' 644 .srccall:hover {color:white;font-weight:bold;border:1px solid white;}\n'
600 if(not sysvals.embedded): 645 aslib.addCSS(hf, sysvals, 1, False, extra)
601 aslib.addCSS(hf, sysvals, 1, False, extra)
602 646
603 # write the device timeline 647 # write the device timeline
604 hf.write(devtl.html) 648 hf.write(devtl.html)
@@ -631,6 +675,9 @@ def createBootGraph(data):
631 if(sysvals.usecallgraph): 675 if(sysvals.usecallgraph):
632 aslib.addCallgraphs(sysvals, hf, data) 676 aslib.addCallgraphs(sysvals, hf, data)
633 677
678 # add the test log as a hidden div
679 if sysvals.testlog and sysvals.logmsg:
680 hf.write('<div id="testlog" style="display:none;">\n'+sysvals.logmsg+'</div>\n')
634 # add the dmesg log as a hidden div 681 # add the dmesg log as a hidden div
635 if sysvals.dmesglog: 682 if sysvals.dmesglog:
636 hf.write('<div id="dmesglog" style="display:none;">\n') 683 hf.write('<div id="dmesglog" style="display:none;">\n')
@@ -639,14 +686,9 @@ def createBootGraph(data):
639 hf.write(line) 686 hf.write(line)
640 hf.write('</div>\n') 687 hf.write('</div>\n')
641 688
642 if(not sysvals.embedded): 689 # write the footer and close
643 # write the footer and close 690 aslib.addScriptCode(hf, [data])
644 aslib.addScriptCode(hf, [data]) 691 hf.write('</body>\n</html>\n')
645 hf.write('</body>\n</html>\n')
646 else:
647 # embedded out will be loaded in a page, skip the js
648 hf.write('<div id=bounds style=display:none>%f,%f</div>' % \
649 (data.start*1000, data.end*1000))
650 hf.close() 692 hf.close()
651 return True 693 return True
652 694
@@ -780,6 +822,7 @@ def doError(msg, help=False):
780 if help == True: 822 if help == True:
781 printHelp() 823 printHelp()
782 print 'ERROR: %s\n' % msg 824 print 'ERROR: %s\n' % msg
825 sysvals.outputResult({'error':msg})
783 sys.exit() 826 sys.exit()
784 827
785# Function: printHelp 828# Function: printHelp
@@ -806,18 +849,21 @@ def printHelp():
806 print('Options:') 849 print('Options:')
807 print(' -h Print this help text') 850 print(' -h Print this help text')
808 print(' -v Print the current tool version') 851 print(' -v Print the current tool version')
852 print(' -verbose Print extra information during execution and analysis')
809 print(' -addlogs Add the dmesg log to the html output') 853 print(' -addlogs Add the dmesg log to the html output')
854 print(' -result fn Export a results table to a text file for parsing.')
810 print(' -o name Overrides the output subdirectory name when running a new test') 855 print(' -o name Overrides the output subdirectory name when running a new test')
811 print(' default: boot-{date}-{time}') 856 print(' default: boot-{date}-{time}')
812 print(' [advanced]') 857 print(' [advanced]')
813 print(' -f Use ftrace to add function detail (default: disabled)') 858 print(' -fstat Use ftrace to add function detail and statistics (default: disabled)')
814 print(' -callgraph Add callgraph detail, can be very large (default: disabled)') 859 print(' -f/-callgraph Add callgraph detail, can be very large (default: disabled)')
815 print(' -maxdepth N limit the callgraph data to N call levels (default: 2)') 860 print(' -maxdepth N limit the callgraph data to N call levels (default: 2)')
816 print(' -mincg ms Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)') 861 print(' -mincg ms Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)')
817 print(' -timeprec N Number of significant digits in timestamps (0:S, 3:ms, [6:us])') 862 print(' -timeprec N Number of significant digits in timestamps (0:S, 3:ms, [6:us])')
818 print(' -expandcg pre-expand the callgraph data in the html output (default: disabled)') 863 print(' -expandcg pre-expand the callgraph data in the html output (default: disabled)')
819 print(' -func list Limit ftrace to comma-delimited list of functions (default: do_one_initcall)') 864 print(' -func list Limit ftrace to comma-delimited list of functions (default: do_one_initcall)')
820 print(' -cgfilter S Filter the callgraph output in the timeline') 865 print(' -cgfilter S Filter the callgraph output in the timeline')
866 print(' -cgskip file Callgraph functions to skip, off to disable (default: cgskip.txt)')
821 print(' -bl name Use the following boot loader for kernel params (default: grub)') 867 print(' -bl name Use the following boot loader for kernel params (default: grub)')
822 print(' -reboot Reboot the machine automatically and generate a new timeline') 868 print(' -reboot Reboot the machine automatically and generate a new timeline')
823 print(' -manual Show the steps to generate a new timeline manually (used with -reboot)') 869 print(' -manual Show the steps to generate a new timeline manually (used with -reboot)')
@@ -837,8 +883,13 @@ if __name__ == '__main__':
837 # loop through the command line arguments 883 # loop through the command line arguments
838 cmd = '' 884 cmd = ''
839 testrun = True 885 testrun = True
886 switchoff = ['disable', 'off', 'false', '0']
840 simplecmds = ['-sysinfo', '-kpupdate', '-flistall', '-checkbl'] 887 simplecmds = ['-sysinfo', '-kpupdate', '-flistall', '-checkbl']
888 cgskip = ''
889 if '-f' in sys.argv:
890 cgskip = sysvals.configFile('cgskip.txt')
841 args = iter(sys.argv[1:]) 891 args = iter(sys.argv[1:])
892 mdset = False
842 for arg in args: 893 for arg in args:
843 if(arg == '-h'): 894 if(arg == '-h'):
844 printHelp() 895 printHelp()
@@ -846,13 +897,17 @@ if __name__ == '__main__':
846 elif(arg == '-v'): 897 elif(arg == '-v'):
847 print("Version %s" % sysvals.version) 898 print("Version %s" % sysvals.version)
848 sys.exit() 899 sys.exit()
900 elif(arg == '-verbose'):
901 sysvals.verbose = True
849 elif(arg in simplecmds): 902 elif(arg in simplecmds):
850 cmd = arg[1:] 903 cmd = arg[1:]
851 elif(arg == '-f'): 904 elif(arg == '-fstat'):
852 sysvals.useftrace = True 905 sysvals.useftrace = True
853 elif(arg == '-callgraph'): 906 elif(arg == '-callgraph' or arg == '-f'):
854 sysvals.useftrace = True 907 sysvals.useftrace = True
855 sysvals.usecallgraph = True 908 sysvals.usecallgraph = True
909 elif(arg == '-cgdump'):
910 sysvals.cgdump = True
856 elif(arg == '-mincg'): 911 elif(arg == '-mincg'):
857 sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0) 912 sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0)
858 elif(arg == '-cgfilter'): 913 elif(arg == '-cgfilter'):
@@ -860,7 +915,18 @@ if __name__ == '__main__':
860 val = args.next() 915 val = args.next()
861 except: 916 except:
862 doError('No callgraph functions supplied', True) 917 doError('No callgraph functions supplied', True)
863 sysvals.setDeviceFilter(val) 918 sysvals.setCallgraphFilter(val)
919 elif(arg == '-cgskip'):
920 try:
921 val = args.next()
922 except:
923 doError('No file supplied', True)
924 if val.lower() in switchoff:
925 cgskip = ''
926 else:
927 cgskip = sysvals.configFile(val)
928 if(not cgskip):
929 doError('%s does not exist' % cgskip)
864 elif(arg == '-bl'): 930 elif(arg == '-bl'):
865 try: 931 try:
866 val = args.next() 932 val = args.next()
@@ -872,6 +938,7 @@ if __name__ == '__main__':
872 elif(arg == '-timeprec'): 938 elif(arg == '-timeprec'):
873 sysvals.setPrecision(aslib.getArgInt('-timeprec', args, 0, 6)) 939 sysvals.setPrecision(aslib.getArgInt('-timeprec', args, 0, 6))
874 elif(arg == '-maxdepth'): 940 elif(arg == '-maxdepth'):
941 mdset = True
875 sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000) 942 sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000)
876 elif(arg == '-func'): 943 elif(arg == '-func'):
877 try: 944 try:
@@ -902,8 +969,6 @@ if __name__ == '__main__':
902 doError('No dmesg file supplied', True) 969 doError('No dmesg file supplied', True)
903 if(os.path.exists(val) == False): 970 if(os.path.exists(val) == False):
904 doError('%s does not exist' % val) 971 doError('%s does not exist' % val)
905 if(sysvals.htmlfile == val or sysvals.outfile == val):
906 doError('Output filename collision')
907 testrun = False 972 testrun = False
908 sysvals.dmesgfile = val 973 sysvals.dmesgfile = val
909 elif(arg == '-o'): 974 elif(arg == '-o'):
@@ -912,6 +977,12 @@ if __name__ == '__main__':
912 except: 977 except:
913 doError('No subdirectory name supplied', True) 978 doError('No subdirectory name supplied', True)
914 sysvals.testdir = sysvals.setOutputFolder(val) 979 sysvals.testdir = sysvals.setOutputFolder(val)
980 elif(arg == '-result'):
981 try:
982 val = args.next()
983 except:
984 doError('No result file supplied', True)
985 sysvals.result = val
915 elif(arg == '-reboot'): 986 elif(arg == '-reboot'):
916 sysvals.reboot = True 987 sysvals.reboot = True
917 elif(arg == '-manual'): 988 elif(arg == '-manual'):
@@ -947,7 +1018,7 @@ if __name__ == '__main__':
947 sysvals.getBootLoader() 1018 sysvals.getBootLoader()
948 print 'Boot Loader: %s\n%s' % (sysvals.bootloader, sysvals.blexec) 1019 print 'Boot Loader: %s\n%s' % (sysvals.bootloader, sysvals.blexec)
949 elif(cmd == 'sysinfo'): 1020 elif(cmd == 'sysinfo'):
950 sysvals.printSystemInfo() 1021 sysvals.printSystemInfo(True)
951 sys.exit() 1022 sys.exit()
952 1023
953 # reboot: update grub, setup a cronjob, and reboot 1024 # reboot: update grub, setup a cronjob, and reboot
@@ -963,6 +1034,10 @@ if __name__ == '__main__':
963 sysvals.manualRebootRequired() 1034 sysvals.manualRebootRequired()
964 sys.exit() 1035 sys.exit()
965 1036
1037 if sysvals.usecallgraph and cgskip:
1038 sysvals.vprint('Using cgskip file: %s' % cgskip)
1039 sysvals.setCallgraphBlacklist(cgskip)
1040
966 # cronjob: remove the cronjob, grub changes, and disable ftrace 1041 # cronjob: remove the cronjob, grub changes, and disable ftrace
967 if sysvals.iscronjob: 1042 if sysvals.iscronjob:
968 updateCron(True) 1043 updateCron(True)
@@ -980,29 +1055,23 @@ if __name__ == '__main__':
980 1055
981 # process the log data 1056 # process the log data
982 if sysvals.dmesgfile: 1057 if sysvals.dmesgfile:
1058 if not mdset:
1059 sysvals.max_graph_depth = 0
983 data = parseKernelLog() 1060 data = parseKernelLog()
984 if(not data.valid): 1061 if(not data.valid):
985 doError('No initcall data found in %s' % sysvals.dmesgfile) 1062 doError('No initcall data found in %s' % sysvals.dmesgfile)
986 if sysvals.useftrace and sysvals.ftracefile: 1063 if sysvals.useftrace and sysvals.ftracefile:
987 parseTraceLog(data) 1064 parseTraceLog(data)
1065 if sysvals.cgdump:
1066 data.debugPrint()
1067 sys.exit()
988 else: 1068 else:
989 doError('dmesg file required') 1069 doError('dmesg file required')
990 1070
991 print(' Host: %s' % sysvals.hostname) 1071 sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile)
992 print(' Test time: %s' % sysvals.testtime) 1072 sysvals.vprint('Command:\n %s' % sysvals.cmdline)
993 print(' Boot time: %s' % data.boottime) 1073 sysvals.vprint('Kernel parameters:\n %s' % sysvals.kparams)
994 print('Kernel Version: %s' % sysvals.kernel) 1074 data.printDetails()
995 print(' Kernel start: %.3f' % (data.start * 1000))
996 print('Usermode start: %.3f' % (data.tUserMode * 1000))
997 print('Last Init Call: %.3f' % (data.end * 1000))
998
999 # handle embedded output logs
1000 if(sysvals.outfile and sysvals.embedded):
1001 fp = open(sysvals.outfile, 'w')
1002 fp.write('pass %s initstart %.3f end %.3f boot %s\n' %
1003 (data.valid, data.tUserMode*1000, data.end*1000, data.boottime))
1004 fp.close()
1005
1006 createBootGraph(data) 1075 createBootGraph(data)
1007 1076
1008 # if running as root, change output dir owner to sudo_user 1077 # if running as root, change output dir owner to sudo_user
@@ -1010,3 +1079,7 @@ if __name__ == '__main__':
1010 os.getuid() == 0 and 'SUDO_USER' in os.environ: 1079 os.getuid() == 0 and 'SUDO_USER' in os.environ:
1011 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1' 1080 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1'
1012 call(cmd.format(os.environ['SUDO_USER'], sysvals.testdir), shell=True) 1081 call(cmd.format(os.environ['SUDO_USER'], sysvals.testdir), shell=True)
1082
1083 sysvals.stamp['boot'] = (data.tUserMode - data.start) * 1000
1084 sysvals.stamp['lastinit'] = data.end * 1000
1085 sysvals.outputResult(sysvals.stamp)
diff --git a/tools/power/pm-graph/config/cgskip.txt b/tools/power/pm-graph/config/cgskip.txt
new file mode 100644
index 000000000000..e48d588fbfb4
--- /dev/null
+++ b/tools/power/pm-graph/config/cgskip.txt
@@ -0,0 +1,65 @@
1# -----------------------------------------------
2# CallGraph function skip list
3#
4# This file contains a list of functions which are
5# meant to be skipped in the callgraph trace. It reduces
6# the callgraph html file size by treating these functions
7# as leaves with no child calls. It can be editted by
8# adding or removing function symbol names.
9#
10# The sleepgraph tool automatically pulls this file in when
11# it is found in the config folder. It can be ignored if
12# the tool is called with "-cgskip off".
13# -----------------------------------------------
14
15# low level scheduling and timing
16up
17down_timeout
18mutex_lock
19down_read
20complete_all
21schedule_timeout
22wake_up_process
23msleep
24__udelay
25ktime_get
26
27# console calls
28printk
29dev_printk
30console_unlock
31
32# memory handling
33__kmalloc
34__kmalloc_track_caller
35kmem_cache_alloc
36kmem_cache_alloc_trace
37kmem_cache_free
38kstrdup
39kstrdup_const
40kmalloc_slab
41new_slab
42__slab_alloc
43__slab_free
44raw_pci_read
45pci_read
46alloc_pages_current
47
48# debugfs and sysfs setup
49debugfs_remove_recursive
50debugfs_create_dir
51debugfs_create_files
52debugfs_create_dir
53debugfs_get_inode
54sysfs_add_file_mode_ns
55sysfs_add_file
56sysfs_create_dir_ns
57sysfs_create_link
58sysfs_create_group
59sysfs_create_groups
60sysfs_create_bin_file
61dpm_sysfs_add
62sysfs_create_file_ns
63sysfs_merge_group
64sysfs_add_link_to_group
65sysfs_create_link_sd
diff --git a/tools/power/pm-graph/config/custom-timeline-functions.cfg b/tools/power/pm-graph/config/custom-timeline-functions.cfg
new file mode 100644
index 000000000000..4f80ad7d7275
--- /dev/null
+++ b/tools/power/pm-graph/config/custom-timeline-functions.cfg
@@ -0,0 +1,205 @@
1#
2# This is the configuration file for sleepgraph. It contains
3# all the tool arguments so that they don't have to be given on the
4# command line. It also includes advanced settings for functions
5# and kprobes. It is run like this
6#
7# sudo ./sleepgraph.py -config thisfile.txt
8#
9
10[Settings]
11
12# Verbosity
13# print verbose messages (default: false)
14verbose: false
15
16# Suspend Mode
17# e.g. standby, mem, freeze, disk (default: mem)
18mode: mem
19
20# Automatic Wakeup
21# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
22rtcwake: 15
23
24# Add Logs
25# add the dmesg and ftrace log to the html output (default: false)
26addlogs: false
27
28# Display function calls
29# graph source functions in the timeline (default: false)
30dev: true
31
32# Callgraph
33# gather detailed ftrace callgraph data on all timeline events (default: false)
34callgraph: false
35
36# Back to Back Suspend/Resume
37# Run two suspend/resumes back to back (default: false)
38x2: false
39
40# Back to Back Suspend Delay
41# Time delay between the two test runs in ms (default: 0 ms)
42x2delay: 0
43
44# Minimum Device Length
45# graph only devices longer than min in the timeline (default: 0.001 ms)
46mindev: 1
47
48# Minimum Callgraph Length
49# provide callgraph data for blocks longer than min (default: 0.001 ms)
50mincg: 1
51
52# Suspend/Resume Gap
53# insert a small visible gap between suspend and resume on the timeline (default: false)
54srgap: false
55
56# Output Directory Format
57# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
58output-dir: suspend-{hostname}-{date}-{time}-custom
59
60# Override default timeline entries
61# Do not use the internal default functions for timeline entries (default: false)
62# Set this to true if you intend to only use the ones defined in this config
63override-timeline-functions: true
64
65# Override default dev timeline entries
66# Do not use the internal default functions for dev timeline entries (default: false)
67# Set this to true if you intend to only use the ones defined in this config
68override-dev-timeline-functions: true
69
70[timeline_functions_x86_64]
71#
72# Function calls to display in the timeline alongside device callbacks.
73# The tool has an internal set of these functions which should cover the
74# whole of kernel execution, but you can append or override here.
75#
76# This is a list of kprobes which use both symbol data and function arg data.
77# The function calls are displayed on the timeline alongside the device blocks.
78# The args are pulled directly from the stack using this architecture's registers
79# and stack formatting. Three pieces of info are required. The function name,
80# a format string, and an argument list
81#
82# Entry format:
83#
84# function: format{fn_arg1}_{fn_arg2} fn_arg1 fn_arg2 ... [color=purple]
85#
86# Required Arguments:
87#
88# function: The symbol name for the function you want probed, this is the
89# minimum required for an entry, it will show up as the function
90# name with no arguments.
91#
92# example: _cpu_up:
93#
94# Optional Arguments:
95#
96# format: The format to display the data on the timeline in. Use braces to
97# enclose the arg names.
98#
99# example: CPU_ON[{cpu}]
100#
101# color: The color of the entry block in the timeline. The default color is
102# transparent, so the entry shares the phase color. The color is an
103# html color string, either a word, or an RGB.
104#
105# example: [color=#CC00CC]
106#
107# arglist: A list of arguments from registers/stack addresses. See URL:
108# https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt
109#
110# example: cpu=%di:s32
111#
112# Example: Display cpu resume in the timeline
113#
114# _cpu_up: CPU_ON[{cpu}] cpu=%di:s32 [color=orange]
115#
116_cpu_down: CPU_OFF[{cpu}] cpu=%di:s32
117_cpu_up: CPU_ON[{cpu}] cpu=%di:s32
118sys_sync:
119pm_prepare_console:
120pm_notifier_call_chain:
121freeze_processes:
122freeze_kernel_threads:
123pm_restrict_gfp_mask:
124acpi_suspend_begin:
125suspend_console:
126acpi_pm_prepare:
127syscore_suspend:
128arch_enable_nonboot_cpus_end:
129syscore_resume:
130acpi_pm_finish:
131resume_console:
132acpi_pm_end:
133pm_restore_gfp_mask:
134thaw_processes:
135pm_restore_console:
136
137[dev_timeline_functions_x86_64]
138#
139# Dev mode function calls to display inside timeline entries
140#
141# This is a list of kprobes which use both symbol data and function arg data.
142# The function calls are displayed on the timeline alongside the device blocks.
143# The args are pulled directly from the stack using this architecture's registers
144# and stack formatting. Three pieces of info are required. The function name,
145# a format string, and an argument list
146#
147# Entry format:
148#
149# function: format{fn_arg1}_{fn_arg2} fn_arg1 fn_arg2 ... [color=purple]
150#
151# Required Arguments:
152#
153# function: The symbol name for the function you want probed, this is the
154# minimum required for an entry, it will show up as the function
155# name with no arguments.
156#
157# example: ata_eh_recover:
158#
159# Optional Arguments:
160#
161# format: The format to display the data on the timeline in. Use braces to
162# enclose the arg names.
163#
164# example: ata{port}_port_reset
165#
166# color: The color of the entry block in the timeline. The default color is
167# transparent, so the entry shares the phase color. The color is an
168# html color string, either a word, or an RGB.
169#
170# example: [color=#CC00CC]
171#
172# arglist: A list of arguments from registers/stack addresses. See URL:
173# https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt
174#
175# example: port=+36(%di):s32
176#
177# Example: Display ATA port reset as ataN_port_reset in the timeline
178#
179# ata_eh_recover: ata{port}_port_reset port=+36(%di):s32
180#
181msleep: msleep time=%di:s32
182schedule_timeout_uninterruptible: schedule_timeout_uninterruptible timeout=%di:s32
183schedule_timeout: schedule_timeout timeout=%di:s32
184usleep_range: usleep_range min=%di:s32 max=%si:s32
185__const_udelay: udelay loops=%di:s32
186__mutex_lock_slowpath: mutex_lock_slowpath
187ata_eh_recover: ata_eh_recover port=+36(%di):s32
188acpi_os_stall:
189acpi_resume_power_resources:
190acpi_ps_parse_aml:
191ext4_sync_fs:
192i915_gem_resume:
193i915_restore_state:
194intel_opregion_setup:
195g4x_pre_enable_dp:
196vlv_pre_enable_dp:
197chv_pre_enable_dp:
198g4x_enable_dp:
199vlv_enable_dp:
200intel_hpd_init:
201intel_opregion_register:
202intel_dp_detect:
203intel_hdmi_detect:
204intel_opregion_init:
205intel_fbdev_set_suspend:
diff --git a/tools/power/pm-graph/config/example.cfg b/tools/power/pm-graph/config/example.cfg
new file mode 100644
index 000000000000..05b2efb9bb54
--- /dev/null
+++ b/tools/power/pm-graph/config/example.cfg
@@ -0,0 +1,133 @@
1#
2# Generic S3 (Suspend to Mem) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/example.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: mem
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: suspend-{hostname}-{date}-{time}
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: true
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# Skip HTML generation
41# Only capture the logs, don't generate the html timeline (default: false)
42skiphtml: false
43
44# Sync filesystem before suspend
45# run sync before the test, minimizes sys_sync call time (default: false)
46sync: true
47
48# Runtime suspend enable/disable
49# Enable/disable runtime suspend for all devices, restore all after test (default: no-action)
50# rs: disable
51
52# Turn display on/off for test
53# Switch the display on/off for the test using xset (default: no-action)
54# display: on
55
56# Print results to text file
57# Print the status of the test run in the given file (default: no-action)
58result: result.txt
59
60# Gzip the log files to save space
61# Gzip the generated log files, and read gzipped log files (default: false)
62gzip: true
63
64# ---- Advanced Options ----
65
66# Command to execute in lieu of suspend (default: "")
67# command: echo mem > /sys/power/state
68
69# Display user processes
70# graph user processes and cpu usage in the timeline (default: false)
71proc: false
72
73# Display function calls
74# graph source functions in the timeline (default: false)
75dev: false
76
77# Multiple test runs
78# Run N tests D seconds apart, generates separate outputs with a summary (default: false)
79# multi: 3 5
80
81# Back to Back Suspend/Resume
82# Run two suspend/resumes back to back and display in the same timeline (default: false)
83x2: false
84
85# Back to Back Suspend Delay
86# Time delay between the two test runs in ms (default: 0 ms)
87x2delay: 0
88
89# Pre Suspend Delay
90# Include an N ms delay before (1st) suspend (default: 0 ms)
91predelay: 0
92
93# Post Resume Delay
94# Include an N ms delay after (last) resume (default: 0 ms)
95postdelay: 0
96
97# Minimum Device Length
98# graph only devices longer than min in the timeline (default: 0.001 ms)
99mindev: 0.001
100
101# ---- Debug Options ----
102
103# Callgraph
104# gather detailed ftrace callgraph data on all timeline events (default: false)
105callgraph: false
106
107# Callgraph phase filter
108# Only enable callgraphs for one phase, i.e. resume_noirq (default: all)
109cgphase: suspend
110
111# Callgraph x2 test filter
112# Only enable callgraphs test 0 or 1 when using -x2 (default: 1)
113cgtest: 0
114
115# Expand Callgraph
116# pre-expand the callgraph data in the html output (default: disabled)
117expandcg: false
118
119# Minimum Callgraph Length
120# provide callgraph data for blocks longer than min (default: 0.001 ms)
121mincg: 1
122
123# Timestamp Precision
124# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
125timeprec: 6
126
127# Device Filter
128# show only devices whose name/driver includes one of these strings
129# devicefilter: _cpu_up,_cpu_down,i915,usb
130
131# Add kprobe functions to the timeline
132# Add functions to the timeline from a text file (default: no-action)
133# fadd: file.txt
diff --git a/tools/power/pm-graph/config/freeze-callgraph.cfg b/tools/power/pm-graph/config/freeze-callgraph.cfg
new file mode 100644
index 000000000000..f692821c4828
--- /dev/null
+++ b/tools/power/pm-graph/config/freeze-callgraph.cfg
@@ -0,0 +1,94 @@
1#
2# Full Callgraph for S2 (Freeze) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/freeze-callgraph.cfg
10#
11# NOTE: the output of this test is very large (> 30MB)
12
13[Settings]
14
15# ---- General Options ----
16
17# Verbosity
18# print verbose messages (default: false)
19verbose: false
20
21# Suspend Mode
22# e.g. standby, mem, freeze, disk (default: mem)
23mode: freeze
24
25# Output Directory Format
26# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
27output-dir: freeze-{hostname}-{date}-{time}-cg
28
29# Automatic Wakeup
30# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
31rtcwake: 15
32
33# Add Logs
34# add the dmesg and ftrace log to the html output (default: false)
35addlogs: false
36
37# Suspend/Resume Gap
38# insert a small visible gap between suspend and resume on the timeline (default: false)
39srgap: false
40
41# ---- Advanced Options ----
42
43# Command to execute in lieu of freeze (default: "")
44# command: echo freeze > /sys/power/state
45
46# Display user processes
47# graph user processes and cpu usage in the timeline (default: false)
48proc: false
49
50# Display function calls
51# graph source functions in the timeline (default: false)
52dev: false
53
54# Back to Back Suspend/Resume
55# Run two suspend/resumes back to back (default: false)
56x2: false
57
58# Back to Back Suspend Delay
59# Time delay between the two test runs in ms (default: 0 ms)
60x2delay: 0
61
62# Pre Suspend Delay
63# Include an N ms delay before (1st) suspend (default: 0 ms)
64predelay: 0
65
66# Post Resume Delay
67# Include an N ms delay after (last) resume (default: 0 ms)
68postdelay: 0
69
70# Minimum Device Length
71# graph only devices longer than min in the timeline (default: 0.001 ms)
72mindev: 1
73
74# ---- Debug Options ----
75
76# Callgraph
77# gather detailed ftrace callgraph data on all timeline events (default: false)
78callgraph: true
79
80# Expand Callgraph
81# pre-expand the callgraph data in the html output (default: disabled)
82expandcg: false
83
84# Minimum Callgraph Length
85# provide callgraph data for blocks longer than min (default: 0.001 ms)
86mincg: 1
87
88# Timestamp Precision
89# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
90timeprec: 6
91
92# Device Filter
93# show only devs whose name/driver includes one of these strings
94# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/freeze-dev.cfg b/tools/power/pm-graph/config/freeze-dev.cfg
new file mode 100644
index 000000000000..c4ad5cea3cbf
--- /dev/null
+++ b/tools/power/pm-graph/config/freeze-dev.cfg
@@ -0,0 +1,93 @@
1#
2# Dev S2 (Freeze) test - includes src calls / kernel threads
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/freeze-dev.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: freeze
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: freeze-{hostname}-{date}-{time}-dev
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of freeze (default: "")
43# command: echo freeze > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: false
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: true
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: false
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 0
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 0
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 0
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 1
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/freeze.cfg b/tools/power/pm-graph/config/freeze.cfg
new file mode 100644
index 000000000000..0b70e0b74527
--- /dev/null
+++ b/tools/power/pm-graph/config/freeze.cfg
@@ -0,0 +1,93 @@
1#
2# Generic S2 (Freeze) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/freeze.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: freeze
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: freeze-{hostname}-{date}-{time}
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of freeze (default: "")
43# command: echo freeze > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: false
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: false
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: false
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 0
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 0
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 0
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 0.001
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/standby-callgraph.cfg b/tools/power/pm-graph/config/standby-callgraph.cfg
new file mode 100644
index 000000000000..f52a6b9d5c32
--- /dev/null
+++ b/tools/power/pm-graph/config/standby-callgraph.cfg
@@ -0,0 +1,94 @@
1#
2# Full Callgraph for S1 (Standby) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/standby-callgraph.cfg
10#
11# NOTE: the output of this test is very large (> 30MB)
12
13[Settings]
14
15# ---- General Options ----
16
17# Verbosity
18# print verbose messages (default: false)
19verbose: false
20
21# Suspend Mode
22# e.g. standby, mem, freeze, disk (default: mem)
23mode: standby
24
25# Output Directory Format
26# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
27output-dir: standby-{hostname}-{date}-{time}-cg
28
29# Automatic Wakeup
30# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
31rtcwake: 15
32
33# Add Logs
34# add the dmesg and ftrace log to the html output (default: false)
35addlogs: false
36
37# Suspend/Resume Gap
38# insert a small visible gap between suspend and resume on the timeline (default: false)
39srgap: false
40
41# ---- Advanced Options ----
42
43# Command to execute in lieu of standby (default: "")
44# command: echo standby > /sys/power/state
45
46# Display user processes
47# graph user processes and cpu usage in the timeline (default: false)
48proc: false
49
50# Display function calls
51# graph source functions in the timeline (default: false)
52dev: false
53
54# Back to Back Suspend/Resume
55# Run two suspend/resumes back to back (default: false)
56x2: false
57
58# Back to Back Suspend Delay
59# Time delay between the two test runs in ms (default: 0 ms)
60x2delay: 0
61
62# Pre Suspend Delay
63# Include an N ms delay before (1st) suspend (default: 0 ms)
64predelay: 0
65
66# Post Resume Delay
67# Include an N ms delay after (last) resume (default: 0 ms)
68postdelay: 0
69
70# Minimum Device Length
71# graph only devices longer than min in the timeline (default: 0.001 ms)
72mindev: 1
73
74# ---- Debug Options ----
75
76# Callgraph
77# gather detailed ftrace callgraph data on all timeline events (default: false)
78callgraph: true
79
80# Expand Callgraph
81# pre-expand the callgraph data in the html output (default: disabled)
82expandcg: false
83
84# Minimum Callgraph Length
85# provide callgraph data for blocks longer than min (default: 0.001 ms)
86mincg: 1
87
88# Timestamp Precision
89# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
90timeprec: 6
91
92# Device Filter
93# show only devs whose name/driver includes one of these strings
94# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/standby-dev.cfg b/tools/power/pm-graph/config/standby-dev.cfg
new file mode 100644
index 000000000000..a5498ece3def
--- /dev/null
+++ b/tools/power/pm-graph/config/standby-dev.cfg
@@ -0,0 +1,93 @@
1#
2# Dev S1 (Standby) test - includes src calls / kernel threads
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/standby-dev.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: standby
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: standby-{hostname}-{date}-{time}-dev
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of standby (default: "")
43# command: echo standby > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: false
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: true
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: false
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 0
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 0
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 0
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 1
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/standby.cfg b/tools/power/pm-graph/config/standby.cfg
new file mode 100644
index 000000000000..f0dd264dfeff
--- /dev/null
+++ b/tools/power/pm-graph/config/standby.cfg
@@ -0,0 +1,93 @@
1#
2# Generic S1 (Standby) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/standby.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: standby
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: standby-{hostname}-{date}-{time}
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of standby (default: "")
43# command: echo standby > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: false
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: false
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: false
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 0
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 0
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 0
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 0.001
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/suspend-callgraph.cfg b/tools/power/pm-graph/config/suspend-callgraph.cfg
new file mode 100644
index 000000000000..11b8cbc12d34
--- /dev/null
+++ b/tools/power/pm-graph/config/suspend-callgraph.cfg
@@ -0,0 +1,98 @@
1#
2# Full Callgraph for S3 (Suspend to Mem) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/suspend.cfg
10#
11# NOTE: the output of this test is very large (> 30MB)
12
13[Settings]
14
15# ---- General Options ----
16
17# Verbosity
18# print verbose messages (default: false)
19verbose: false
20
21# Suspend Mode
22# e.g. standby, mem, freeze, disk (default: mem)
23mode: mem
24
25# Output Directory Format
26# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
27output-dir: suspend-{hostname}-{date}-{time}-cg
28
29# Automatic Wakeup
30# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
31rtcwake: 15
32
33# Add Logs
34# add the dmesg and ftrace log to the html output (default: false)
35addlogs: false
36
37# Suspend/Resume Gap
38# insert a small visible gap between suspend and resume on the timeline (default: false)
39srgap: false
40
41# ---- Advanced Options ----
42
43# Command to execute in lieu of suspend (default: "")
44# command: echo mem > /sys/power/state
45
46# Display user processes
47# graph user processes and cpu usage in the timeline (default: false)
48proc: false
49
50# Display function calls
51# graph source functions in the timeline (default: false)
52dev: false
53
54# Back to Back Suspend/Resume
55# Run two suspend/resumes back to back (default: false)
56x2: false
57
58# Back to Back Suspend Delay
59# Time delay between the two test runs in ms (default: 0 ms)
60x2delay: 0
61
62# Pre Suspend Delay
63# Include an N ms delay before (1st) suspend (default: 0 ms)
64predelay: 0
65
66# Post Resume Delay
67# Include an N ms delay after (last) resume (default: 0 ms)
68postdelay: 0
69
70# Minimum Device Length
71# graph only devices longer than min in the timeline (default: 0.001 ms)
72mindev: 0.001
73
74# ---- Debug Options ----
75
76# Callgraph
77# gather detailed ftrace callgraph data on all timeline events (default: false)
78callgraph: true
79
80# Max graph depth
81# limit the callgraph trace to this depth (default: 0 = all)
82maxdepth: 5
83
84# Expand Callgraph
85# pre-expand the callgraph data in the html output (default: disabled)
86expandcg: false
87
88# Minimum Callgraph Length
89# provide callgraph data for blocks longer than min (default: 0.001 ms)
90mincg: 1
91
92# Timestamp Precision
93# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
94timeprec: 6
95
96# Device Filter
97# show only devs whose name/driver includes one of these strings
98# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/suspend-dev.cfg b/tools/power/pm-graph/config/suspend-dev.cfg
new file mode 100644
index 000000000000..56f1d21cc79b
--- /dev/null
+++ b/tools/power/pm-graph/config/suspend-dev.cfg
@@ -0,0 +1,93 @@
1#
2# Dev S3 (Suspend to Mem) test - includes src calls / kernel threads
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/suspend-dev.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: mem
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: suspend-{hostname}-{date}-{time}-dev
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of suspend (default: "")
43# command: echo mem > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: false
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: true
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: false
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 0
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 0
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 0
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 1
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/suspend-x2-proc.cfg b/tools/power/pm-graph/config/suspend-x2-proc.cfg
new file mode 100644
index 000000000000..0ecca0ede138
--- /dev/null
+++ b/tools/power/pm-graph/config/suspend-x2-proc.cfg
@@ -0,0 +1,93 @@
1#
2# Proc S3 (Suspend to Mem) x2 test - includes user processes
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/suspend-proc.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: mem
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: suspend-{hostname}-{date}-{time}-x2-proc
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of suspend (default: "")
43# command: echo mem > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: true
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: false
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: true
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 1000
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 1000
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 1000
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 1
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/config/suspend.cfg b/tools/power/pm-graph/config/suspend.cfg
new file mode 100644
index 000000000000..70d293231b06
--- /dev/null
+++ b/tools/power/pm-graph/config/suspend.cfg
@@ -0,0 +1,93 @@
1#
2# Generic S3 (Suspend to Mem) test
3#
4# This is the configuration file for sleepgraph. It contains
5# all the tool arguments so that they don't have to be given on the
6# command line. It also includes advanced settings for functions
7# and kprobes. It is run like this
8#
9# sudo ./sleepgraph.py -config config/suspend.cfg
10#
11
12[Settings]
13
14# ---- General Options ----
15
16# Verbosity
17# print verbose messages (default: false)
18verbose: false
19
20# Suspend Mode
21# e.g. standby, mem, freeze, disk (default: mem)
22mode: mem
23
24# Output Directory Format
25# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
26output-dir: suspend-{hostname}-{date}-{time}
27
28# Automatic Wakeup
29# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
30rtcwake: 15
31
32# Add Logs
33# add the dmesg and ftrace log to the html output (default: false)
34addlogs: false
35
36# Suspend/Resume Gap
37# insert a small visible gap between suspend and resume on the timeline (default: false)
38srgap: false
39
40# ---- Advanced Options ----
41
42# Command to execute in lieu of suspend (default: "")
43# command: echo mem > /sys/power/state
44
45# Display user processes
46# graph user processes and cpu usage in the timeline (default: false)
47proc: false
48
49# Display function calls
50# graph source functions in the timeline (default: false)
51dev: false
52
53# Back to Back Suspend/Resume
54# Run two suspend/resumes back to back (default: false)
55x2: false
56
57# Back to Back Suspend Delay
58# Time delay between the two test runs in ms (default: 0 ms)
59x2delay: 0
60
61# Pre Suspend Delay
62# Include an N ms delay before (1st) suspend (default: 0 ms)
63predelay: 0
64
65# Post Resume Delay
66# Include an N ms delay after (last) resume (default: 0 ms)
67postdelay: 0
68
69# Minimum Device Length
70# graph only devices longer than min in the timeline (default: 0.001 ms)
71mindev: 0.001
72
73# ---- Debug Options ----
74
75# Callgraph
76# gather detailed ftrace callgraph data on all timeline events (default: false)
77callgraph: false
78
79# Expand Callgraph
80# pre-expand the callgraph data in the html output (default: disabled)
81expandcg: false
82
83# Minimum Callgraph Length
84# provide callgraph data for blocks longer than min (default: 0.001 ms)
85mincg: 1
86
87# Timestamp Precision
88# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
89timeprec: 3
90
91# Device Filter
92# show only devs whose name/driver includes one of these strings
93# devicefilter: _cpu_up,_cpu_down,i915,usb
diff --git a/tools/power/pm-graph/sleepgraph.8 b/tools/power/pm-graph/sleepgraph.8
index fbe7bd3eae8e..18baaf6300c9 100644
--- a/tools/power/pm-graph/sleepgraph.8
+++ b/tools/power/pm-graph/sleepgraph.8
@@ -52,9 +52,32 @@ disable rtcwake and require a user keypress to resume.
52\fB-addlogs\fR 52\fB-addlogs\fR
53Add the dmesg and ftrace logs to the html output. They will be viewable by 53Add the dmesg and ftrace logs to the html output. They will be viewable by
54clicking buttons in the timeline. 54clicking buttons in the timeline.
55.TP
56\fB-result \fIfile\fR
57Export a results table to a text file for parsing.
58.TP
59\fB-sync\fR
60Sync the filesystems before starting the test. This reduces the size of
61the sys_sync call which happens in the suspend_prepare phase.
62.TP
63\fB-rs \fIenable/disable\fR
64During test, enable/disable runtime suspend for all devices. The test is delayed
65by 5 seconds to allow runtime suspend changes to occur. The settings are restored
66after the test is complete.
67.TP
68\fB-display \fIon/off\fR
69Turn the display on or off for the test using the xset command. This helps
70maintain the consistecy of test data for better comparison.
71.TP
72\fB-skiphtml\fR
73Run the test and capture the trace logs, but skip the timeline generation.
55 74
56.SS "advanced" 75.SS "advanced"
57.TP 76.TP
77\fB-gzip\fR
78Gzip the trace and dmesg logs to save space. The tool can also read in gzipped
79logs for processing.
80.TP
58\fB-cmd \fIstr\fR 81\fB-cmd \fIstr\fR
59Run the timeline over a custom suspend command, e.g. pm-suspend. By default 82Run the timeline over a custom suspend command, e.g. pm-suspend. By default
60the tool forces suspend via /sys/power/state so this allows testing over 83the tool forces suspend via /sys/power/state so this allows testing over
@@ -114,6 +137,18 @@ This reduces the html file size as there can be many tiny callgraphs
114which are barely visible in the timeline. 137which are barely visible in the timeline.
115The value is a float: e.g. 0.001 represents 1 us. 138The value is a float: e.g. 0.001 represents 1 us.
116.TP 139.TP
140\fB-cgfilter \fI"func1,func2,..."\fR
141Reduce callgraph output in the timeline by limiting it to a list of calls. The
142argument can be a single function name or a comma delimited list.
143(default: none)
144.TP
145\fB-cgskip \fIfile\fR
146Reduce callgraph timeline size by skipping over uninteresting functions
147in the trace, e.g. printk or console_unlock. The functions listed
148in this file will show up as empty leaves in the callgraph with only the start/end
149times displayed. cgskip.txt is used automatically if found in the path, so
150use "off" to disable completely (default: cgskip.txt)
151.TP
117\fB-cgphase \fIp\fR 152\fB-cgphase \fIp\fR
118Only show callgraph data for phase \fIp\fR (e.g. suspend_late). 153Only show callgraph data for phase \fIp\fR (e.g. suspend_late).
119.TP 154.TP
@@ -122,6 +157,9 @@ In an x2 run, only show callgraph data for test \fIn\fR (e.g. 0 or 1).
122.TP 157.TP
123\fB-timeprec \fIn\fR 158\fB-timeprec \fIn\fR
124Number of significant digits in timestamps (0:S, [3:ms], 6:us). 159Number of significant digits in timestamps (0:S, [3:ms], 6:us).
160.TP
161\fB-bufsize \fIN\fR
162Set trace buffer size to N kilo-bytes (default: all of free memory up to 3GB)
125 163
126.SH COMMANDS 164.SH COMMANDS
127.TP 165.TP
@@ -144,11 +182,8 @@ Print out the contents of the ACPI Firmware Performance Data Table.
144\fB-sysinfo\fR 182\fB-sysinfo\fR
145Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode. 183Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode.
146.TP 184.TP
147\fB-usbtopo\fR 185\fB-devinfo\fR
148Print out the current USB topology with power info. 186Print out the pm settings of all devices which support runtime suspend.
149.TP
150\fB-usbauto\fR
151Enable autosuspend for all connected USB devices.
152.TP 187.TP
153\fB-flist\fR 188\fB-flist\fR
154Print the list of ftrace functions currently being captured. Functions 189Print the list of ftrace functions currently being captured. Functions
@@ -198,7 +233,7 @@ Execute a mem suspend with a 15 second wakeup. Include the logs in the html.
198.PP 233.PP
199Execute a standby with a 15 second wakeup. Change the output folder name. 234Execute a standby with a 15 second wakeup. Change the output folder name.
200.IP 235.IP
201\f(CW$ sudo sleepgraph -m standby -rtcwake 15 -o "standby-{hostname}-{date}-{time}"\fR 236\f(CW$ sudo sleepgraph -m standby -rtcwake 15 -o "standby-{host}-{date}-{time}"\fR
202.PP 237.PP
203Execute a freeze with no wakeup (require keypress). Change output folder name. 238Execute a freeze with no wakeup (require keypress). Change output folder name.
204.IP 239.IP
diff --git a/tools/power/pm-graph/analyze_suspend.py b/tools/power/pm-graph/sleepgraph.py
index 1b60fe203741..266409fb27ae 100755
--- a/tools/power/pm-graph/analyze_suspend.py
+++ b/tools/power/pm-graph/sleepgraph.py
@@ -19,7 +19,7 @@
19# Home Page 19# Home Page
20# https://01.org/suspendresume 20# https://01.org/suspendresume
21# Source repo 21# Source repo
22# https://github.com/01org/pm-graph 22# git@github.com:01org/pm-graph
23# 23#
24# Description: 24# Description:
25# This tool is designed to assist kernel and OS developers in optimizing 25# This tool is designed to assist kernel and OS developers in optimizing
@@ -57,6 +57,7 @@ import platform
57from datetime import datetime 57from datetime import datetime
58import struct 58import struct
59import ConfigParser 59import ConfigParser
60import gzip
60from threading import Thread 61from threading import Thread
61from subprocess import call, Popen, PIPE 62from subprocess import call, Popen, PIPE
62 63
@@ -68,8 +69,12 @@ from subprocess import call, Popen, PIPE
68# store system values and test parameters 69# store system values and test parameters
69class SystemValues: 70class SystemValues:
70 title = 'SleepGraph' 71 title = 'SleepGraph'
71 version = '4.7' 72 version = '5.0'
72 ansi = False 73 ansi = False
74 rs = 0
75 display = 0
76 gzip = False
77 sync = False
73 verbose = False 78 verbose = False
74 testlog = True 79 testlog = True
75 dmesglog = False 80 dmesglog = False
@@ -78,14 +83,19 @@ class SystemValues:
78 mincglen = 0.0 83 mincglen = 0.0
79 cgphase = '' 84 cgphase = ''
80 cgtest = -1 85 cgtest = -1
86 cgskip = ''
87 multitest = {'run': False, 'count': 0, 'delay': 0}
81 max_graph_depth = 0 88 max_graph_depth = 0
82 callloopmaxgap = 0.0001 89 callloopmaxgap = 0.0001
83 callloopmaxlen = 0.005 90 callloopmaxlen = 0.005
91 bufsize = 0
84 cpucount = 0 92 cpucount = 0
85 memtotal = 204800 93 memtotal = 204800
94 memfree = 204800
86 srgap = 0 95 srgap = 0
87 cgexp = False 96 cgexp = False
88 testdir = '' 97 testdir = ''
98 outdir = ''
89 tpath = '/sys/kernel/debug/tracing/' 99 tpath = '/sys/kernel/debug/tracing/'
90 fpdtpath = '/sys/firmware/acpi/tables/FPDT' 100 fpdtpath = '/sys/firmware/acpi/tables/FPDT'
91 epath = '/sys/kernel/debug/tracing/events/power/' 101 epath = '/sys/kernel/debug/tracing/events/power/'
@@ -109,22 +119,24 @@ class SystemValues:
109 dmesgfile = '' 119 dmesgfile = ''
110 ftracefile = '' 120 ftracefile = ''
111 htmlfile = 'output.html' 121 htmlfile = 'output.html'
112 embedded = False 122 result = ''
113 rtcwake = True 123 rtcwake = True
114 rtcwaketime = 15 124 rtcwaketime = 15
115 rtcpath = '' 125 rtcpath = ''
116 devicefilter = [] 126 devicefilter = []
127 cgfilter = []
117 stamp = 0 128 stamp = 0
118 execcount = 1 129 execcount = 1
119 x2delay = 0 130 x2delay = 0
131 skiphtml = False
120 usecallgraph = False 132 usecallgraph = False
121 usetraceevents = False 133 usetraceevents = False
122 usetraceeventsonly = False
123 usetracemarkers = True 134 usetracemarkers = True
124 usekprobes = True 135 usekprobes = True
125 usedevsrc = False 136 usedevsrc = False
126 useprocmon = False 137 useprocmon = False
127 notestrun = False 138 notestrun = False
139 cgdump = False
128 mixedphaseheight = True 140 mixedphaseheight = True
129 devprops = dict() 141 devprops = dict()
130 predelay = 0 142 predelay = 0
@@ -134,24 +146,33 @@ class SystemValues:
134 tracertypefmt = '# tracer: (?P<t>.*)' 146 tracertypefmt = '# tracer: (?P<t>.*)'
135 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$' 147 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$'
136 tracefuncs = { 148 tracefuncs = {
137 'sys_sync': dict(), 149 'sys_sync': {},
138 'pm_prepare_console': dict(), 150 '__pm_notifier_call_chain': {},
139 'pm_notifier_call_chain': dict(), 151 'pm_prepare_console': {},
140 'freeze_processes': dict(), 152 'pm_notifier_call_chain': {},
141 'freeze_kernel_threads': dict(), 153 'freeze_processes': {},
142 'pm_restrict_gfp_mask': dict(), 154 'freeze_kernel_threads': {},
143 'acpi_suspend_begin': dict(), 155 'pm_restrict_gfp_mask': {},
144 'suspend_console': dict(), 156 'acpi_suspend_begin': {},
145 'acpi_pm_prepare': dict(), 157 'acpi_hibernation_begin': {},
146 'syscore_suspend': dict(), 158 'acpi_hibernation_enter': {},
147 'arch_enable_nonboot_cpus_end': dict(), 159 'acpi_hibernation_leave': {},
148 'syscore_resume': dict(), 160 'acpi_pm_freeze': {},
149 'acpi_pm_finish': dict(), 161 'acpi_pm_thaw': {},
150 'resume_console': dict(), 162 'hibernate_preallocate_memory': {},
151 'acpi_pm_end': dict(), 163 'create_basic_memory_bitmaps': {},
152 'pm_restore_gfp_mask': dict(), 164 'swsusp_write': {},
153 'thaw_processes': dict(), 165 'suspend_console': {},
154 'pm_restore_console': dict(), 166 'acpi_pm_prepare': {},
167 'syscore_suspend': {},
168 'arch_enable_nonboot_cpus_end': {},
169 'syscore_resume': {},
170 'acpi_pm_finish': {},
171 'resume_console': {},
172 'acpi_pm_end': {},
173 'pm_restore_gfp_mask': {},
174 'thaw_processes': {},
175 'pm_restore_console': {},
155 'CPU_OFF': { 176 'CPU_OFF': {
156 'func':'_cpu_down', 177 'func':'_cpu_down',
157 'args_x86_64': {'cpu':'%di:s32'}, 178 'args_x86_64': {'cpu':'%di:s32'},
@@ -173,56 +194,54 @@ class SystemValues:
173 'mutex_lock_slowpath': { 'func':'__mutex_lock_slowpath', 'ub': 1 }, 194 'mutex_lock_slowpath': { 'func':'__mutex_lock_slowpath', 'ub': 1 },
174 'acpi_os_stall': {'ub': 1}, 195 'acpi_os_stall': {'ub': 1},
175 # ACPI 196 # ACPI
176 'acpi_resume_power_resources': dict(), 197 'acpi_resume_power_resources': {},
177 'acpi_ps_parse_aml': dict(), 198 'acpi_ps_parse_aml': {},
178 # filesystem 199 # filesystem
179 'ext4_sync_fs': dict(), 200 'ext4_sync_fs': {},
180 # 80211 201 # 80211
181 'iwlagn_mac_start': dict(), 202 'iwlagn_mac_start': {},
182 'iwlagn_alloc_bcast_station': dict(), 203 'iwlagn_alloc_bcast_station': {},
183 'iwl_trans_pcie_start_hw': dict(), 204 'iwl_trans_pcie_start_hw': {},
184 'iwl_trans_pcie_start_fw': dict(), 205 'iwl_trans_pcie_start_fw': {},
185 'iwl_run_init_ucode': dict(), 206 'iwl_run_init_ucode': {},
186 'iwl_load_ucode_wait_alive': dict(), 207 'iwl_load_ucode_wait_alive': {},
187 'iwl_alive_start': dict(), 208 'iwl_alive_start': {},
188 'iwlagn_mac_stop': dict(), 209 'iwlagn_mac_stop': {},
189 'iwlagn_mac_suspend': dict(), 210 'iwlagn_mac_suspend': {},
190 'iwlagn_mac_resume': dict(), 211 'iwlagn_mac_resume': {},
191 'iwlagn_mac_add_interface': dict(), 212 'iwlagn_mac_add_interface': {},
192 'iwlagn_mac_remove_interface': dict(), 213 'iwlagn_mac_remove_interface': {},
193 'iwlagn_mac_change_interface': dict(), 214 'iwlagn_mac_change_interface': {},
194 'iwlagn_mac_config': dict(), 215 'iwlagn_mac_config': {},
195 'iwlagn_configure_filter': dict(), 216 'iwlagn_configure_filter': {},
196 'iwlagn_mac_hw_scan': dict(), 217 'iwlagn_mac_hw_scan': {},
197 'iwlagn_bss_info_changed': dict(), 218 'iwlagn_bss_info_changed': {},
198 'iwlagn_mac_channel_switch': dict(), 219 'iwlagn_mac_channel_switch': {},
199 'iwlagn_mac_flush': dict(), 220 'iwlagn_mac_flush': {},
200 # ATA 221 # ATA
201 'ata_eh_recover': { 'args_x86_64': {'port':'+36(%di):s32'} }, 222 'ata_eh_recover': { 'args_x86_64': {'port':'+36(%di):s32'} },
202 # i915 223 # i915
203 'i915_gem_resume': dict(), 224 'i915_gem_resume': {},
204 'i915_restore_state': dict(), 225 'i915_restore_state': {},
205 'intel_opregion_setup': dict(), 226 'intel_opregion_setup': {},
206 'g4x_pre_enable_dp': dict(), 227 'g4x_pre_enable_dp': {},
207 'vlv_pre_enable_dp': dict(), 228 'vlv_pre_enable_dp': {},
208 'chv_pre_enable_dp': dict(), 229 'chv_pre_enable_dp': {},
209 'g4x_enable_dp': dict(), 230 'g4x_enable_dp': {},
210 'vlv_enable_dp': dict(), 231 'vlv_enable_dp': {},
211 'intel_hpd_init': dict(), 232 'intel_hpd_init': {},
212 'intel_opregion_register': dict(), 233 'intel_opregion_register': {},
213 'intel_dp_detect': dict(), 234 'intel_dp_detect': {},
214 'intel_hdmi_detect': dict(), 235 'intel_hdmi_detect': {},
215 'intel_opregion_init': dict(), 236 'intel_opregion_init': {},
216 'intel_fbdev_set_suspend': dict(), 237 'intel_fbdev_set_suspend': {},
217 } 238 }
239 cgblacklist = []
218 kprobes = dict() 240 kprobes = dict()
219 timeformat = '%.3f' 241 timeformat = '%.3f'
242 cmdline = '%s %s' % \
243 (os.path.basename(sys.argv[0]), string.join(sys.argv[1:], ' '))
220 def __init__(self): 244 def __init__(self):
221 # if this is a phoronix test run, set some default options
222 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ):
223 self.embedded = True
224 self.dmesglog = self.ftracelog = True
225 self.htmlfile = os.environ['LOG_FILE']
226 self.archargs = 'args_'+platform.machine() 245 self.archargs = 'args_'+platform.machine()
227 self.hostname = platform.node() 246 self.hostname = platform.node()
228 if(self.hostname == ''): 247 if(self.hostname == ''):
@@ -237,18 +256,36 @@ class SystemValues:
237 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()): 256 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()):
238 self.ansi = True 257 self.ansi = True
239 self.testdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S') 258 self.testdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S')
259 def vprint(self, msg):
260 self.logmsg += msg+'\n'
261 if(self.verbose):
262 print(msg)
240 def rootCheck(self, fatal=True): 263 def rootCheck(self, fatal=True):
241 if(os.access(self.powerfile, os.W_OK)): 264 if(os.access(self.powerfile, os.W_OK)):
242 return True 265 return True
243 if fatal: 266 if fatal:
244 doError('This command requires sysfs mount and root access') 267 msg = 'This command requires sysfs mount and root access'
268 print('ERROR: %s\n') % msg
269 self.outputResult({'error':msg})
270 sys.exit()
245 return False 271 return False
246 def rootUser(self, fatal=False): 272 def rootUser(self, fatal=False):
247 if 'USER' in os.environ and os.environ['USER'] == 'root': 273 if 'USER' in os.environ and os.environ['USER'] == 'root':
248 return True 274 return True
249 if fatal: 275 if fatal:
250 doError('This command must be run as root') 276 msg = 'This command must be run as root'
277 print('ERROR: %s\n') % msg
278 self.outputResult({'error':msg})
279 sys.exit()
251 return False 280 return False
281 def getExec(self, cmd):
282 dirlist = ['/sbin', '/bin', '/usr/sbin', '/usr/bin',
283 '/usr/local/sbin', '/usr/local/bin']
284 for path in dirlist:
285 cmdfull = os.path.join(path, cmd)
286 if os.path.exists(cmdfull):
287 return cmdfull
288 return ''
252 def setPrecision(self, num): 289 def setPrecision(self, num):
253 if num < 0 or num > 6: 290 if num < 0 or num > 6:
254 return 291 return
@@ -258,15 +295,15 @@ class SystemValues:
258 n = datetime.now() 295 n = datetime.now()
259 args['date'] = n.strftime('%y%m%d') 296 args['date'] = n.strftime('%y%m%d')
260 args['time'] = n.strftime('%H%M%S') 297 args['time'] = n.strftime('%H%M%S')
261 args['hostname'] = self.hostname 298 args['hostname'] = args['host'] = self.hostname
262 return value.format(**args) 299 return value.format(**args)
263 def setOutputFile(self): 300 def setOutputFile(self):
264 if self.dmesgfile != '': 301 if self.dmesgfile != '':
265 m = re.match('(?P<name>.*)_dmesg\.txt$', self.dmesgfile) 302 m = re.match('(?P<name>.*)_dmesg\.txt.*', self.dmesgfile)
266 if(m): 303 if(m):
267 self.htmlfile = m.group('name')+'.html' 304 self.htmlfile = m.group('name')+'.html'
268 if self.ftracefile != '': 305 if self.ftracefile != '':
269 m = re.match('(?P<name>.*)_ftrace\.txt$', self.ftracefile) 306 m = re.match('(?P<name>.*)_ftrace\.txt.*', self.ftracefile)
270 if(m): 307 if(m):
271 self.htmlfile = m.group('name')+'.html' 308 self.htmlfile = m.group('name')+'.html'
272 def systemInfo(self, info): 309 def systemInfo(self, info):
@@ -283,16 +320,19 @@ class SystemValues:
283 c = info['processor-version'] 320 c = info['processor-version']
284 if 'bios-version' in info: 321 if 'bios-version' in info:
285 b = info['bios-version'] 322 b = info['bios-version']
286 self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | numcpu:%d | memsz:%d' % \ 323 self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | numcpu:%d | memsz:%d | memfr:%d' % \
287 (m, p, c, b, self.cpucount, self.memtotal) 324 (m, p, c, b, self.cpucount, self.memtotal, self.memfree)
288 def printSystemInfo(self): 325 def printSystemInfo(self, fatal=False):
289 self.rootCheck(True) 326 self.rootCheck(True)
290 out = dmidecode(self.mempath, True) 327 out = dmidecode(self.mempath, fatal)
328 if len(out) < 1:
329 return
291 fmt = '%-24s: %s' 330 fmt = '%-24s: %s'
292 for name in sorted(out): 331 for name in sorted(out):
293 print fmt % (name, out[name]) 332 print fmt % (name, out[name])
294 print fmt % ('cpucount', ('%d' % self.cpucount)) 333 print fmt % ('cpucount', ('%d' % self.cpucount))
295 print fmt % ('memtotal', ('%d kB' % self.memtotal)) 334 print fmt % ('memtotal', ('%d kB' % self.memtotal))
335 print fmt % ('memfree', ('%d kB' % self.memfree))
296 def cpuInfo(self): 336 def cpuInfo(self):
297 self.cpucount = 0 337 self.cpucount = 0
298 fp = open('/proc/cpuinfo', 'r') 338 fp = open('/proc/cpuinfo', 'r')
@@ -305,7 +345,9 @@ class SystemValues:
305 m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line) 345 m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line)
306 if m: 346 if m:
307 self.memtotal = int(m.group('sz')) 347 self.memtotal = int(m.group('sz'))
308 break 348 m = re.match('^MemFree:[ \t]*(?P<sz>[0-9]*) *kB', line)
349 if m:
350 self.memfree = int(m.group('sz'))
309 fp.close() 351 fp.close()
310 def initTestOutput(self, name): 352 def initTestOutput(self, name):
311 self.prefix = self.hostname 353 self.prefix = self.hostname
@@ -315,39 +357,34 @@ class SystemValues:
315 testtime = datetime.now().strftime(fmt) 357 testtime = datetime.now().strftime(fmt)
316 self.teststamp = \ 358 self.teststamp = \
317 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver 359 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver
318 if(self.embedded): 360 ext = ''
319 self.dmesgfile = \ 361 if self.gzip:
320 '/tmp/'+testtime+'_'+self.suspendmode+'_dmesg.txt' 362 ext = '.gz'
321 self.ftracefile = \
322 '/tmp/'+testtime+'_'+self.suspendmode+'_ftrace.txt'
323 return
324 self.dmesgfile = \ 363 self.dmesgfile = \
325 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt' 364 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt'+ext
326 self.ftracefile = \ 365 self.ftracefile = \
327 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt' 366 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt'+ext
328 self.htmlfile = \ 367 self.htmlfile = \
329 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html' 368 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html'
330 if not os.path.isdir(self.testdir): 369 if not os.path.isdir(self.testdir):
331 os.mkdir(self.testdir) 370 os.mkdir(self.testdir)
371 def getValueList(self, value):
372 out = []
373 for i in value.split(','):
374 if i.strip():
375 out.append(i.strip())
376 return out
332 def setDeviceFilter(self, value): 377 def setDeviceFilter(self, value):
333 self.devicefilter = [] 378 self.devicefilter = self.getValueList(value)
334 if value: 379 def setCallgraphFilter(self, value):
335 value = value.split(',') 380 self.cgfilter = self.getValueList(value)
336 for i in value: 381 def setCallgraphBlacklist(self, file):
337 self.devicefilter.append(i.strip()) 382 self.cgblacklist = self.listFromFile(file)
338 def rtcWakeAlarmOn(self): 383 def rtcWakeAlarmOn(self):
339 call('echo 0 > '+self.rtcpath+'/wakealarm', shell=True) 384 call('echo 0 > '+self.rtcpath+'/wakealarm', shell=True)
340 outD = open(self.rtcpath+'/date', 'r').read().strip() 385 nowtime = open(self.rtcpath+'/since_epoch', 'r').read().strip()
341 outT = open(self.rtcpath+'/time', 'r').read().strip() 386 if nowtime:
342 mD = re.match('^(?P<y>[0-9]*)-(?P<m>[0-9]*)-(?P<d>[0-9]*)', outD) 387 nowtime = int(nowtime)
343 mT = re.match('^(?P<h>[0-9]*):(?P<m>[0-9]*):(?P<s>[0-9]*)', outT)
344 if(mD and mT):
345 # get the current time from hardware
346 utcoffset = int((datetime.now() - datetime.utcnow()).total_seconds())
347 dt = datetime(\
348 int(mD.group('y')), int(mD.group('m')), int(mD.group('d')),
349 int(mT.group('h')), int(mT.group('m')), int(mT.group('s')))
350 nowtime = int(dt.strftime('%s')) + utcoffset
351 else: 388 else:
352 # if hardware time fails, use the software time 389 # if hardware time fails, use the software time
353 nowtime = int(datetime.now().strftime('%s')) 390 nowtime = int(datetime.now().strftime('%s'))
@@ -369,10 +406,10 @@ class SystemValues:
369 ktime = m.group('ktime') 406 ktime = m.group('ktime')
370 fp.close() 407 fp.close()
371 self.dmesgstart = float(ktime) 408 self.dmesgstart = float(ktime)
372 def getdmesg(self): 409 def getdmesg(self, fwdata=[]):
410 op = self.writeDatafileHeader(sysvals.dmesgfile, fwdata)
373 # store all new dmesg lines since initdmesg was called 411 # store all new dmesg lines since initdmesg was called
374 fp = Popen('dmesg', stdout=PIPE).stdout 412 fp = Popen('dmesg', stdout=PIPE).stdout
375 op = open(self.dmesgfile, 'a')
376 for line in fp: 413 for line in fp:
377 line = line.replace('\r\n', '') 414 line = line.replace('\r\n', '')
378 idx = line.find('[') 415 idx = line.find('[')
@@ -386,11 +423,17 @@ class SystemValues:
386 op.write(line) 423 op.write(line)
387 fp.close() 424 fp.close()
388 op.close() 425 op.close()
389 def addFtraceFilterFunctions(self, file): 426 def listFromFile(self, file):
427 list = []
390 fp = open(file) 428 fp = open(file)
391 list = fp.read().split('\n') 429 for i in fp.read().split('\n'):
430 i = i.strip()
431 if i and i[0] != '#':
432 list.append(i)
392 fp.close() 433 fp.close()
393 for i in list: 434 return list
435 def addFtraceFilterFunctions(self, file):
436 for i in self.listFromFile(file):
394 if len(i) < 2: 437 if len(i) < 2:
395 continue 438 continue
396 self.tracefuncs[i] = dict() 439 self.tracefuncs[i] = dict()
@@ -399,9 +442,7 @@ class SystemValues:
399 if not current: 442 if not current:
400 call('cat '+self.tpath+'available_filter_functions', shell=True) 443 call('cat '+self.tpath+'available_filter_functions', shell=True)
401 return 444 return
402 fp = open(self.tpath+'available_filter_functions') 445 master = self.listFromFile(self.tpath+'available_filter_functions')
403 master = fp.read().split('\n')
404 fp.close()
405 for i in self.tracefuncs: 446 for i in self.tracefuncs:
406 if 'func' in self.tracefuncs[i]: 447 if 'func' in self.tracefuncs[i]:
407 i = self.tracefuncs[i]['func'] 448 i = self.tracefuncs[i]['func']
@@ -410,9 +451,7 @@ class SystemValues:
410 else: 451 else:
411 print self.colorText(i) 452 print self.colorText(i)
412 def setFtraceFilterFunctions(self, list): 453 def setFtraceFilterFunctions(self, list):
413 fp = open(self.tpath+'available_filter_functions') 454 master = self.listFromFile(self.tpath+'available_filter_functions')
414 master = fp.read().split('\n')
415 fp.close()
416 flist = '' 455 flist = ''
417 for i in list: 456 for i in list:
418 if i not in master: 457 if i not in master:
@@ -501,6 +540,7 @@ class SystemValues:
501 rejects = [] 540 rejects = []
502 # sort kprobes: trace, ub-dev, custom, dev 541 # sort kprobes: trace, ub-dev, custom, dev
503 kpl = [[], [], [], []] 542 kpl = [[], [], [], []]
543 linesout = len(self.kprobes)
504 for name in sorted(self.kprobes): 544 for name in sorted(self.kprobes):
505 res = self.colorText('YES', 32) 545 res = self.colorText('YES', 32)
506 if not self.testKprobe(name, self.kprobes[name]): 546 if not self.testKprobe(name, self.kprobes[name]):
@@ -528,17 +568,10 @@ class SystemValues:
528 for kp in kplist: 568 for kp in kplist:
529 kprobeevents += self.kprobeText(kp, self.kprobes[kp]) 569 kprobeevents += self.kprobeText(kp, self.kprobes[kp])
530 self.fsetVal(kprobeevents, 'kprobe_events') 570 self.fsetVal(kprobeevents, 'kprobe_events')
531 # verify that the kprobes were set as ordered
532 check = self.fgetVal('kprobe_events')
533 linesout = len(kprobeevents.split('\n')) - 1
534 linesack = len(check.split('\n')) - 1
535 if output: 571 if output:
536 res = '%d/%d' % (linesack, linesout) 572 check = self.fgetVal('kprobe_events')
537 if linesack < linesout: 573 linesack = (len(check.split('\n')) - 1) / 2
538 res = self.colorText(res, 31) 574 print(' kprobe functions enabled: %d/%d' % (linesack, linesout))
539 else:
540 res = self.colorText(res, 32)
541 print(' working kprobe functions enabled: %s' % res)
542 self.fsetVal('1', 'events/kprobes/enable') 575 self.fsetVal('1', 'events/kprobes/enable')
543 def testKprobe(self, kname, kprobe): 576 def testKprobe(self, kname, kprobe):
544 self.fsetVal('0', 'events/kprobes/enable') 577 self.fsetVal('0', 'events/kprobes/enable')
@@ -555,8 +588,7 @@ class SystemValues:
555 if linesack < linesout: 588 if linesack < linesout:
556 return False 589 return False
557 return True 590 return True
558 def fsetVal(self, val, path, mode='w'): 591 def setVal(self, val, file, mode='w'):
559 file = self.tpath+path
560 if not os.path.exists(file): 592 if not os.path.exists(file):
561 return False 593 return False
562 try: 594 try:
@@ -567,8 +599,9 @@ class SystemValues:
567 except: 599 except:
568 return False 600 return False
569 return True 601 return True
570 def fgetVal(self, path): 602 def fsetVal(self, val, path, mode='w'):
571 file = self.tpath+path 603 return self.setVal(val, self.tpath+path, mode)
604 def getVal(self, file):
572 res = '' 605 res = ''
573 if not os.path.exists(file): 606 if not os.path.exists(file):
574 return res 607 return res
@@ -579,10 +612,13 @@ class SystemValues:
579 except: 612 except:
580 pass 613 pass
581 return res 614 return res
615 def fgetVal(self, path):
616 return self.getVal(self.tpath+path)
582 def cleanupFtrace(self): 617 def cleanupFtrace(self):
583 if(self.usecallgraph or self.usetraceevents): 618 if(self.usecallgraph or self.usetraceevents or self.usedevsrc):
584 self.fsetVal('0', 'events/kprobes/enable') 619 self.fsetVal('0', 'events/kprobes/enable')
585 self.fsetVal('', 'kprobe_events') 620 self.fsetVal('', 'kprobe_events')
621 self.fsetVal('1024', 'buffer_size_kb')
586 def setupAllKprobes(self): 622 def setupAllKprobes(self):
587 for name in self.tracefuncs: 623 for name in self.tracefuncs:
588 self.defaultKprobe(name, self.tracefuncs[name]) 624 self.defaultKprobe(name, self.tracefuncs[name])
@@ -599,7 +635,8 @@ class SystemValues:
599 if name == f: 635 if name == f:
600 return True 636 return True
601 return False 637 return False
602 def initFtrace(self, testing=False): 638 def initFtrace(self):
639 self.printSystemInfo(False)
603 print('INITIALIZING FTRACE...') 640 print('INITIALIZING FTRACE...')
604 # turn trace off 641 # turn trace off
605 self.fsetVal('0', 'tracing_on') 642 self.fsetVal('0', 'tracing_on')
@@ -607,17 +644,21 @@ class SystemValues:
607 # set the trace clock to global 644 # set the trace clock to global
608 self.fsetVal('global', 'trace_clock') 645 self.fsetVal('global', 'trace_clock')
609 self.fsetVal('nop', 'current_tracer') 646 self.fsetVal('nop', 'current_tracer')
610 # set trace buffer to a huge value 647 # set trace buffer to an appropriate value
611 if self.usecallgraph or self.usedevsrc: 648 cpus = max(1, self.cpucount)
612 tgtsize = min(self.memtotal / 2, 2*1024*1024) 649 if self.bufsize > 0:
613 maxbuf = '%d' % (tgtsize / max(1, self.cpucount)) 650 tgtsize = self.bufsize
614 if self.cpucount < 1 or not self.fsetVal(maxbuf, 'buffer_size_kb'): 651 elif self.usecallgraph or self.usedevsrc:
615 self.fsetVal('131072', 'buffer_size_kb') 652 tgtsize = min(self.memfree, 3*1024*1024)
616 else: 653 else:
617 self.fsetVal('16384', 'buffer_size_kb') 654 tgtsize = 65536
618 # go no further if this is just a status check 655 while not self.fsetVal('%d' % (tgtsize / cpus), 'buffer_size_kb'):
619 if testing: 656 # if the size failed to set, lower it and keep trying
620 return 657 tgtsize -= 65536
658 if tgtsize < 65536:
659 tgtsize = int(self.fgetVal('buffer_size_kb')) * cpus
660 break
661 print 'Setting trace buffers to %d kB (%d kB per cpu)' % (tgtsize, tgtsize/cpus)
621 # initialize the callgraph trace 662 # initialize the callgraph trace
622 if(self.usecallgraph): 663 if(self.usecallgraph):
623 # set trace type 664 # set trace type
@@ -635,7 +676,7 @@ class SystemValues:
635 self.fsetVal('graph-time', 'trace_options') 676 self.fsetVal('graph-time', 'trace_options')
636 self.fsetVal('%d' % self.max_graph_depth, 'max_graph_depth') 677 self.fsetVal('%d' % self.max_graph_depth, 'max_graph_depth')
637 cf = ['dpm_run_callback'] 678 cf = ['dpm_run_callback']
638 if(self.usetraceeventsonly): 679 if(self.usetraceevents):
639 cf += ['dpm_prepare', 'dpm_complete'] 680 cf += ['dpm_prepare', 'dpm_complete']
640 for fn in self.tracefuncs: 681 for fn in self.tracefuncs:
641 if 'func' in self.tracefuncs[fn]: 682 if 'func' in self.tracefuncs[fn]:
@@ -688,16 +729,65 @@ class SystemValues:
688 return str 729 return str
689 return '\x1B[%d;40m%s\x1B[m' % (color, str) 730 return '\x1B[%d;40m%s\x1B[m' % (color, str)
690 def writeDatafileHeader(self, filename, fwdata=[]): 731 def writeDatafileHeader(self, filename, fwdata=[]):
691 fp = open(filename, 'w') 732 fp = self.openlog(filename, 'w')
692 fp.write(self.teststamp+'\n') 733 fp.write('%s\n%s\n# command | %s\n' % (self.teststamp, self.sysstamp, self.cmdline))
693 fp.write(self.sysstamp+'\n')
694 if(self.suspendmode == 'mem' or self.suspendmode == 'command'): 734 if(self.suspendmode == 'mem' or self.suspendmode == 'command'):
695 for fw in fwdata: 735 for fw in fwdata:
696 if(fw): 736 if(fw):
697 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1])) 737 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1]))
738 return fp
739 def sudouser(self, dir):
740 if os.path.exists(dir) and os.getuid() == 0 and \
741 'SUDO_USER' in os.environ:
742 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1'
743 call(cmd.format(os.environ['SUDO_USER'], dir), shell=True)
744 def outputResult(self, testdata, num=0):
745 if not self.result:
746 return
747 n = ''
748 if num > 0:
749 n = '%d' % num
750 fp = open(self.result, 'a')
751 if 'error' in testdata:
752 fp.write('result%s: fail\n' % n)
753 fp.write('error%s: %s\n' % (n, testdata['error']))
754 else:
755 fp.write('result%s: pass\n' % n)
756 for v in ['suspend', 'resume', 'boot', 'lastinit']:
757 if v in testdata:
758 fp.write('%s%s: %.3f\n' % (v, n, testdata[v]))
759 for v in ['fwsuspend', 'fwresume']:
760 if v in testdata:
761 fp.write('%s%s: %.3f\n' % (v, n, testdata[v] / 1000000.0))
762 if 'bugurl' in testdata:
763 fp.write('url%s: %s\n' % (n, testdata['bugurl']))
698 fp.close() 764 fp.close()
765 self.sudouser(self.result)
766 def configFile(self, file):
767 dir = os.path.dirname(os.path.realpath(__file__))
768 if os.path.exists(file):
769 return file
770 elif os.path.exists(dir+'/'+file):
771 return dir+'/'+file
772 elif os.path.exists(dir+'/config/'+file):
773 return dir+'/config/'+file
774 return ''
775 def openlog(self, filename, mode):
776 isgz = self.gzip
777 if mode == 'r':
778 try:
779 with gzip.open(filename, mode+'b') as fp:
780 test = fp.read(64)
781 isgz = True
782 except:
783 isgz = False
784 if isgz:
785 return gzip.open(filename, mode+'b')
786 return open(filename, mode)
699 787
700sysvals = SystemValues() 788sysvals = SystemValues()
789switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0']
790switchoff = ['disable', 'off', 'false', '0']
701suspendmodename = { 791suspendmodename = {
702 'freeze': 'Freeze (S0)', 792 'freeze': 'Freeze (S0)',
703 'standby': 'Standby (S1)', 793 'standby': 'Standby (S1)',
@@ -826,34 +916,65 @@ class Data:
826 for phase in self.phases: 916 for phase in self.phases:
827 self.devicegroups.append([phase]) 917 self.devicegroups.append([phase])
828 self.errorinfo = {'suspend':[],'resume':[]} 918 self.errorinfo = {'suspend':[],'resume':[]}
829 def extractErrorInfo(self, dmesg): 919 def extractErrorInfo(self):
830 error = '' 920 lf = sysvals.openlog(sysvals.dmesgfile, 'r')
831 tm = 0.0 921 i = 0
832 for i in range(len(dmesg)): 922 list = []
833 if 'Call Trace:' in dmesg[i]: 923 # sl = start line, et = error time, el = error line
834 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) .*', dmesg[i]) 924 type = 'ERROR'
835 if not m: 925 sl = et = el = -1
836 continue 926 for line in lf:
837 tm = float(m.group('ktime')) 927 i += 1
838 if tm < self.start or tm > self.end: 928 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
839 continue 929 if not m:
840 for j in range(i-10, i+1):
841 error += dmesg[j]
842 continue 930 continue
843 if error: 931 t = float(m.group('ktime'))
844 m = re.match('[ \t]*\[ *[0-9\.]*\] \[\<[0-9a-fA-F]*\>\] .*', dmesg[i]) 932 if t < self.start or t > self.end:
845 if m: 933 continue
846 error += dmesg[i] 934 if t < self.tSuspended:
847 else: 935 dir = 'suspend'
848 if tm < self.tSuspended: 936 else:
849 dir = 'suspend' 937 dir = 'resume'
850 else: 938 msg = m.group('msg')
851 dir = 'resume' 939 if re.match('-*\[ *cut here *\]-*', msg):
852 error = error.replace('<', '&lt').replace('>', '&gt') 940 type = 'WARNING'
853 vprint('kernel error found in %s at %f' % (dir, tm)) 941 sl = i
854 self.errorinfo[dir].append((tm, error)) 942 elif re.match('genirq: .*', msg):
943 type = 'IRQ'
944 sl = i
945 elif re.match('BUG: .*', msg) or re.match('kernel BUG .*', msg):
946 type = 'BUG'
947 sl = i
948 elif re.match('-*\[ *end trace .*\]-*', msg) or \
949 re.match('R13: .*', msg):
950 if et >= 0 and sl >= 0:
951 list.append((type, dir, et, sl, i))
855 self.kerror = True 952 self.kerror = True
856 error = '' 953 sl = et = el = -1
954 type = 'ERROR'
955 elif 'Call Trace:' in msg:
956 if el >= 0 and et >= 0:
957 list.append((type, dir, et, el, el))
958 self.kerror = True
959 et, el = t, i
960 if sl < 0 or type == 'BUG':
961 slval = i
962 if sl >= 0:
963 slval = sl
964 list.append((type, dir, et, slval, i))
965 self.kerror = True
966 sl = et = el = -1
967 type = 'ERROR'
968 if el >= 0 and et >= 0:
969 list.append((type, dir, et, el, el))
970 self.kerror = True
971 for e in list:
972 type, dir, t, idx1, idx2 = e
973 sysvals.vprint('kernel %s found in %s at %f' % (type, dir, t))
974 self.errorinfo[dir].append((type, t, idx1, idx2))
975 if self.kerror:
976 sysvals.dmesglog = True
977 lf.close()
857 def setStart(self, time): 978 def setStart(self, time):
858 self.start = time 979 self.start = time
859 def setEnd(self, time): 980 def setEnd(self, time):
@@ -867,6 +988,14 @@ class Data:
867 time < d['end']): 988 time < d['end']):
868 return False 989 return False
869 return True 990 return True
991 def phaseCollision(self, phase, isbegin, line):
992 key = 'end'
993 if isbegin:
994 key = 'start'
995 if self.dmesg[phase][key] >= 0:
996 sysvals.vprint('IGNORE: %s' % line.strip())
997 return True
998 return False
870 def sourcePhase(self, start): 999 def sourcePhase(self, start):
871 for phase in self.phases: 1000 for phase in self.phases:
872 pend = self.dmesg[phase]['end'] 1001 pend = self.dmesg[phase]['end']
@@ -918,7 +1047,7 @@ class Data:
918 return self.addDeviceFunctionCall(displayname, kprobename, proc, pid, start, end, cdata, rdata) 1047 return self.addDeviceFunctionCall(displayname, kprobename, proc, pid, start, end, cdata, rdata)
919 # this should not happen 1048 # this should not happen
920 if not tgtdev: 1049 if not tgtdev:
921 vprint('[%f - %f] %s-%d %s %s %s' % \ 1050 sysvals.vprint('[%f - %f] %s-%d %s %s %s' % \
922 (start, end, proc, pid, kprobename, cdata, rdata)) 1051 (start, end, proc, pid, kprobename, cdata, rdata))
923 return False 1052 return False
924 # place the call data inside the src element of the tgtdev 1053 # place the call data inside the src element of the tgtdev
@@ -1054,6 +1183,13 @@ class Data:
1054 if('src' in d): 1183 if('src' in d):
1055 for e in d['src']: 1184 for e in d['src']:
1056 e.time = self.trimTimeVal(e.time, t0, dT, left) 1185 e.time = self.trimTimeVal(e.time, t0, dT, left)
1186 for dir in ['suspend', 'resume']:
1187 list = []
1188 for e in self.errorinfo[dir]:
1189 type, tm, idx1, idx2 = e
1190 tm = self.trimTimeVal(tm, t0, dT, left)
1191 list.append((type, tm, idx1, idx2))
1192 self.errorinfo[dir] = list
1057 def normalizeTime(self, tZero): 1193 def normalizeTime(self, tZero):
1058 # trim out any standby or freeze clock time 1194 # trim out any standby or freeze clock time
1059 if(self.tSuspended != self.tResumed): 1195 if(self.tSuspended != self.tResumed):
@@ -1100,7 +1236,7 @@ class Data:
1100 if self.dmesg[p]['end'] > dev['start']: 1236 if self.dmesg[p]['end'] > dev['start']:
1101 dev['end'] = self.dmesg[p]['end'] 1237 dev['end'] = self.dmesg[p]['end']
1102 break 1238 break
1103 vprint('%s (%s): callback didnt return' % (devname, phase)) 1239 sysvals.vprint('%s (%s): callback didnt return' % (devname, phase))
1104 def deviceFilter(self, devicefilter): 1240 def deviceFilter(self, devicefilter):
1105 for phase in self.phases: 1241 for phase in self.phases:
1106 list = self.dmesg[phase]['list'] 1242 list = self.dmesg[phase]['list']
@@ -1200,15 +1336,15 @@ class Data:
1200 devlist.append(child) 1336 devlist.append(child)
1201 return devlist 1337 return devlist
1202 def printDetails(self): 1338 def printDetails(self):
1203 vprint('Timeline Details:') 1339 sysvals.vprint('Timeline Details:')
1204 vprint(' test start: %f' % self.start) 1340 sysvals.vprint(' test start: %f' % self.start)
1205 vprint('kernel suspend start: %f' % self.tKernSus) 1341 sysvals.vprint('kernel suspend start: %f' % self.tKernSus)
1206 for phase in self.phases: 1342 for phase in self.phases:
1207 dc = len(self.dmesg[phase]['list']) 1343 dc = len(self.dmesg[phase]['list'])
1208 vprint(' %16s: %f - %f (%d devices)' % (phase, \ 1344 sysvals.vprint(' %16s: %f - %f (%d devices)' % (phase, \
1209 self.dmesg[phase]['start'], self.dmesg[phase]['end'], dc)) 1345 self.dmesg[phase]['start'], self.dmesg[phase]['end'], dc))
1210 vprint(' kernel resume end: %f' % self.tKernRes) 1346 sysvals.vprint(' kernel resume end: %f' % self.tKernRes)
1211 vprint(' test end: %f' % self.end) 1347 sysvals.vprint(' test end: %f' % self.end)
1212 def deviceChildrenAllPhases(self, devname): 1348 def deviceChildrenAllPhases(self, devname):
1213 devlist = [] 1349 devlist = []
1214 for phase in self.phases: 1350 for phase in self.phases:
@@ -1358,14 +1494,21 @@ class Data:
1358 tres.append(t) 1494 tres.append(t)
1359 # process the events for suspend and resume 1495 # process the events for suspend and resume
1360 if len(proclist) > 0: 1496 if len(proclist) > 0:
1361 vprint('Process Execution:') 1497 sysvals.vprint('Process Execution:')
1362 for ps in proclist: 1498 for ps in proclist:
1363 c = self.addProcessUsageEvent(ps, tsus) 1499 c = self.addProcessUsageEvent(ps, tsus)
1364 if c > 0: 1500 if c > 0:
1365 vprint('%25s (sus): %d' % (ps, c)) 1501 sysvals.vprint('%25s (sus): %d' % (ps, c))
1366 c = self.addProcessUsageEvent(ps, tres) 1502 c = self.addProcessUsageEvent(ps, tres)
1367 if c > 0: 1503 if c > 0:
1368 vprint('%25s (res): %d' % (ps, c)) 1504 sysvals.vprint('%25s (res): %d' % (ps, c))
1505 def debugPrint(self):
1506 for p in self.phases:
1507 list = self.dmesg[p]['list']
1508 for devname in list:
1509 dev = list[devname]
1510 if 'ftrace' in dev:
1511 dev['ftrace'].debugPrint(' [%s]' % devname)
1369 1512
1370# Class: DevFunction 1513# Class: DevFunction
1371# Description: 1514# Description:
@@ -1504,18 +1647,24 @@ class FTraceLine:
1504 # something else (possibly a trace marker) 1647 # something else (possibly a trace marker)
1505 else: 1648 else:
1506 self.name = m 1649 self.name = m
1650 def isCall(self):
1651 return self.fcall and not self.freturn
1652 def isReturn(self):
1653 return self.freturn and not self.fcall
1654 def isLeaf(self):
1655 return self.fcall and self.freturn
1507 def getDepth(self, str): 1656 def getDepth(self, str):
1508 return len(str)/2 1657 return len(str)/2
1509 def debugPrint(self, dev=''): 1658 def debugPrint(self, info=''):
1510 if(self.freturn and self.fcall): 1659 if self.isLeaf():
1511 print('%s -- %f (%02d): %s(); (%.3f us)' % (dev, self.time, \ 1660 print(' -- %12.6f (depth=%02d): %s(); (%.3f us) %s' % (self.time, \
1512 self.depth, self.name, self.length*1000000)) 1661 self.depth, self.name, self.length*1000000, info))
1513 elif(self.freturn): 1662 elif self.freturn:
1514 print('%s -- %f (%02d): %s} (%.3f us)' % (dev, self.time, \ 1663 print(' -- %12.6f (depth=%02d): %s} (%.3f us) %s' % (self.time, \
1515 self.depth, self.name, self.length*1000000)) 1664 self.depth, self.name, self.length*1000000, info))
1516 else: 1665 else:
1517 print('%s -- %f (%02d): %s() { (%.3f us)' % (dev, self.time, \ 1666 print(' -- %12.6f (depth=%02d): %s() { (%.3f us) %s' % (self.time, \
1518 self.depth, self.name, self.length*1000000)) 1667 self.depth, self.name, self.length*1000000, info))
1519 def startMarker(self): 1668 def startMarker(self):
1520 # Is this the starting line of a suspend? 1669 # Is this the starting line of a suspend?
1521 if not self.fevent: 1670 if not self.fevent:
@@ -1558,107 +1707,160 @@ class FTraceCallGraph:
1558 depth = 0 1707 depth = 0
1559 pid = 0 1708 pid = 0
1560 name = '' 1709 name = ''
1561 def __init__(self, pid): 1710 partial = False
1711 vfname = 'missing_function_name'
1712 ignore = False
1713 sv = 0
1714 def __init__(self, pid, sv):
1562 self.start = -1.0 1715 self.start = -1.0
1563 self.end = -1.0 1716 self.end = -1.0
1564 self.list = [] 1717 self.list = []
1565 self.depth = 0 1718 self.depth = 0
1566 self.pid = pid 1719 self.pid = pid
1567 def addLine(self, line, debug=False): 1720 self.sv = sv
1721 def addLine(self, line):
1568 # if this is already invalid, just leave 1722 # if this is already invalid, just leave
1569 if(self.invalid): 1723 if(self.invalid):
1570 return False 1724 if(line.depth == 0 and line.freturn):
1571 # invalidate on too much data or bad depth 1725 return 1
1572 if(len(self.list) >= 1000000 or self.depth < 0): 1726 return 0
1727 # invalidate on bad depth
1728 if(self.depth < 0):
1573 self.invalidate(line) 1729 self.invalidate(line)
1574 return False 1730 return 0
1731 # ignore data til we return to the current depth
1732 if self.ignore:
1733 if line.depth > self.depth:
1734 return 0
1735 else:
1736 self.list[-1].freturn = True
1737 self.list[-1].length = line.time - self.list[-1].time
1738 self.ignore = False
1739 # if this is a return at self.depth, no more work is needed
1740 if line.depth == self.depth and line.isReturn():
1741 if line.depth == 0:
1742 self.end = line.time
1743 return 1
1744 return 0
1575 # compare current depth with this lines pre-call depth 1745 # compare current depth with this lines pre-call depth
1576 prelinedep = line.depth 1746 prelinedep = line.depth
1577 if(line.freturn and not line.fcall): 1747 if line.isReturn():
1578 prelinedep += 1 1748 prelinedep += 1
1579 last = 0 1749 last = 0
1580 lasttime = line.time 1750 lasttime = line.time
1581 virtualfname = 'missing_function_name'
1582 if len(self.list) > 0: 1751 if len(self.list) > 0:
1583 last = self.list[-1] 1752 last = self.list[-1]
1584 lasttime = last.time 1753 lasttime = last.time
1754 if last.isLeaf():
1755 lasttime += last.length
1585 # handle low misalignments by inserting returns 1756 # handle low misalignments by inserting returns
1586 if prelinedep < self.depth: 1757 mismatch = prelinedep - self.depth
1587 if debug and last: 1758 warning = self.sv.verbose and abs(mismatch) > 1
1588 print '-------- task %d --------' % self.pid 1759 info = []
1589 last.debugPrint() 1760 if mismatch < 0:
1590 idx = 0 1761 idx = 0
1591 # add return calls to get the depth down 1762 # add return calls to get the depth down
1592 while prelinedep < self.depth: 1763 while prelinedep < self.depth:
1593 if debug:
1594 print 'MISALIGN LOW (add returns): C%d - eC%d' % (self.depth, prelinedep)
1595 self.depth -= 1 1764 self.depth -= 1
1596 if idx == 0 and last and last.fcall and not last.freturn: 1765 if idx == 0 and last and last.isCall():
1597 # special case, turn last call into a leaf 1766 # special case, turn last call into a leaf
1598 last.depth = self.depth 1767 last.depth = self.depth
1599 last.freturn = True 1768 last.freturn = True
1600 last.length = line.time - last.time 1769 last.length = line.time - last.time
1601 if debug: 1770 if warning:
1602 last.debugPrint() 1771 info.append(('[make leaf]', last))
1603 else: 1772 else:
1604 vline = FTraceLine(lasttime) 1773 vline = FTraceLine(lasttime)
1605 vline.depth = self.depth 1774 vline.depth = self.depth
1606 vline.name = virtualfname 1775 vline.name = self.vfname
1607 vline.freturn = True 1776 vline.freturn = True
1608 self.list.append(vline) 1777 self.list.append(vline)
1609 if debug: 1778 if warning:
1610 vline.debugPrint() 1779 if idx == 0:
1780 info.append(('', last))
1781 info.append(('[add return]', vline))
1611 idx += 1 1782 idx += 1
1612 if debug: 1783 if warning:
1613 line.debugPrint() 1784 info.append(('', line))
1614 print ''
1615 # handle high misalignments by inserting calls 1785 # handle high misalignments by inserting calls
1616 elif prelinedep > self.depth: 1786 elif mismatch > 0:
1617 if debug and last:
1618 print '-------- task %d --------' % self.pid
1619 last.debugPrint()
1620 idx = 0 1787 idx = 0
1788 if warning:
1789 info.append(('', last))
1621 # add calls to get the depth up 1790 # add calls to get the depth up
1622 while prelinedep > self.depth: 1791 while prelinedep > self.depth:
1623 if debug: 1792 if idx == 0 and line.isReturn():
1624 print 'MISALIGN HIGH (add calls): C%d - eC%d' % (self.depth, prelinedep)
1625 if idx == 0 and line.freturn and not line.fcall:
1626 # special case, turn this return into a leaf 1793 # special case, turn this return into a leaf
1627 line.fcall = True 1794 line.fcall = True
1628 prelinedep -= 1 1795 prelinedep -= 1
1796 if warning:
1797 info.append(('[make leaf]', line))
1629 else: 1798 else:
1630 vline = FTraceLine(lasttime) 1799 vline = FTraceLine(lasttime)
1631 vline.depth = self.depth 1800 vline.depth = self.depth
1632 vline.name = virtualfname 1801 vline.name = self.vfname
1633 vline.fcall = True 1802 vline.fcall = True
1634 if debug:
1635 vline.debugPrint()
1636 self.list.append(vline) 1803 self.list.append(vline)
1637 self.depth += 1 1804 self.depth += 1
1638 if not last: 1805 if not last:
1639 self.start = vline.time 1806 self.start = vline.time
1807 if warning:
1808 info.append(('[add call]', vline))
1640 idx += 1 1809 idx += 1
1641 if debug: 1810 if warning and ('[make leaf]', line) not in info:
1642 line.debugPrint() 1811 info.append(('', line))
1643 print '' 1812 if warning:
1813 print 'WARNING: ftrace data missing, corrections made:'
1814 for i in info:
1815 t, obj = i
1816 if obj:
1817 obj.debugPrint(t)
1644 # process the call and set the new depth 1818 # process the call and set the new depth
1645 if(line.fcall and not line.freturn): 1819 skipadd = False
1646 self.depth += 1 1820 md = self.sv.max_graph_depth
1647 elif(line.freturn and not line.fcall): 1821 if line.isCall():
1822 # ignore blacklisted/overdepth funcs
1823 if (md and self.depth >= md - 1) or (line.name in self.sv.cgblacklist):
1824 self.ignore = True
1825 else:
1826 self.depth += 1
1827 elif line.isReturn():
1648 self.depth -= 1 1828 self.depth -= 1
1829 # remove blacklisted/overdepth/empty funcs that slipped through
1830 if (last and last.isCall() and last.depth == line.depth) or \
1831 (md and last and last.depth >= md) or \
1832 (line.name in self.sv.cgblacklist):
1833 while len(self.list) > 0 and self.list[-1].depth > line.depth:
1834 self.list.pop(-1)
1835 if len(self.list) == 0:
1836 self.invalid = True
1837 return 1
1838 self.list[-1].freturn = True
1839 self.list[-1].length = line.time - self.list[-1].time
1840 self.list[-1].name = line.name
1841 skipadd = True
1649 if len(self.list) < 1: 1842 if len(self.list) < 1:
1650 self.start = line.time 1843 self.start = line.time
1651 self.list.append(line) 1844 # check for a mismatch that returned all the way to callgraph end
1845 res = 1
1846 if mismatch < 0 and self.list[-1].depth == 0 and self.list[-1].freturn:
1847 line = self.list[-1]
1848 skipadd = True
1849 res = -1
1850 if not skipadd:
1851 self.list.append(line)
1652 if(line.depth == 0 and line.freturn): 1852 if(line.depth == 0 and line.freturn):
1653 if(self.start < 0): 1853 if(self.start < 0):
1654 self.start = line.time 1854 self.start = line.time
1655 self.end = line.time 1855 self.end = line.time
1656 if line.fcall: 1856 if line.fcall:
1657 self.end += line.length 1857 self.end += line.length
1658 if self.list[0].name == virtualfname: 1858 if self.list[0].name == self.vfname:
1659 self.invalid = True 1859 self.invalid = True
1660 return True 1860 if res == -1:
1661 return False 1861 self.partial = True
1862 return res
1863 return 0
1662 def invalidate(self, line): 1864 def invalidate(self, line):
1663 if(len(self.list) > 0): 1865 if(len(self.list) > 0):
1664 first = self.list[0] 1866 first = self.list[0]
@@ -1668,29 +1870,30 @@ class FTraceCallGraph:
1668 id = 'task %s' % (self.pid) 1870 id = 'task %s' % (self.pid)
1669 window = '(%f - %f)' % (self.start, line.time) 1871 window = '(%f - %f)' % (self.start, line.time)
1670 if(self.depth < 0): 1872 if(self.depth < 0):
1671 vprint('Too much data for '+id+\ 1873 print('Data misalignment for '+id+\
1672 ' (buffer overflow), ignoring this callback') 1874 ' (buffer overflow), ignoring this callback')
1673 else: 1875 else:
1674 vprint('Too much data for '+id+\ 1876 print('Too much data for '+id+\
1675 ' '+window+', ignoring this callback') 1877 ' '+window+', ignoring this callback')
1676 def slice(self, t0, tN): 1878 def slice(self, dev):
1677 minicg = FTraceCallGraph(0) 1879 minicg = FTraceCallGraph(dev['pid'], self.sv)
1678 count = -1 1880 minicg.name = self.name
1679 firstdepth = 0 1881 mydepth = -1
1882 good = False
1680 for l in self.list: 1883 for l in self.list:
1681 if(l.time < t0 or l.time > tN): 1884 if(l.time < dev['start'] or l.time > dev['end']):
1682 continue 1885 continue
1683 if(count < 0): 1886 if mydepth < 0:
1684 if(not l.fcall or l.name == 'dev_driver_string'): 1887 if l.name == 'mutex_lock' and l.freturn:
1685 continue 1888 mydepth = l.depth
1686 firstdepth = l.depth 1889 continue
1687 count = 0 1890 elif l.depth == mydepth and l.name == 'mutex_unlock' and l.fcall:
1688 l.depth -= firstdepth 1891 good = True
1689 minicg.addLine(l)
1690 if((count == 0 and l.freturn and l.fcall) or
1691 (count > 0 and l.depth <= 0)):
1692 break 1892 break
1693 count += 1 1893 l.depth -= mydepth
1894 minicg.addLine(l)
1895 if not good or len(minicg.list) < 1:
1896 return 0
1694 return minicg 1897 return minicg
1695 def repair(self, enddepth): 1898 def repair(self, enddepth):
1696 # bring the depth back to 0 with additional returns 1899 # bring the depth back to 0 with additional returns
@@ -1701,11 +1904,11 @@ class FTraceCallGraph:
1701 t.depth = i 1904 t.depth = i
1702 t.freturn = True 1905 t.freturn = True
1703 fixed = self.addLine(t) 1906 fixed = self.addLine(t)
1704 if fixed: 1907 if fixed != 0:
1705 self.end = last.time 1908 self.end = last.time
1706 return True 1909 return True
1707 return False 1910 return False
1708 def postProcess(self, debug=False): 1911 def postProcess(self):
1709 if len(self.list) > 0: 1912 if len(self.list) > 0:
1710 self.name = self.list[0].name 1913 self.name = self.list[0].name
1711 stack = dict() 1914 stack = dict()
@@ -1714,20 +1917,23 @@ class FTraceCallGraph:
1714 for l in self.list: 1917 for l in self.list:
1715 # ftrace bug: reported duration is not reliable 1918 # ftrace bug: reported duration is not reliable
1716 # check each leaf and clip it at max possible length 1919 # check each leaf and clip it at max possible length
1717 if(last and last.freturn and last.fcall): 1920 if last and last.isLeaf():
1718 if last.length > l.time - last.time: 1921 if last.length > l.time - last.time:
1719 last.length = l.time - last.time 1922 last.length = l.time - last.time
1720 if(l.fcall and not l.freturn): 1923 if l.isCall():
1721 stack[l.depth] = l 1924 stack[l.depth] = l
1722 cnt += 1 1925 cnt += 1
1723 elif(l.freturn and not l.fcall): 1926 elif l.isReturn():
1724 if(l.depth not in stack): 1927 if(l.depth not in stack):
1725 if debug: 1928 if self.sv.verbose:
1726 print 'Post Process Error: Depth missing' 1929 print 'Post Process Error: Depth missing'
1727 l.debugPrint() 1930 l.debugPrint()
1728 return False 1931 return False
1729 # calculate call length from call/return lines 1932 # calculate call length from call/return lines
1730 stack[l.depth].length = l.time - stack[l.depth].time 1933 cl = stack[l.depth]
1934 cl.length = l.time - cl.time
1935 if cl.name == self.vfname:
1936 cl.name = l.name
1731 stack.pop(l.depth) 1937 stack.pop(l.depth)
1732 l.length = 0 1938 l.length = 0
1733 cnt -= 1 1939 cnt -= 1
@@ -1736,13 +1942,13 @@ class FTraceCallGraph:
1736 # trace caught the whole call tree 1942 # trace caught the whole call tree
1737 return True 1943 return True
1738 elif(cnt < 0): 1944 elif(cnt < 0):
1739 if debug: 1945 if self.sv.verbose:
1740 print 'Post Process Error: Depth is less than 0' 1946 print 'Post Process Error: Depth is less than 0'
1741 return False 1947 return False
1742 # trace ended before call tree finished 1948 # trace ended before call tree finished
1743 return self.repair(cnt) 1949 return self.repair(cnt)
1744 def deviceMatch(self, pid, data): 1950 def deviceMatch(self, pid, data):
1745 found = False 1951 found = ''
1746 # add the callgraph data to the device hierarchy 1952 # add the callgraph data to the device hierarchy
1747 borderphase = { 1953 borderphase = {
1748 'dpm_prepare': 'suspend_prepare', 1954 'dpm_prepare': 'suspend_prepare',
@@ -1756,8 +1962,10 @@ class FTraceCallGraph:
1756 if(pid == dev['pid'] and 1962 if(pid == dev['pid'] and
1757 self.start <= dev['start'] and 1963 self.start <= dev['start'] and
1758 self.end >= dev['end']): 1964 self.end >= dev['end']):
1759 dev['ftrace'] = self.slice(dev['start'], dev['end']) 1965 cg = self.slice(dev)
1760 found = True 1966 if cg:
1967 dev['ftrace'] = cg
1968 found = devname
1761 return found 1969 return found
1762 for p in data.phases: 1970 for p in data.phases:
1763 if(data.dmesg[p]['start'] <= self.start and 1971 if(data.dmesg[p]['start'] <= self.start and
@@ -1769,7 +1977,7 @@ class FTraceCallGraph:
1769 self.start <= dev['start'] and 1977 self.start <= dev['start'] and
1770 self.end >= dev['end']): 1978 self.end >= dev['end']):
1771 dev['ftrace'] = self 1979 dev['ftrace'] = self
1772 found = True 1980 found = devname
1773 break 1981 break
1774 break 1982 break
1775 return found 1983 return found
@@ -1793,18 +2001,20 @@ class FTraceCallGraph:
1793 if out: 2001 if out:
1794 phase, myname = out 2002 phase, myname = out
1795 data.dmesg[phase]['list'][myname]['ftrace'] = self 2003 data.dmesg[phase]['list'][myname]['ftrace'] = self
1796 def debugPrint(self): 2004 def debugPrint(self, info=''):
1797 print('[%f - %f] %s (%d)') % (self.start, self.end, self.name, self.pid) 2005 print('%s pid=%d [%f - %f] %.3f us') % \
2006 (self.name, self.pid, self.start, self.end,
2007 (self.end - self.start)*1000000)
1798 for l in self.list: 2008 for l in self.list:
1799 if(l.freturn and l.fcall): 2009 if l.isLeaf():
1800 print('%f (%02d): %s(); (%.3f us)' % (l.time, \ 2010 print('%f (%02d): %s(); (%.3f us)%s' % (l.time, \
1801 l.depth, l.name, l.length*1000000)) 2011 l.depth, l.name, l.length*1000000, info))
1802 elif(l.freturn): 2012 elif l.freturn:
1803 print('%f (%02d): %s} (%.3f us)' % (l.time, \ 2013 print('%f (%02d): %s} (%.3f us)%s' % (l.time, \
1804 l.depth, l.name, l.length*1000000)) 2014 l.depth, l.name, l.length*1000000, info))
1805 else: 2015 else:
1806 print('%f (%02d): %s() { (%.3f us)' % (l.time, \ 2016 print('%f (%02d): %s() { (%.3f us)%s' % (l.time, \
1807 l.depth, l.name, l.length*1000000)) 2017 l.depth, l.name, l.length*1000000, info))
1808 print(' ') 2018 print(' ')
1809 2019
1810class DevItem: 2020class DevItem:
@@ -1839,8 +2049,8 @@ class Timeline:
1839 self.rowH = rowheight 2049 self.rowH = rowheight
1840 self.scaleH = scaleheight 2050 self.scaleH = scaleheight
1841 self.html = '' 2051 self.html = ''
1842 def createHeader(self, sv): 2052 def createHeader(self, sv, stamp):
1843 if(not sv.stamp['time']): 2053 if(not stamp['time']):
1844 return 2054 return
1845 self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \ 2055 self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \
1846 % (sv.title, sv.version) 2056 % (sv.title, sv.version)
@@ -1851,12 +2061,12 @@ class Timeline:
1851 if sv.ftracelog: 2061 if sv.ftracelog:
1852 self.html += '<button id="showftrace" class="logbtn btnfmt">ftrace</button>' 2062 self.html += '<button id="showftrace" class="logbtn btnfmt">ftrace</button>'
1853 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n' 2063 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n'
1854 self.html += headline_stamp.format(sv.stamp['host'], sv.stamp['kernel'], 2064 self.html += headline_stamp.format(stamp['host'], stamp['kernel'],
1855 sv.stamp['mode'], sv.stamp['time']) 2065 stamp['mode'], stamp['time'])
1856 if 'man' in sv.stamp and 'plat' in sv.stamp and 'cpu' in sv.stamp: 2066 if 'man' in stamp and 'plat' in stamp and 'cpu' in stamp and \
2067 stamp['man'] and stamp['plat'] and stamp['cpu']:
1857 headline_sysinfo = '<div class="stamp sysinfo">{0} {1} <i>with</i> {2}</div>\n' 2068 headline_sysinfo = '<div class="stamp sysinfo">{0} {1} <i>with</i> {2}</div>\n'
1858 self.html += headline_sysinfo.format(sv.stamp['man'], 2069 self.html += headline_sysinfo.format(stamp['man'], stamp['plat'], stamp['cpu'])
1859 sv.stamp['plat'], sv.stamp['cpu'])
1860 2070
1861 # Function: getDeviceRows 2071 # Function: getDeviceRows
1862 # Description: 2072 # Description:
@@ -2067,12 +2277,16 @@ class Timeline:
2067class TestProps: 2277class TestProps:
2068 stamp = '' 2278 stamp = ''
2069 sysinfo = '' 2279 sysinfo = ''
2280 cmdline = ''
2281 kparams = ''
2070 S0i3 = False 2282 S0i3 = False
2071 fwdata = [] 2283 fwdata = []
2072 stampfmt = '# [a-z]*-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\ 2284 stampfmt = '# [a-z]*-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\
2073 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\ 2285 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\
2074 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$' 2286 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
2075 sysinfofmt = '^# sysinfo .*' 2287 sysinfofmt = '^# sysinfo .*'
2288 cmdlinefmt = '^# command \| (?P<cmd>.*)'
2289 kparamsfmt = '^# kparams \| (?P<kp>.*)'
2076 ftrace_line_fmt_fg = \ 2290 ftrace_line_fmt_fg = \
2077 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\ 2291 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\
2078 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\ 2292 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\
@@ -2116,13 +2330,20 @@ class TestProps:
2116 sv.hostname = data.stamp['host'] 2330 sv.hostname = data.stamp['host']
2117 sv.suspendmode = data.stamp['mode'] 2331 sv.suspendmode = data.stamp['mode']
2118 if sv.suspendmode == 'command' and sv.ftracefile != '': 2332 if sv.suspendmode == 'command' and sv.ftracefile != '':
2119 modes = ['on', 'freeze', 'standby', 'mem'] 2333 modes = ['on', 'freeze', 'standby', 'mem', 'disk']
2120 out = Popen(['grep', 'suspend_enter', sv.ftracefile], 2334 out = Popen(['grep', 'machine_suspend', sv.ftracefile],
2121 stderr=PIPE, stdout=PIPE).stdout.read() 2335 stderr=PIPE, stdout=PIPE).stdout.read()
2122 m = re.match('.* suspend_enter\[(?P<mode>.*)\]', out) 2336 m = re.match('.* machine_suspend\[(?P<mode>.*)\]', out)
2123 if m and m.group('mode') in ['1', '2', '3']: 2337 if m and m.group('mode') in ['1', '2', '3', '4']:
2124 sv.suspendmode = modes[int(m.group('mode'))] 2338 sv.suspendmode = modes[int(m.group('mode'))]
2125 data.stamp['mode'] = sv.suspendmode 2339 data.stamp['mode'] = sv.suspendmode
2340 m = re.match(self.cmdlinefmt, self.cmdline)
2341 if m:
2342 sv.cmdline = m.group('cmd')
2343 if self.kparams:
2344 m = re.match(self.kparamsfmt, self.kparams)
2345 if m:
2346 sv.kparams = m.group('kp')
2126 if not sv.stamp: 2347 if not sv.stamp:
2127 sv.stamp = data.stamp 2348 sv.stamp = data.stamp
2128 2349
@@ -2186,47 +2407,43 @@ class ProcessMonitor:
2186 2407
2187# ----------------- FUNCTIONS -------------------- 2408# ----------------- FUNCTIONS --------------------
2188 2409
2189# Function: vprint
2190# Description:
2191# verbose print (prints only with -verbose option)
2192# Arguments:
2193# msg: the debug/log message to print
2194def vprint(msg):
2195 sysvals.logmsg += msg+'\n'
2196 if(sysvals.verbose):
2197 print(msg)
2198
2199# Function: doesTraceLogHaveTraceEvents 2410# Function: doesTraceLogHaveTraceEvents
2200# Description: 2411# Description:
2201# Quickly determine if the ftrace log has some or all of the trace events 2412# Quickly determine if the ftrace log has all of the trace events,
2202# required for primary parsing. Set the usetraceevents and/or 2413# markers, and/or kprobes required for primary parsing.
2203# usetraceeventsonly flags in the global sysvals object
2204def doesTraceLogHaveTraceEvents(): 2414def doesTraceLogHaveTraceEvents():
2205 # check for kprobes 2415 kpcheck = ['_cal: (', '_cpu_down()']
2416 techeck = sysvals.traceevents[:]
2417 tmcheck = ['SUSPEND START', 'RESUME COMPLETE']
2206 sysvals.usekprobes = False 2418 sysvals.usekprobes = False
2207 out = call('grep -q "_cal: (" '+sysvals.ftracefile, shell=True) 2419 fp = sysvals.openlog(sysvals.ftracefile, 'r')
2208 if(out == 0): 2420 for line in fp:
2209 sysvals.usekprobes = True 2421 # check for kprobes
2210 # check for callgraph data on trace event blocks 2422 if not sysvals.usekprobes:
2211 out = call('grep -q "_cpu_down()" '+sysvals.ftracefile, shell=True) 2423 for i in kpcheck:
2212 if(out == 0): 2424 if i in line:
2213 sysvals.usekprobes = True 2425 sysvals.usekprobes = True
2214 out = Popen(['head', '-1', sysvals.ftracefile], 2426 # check for all necessary trace events
2215 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '') 2427 check = techeck[:]
2216 # figure out what level of trace events are supported 2428 for i in techeck:
2217 sysvals.usetraceeventsonly = True 2429 if i in line:
2218 sysvals.usetraceevents = False 2430 check.remove(i)
2219 for e in sysvals.traceevents: 2431 techeck = check
2220 out = call('grep -q "'+e+': " '+sysvals.ftracefile, shell=True) 2432 # check for all necessary trace markers
2221 if(out != 0): 2433 check = tmcheck[:]
2222 sysvals.usetraceeventsonly = False 2434 for i in tmcheck:
2223 if(e == 'suspend_resume' and out == 0): 2435 if i in line:
2224 sysvals.usetraceevents = True 2436 check.remove(i)
2225 # determine is this log is properly formatted 2437 tmcheck = check
2226 for e in ['SUSPEND START', 'RESUME COMPLETE']: 2438 fp.close()
2227 out = call('grep -q "'+e+'" '+sysvals.ftracefile, shell=True) 2439 if len(techeck) == 0:
2228 if(out != 0): 2440 sysvals.usetraceevents = True
2229 sysvals.usetracemarkers = False 2441 else:
2442 sysvals.usetraceevents = False
2443 if len(tmcheck) == 0:
2444 sysvals.usetracemarkers = True
2445 else:
2446 sysvals.usetracemarkers = False
2230 2447
2231# Function: appendIncompleteTraceLog 2448# Function: appendIncompleteTraceLog
2232# Description: 2449# Description:
@@ -2247,9 +2464,10 @@ def appendIncompleteTraceLog(testruns):
2247 testrun.append(TestRun(data)) 2464 testrun.append(TestRun(data))
2248 2465
2249 # extract the callgraph and traceevent data 2466 # extract the callgraph and traceevent data
2250 vprint('Analyzing the ftrace data...') 2467 sysvals.vprint('Analyzing the ftrace data (%s)...' % \
2468 os.path.basename(sysvals.ftracefile))
2251 tp = TestProps() 2469 tp = TestProps()
2252 tf = open(sysvals.ftracefile, 'r') 2470 tf = sysvals.openlog(sysvals.ftracefile, 'r')
2253 data = 0 2471 data = 0
2254 for line in tf: 2472 for line in tf:
2255 # remove any latent carriage returns 2473 # remove any latent carriage returns
@@ -2261,6 +2479,9 @@ def appendIncompleteTraceLog(testruns):
2261 elif re.match(tp.sysinfofmt, line): 2479 elif re.match(tp.sysinfofmt, line):
2262 tp.sysinfo = line 2480 tp.sysinfo = line
2263 continue 2481 continue
2482 elif re.match(tp.cmdlinefmt, line):
2483 tp.cmdline = line
2484 continue
2264 # determine the trace data type (required for further parsing) 2485 # determine the trace data type (required for further parsing)
2265 m = re.match(sysvals.tracertypefmt, line) 2486 m = re.match(sysvals.tracertypefmt, line)
2266 if(m): 2487 if(m):
@@ -2393,11 +2614,14 @@ def appendIncompleteTraceLog(testruns):
2393 # create a callgraph object for the data 2614 # create a callgraph object for the data
2394 if(pid not in testrun[testidx].ftemp): 2615 if(pid not in testrun[testidx].ftemp):
2395 testrun[testidx].ftemp[pid] = [] 2616 testrun[testidx].ftemp[pid] = []
2396 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid)) 2617 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals))
2397 # when the call is finished, see which device matches it 2618 # when the call is finished, see which device matches it
2398 cg = testrun[testidx].ftemp[pid][-1] 2619 cg = testrun[testidx].ftemp[pid][-1]
2399 if(cg.addLine(t)): 2620 res = cg.addLine(t)
2400 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid)) 2621 if(res != 0):
2622 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals))
2623 if(res == -1):
2624 testrun[testidx].ftemp[pid][-1].addLine(t)
2401 tf.close() 2625 tf.close()
2402 2626
2403 for test in testrun: 2627 for test in testrun:
@@ -2410,11 +2634,11 @@ def appendIncompleteTraceLog(testruns):
2410 # add the callgraph data to the device hierarchy 2634 # add the callgraph data to the device hierarchy
2411 for pid in test.ftemp: 2635 for pid in test.ftemp:
2412 for cg in test.ftemp[pid]: 2636 for cg in test.ftemp[pid]:
2413 if len(cg.list) < 1 or cg.invalid: 2637 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0):
2414 continue 2638 continue
2415 if(not cg.postProcess()): 2639 if(not cg.postProcess()):
2416 id = 'task %s cpu %s' % (pid, m.group('cpu')) 2640 id = 'task %s cpu %s' % (pid, m.group('cpu'))
2417 vprint('Sanity check failed for '+\ 2641 sysvals.vprint('Sanity check failed for '+\
2418 id+', ignoring this callback') 2642 id+', ignoring this callback')
2419 continue 2643 continue
2420 callstart = cg.start 2644 callstart = cg.start
@@ -2431,8 +2655,6 @@ def appendIncompleteTraceLog(testruns):
2431 dev['ftrace'] = cg 2655 dev['ftrace'] = cg
2432 break 2656 break
2433 2657
2434 test.data.printDetails()
2435
2436# Function: parseTraceLog 2658# Function: parseTraceLog
2437# Description: 2659# Description:
2438# Analyze an ftrace log output file generated from this app during 2660# Analyze an ftrace log output file generated from this app during
@@ -2441,12 +2663,13 @@ def appendIncompleteTraceLog(testruns):
2441# The ftrace filename is taken from sysvals 2663# The ftrace filename is taken from sysvals
2442# Output: 2664# Output:
2443# An array of Data objects 2665# An array of Data objects
2444def parseTraceLog(): 2666def parseTraceLog(live=False):
2445 vprint('Analyzing the ftrace data...') 2667 sysvals.vprint('Analyzing the ftrace data (%s)...' % \
2668 os.path.basename(sysvals.ftracefile))
2446 if(os.path.exists(sysvals.ftracefile) == False): 2669 if(os.path.exists(sysvals.ftracefile) == False):
2447 doError('%s does not exist' % sysvals.ftracefile) 2670 doError('%s does not exist' % sysvals.ftracefile)
2448 2671 if not live:
2449 sysvals.setupAllKprobes() 2672 sysvals.setupAllKprobes()
2450 tracewatch = [] 2673 tracewatch = []
2451 if sysvals.usekprobes: 2674 if sysvals.usekprobes:
2452 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend', 2675 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend',
@@ -2458,7 +2681,7 @@ def parseTraceLog():
2458 testdata = [] 2681 testdata = []
2459 testrun = 0 2682 testrun = 0
2460 data = 0 2683 data = 0
2461 tf = open(sysvals.ftracefile, 'r') 2684 tf = sysvals.openlog(sysvals.ftracefile, 'r')
2462 phase = 'suspend_prepare' 2685 phase = 'suspend_prepare'
2463 for line in tf: 2686 for line in tf:
2464 # remove any latent carriage returns 2687 # remove any latent carriage returns
@@ -2470,6 +2693,9 @@ def parseTraceLog():
2470 elif re.match(tp.sysinfofmt, line): 2693 elif re.match(tp.sysinfofmt, line):
2471 tp.sysinfo = line 2694 tp.sysinfo = line
2472 continue 2695 continue
2696 elif re.match(tp.cmdlinefmt, line):
2697 tp.cmdline = line
2698 continue
2473 # firmware line: pull out any firmware data 2699 # firmware line: pull out any firmware data
2474 m = re.match(sysvals.firmwarefmt, line) 2700 m = re.match(sysvals.firmwarefmt, line)
2475 if(m): 2701 if(m):
@@ -2591,6 +2817,8 @@ def parseTraceLog():
2591 phase = 'suspend_prepare' 2817 phase = 'suspend_prepare'
2592 if(not isbegin): 2818 if(not isbegin):
2593 data.dmesg[phase]['end'] = t.time 2819 data.dmesg[phase]['end'] = t.time
2820 if data.dmesg[phase]['start'] < 0:
2821 data.dmesg[phase]['start'] = data.start
2594 continue 2822 continue
2595 # suspend start 2823 # suspend start
2596 elif(re.match('dpm_suspend\[.*', t.name)): 2824 elif(re.match('dpm_suspend\[.*', t.name)):
@@ -2604,6 +2832,8 @@ def parseTraceLog():
2604 continue 2832 continue
2605 # suspend_noirq start 2833 # suspend_noirq start
2606 elif(re.match('dpm_suspend_noirq\[.*', t.name)): 2834 elif(re.match('dpm_suspend_noirq\[.*', t.name)):
2835 if data.phaseCollision('suspend_noirq', isbegin, line):
2836 continue
2607 phase = 'suspend_noirq' 2837 phase = 'suspend_noirq'
2608 data.setPhase(phase, t.time, isbegin) 2838 data.setPhase(phase, t.time, isbegin)
2609 if(not isbegin): 2839 if(not isbegin):
@@ -2636,6 +2866,8 @@ def parseTraceLog():
2636 continue 2866 continue
2637 # resume_noirq start 2867 # resume_noirq start
2638 elif(re.match('dpm_resume_noirq\[.*', t.name)): 2868 elif(re.match('dpm_resume_noirq\[.*', t.name)):
2869 if data.phaseCollision('resume_noirq', isbegin, line):
2870 continue
2639 phase = 'resume_noirq' 2871 phase = 'resume_noirq'
2640 data.setPhase(phase, t.time, isbegin) 2872 data.setPhase(phase, t.time, isbegin)
2641 if(isbegin): 2873 if(isbegin):
@@ -2742,11 +2974,14 @@ def parseTraceLog():
2742 key = (m_proc, pid) 2974 key = (m_proc, pid)
2743 if(key not in testrun.ftemp): 2975 if(key not in testrun.ftemp):
2744 testrun.ftemp[key] = [] 2976 testrun.ftemp[key] = []
2745 testrun.ftemp[key].append(FTraceCallGraph(pid)) 2977 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals))
2746 # when the call is finished, see which device matches it 2978 # when the call is finished, see which device matches it
2747 cg = testrun.ftemp[key][-1] 2979 cg = testrun.ftemp[key][-1]
2748 if(cg.addLine(t)): 2980 res = cg.addLine(t)
2749 testrun.ftemp[key].append(FTraceCallGraph(pid)) 2981 if(res != 0):
2982 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals))
2983 if(res == -1):
2984 testrun.ftemp[key][-1].addLine(t)
2750 tf.close() 2985 tf.close()
2751 2986
2752 if sysvals.suspendmode == 'command': 2987 if sysvals.suspendmode == 'command':
@@ -2812,28 +3047,31 @@ def parseTraceLog():
2812 for key in test.ftemp: 3047 for key in test.ftemp:
2813 proc, pid = key 3048 proc, pid = key
2814 for cg in test.ftemp[key]: 3049 for cg in test.ftemp[key]:
2815 if len(cg.list) < 1 or cg.invalid: 3050 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0):
2816 continue 3051 continue
2817 if(not cg.postProcess()): 3052 if(not cg.postProcess()):
2818 id = 'task %s' % (pid) 3053 id = 'task %s' % (pid)
2819 vprint('Sanity check failed for '+\ 3054 sysvals.vprint('Sanity check failed for '+\
2820 id+', ignoring this callback') 3055 id+', ignoring this callback')
2821 continue 3056 continue
2822 # match cg data to devices 3057 # match cg data to devices
2823 if sysvals.suspendmode == 'command' or not cg.deviceMatch(pid, data): 3058 devname = ''
3059 if sysvals.suspendmode != 'command':
3060 devname = cg.deviceMatch(pid, data)
3061 if not devname:
2824 sortkey = '%f%f%d' % (cg.start, cg.end, pid) 3062 sortkey = '%f%f%d' % (cg.start, cg.end, pid)
2825 sortlist[sortkey] = cg 3063 sortlist[sortkey] = cg
3064 elif len(cg.list) > 1000000:
3065 print 'WARNING: the callgraph for %s is massive (%d lines)' %\
3066 (devname, len(cg.list))
2826 # create blocks for orphan cg data 3067 # create blocks for orphan cg data
2827 for sortkey in sorted(sortlist): 3068 for sortkey in sorted(sortlist):
2828 cg = sortlist[sortkey] 3069 cg = sortlist[sortkey]
2829 name = cg.name 3070 name = cg.name
2830 if sysvals.isCallgraphFunc(name): 3071 if sysvals.isCallgraphFunc(name):
2831 vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name)) 3072 sysvals.vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name))
2832 cg.newActionFromFunction(data) 3073 cg.newActionFromFunction(data)
2833
2834 if sysvals.suspendmode == 'command': 3074 if sysvals.suspendmode == 'command':
2835 for data in testdata:
2836 data.printDetails()
2837 return testdata 3075 return testdata
2838 3076
2839 # fill in any missing phases 3077 # fill in any missing phases
@@ -2841,7 +3079,7 @@ def parseTraceLog():
2841 lp = data.phases[0] 3079 lp = data.phases[0]
2842 for p in data.phases: 3080 for p in data.phases:
2843 if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0): 3081 if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0):
2844 vprint('WARNING: phase "%s" is missing!' % p) 3082 sysvals.vprint('WARNING: phase "%s" is missing!' % p)
2845 if(data.dmesg[p]['start'] < 0): 3083 if(data.dmesg[p]['start'] < 0):
2846 data.dmesg[p]['start'] = data.dmesg[lp]['end'] 3084 data.dmesg[p]['start'] = data.dmesg[lp]['end']
2847 if(p == 'resume_machine'): 3085 if(p == 'resume_machine'):
@@ -2859,7 +3097,6 @@ def parseTraceLog():
2859 data.fixupInitcallsThatDidntReturn() 3097 data.fixupInitcallsThatDidntReturn()
2860 if sysvals.usedevsrc: 3098 if sysvals.usedevsrc:
2861 data.optimizeDevSrc() 3099 data.optimizeDevSrc()
2862 data.printDetails()
2863 3100
2864 # x2: merge any overlapping devices between test runs 3101 # x2: merge any overlapping devices between test runs
2865 if sysvals.usedevsrc and len(testdata) > 1: 3102 if sysvals.usedevsrc and len(testdata) > 1:
@@ -2878,19 +3115,18 @@ def parseTraceLog():
2878# The dmesg filename is taken from sysvals 3115# The dmesg filename is taken from sysvals
2879# Output: 3116# Output:
2880# An array of empty Data objects with only their dmesgtext attributes set 3117# An array of empty Data objects with only their dmesgtext attributes set
2881def loadKernelLog(justtext=False): 3118def loadKernelLog():
2882 vprint('Analyzing the dmesg data...') 3119 sysvals.vprint('Analyzing the dmesg data (%s)...' % \
3120 os.path.basename(sysvals.dmesgfile))
2883 if(os.path.exists(sysvals.dmesgfile) == False): 3121 if(os.path.exists(sysvals.dmesgfile) == False):
2884 doError('%s does not exist' % sysvals.dmesgfile) 3122 doError('%s does not exist' % sysvals.dmesgfile)
2885 3123
2886 if justtext:
2887 dmesgtext = []
2888 # there can be multiple test runs in a single file 3124 # there can be multiple test runs in a single file
2889 tp = TestProps() 3125 tp = TestProps()
2890 tp.stamp = datetime.now().strftime('# suspend-%m%d%y-%H%M%S localhost mem unknown') 3126 tp.stamp = datetime.now().strftime('# suspend-%m%d%y-%H%M%S localhost mem unknown')
2891 testruns = [] 3127 testruns = []
2892 data = 0 3128 data = 0
2893 lf = open(sysvals.dmesgfile, 'r') 3129 lf = sysvals.openlog(sysvals.dmesgfile, 'r')
2894 for line in lf: 3130 for line in lf:
2895 line = line.replace('\r\n', '') 3131 line = line.replace('\r\n', '')
2896 idx = line.find('[') 3132 idx = line.find('[')
@@ -2903,6 +3139,9 @@ def loadKernelLog(justtext=False):
2903 elif re.match(tp.sysinfofmt, line): 3139 elif re.match(tp.sysinfofmt, line):
2904 tp.sysinfo = line 3140 tp.sysinfo = line
2905 continue 3141 continue
3142 elif re.match(tp.cmdlinefmt, line):
3143 tp.cmdline = line
3144 continue
2906 m = re.match(sysvals.firmwarefmt, line) 3145 m = re.match(sysvals.firmwarefmt, line)
2907 if(m): 3146 if(m):
2908 tp.fwdata.append((int(m.group('s')), int(m.group('r')))) 3147 tp.fwdata.append((int(m.group('s')), int(m.group('r'))))
@@ -2911,9 +3150,6 @@ def loadKernelLog(justtext=False):
2911 if(not m): 3150 if(not m):
2912 continue 3151 continue
2913 msg = m.group("msg") 3152 msg = m.group("msg")
2914 if justtext:
2915 dmesgtext.append(line)
2916 continue
2917 if(re.match('PM: Syncing filesystems.*', msg)): 3153 if(re.match('PM: Syncing filesystems.*', msg)):
2918 if(data): 3154 if(data):
2919 testruns.append(data) 3155 testruns.append(data)
@@ -2934,8 +3170,6 @@ def loadKernelLog(justtext=False):
2934 data.dmesgtext.append(line) 3170 data.dmesgtext.append(line)
2935 lf.close() 3171 lf.close()
2936 3172
2937 if justtext:
2938 return dmesgtext
2939 if data: 3173 if data:
2940 testruns.append(data) 3174 testruns.append(data)
2941 if len(testruns) < 1: 3175 if len(testruns) < 1:
@@ -2975,7 +3209,7 @@ def parseKernelLog(data):
2975 phase = 'suspend_runtime' 3209 phase = 'suspend_runtime'
2976 3210
2977 if(data.fwValid): 3211 if(data.fwValid):
2978 vprint('Firmware Suspend = %u ns, Firmware Resume = %u ns' % \ 3212 sysvals.vprint('Firmware Suspend = %u ns, Firmware Resume = %u ns' % \
2979 (data.fwSuspend, data.fwResume)) 3213 (data.fwSuspend, data.fwResume))
2980 3214
2981 # dmesg phase match table 3215 # dmesg phase match table
@@ -3201,7 +3435,6 @@ def parseKernelLog(data):
3201 for event in actions[name]: 3435 for event in actions[name]:
3202 data.newActionGlobal(name, event['begin'], event['end']) 3436 data.newActionGlobal(name, event['begin'], event['end'])
3203 3437
3204 data.printDetails()
3205 if(len(sysvals.devicefilter) > 0): 3438 if(len(sysvals.devicefilter) > 0):
3206 data.deviceFilter(sysvals.devicefilter) 3439 data.deviceFilter(sysvals.devicefilter)
3207 data.fixupInitcallsThatDidntReturn() 3440 data.fixupInitcallsThatDidntReturn()
@@ -3230,9 +3463,9 @@ def callgraphHTML(sv, hf, num, cg, title, color, devid):
3230 else: 3463 else:
3231 fmt = '<n>(%.3f ms @ '+sv.timeformat+')</n>' 3464 fmt = '<n>(%.3f ms @ '+sv.timeformat+')</n>'
3232 flen = fmt % (line.length*1000, line.time) 3465 flen = fmt % (line.length*1000, line.time)
3233 if(line.freturn and line.fcall): 3466 if line.isLeaf():
3234 hf.write(html_func_leaf.format(line.name, flen)) 3467 hf.write(html_func_leaf.format(line.name, flen))
3235 elif(line.freturn): 3468 elif line.freturn:
3236 hf.write(html_func_end) 3469 hf.write(html_func_end)
3237 else: 3470 else:
3238 hf.write(html_func_start.format(num, line.name, flen)) 3471 hf.write(html_func_start.format(num, line.name, flen))
@@ -3249,7 +3482,7 @@ def addCallgraphs(sv, hf, data):
3249 continue 3482 continue
3250 list = data.dmesg[p]['list'] 3483 list = data.dmesg[p]['list']
3251 for devname in data.sortedDevices(p): 3484 for devname in data.sortedDevices(p):
3252 if len(sv.devicefilter) > 0 and devname not in sv.devicefilter: 3485 if len(sv.cgfilter) > 0 and devname not in sv.cgfilter:
3253 continue 3486 continue
3254 dev = list[devname] 3487 dev = list[devname]
3255 color = 'white' 3488 color = 'white'
@@ -3270,7 +3503,6 @@ def addCallgraphs(sv, hf, data):
3270 for cg in dev['ftraces']: 3503 for cg in dev['ftraces']:
3271 num = callgraphHTML(sv, hf, num, cg, 3504 num = callgraphHTML(sv, hf, num, cg,
3272 name+' &rarr; '+cg.name, color, dev['id']) 3505 name+' &rarr; '+cg.name, color, dev['id'])
3273
3274 hf.write('\n\n </section>\n') 3506 hf.write('\n\n </section>\n')
3275 3507
3276# Function: createHTMLSummarySimple 3508# Function: createHTMLSummarySimple
@@ -3311,7 +3543,7 @@ def createHTMLSummarySimple(testruns, htmlfile, folder):
3311 sTimeAvg = rTimeAvg = 0.0 3543 sTimeAvg = rTimeAvg = 0.0
3312 mode = '' 3544 mode = ''
3313 num = 0 3545 num = 0
3314 for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'])): 3546 for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])):
3315 if mode != data['mode']: 3547 if mode != data['mode']:
3316 # test average line 3548 # test average line
3317 if(num > 0): 3549 if(num > 0):
@@ -3387,7 +3619,7 @@ def createHTML(testruns):
3387 data.normalizeTime(testruns[-1].tSuspended) 3619 data.normalizeTime(testruns[-1].tSuspended)
3388 3620
3389 # html function templates 3621 # html function templates
3390 html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">ERROR&rarr;</div>\n' 3622 html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">{2}&rarr;</div>\n'
3391 html_traceevent = '<div title="{0}" class="traceevent{6}" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;{7}">{5}</div>\n' 3623 html_traceevent = '<div title="{0}" class="traceevent{6}" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;{7}">{5}</div>\n'
3392 html_cpuexec = '<div class="jiffie" style="left:{0}%;top:{1}px;height:{2}px;width:{3}%;background:{4};"></div>\n' 3624 html_cpuexec = '<div class="jiffie" style="left:{0}%;top:{1}px;height:{2}px;width:{3}%;background:{4};"></div>\n'
3393 html_timetotal = '<table class="time1">\n<tr>'\ 3625 html_timetotal = '<table class="time1">\n<tr>'\
@@ -3416,20 +3648,17 @@ def createHTML(testruns):
3416 scaleH = 40 3648 scaleH = 40
3417 3649
3418 # device timeline 3650 # device timeline
3419 vprint('Creating Device Timeline...')
3420
3421 devtl = Timeline(30, scaleH) 3651 devtl = Timeline(30, scaleH)
3422 3652
3423 # write the test title and general info header 3653 # write the test title and general info header
3424 devtl.createHeader(sysvals) 3654 devtl.createHeader(sysvals, testruns[0].stamp)
3425 3655
3426 # Generate the header for this timeline 3656 # Generate the header for this timeline
3427 for data in testruns: 3657 for data in testruns:
3428 tTotal = data.end - data.start 3658 tTotal = data.end - data.start
3429 sktime, rktime = data.getTimeValues() 3659 sktime, rktime = data.getTimeValues()
3430 if(tTotal == 0): 3660 if(tTotal == 0):
3431 print('ERROR: No timeline data') 3661 doError('No timeline data')
3432 sys.exit()
3433 if(data.tLow > 0): 3662 if(data.tLow > 0):
3434 low_time = '%.0f'%(data.tLow*1000) 3663 low_time = '%.0f'%(data.tLow*1000)
3435 if sysvals.suspendmode == 'command': 3664 if sysvals.suspendmode == 'command':
@@ -3567,9 +3796,10 @@ def createHTML(testruns):
3567 data.dmesg[b]['color'], '') 3796 data.dmesg[b]['color'], '')
3568 for e in data.errorinfo[dir]: 3797 for e in data.errorinfo[dir]:
3569 # draw red lines for any kernel errors found 3798 # draw red lines for any kernel errors found
3570 t, err = e 3799 type, t, idx1, idx2 = e
3800 id = '%d_%d' % (idx1, idx2)
3571 right = '%f' % (((mMax-t)*100.0)/mTotal) 3801 right = '%f' % (((mMax-t)*100.0)/mTotal)
3572 devtl.html += html_error.format(right, err) 3802 devtl.html += html_error.format(right, id, type)
3573 for b in sorted(phases[dir]): 3803 for b in sorted(phases[dir]):
3574 # draw the devices for this phase 3804 # draw the devices for this phase
3575 phaselist = data.dmesg[b]['list'] 3805 phaselist = data.dmesg[b]['list']
@@ -3663,14 +3893,7 @@ def createHTML(testruns):
3663 devtl.html += '</div>\n' 3893 devtl.html += '</div>\n'
3664 3894
3665 hf = open(sysvals.htmlfile, 'w') 3895 hf = open(sysvals.htmlfile, 'w')
3666 3896 addCSS(hf, sysvals, len(testruns), kerror)
3667 # no header or css if its embedded
3668 if(sysvals.embedded):
3669 hf.write('pass True tSus %.3f tRes %.3f tLow %.3f fwvalid %s tSus %.3f tRes %.3f\n' %
3670 (data.tSuspended-data.start, data.end-data.tSuspended, data.tLow, data.fwValid, \
3671 data.fwSuspend/1000000, data.fwResume/1000000))
3672 else:
3673 addCSS(hf, sysvals, len(testruns), kerror)
3674 3897
3675 # write the device timeline 3898 # write the device timeline
3676 hf.write(devtl.html) 3899 hf.write(devtl.html)
@@ -3701,7 +3924,7 @@ def createHTML(testruns):
3701 data = testruns[sysvals.cgtest] 3924 data = testruns[sysvals.cgtest]
3702 else: 3925 else:
3703 data = testruns[-1] 3926 data = testruns[-1]
3704 if(sysvals.usecallgraph and not sysvals.embedded): 3927 if sysvals.usecallgraph:
3705 addCallgraphs(sysvals, hf, data) 3928 addCallgraphs(sysvals, hf, data)
3706 3929
3707 # add the test log as a hidden div 3930 # add the test log as a hidden div
@@ -3710,7 +3933,7 @@ def createHTML(testruns):
3710 # add the dmesg log as a hidden div 3933 # add the dmesg log as a hidden div
3711 if sysvals.dmesglog and sysvals.dmesgfile: 3934 if sysvals.dmesglog and sysvals.dmesgfile:
3712 hf.write('<div id="dmesglog" style="display:none;">\n') 3935 hf.write('<div id="dmesglog" style="display:none;">\n')
3713 lf = open(sysvals.dmesgfile, 'r') 3936 lf = sysvals.openlog(sysvals.dmesgfile, 'r')
3714 for line in lf: 3937 for line in lf:
3715 line = line.replace('<', '&lt').replace('>', '&gt') 3938 line = line.replace('<', '&lt').replace('>', '&gt')
3716 hf.write(line) 3939 hf.write(line)
@@ -3719,28 +3942,15 @@ def createHTML(testruns):
3719 # add the ftrace log as a hidden div 3942 # add the ftrace log as a hidden div
3720 if sysvals.ftracelog and sysvals.ftracefile: 3943 if sysvals.ftracelog and sysvals.ftracefile:
3721 hf.write('<div id="ftracelog" style="display:none;">\n') 3944 hf.write('<div id="ftracelog" style="display:none;">\n')
3722 lf = open(sysvals.ftracefile, 'r') 3945 lf = sysvals.openlog(sysvals.ftracefile, 'r')
3723 for line in lf: 3946 for line in lf:
3724 hf.write(line) 3947 hf.write(line)
3725 lf.close() 3948 lf.close()
3726 hf.write('</div>\n') 3949 hf.write('</div>\n')
3727 3950
3728 if(not sysvals.embedded): 3951 # write the footer and close
3729 # write the footer and close 3952 addScriptCode(hf, testruns)
3730 addScriptCode(hf, testruns) 3953 hf.write('</body>\n</html>\n')
3731 hf.write('</body>\n</html>\n')
3732 else:
3733 # embedded out will be loaded in a page, skip the js
3734 t0 = (testruns[0].start - testruns[-1].tSuspended) * 1000
3735 tMax = (testruns[-1].end - testruns[-1].tSuspended) * 1000
3736 # add js code in a div entry for later evaluation
3737 detail = 'var bounds = [%f,%f];\n' % (t0, tMax)
3738 detail += 'var devtable = [\n'
3739 for data in testruns:
3740 topo = data.deviceTopology()
3741 detail += '\t"%s",\n' % (topo)
3742 detail += '];\n'
3743 hf.write('<div id=customcode style=display:none>\n'+detail+'</div>\n')
3744 hf.close() 3954 hf.close()
3745 return True 3955 return True
3746 3956
@@ -4149,9 +4359,25 @@ def addScriptCode(hf, testruns):
4149 ' win.document.write(html+dt);\n'\ 4359 ' win.document.write(html+dt);\n'\
4150 ' }\n'\ 4360 ' }\n'\
4151 ' function errWindow() {\n'\ 4361 ' function errWindow() {\n'\
4152 ' var text = this.id;\n'\ 4362 ' var range = this.id.split("_");\n'\
4363 ' var idx1 = parseInt(range[0]);\n'\
4364 ' var idx2 = parseInt(range[1]);\n'\
4153 ' var win = window.open();\n'\ 4365 ' var win = window.open();\n'\
4154 ' win.document.write("<pre>"+text+"</pre>");\n'\ 4366 ' var log = document.getElementById("dmesglog");\n'\
4367 ' var title = "<title>dmesg log</title>";\n'\
4368 ' var text = log.innerHTML.split("\\n");\n'\
4369 ' var html = "";\n'\
4370 ' for(var i = 0; i < text.length; i++) {\n'\
4371 ' if(i == idx1) {\n'\
4372 ' html += "<e id=target>"+text[i]+"</e>\\n";\n'\
4373 ' } else if(i > idx1 && i <= idx2) {\n'\
4374 ' html += "<e>"+text[i]+"</e>\\n";\n'\
4375 ' } else {\n'\
4376 ' html += text[i]+"\\n";\n'\
4377 ' }\n'\
4378 ' }\n'\
4379 ' win.document.write("<style>e{color:red}</style>"+title+"<pre>"+html+"</pre>");\n'\
4380 ' win.location.hash = "#target";\n'\
4155 ' win.document.close();\n'\ 4381 ' win.document.close();\n'\
4156 ' }\n'\ 4382 ' }\n'\
4157 ' function logWindow(e) {\n'\ 4383 ' function logWindow(e) {\n'\
@@ -4219,6 +4445,30 @@ def addScriptCode(hf, testruns):
4219 '</script>\n' 4445 '</script>\n'
4220 hf.write(script_code); 4446 hf.write(script_code);
4221 4447
4448def setRuntimeSuspend(before=True):
4449 global sysvals
4450 sv = sysvals
4451 if sv.rs == 0:
4452 return
4453 if before:
4454 # runtime suspend disable or enable
4455 if sv.rs > 0:
4456 sv.rstgt, sv.rsval, sv.rsdir = 'on', 'auto', 'enabled'
4457 else:
4458 sv.rstgt, sv.rsval, sv.rsdir = 'auto', 'on', 'disabled'
4459 print('CONFIGURING RUNTIME SUSPEND...')
4460 sv.rslist = deviceInfo(sv.rstgt)
4461 for i in sv.rslist:
4462 sv.setVal(sv.rsval, i)
4463 print('runtime suspend %s on all devices (%d changed)' % (sv.rsdir, len(sv.rslist)))
4464 print('waiting 5 seconds...')
4465 time.sleep(5)
4466 else:
4467 # runtime suspend re-enable or re-disable
4468 for i in sv.rslist:
4469 sv.setVal(sv.rstgt, i)
4470 print('runtime suspend settings restored on %d devices' % len(sv.rslist))
4471
4222# Function: executeSuspend 4472# Function: executeSuspend
4223# Description: 4473# Description:
4224# Execute system suspend through the sysfs interface, then copy the output 4474# Execute system suspend through the sysfs interface, then copy the output
@@ -4227,6 +4477,19 @@ def executeSuspend():
4227 pm = ProcessMonitor() 4477 pm = ProcessMonitor()
4228 tp = sysvals.tpath 4478 tp = sysvals.tpath
4229 fwdata = [] 4479 fwdata = []
4480 # run these commands to prepare the system for suspend
4481 if sysvals.display:
4482 if sysvals.display > 0:
4483 print('TURN DISPLAY ON')
4484 call('xset -d :0.0 dpms force suspend', shell=True)
4485 call('xset -d :0.0 dpms force on', shell=True)
4486 else:
4487 print('TURN DISPLAY OFF')
4488 call('xset -d :0.0 dpms force suspend', shell=True)
4489 time.sleep(1)
4490 if sysvals.sync:
4491 print('SYNCING FILESYSTEMS')
4492 call('sync', shell=True)
4230 # mark the start point in the kernel ring buffer just as we start 4493 # mark the start point in the kernel ring buffer just as we start
4231 sysvals.initdmesg() 4494 sysvals.initdmesg()
4232 # start ftrace 4495 # start ftrace
@@ -4298,47 +4561,22 @@ def executeSuspend():
4298 pm.stop() 4561 pm.stop()
4299 sysvals.fsetVal('0', 'tracing_on') 4562 sysvals.fsetVal('0', 'tracing_on')
4300 print('CAPTURING TRACE') 4563 print('CAPTURING TRACE')
4301 sysvals.writeDatafileHeader(sysvals.ftracefile, fwdata) 4564 op = sysvals.writeDatafileHeader(sysvals.ftracefile, fwdata)
4302 call('cat '+tp+'trace >> '+sysvals.ftracefile, shell=True) 4565 fp = open(tp+'trace', 'r')
4566 for line in fp:
4567 op.write(line)
4568 op.close()
4303 sysvals.fsetVal('', 'trace') 4569 sysvals.fsetVal('', 'trace')
4304 devProps() 4570 devProps()
4305 # grab a copy of the dmesg output 4571 # grab a copy of the dmesg output
4306 print('CAPTURING DMESG') 4572 print('CAPTURING DMESG')
4307 sysvals.writeDatafileHeader(sysvals.dmesgfile, fwdata) 4573 sysvals.getdmesg(fwdata)
4308 sysvals.getdmesg()
4309 4574
4310# Function: setUSBDevicesAuto 4575def readFile(file):
4311# Description: 4576 if os.path.islink(file):
4312# Set the autosuspend control parameter of all USB devices to auto 4577 return os.readlink(file).split('/')[-1]
4313# This can be dangerous, so use at your own risk, most devices are set 4578 else:
4314# to always-on since the kernel cant determine if the device can 4579 return sysvals.getVal(file).strip()
4315# properly autosuspend
4316def setUSBDevicesAuto():
4317 sysvals.rootCheck(True)
4318 for dirname, dirnames, filenames in os.walk('/sys/devices'):
4319 if(re.match('.*/usb[0-9]*.*', dirname) and
4320 'idVendor' in filenames and 'idProduct' in filenames):
4321 call('echo auto > %s/power/control' % dirname, shell=True)
4322 name = dirname.split('/')[-1]
4323 desc = Popen(['cat', '%s/product' % dirname],
4324 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '')
4325 ctrl = Popen(['cat', '%s/power/control' % dirname],
4326 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '')
4327 print('control is %s for %6s: %s' % (ctrl, name, desc))
4328
4329# Function: yesno
4330# Description:
4331# Print out an equivalent Y or N for a set of known parameter values
4332# Output:
4333# 'Y', 'N', or ' ' if the value is unknown
4334def yesno(val):
4335 yesvals = ['auto', 'enabled', 'active', '1']
4336 novals = ['on', 'disabled', 'suspended', 'forbidden', 'unsupported']
4337 if val in yesvals:
4338 return 'Y'
4339 elif val in novals:
4340 return 'N'
4341 return ' '
4342 4580
4343# Function: ms2nice 4581# Function: ms2nice
4344# Description: 4582# Description:
@@ -4346,69 +4584,81 @@ def yesno(val):
4346# Output: 4584# Output:
4347# The time string, e.g. "1901m16s" 4585# The time string, e.g. "1901m16s"
4348def ms2nice(val): 4586def ms2nice(val):
4349 ms = 0 4587 val = int(val)
4350 try: 4588 h = val / 3600000
4351 ms = int(val) 4589 m = (val / 60000) % 60
4352 except: 4590 s = (val / 1000) % 60
4353 return 0.0 4591 if h > 0:
4354 m = ms / 60000 4592 return '%d:%02d:%02d' % (h, m, s)
4355 s = (ms / 1000) - (m * 60) 4593 if m > 0:
4356 return '%3dm%2ds' % (m, s) 4594 return '%02d:%02d' % (m, s)
4595 return '%ds' % s
4357 4596
4358# Function: detectUSB 4597def yesno(val):
4598 list = {'enabled':'A', 'disabled':'S', 'auto':'E', 'on':'D',
4599 'active':'A', 'suspended':'S', 'suspending':'S'}
4600 if val not in list:
4601 return ' '
4602 return list[val]
4603
4604# Function: deviceInfo
4359# Description: 4605# Description:
4360# Detect all the USB hosts and devices currently connected and add 4606# Detect all the USB hosts and devices currently connected and add
4361# a list of USB device names to sysvals for better timeline readability 4607# a list of USB device names to sysvals for better timeline readability
4362def detectUSB(): 4608def deviceInfo(output=''):
4363 field = {'idVendor':'', 'idProduct':'', 'product':'', 'speed':''} 4609 if not output:
4364 power = {'async':'', 'autosuspend':'', 'autosuspend_delay_ms':'', 4610 print('LEGEND')
4365 'control':'', 'persist':'', 'runtime_enabled':'', 4611 print('---------------------------------------------------------------------------------------------')
4366 'runtime_status':'', 'runtime_usage':'', 4612 print(' A = async/sync PM queue (A/S) C = runtime active children')
4367 'runtime_active_time':'', 4613 print(' R = runtime suspend enabled/disabled (E/D) rACTIVE = runtime active (min/sec)')
4368 'runtime_suspended_time':'', 4614 print(' S = runtime status active/suspended (A/S) rSUSPEND = runtime suspend (min/sec)')
4369 'active_duration':'', 4615 print(' U = runtime usage count')
4370 'connected_duration':''} 4616 print('---------------------------------------------------------------------------------------------')
4371 4617 print('DEVICE NAME A R S U C rACTIVE rSUSPEND')
4372 print('LEGEND') 4618 print('---------------------------------------------------------------------------------------------')
4373 print('---------------------------------------------------------------------------------------------') 4619
4374 print(' A = async/sync PM queue Y/N D = autosuspend delay (seconds)') 4620 res = []
4375 print(' S = autosuspend Y/N rACTIVE = runtime active (min/sec)') 4621 tgtval = 'runtime_status'
4376 print(' P = persist across suspend Y/N rSUSPEN = runtime suspend (min/sec)') 4622 lines = dict()
4377 print(' E = runtime suspend enabled/forbidden Y/N ACTIVE = active duration (min/sec)')
4378 print(' R = runtime status active/suspended Y/N CONNECT = connected duration (min/sec)')
4379 print(' U = runtime usage count')
4380 print('---------------------------------------------------------------------------------------------')
4381 print(' NAME ID DESCRIPTION SPEED A S P E R U D rACTIVE rSUSPEN ACTIVE CONNECT')
4382 print('---------------------------------------------------------------------------------------------')
4383
4384 for dirname, dirnames, filenames in os.walk('/sys/devices'): 4623 for dirname, dirnames, filenames in os.walk('/sys/devices'):
4385 if(re.match('.*/usb[0-9]*.*', dirname) and 4624 if(not re.match('.*/power', dirname) or
4386 'idVendor' in filenames and 'idProduct' in filenames): 4625 'control' not in filenames or
4387 for i in field: 4626 tgtval not in filenames):
4388 field[i] = Popen(['cat', '%s/%s' % (dirname, i)], 4627 continue
4389 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '') 4628 name = ''
4390 name = dirname.split('/')[-1] 4629 dirname = dirname[:-6]
4391 for i in power: 4630 device = dirname.split('/')[-1]
4392 power[i] = Popen(['cat', '%s/power/%s' % (dirname, i)], 4631 power = dict()
4393 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '') 4632 power[tgtval] = readFile('%s/power/%s' % (dirname, tgtval))
4394 if(re.match('usb[0-9]*', name)): 4633 # only list devices which support runtime suspend
4395 first = '%-8s' % name 4634 if power[tgtval] not in ['active', 'suspended', 'suspending']:
4396 else: 4635 continue
4397 first = '%8s' % name 4636 for i in ['product', 'driver', 'subsystem']:
4398 print('%s [%s:%s] %-20s %-4s %1s %1s %1s %1s %1s %1s %1s %s %s %s %s' % \ 4637 file = '%s/%s' % (dirname, i)
4399 (first, field['idVendor'], field['idProduct'], \ 4638 if os.path.exists(file):
4400 field['product'][0:20], field['speed'], \ 4639 name = readFile(file)
4401 yesno(power['async']), \ 4640 break
4402 yesno(power['control']), \ 4641 for i in ['async', 'control', 'runtime_status', 'runtime_usage',
4403 yesno(power['persist']), \ 4642 'runtime_active_kids', 'runtime_active_time',
4404 yesno(power['runtime_enabled']), \ 4643 'runtime_suspended_time']:
4405 yesno(power['runtime_status']), \ 4644 if i in filenames:
4406 power['runtime_usage'], \ 4645 power[i] = readFile('%s/power/%s' % (dirname, i))
4407 power['autosuspend'], \ 4646 if output:
4408 ms2nice(power['runtime_active_time']), \ 4647 if power['control'] == output:
4409 ms2nice(power['runtime_suspended_time']), \ 4648 res.append('%s/power/control' % dirname)
4410 ms2nice(power['active_duration']), \ 4649 continue
4411 ms2nice(power['connected_duration']))) 4650 lines[dirname] = '%-26s %-26s %1s %1s %1s %1s %1s %10s %10s' % \
4651 (device[:26], name[:26],
4652 yesno(power['async']), \
4653 yesno(power['control']), \
4654 yesno(power['runtime_status']), \
4655 power['runtime_usage'], \
4656 power['runtime_active_kids'], \
4657 ms2nice(power['runtime_active_time']), \
4658 ms2nice(power['runtime_suspended_time']))
4659 for i in sorted(lines):
4660 print lines[i]
4661 return res
4412 4662
4413# Function: devProps 4663# Function: devProps
4414# Description: 4664# Description:
@@ -4444,7 +4694,7 @@ def devProps(data=0):
4444 msghead = 'Additional data added by AnalyzeSuspend' 4694 msghead = 'Additional data added by AnalyzeSuspend'
4445 alreadystamped = False 4695 alreadystamped = False
4446 tp = TestProps() 4696 tp = TestProps()
4447 tf = open(sysvals.ftracefile, 'r') 4697 tf = sysvals.openlog(sysvals.ftracefile, 'r')
4448 for line in tf: 4698 for line in tf:
4449 if msghead in line: 4699 if msghead in line:
4450 alreadystamped = True 4700 alreadystamped = True
@@ -4469,7 +4719,7 @@ def devProps(data=0):
4469 if not alreadystamped and sysvals.suspendmode == 'command': 4719 if not alreadystamped and sysvals.suspendmode == 'command':
4470 out = '#\n# '+msghead+'\n# Device Properties: ' 4720 out = '#\n# '+msghead+'\n# Device Properties: '
4471 out += 'testcommandstring,%s,0;' % (sysvals.testcommand) 4721 out += 'testcommandstring,%s,0;' % (sysvals.testcommand)
4472 with open(sysvals.ftracefile, 'a') as fp: 4722 with sysvals.openlog(sysvals.ftracefile, 'a') as fp:
4473 fp.write(out+'\n') 4723 fp.write(out+'\n')
4474 sysvals.devprops = props 4724 sysvals.devprops = props
4475 return 4725 return
@@ -4526,7 +4776,7 @@ def devProps(data=0):
4526 out = '#\n# '+msghead+'\n# Device Properties: ' 4776 out = '#\n# '+msghead+'\n# Device Properties: '
4527 for dev in sorted(props): 4777 for dev in sorted(props):
4528 out += props[dev].out(dev) 4778 out += props[dev].out(dev)
4529 with open(sysvals.ftracefile, 'a') as fp: 4779 with sysvals.openlog(sysvals.ftracefile, 'a') as fp:
4530 fp.write(out+'\n') 4780 fp.write(out+'\n')
4531 4781
4532 sysvals.devprops = props 4782 sysvals.devprops = props
@@ -4869,20 +5119,12 @@ def statusCheck(probecheck=False):
4869 # what data source are we using 5119 # what data source are we using
4870 res = 'DMESG' 5120 res = 'DMESG'
4871 if(ftgood): 5121 if(ftgood):
4872 sysvals.usetraceeventsonly = True 5122 sysvals.usetraceevents = True
4873 sysvals.usetraceevents = False
4874 for e in sysvals.traceevents: 5123 for e in sysvals.traceevents:
4875 check = False 5124 if not os.path.exists(sysvals.epath+e):
4876 if(os.path.exists(sysvals.epath+e)): 5125 sysvals.usetraceevents = False
4877 check = True 5126 if(sysvals.usetraceevents):
4878 if(not check):
4879 sysvals.usetraceeventsonly = False
4880 if(e == 'suspend_resume' and check):
4881 sysvals.usetraceevents = True
4882 if(sysvals.usetraceevents and sysvals.usetraceeventsonly):
4883 res = 'FTRACE (all trace events found)' 5127 res = 'FTRACE (all trace events found)'
4884 elif(sysvals.usetraceevents):
4885 res = 'DMESG and FTRACE (suspend_resume trace event found)'
4886 print(' timeline data source: %s' % res) 5128 print(' timeline data source: %s' % res)
4887 5129
4888 # check if rtcwake 5130 # check if rtcwake
@@ -4917,6 +5159,7 @@ def doError(msg, help=False):
4917 if(help == True): 5159 if(help == True):
4918 printHelp() 5160 printHelp()
4919 print('ERROR: %s\n') % msg 5161 print('ERROR: %s\n') % msg
5162 sysvals.outputResult({'error':msg})
4920 sys.exit() 5163 sys.exit()
4921 5164
4922# Function: getArgInt 5165# Function: getArgInt
@@ -4957,22 +5200,36 @@ def getArgFloat(name, args, min, max, main=True):
4957 doError(name+': value should be between %f and %f' % (min, max), True) 5200 doError(name+': value should be between %f and %f' % (min, max), True)
4958 return val 5201 return val
4959 5202
4960def processData(): 5203def processData(live=False):
4961 print('PROCESSING DATA') 5204 print('PROCESSING DATA')
4962 if(sysvals.usetraceeventsonly): 5205 if(sysvals.usetraceevents):
4963 testruns = parseTraceLog() 5206 testruns = parseTraceLog(live)
4964 if sysvals.dmesgfile: 5207 if sysvals.dmesgfile:
4965 dmesgtext = loadKernelLog(True)
4966 for data in testruns: 5208 for data in testruns:
4967 data.extractErrorInfo(dmesgtext) 5209 data.extractErrorInfo()
4968 else: 5210 else:
4969 testruns = loadKernelLog() 5211 testruns = loadKernelLog()
4970 for data in testruns: 5212 for data in testruns:
4971 parseKernelLog(data) 5213 parseKernelLog(data)
4972 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)): 5214 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)):
4973 appendIncompleteTraceLog(testruns) 5215 appendIncompleteTraceLog(testruns)
5216 sysvals.vprint('Command:\n %s' % sysvals.cmdline)
5217 for data in testruns:
5218 data.printDetails()
5219 if sysvals.cgdump:
5220 for data in testruns:
5221 data.debugPrint()
5222 sys.exit()
5223
5224 sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile)
4974 createHTML(testruns) 5225 createHTML(testruns)
4975 return testruns 5226 print('DONE')
5227 data = testruns[0]
5228 stamp = data.stamp
5229 stamp['suspend'], stamp['resume'] = data.getTimeValues()
5230 if data.fwValid:
5231 stamp['fwsuspend'], stamp['fwresume'] = data.fwSuspend, data.fwResume
5232 return (testruns, stamp)
4976 5233
4977# Function: rerunTest 5234# Function: rerunTest
4978# Description: 5235# Description:
@@ -4980,37 +5237,36 @@ def processData():
4980def rerunTest(): 5237def rerunTest():
4981 if sysvals.ftracefile: 5238 if sysvals.ftracefile:
4982 doesTraceLogHaveTraceEvents() 5239 doesTraceLogHaveTraceEvents()
4983 if not sysvals.dmesgfile and not sysvals.usetraceeventsonly: 5240 if not sysvals.dmesgfile and not sysvals.usetraceevents:
4984 doError('recreating this html output requires a dmesg file') 5241 doError('recreating this html output requires a dmesg file')
4985 sysvals.setOutputFile() 5242 sysvals.setOutputFile()
4986 vprint('Output file: %s' % sysvals.htmlfile)
4987 if os.path.exists(sysvals.htmlfile): 5243 if os.path.exists(sysvals.htmlfile):
4988 if not os.path.isfile(sysvals.htmlfile): 5244 if not os.path.isfile(sysvals.htmlfile):
4989 doError('a directory already exists with this name: %s' % sysvals.htmlfile) 5245 doError('a directory already exists with this name: %s' % sysvals.htmlfile)
4990 elif not os.access(sysvals.htmlfile, os.W_OK): 5246 elif not os.access(sysvals.htmlfile, os.W_OK):
4991 doError('missing permission to write to %s' % sysvals.htmlfile) 5247 doError('missing permission to write to %s' % sysvals.htmlfile)
4992 return processData() 5248 testruns, stamp = processData(False)
5249 return stamp
4993 5250
4994# Function: runTest 5251# Function: runTest
4995# Description: 5252# Description:
4996# execute a suspend/resume, gather the logs, and generate the output 5253# execute a suspend/resume, gather the logs, and generate the output
4997def runTest(): 5254def runTest(n=0):
4998 # prepare for the test 5255 # prepare for the test
4999 sysvals.initFtrace() 5256 sysvals.initFtrace()
5000 sysvals.initTestOutput('suspend') 5257 sysvals.initTestOutput('suspend')
5001 vprint('Output files:\n\t%s\n\t%s\n\t%s' % \
5002 (sysvals.dmesgfile, sysvals.ftracefile, sysvals.htmlfile))
5003 5258
5004 # execute the test 5259 # execute the test
5005 executeSuspend() 5260 executeSuspend()
5006 sysvals.cleanupFtrace() 5261 sysvals.cleanupFtrace()
5007 processData() 5262 if sysvals.skiphtml:
5008 5263 sysvals.sudouser(sysvals.testdir)
5009 # if running as root, change output dir owner to sudo_user 5264 return
5010 if os.path.isdir(sysvals.testdir) and os.getuid() == 0 and \ 5265 testruns, stamp = processData(True)
5011 'SUDO_USER' in os.environ: 5266 for data in testruns:
5012 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1' 5267 del data
5013 call(cmd.format(os.environ['SUDO_USER'], sysvals.testdir), shell=True) 5268 sysvals.sudouser(sysvals.testdir)
5269 sysvals.outputResult(stamp, n)
5014 5270
5015def find_in_html(html, strs, div=False): 5271def find_in_html(html, strs, div=False):
5016 for str in strs: 5272 for str in strs:
@@ -5072,10 +5328,12 @@ def runSummary(subdir, local=True):
5072# Function: checkArgBool 5328# Function: checkArgBool
5073# Description: 5329# Description:
5074# check if a boolean string value is true or false 5330# check if a boolean string value is true or false
5075def checkArgBool(value): 5331def checkArgBool(name, value):
5076 yes = ['1', 'true', 'yes', 'on'] 5332 if value in switchvalues:
5077 if value.lower() in yes: 5333 if value in switchoff:
5334 return False
5078 return True 5335 return True
5336 doError('invalid boolean --> (%s: %s), use "true/false" or "1/0"' % (name, value), True)
5079 return False 5337 return False
5080 5338
5081# Function: configFromFile 5339# Function: configFromFile
@@ -5091,60 +5349,116 @@ def configFromFile(file):
5091 if 'Settings' in sections: 5349 if 'Settings' in sections:
5092 for opt in Config.options('Settings'): 5350 for opt in Config.options('Settings'):
5093 value = Config.get('Settings', opt).lower() 5351 value = Config.get('Settings', opt).lower()
5094 if(opt.lower() == 'verbose'): 5352 option = opt.lower()
5095 sysvals.verbose = checkArgBool(value) 5353 if(option == 'verbose'):
5096 elif(opt.lower() == 'addlogs'): 5354 sysvals.verbose = checkArgBool(option, value)
5097 sysvals.dmesglog = sysvals.ftracelog = checkArgBool(value) 5355 elif(option == 'addlogs'):
5098 elif(opt.lower() == 'dev'): 5356 sysvals.dmesglog = sysvals.ftracelog = checkArgBool(option, value)
5099 sysvals.usedevsrc = checkArgBool(value) 5357 elif(option == 'dev'):
5100 elif(opt.lower() == 'proc'): 5358 sysvals.usedevsrc = checkArgBool(option, value)
5101 sysvals.useprocmon = checkArgBool(value) 5359 elif(option == 'proc'):
5102 elif(opt.lower() == 'x2'): 5360 sysvals.useprocmon = checkArgBool(option, value)
5103 if checkArgBool(value): 5361 elif(option == 'x2'):
5362 if checkArgBool(option, value):
5104 sysvals.execcount = 2 5363 sysvals.execcount = 2
5105 elif(opt.lower() == 'callgraph'): 5364 elif(option == 'callgraph'):
5106 sysvals.usecallgraph = checkArgBool(value) 5365 sysvals.usecallgraph = checkArgBool(option, value)
5107 elif(opt.lower() == 'override-timeline-functions'): 5366 elif(option == 'override-timeline-functions'):
5108 overridekprobes = checkArgBool(value) 5367 overridekprobes = checkArgBool(option, value)
5109 elif(opt.lower() == 'override-dev-timeline-functions'): 5368 elif(option == 'override-dev-timeline-functions'):
5110 overridedevkprobes = checkArgBool(value) 5369 overridedevkprobes = checkArgBool(option, value)
5111 elif(opt.lower() == 'devicefilter'): 5370 elif(option == 'skiphtml'):
5371 sysvals.skiphtml = checkArgBool(option, value)
5372 elif(option == 'sync'):
5373 sysvals.sync = checkArgBool(option, value)
5374 elif(option == 'rs' or option == 'runtimesuspend'):
5375 if value in switchvalues:
5376 if value in switchoff:
5377 sysvals.rs = -1
5378 else:
5379 sysvals.rs = 1
5380 else:
5381 doError('invalid value --> (%s: %s), use "enable/disable"' % (option, value), True)
5382 elif(option == 'display'):
5383 if value in switchvalues:
5384 if value in switchoff:
5385 sysvals.display = -1
5386 else:
5387 sysvals.display = 1
5388 else:
5389 doError('invalid value --> (%s: %s), use "on/off"' % (option, value), True)
5390 elif(option == 'gzip'):
5391 sysvals.gzip = checkArgBool(option, value)
5392 elif(option == 'cgfilter'):
5393 sysvals.setCallgraphFilter(value)
5394 elif(option == 'cgskip'):
5395 if value in switchoff:
5396 sysvals.cgskip = ''
5397 else:
5398 sysvals.cgskip = sysvals.configFile(val)
5399 if(not sysvals.cgskip):
5400 doError('%s does not exist' % sysvals.cgskip)
5401 elif(option == 'cgtest'):
5402 sysvals.cgtest = getArgInt('cgtest', value, 0, 1, False)
5403 elif(option == 'cgphase'):
5404 d = Data(0)
5405 if value not in d.phases:
5406 doError('invalid phase --> (%s: %s), valid phases are %s'\
5407 % (option, value, d.phases), True)
5408 sysvals.cgphase = value
5409 elif(option == 'fadd'):
5410 file = sysvals.configFile(value)
5411 if(not file):
5412 doError('%s does not exist' % value)
5413 sysvals.addFtraceFilterFunctions(file)
5414 elif(option == 'result'):
5415 sysvals.result = value
5416 elif(option == 'multi'):
5417 nums = value.split()
5418 if len(nums) != 2:
5419 doError('multi requires 2 integers (exec_count and delay)', True)
5420 sysvals.multitest['run'] = True
5421 sysvals.multitest['count'] = getArgInt('multi: n d (exec count)', nums[0], 2, 1000000, False)
5422 sysvals.multitest['delay'] = getArgInt('multi: n d (delay between tests)', nums[1], 0, 3600, False)
5423 elif(option == 'devicefilter'):
5112 sysvals.setDeviceFilter(value) 5424 sysvals.setDeviceFilter(value)
5113 elif(opt.lower() == 'expandcg'): 5425 elif(option == 'expandcg'):
5114 sysvals.cgexp = checkArgBool(value) 5426 sysvals.cgexp = checkArgBool(option, value)
5115 elif(opt.lower() == 'srgap'): 5427 elif(option == 'srgap'):
5116 if checkArgBool(value): 5428 if checkArgBool(option, value):
5117 sysvals.srgap = 5 5429 sysvals.srgap = 5
5118 elif(opt.lower() == 'mode'): 5430 elif(option == 'mode'):
5119 sysvals.suspendmode = value 5431 sysvals.suspendmode = value
5120 elif(opt.lower() == 'command'): 5432 elif(option == 'command' or option == 'cmd'):
5121 sysvals.testcommand = value 5433 sysvals.testcommand = value
5122 elif(opt.lower() == 'x2delay'): 5434 elif(option == 'x2delay'):
5123 sysvals.x2delay = getArgInt('-x2delay', value, 0, 60000, False) 5435 sysvals.x2delay = getArgInt('x2delay', value, 0, 60000, False)
5124 elif(opt.lower() == 'predelay'): 5436 elif(option == 'predelay'):
5125 sysvals.predelay = getArgInt('-predelay', value, 0, 60000, False) 5437 sysvals.predelay = getArgInt('predelay', value, 0, 60000, False)
5126 elif(opt.lower() == 'postdelay'): 5438 elif(option == 'postdelay'):
5127 sysvals.postdelay = getArgInt('-postdelay', value, 0, 60000, False) 5439 sysvals.postdelay = getArgInt('postdelay', value, 0, 60000, False)
5128 elif(opt.lower() == 'maxdepth'): 5440 elif(option == 'maxdepth'):
5129 sysvals.max_graph_depth = getArgInt('-maxdepth', value, 0, 1000, False) 5441 sysvals.max_graph_depth = getArgInt('maxdepth', value, 0, 1000, False)
5130 elif(opt.lower() == 'rtcwake'): 5442 elif(option == 'rtcwake'):
5131 if value.lower() == 'off': 5443 if value in switchoff:
5132 sysvals.rtcwake = False 5444 sysvals.rtcwake = False
5133 else: 5445 else:
5134 sysvals.rtcwake = True 5446 sysvals.rtcwake = True
5135 sysvals.rtcwaketime = getArgInt('-rtcwake', value, 0, 3600, False) 5447 sysvals.rtcwaketime = getArgInt('rtcwake', value, 0, 3600, False)
5136 elif(opt.lower() == 'timeprec'): 5448 elif(option == 'timeprec'):
5137 sysvals.setPrecision(getArgInt('-timeprec', value, 0, 6, False)) 5449 sysvals.setPrecision(getArgInt('timeprec', value, 0, 6, False))
5138 elif(opt.lower() == 'mindev'): 5450 elif(option == 'mindev'):
5139 sysvals.mindevlen = getArgFloat('-mindev', value, 0.0, 10000.0, False) 5451 sysvals.mindevlen = getArgFloat('mindev', value, 0.0, 10000.0, False)
5140 elif(opt.lower() == 'callloop-maxgap'): 5452 elif(option == 'callloop-maxgap'):
5141 sysvals.callloopmaxgap = getArgFloat('-callloop-maxgap', value, 0.0, 1.0, False) 5453 sysvals.callloopmaxgap = getArgFloat('callloop-maxgap', value, 0.0, 1.0, False)
5142 elif(opt.lower() == 'callloop-maxlen'): 5454 elif(option == 'callloop-maxlen'):
5143 sysvals.callloopmaxgap = getArgFloat('-callloop-maxlen', value, 0.0, 1.0, False) 5455 sysvals.callloopmaxgap = getArgFloat('callloop-maxlen', value, 0.0, 1.0, False)
5144 elif(opt.lower() == 'mincg'): 5456 elif(option == 'mincg'):
5145 sysvals.mincglen = getArgFloat('-mincg', value, 0.0, 10000.0, False) 5457 sysvals.mincglen = getArgFloat('mincg', value, 0.0, 10000.0, False)
5146 elif(opt.lower() == 'output-dir'): 5458 elif(option == 'bufsize'):
5147 sysvals.testdir = sysvals.setOutputFolder(value) 5459 sysvals.bufsize = getArgInt('bufsize', value, 1, 1024*1024*8, False)
5460 elif(option == 'output-dir'):
5461 sysvals.outdir = sysvals.setOutputFolder(value)
5148 5462
5149 if sysvals.suspendmode == 'command' and not sysvals.testcommand: 5463 if sysvals.suspendmode == 'command' and not sysvals.testcommand:
5150 doError('No command supplied for mode "command"') 5464 doError('No command supplied for mode "command"')
@@ -5259,7 +5573,14 @@ def printHelp():
5259 print(' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)') 5573 print(' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)')
5260 print(' -addlogs Add the dmesg and ftrace logs to the html output') 5574 print(' -addlogs Add the dmesg and ftrace logs to the html output')
5261 print(' -srgap Add a visible gap in the timeline between sus/res (default: disabled)') 5575 print(' -srgap Add a visible gap in the timeline between sus/res (default: disabled)')
5576 print(' -skiphtml Run the test and capture the trace logs, but skip the timeline (default: disabled)')
5577 print(' -result fn Export a results table to a text file for parsing.')
5578 print(' [testprep]')
5579 print(' -sync Sync the filesystems before starting the test')
5580 print(' -rs on/off Enable/disable runtime suspend for all devices, restore all after test')
5581 print(' -display on/off Turn the display on or off for the test')
5262 print(' [advanced]') 5582 print(' [advanced]')
5583 print(' -gzip Gzip the trace and dmesg logs to save space')
5263 print(' -cmd {s} Run the timeline over a custom command, e.g. "sync -d"') 5584 print(' -cmd {s} Run the timeline over a custom command, e.g. "sync -d"')
5264 print(' -proc Add usermode process info into the timeline (default: disabled)') 5585 print(' -proc Add usermode process info into the timeline (default: disabled)')
5265 print(' -dev Add kernel function calls and threads to the timeline (default: disabled)') 5586 print(' -dev Add kernel function calls and threads to the timeline (default: disabled)')
@@ -5280,14 +5601,16 @@ def printHelp():
5280 print(' -cgphase P Only show callgraph data for phase P (e.g. suspend_late)') 5601 print(' -cgphase P Only show callgraph data for phase P (e.g. suspend_late)')
5281 print(' -cgtest N Only show callgraph data for test N (e.g. 0 or 1 in an x2 run)') 5602 print(' -cgtest N Only show callgraph data for test N (e.g. 0 or 1 in an x2 run)')
5282 print(' -timeprec N Number of significant digits in timestamps (0:S, [3:ms], 6:us)') 5603 print(' -timeprec N Number of significant digits in timestamps (0:S, [3:ms], 6:us)')
5604 print(' -cgfilter S Filter the callgraph output in the timeline')
5605 print(' -cgskip file Callgraph functions to skip, off to disable (default: cgskip.txt)')
5606 print(' -bufsize N Set trace buffer size to N kilo-bytes (default: all of free memory)')
5283 print('') 5607 print('')
5284 print('Other commands:') 5608 print('Other commands:')
5285 print(' -modes List available suspend modes') 5609 print(' -modes List available suspend modes')
5286 print(' -status Test to see if the system is enabled to run this tool') 5610 print(' -status Test to see if the system is enabled to run this tool')
5287 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table') 5611 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table')
5288 print(' -sysinfo Print out system info extracted from BIOS') 5612 print(' -sysinfo Print out system info extracted from BIOS')
5289 print(' -usbtopo Print out the current USB topology with power info') 5613 print(' -devinfo Print out the pm settings of all devices which support runtime suspend')
5290 print(' -usbauto Enable autosuspend for all connected USB devices')
5291 print(' -flist Print the list of functions currently being captured in ftrace') 5614 print(' -flist Print the list of functions currently being captured in ftrace')
5292 print(' -flistall Print all functions capable of being captured in ftrace') 5615 print(' -flistall Print all functions capable of being captured in ftrace')
5293 print(' -summary directory Create a summary of all test in this dir') 5616 print(' -summary directory Create a summary of all test in this dir')
@@ -5301,9 +5624,9 @@ def printHelp():
5301# exec start (skipped if script is loaded as library) 5624# exec start (skipped if script is loaded as library)
5302if __name__ == '__main__': 5625if __name__ == '__main__':
5303 cmd = '' 5626 cmd = ''
5304 outdir = '' 5627 simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', '-devinfo', '-status']
5305 multitest = {'run': False, 'count': 0, 'delay': 0} 5628 if '-f' in sys.argv:
5306 simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', '-usbtopo', '-usbauto', '-status'] 5629 sysvals.cgskip = sysvals.configFile('cgskip.txt')
5307 # loop through the command line arguments 5630 # loop through the command line arguments
5308 args = iter(sys.argv[1:]) 5631 args = iter(sys.argv[1:])
5309 for arg in args: 5632 for arg in args:
@@ -5333,6 +5656,10 @@ if __name__ == '__main__':
5333 sysvals.postdelay = getArgInt('-postdelay', args, 0, 60000) 5656 sysvals.postdelay = getArgInt('-postdelay', args, 0, 60000)
5334 elif(arg == '-f'): 5657 elif(arg == '-f'):
5335 sysvals.usecallgraph = True 5658 sysvals.usecallgraph = True
5659 elif(arg == '-skiphtml'):
5660 sysvals.skiphtml = True
5661 elif(arg == '-cgdump'):
5662 sysvals.cgdump = True
5336 elif(arg == '-addlogs'): 5663 elif(arg == '-addlogs'):
5337 sysvals.dmesglog = sysvals.ftracelog = True 5664 sysvals.dmesglog = sysvals.ftracelog = True
5338 elif(arg == '-verbose'): 5665 elif(arg == '-verbose'):
@@ -5341,6 +5668,34 @@ if __name__ == '__main__':
5341 sysvals.useprocmon = True 5668 sysvals.useprocmon = True
5342 elif(arg == '-dev'): 5669 elif(arg == '-dev'):
5343 sysvals.usedevsrc = True 5670 sysvals.usedevsrc = True
5671 elif(arg == '-sync'):
5672 sysvals.sync = True
5673 elif(arg == '-gzip'):
5674 sysvals.gzip = True
5675 elif(arg == '-rs'):
5676 try:
5677 val = args.next()
5678 except:
5679 doError('-rs requires "enable" or "disable"', True)
5680 if val.lower() in switchvalues:
5681 if val.lower() in switchoff:
5682 sysvals.rs = -1
5683 else:
5684 sysvals.rs = 1
5685 else:
5686 doError('invalid option: %s, use "enable/disable" or "on/off"' % val, True)
5687 elif(arg == '-display'):
5688 try:
5689 val = args.next()
5690 except:
5691 doError('-display requires "on" or "off"', True)
5692 if val.lower() in switchvalues:
5693 if val.lower() in switchoff:
5694 sysvals.display = -1
5695 else:
5696 sysvals.display = 1
5697 else:
5698 doError('invalid option: %s, use "on/off"' % val, True)
5344 elif(arg == '-maxdepth'): 5699 elif(arg == '-maxdepth'):
5345 sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000) 5700 sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000)
5346 elif(arg == '-rtcwake'): 5701 elif(arg == '-rtcwake'):
@@ -5348,7 +5703,7 @@ if __name__ == '__main__':
5348 val = args.next() 5703 val = args.next()
5349 except: 5704 except:
5350 doError('No rtcwake time supplied', True) 5705 doError('No rtcwake time supplied', True)
5351 if val.lower() == 'off': 5706 if val.lower() in switchoff:
5352 sysvals.rtcwake = False 5707 sysvals.rtcwake = False
5353 else: 5708 else:
5354 sysvals.rtcwake = True 5709 sysvals.rtcwake = True
@@ -5359,6 +5714,8 @@ if __name__ == '__main__':
5359 sysvals.mindevlen = getArgFloat('-mindev', args, 0.0, 10000.0) 5714 sysvals.mindevlen = getArgFloat('-mindev', args, 0.0, 10000.0)
5360 elif(arg == '-mincg'): 5715 elif(arg == '-mincg'):
5361 sysvals.mincglen = getArgFloat('-mincg', args, 0.0, 10000.0) 5716 sysvals.mincglen = getArgFloat('-mincg', args, 0.0, 10000.0)
5717 elif(arg == '-bufsize'):
5718 sysvals.bufsize = getArgInt('-bufsize', args, 1, 1024*1024*8)
5362 elif(arg == '-cgtest'): 5719 elif(arg == '-cgtest'):
5363 sysvals.cgtest = getArgInt('-cgtest', args, 0, 1) 5720 sysvals.cgtest = getArgInt('-cgtest', args, 0, 1)
5364 elif(arg == '-cgphase'): 5721 elif(arg == '-cgphase'):
@@ -5368,8 +5725,26 @@ if __name__ == '__main__':
5368 doError('No phase name supplied', True) 5725 doError('No phase name supplied', True)
5369 d = Data(0) 5726 d = Data(0)
5370 if val not in d.phases: 5727 if val not in d.phases:
5371 doError('Invalid phase, valid phaess are %s' % d.phases, True) 5728 doError('invalid phase --> (%s: %s), valid phases are %s'\
5729 % (arg, val, d.phases), True)
5372 sysvals.cgphase = val 5730 sysvals.cgphase = val
5731 elif(arg == '-cgfilter'):
5732 try:
5733 val = args.next()
5734 except:
5735 doError('No callgraph functions supplied', True)
5736 sysvals.setCallgraphFilter(val)
5737 elif(arg == '-cgskip'):
5738 try:
5739 val = args.next()
5740 except:
5741 doError('No file supplied', True)
5742 if val.lower() in switchoff:
5743 sysvals.cgskip = ''
5744 else:
5745 sysvals.cgskip = sysvals.configFile(val)
5746 if(not sysvals.cgskip):
5747 doError('%s does not exist' % sysvals.cgskip)
5373 elif(arg == '-callloop-maxgap'): 5748 elif(arg == '-callloop-maxgap'):
5374 sysvals.callloopmaxgap = getArgFloat('-callloop-maxgap', args, 0.0, 1.0) 5749 sysvals.callloopmaxgap = getArgFloat('-callloop-maxgap', args, 0.0, 1.0)
5375 elif(arg == '-callloop-maxlen'): 5750 elif(arg == '-callloop-maxlen'):
@@ -5386,31 +5761,33 @@ if __name__ == '__main__':
5386 elif(arg == '-srgap'): 5761 elif(arg == '-srgap'):
5387 sysvals.srgap = 5 5762 sysvals.srgap = 5
5388 elif(arg == '-multi'): 5763 elif(arg == '-multi'):
5389 multitest['run'] = True 5764 sysvals.multitest['run'] = True
5390 multitest['count'] = getArgInt('-multi n (exec count)', args, 2, 1000000) 5765 sysvals.multitest['count'] = getArgInt('-multi n d (exec count)', args, 2, 1000000)
5391 multitest['delay'] = getArgInt('-multi d (delay between tests)', args, 0, 3600) 5766 sysvals.multitest['delay'] = getArgInt('-multi n d (delay between tests)', args, 0, 3600)
5392 elif(arg == '-o'): 5767 elif(arg == '-o'):
5393 try: 5768 try:
5394 val = args.next() 5769 val = args.next()
5395 except: 5770 except:
5396 doError('No subdirectory name supplied', True) 5771 doError('No subdirectory name supplied', True)
5397 outdir = sysvals.setOutputFolder(val) 5772 sysvals.outdir = sysvals.setOutputFolder(val)
5398 elif(arg == '-config'): 5773 elif(arg == '-config'):
5399 try: 5774 try:
5400 val = args.next() 5775 val = args.next()
5401 except: 5776 except:
5402 doError('No text file supplied', True) 5777 doError('No text file supplied', True)
5403 if(os.path.exists(val) == False): 5778 file = sysvals.configFile(val)
5779 if(not file):
5404 doError('%s does not exist' % val) 5780 doError('%s does not exist' % val)
5405 configFromFile(val) 5781 configFromFile(file)
5406 elif(arg == '-fadd'): 5782 elif(arg == '-fadd'):
5407 try: 5783 try:
5408 val = args.next() 5784 val = args.next()
5409 except: 5785 except:
5410 doError('No text file supplied', True) 5786 doError('No text file supplied', True)
5411 if(os.path.exists(val) == False): 5787 file = sysvals.configFile(val)
5788 if(not file):
5412 doError('%s does not exist' % val) 5789 doError('%s does not exist' % val)
5413 sysvals.addFtraceFilterFunctions(val) 5790 sysvals.addFtraceFilterFunctions(file)
5414 elif(arg == '-dmesg'): 5791 elif(arg == '-dmesg'):
5415 try: 5792 try:
5416 val = args.next() 5793 val = args.next()
@@ -5435,7 +5812,7 @@ if __name__ == '__main__':
5435 except: 5812 except:
5436 doError('No directory supplied', True) 5813 doError('No directory supplied', True)
5437 cmd = 'summary' 5814 cmd = 'summary'
5438 outdir = val 5815 sysvals.outdir = val
5439 sysvals.notestrun = True 5816 sysvals.notestrun = True
5440 if(os.path.isdir(val) == False): 5817 if(os.path.isdir(val) == False):
5441 doError('%s is not accesible' % val) 5818 doError('%s is not accesible' % val)
@@ -5445,6 +5822,12 @@ if __name__ == '__main__':
5445 except: 5822 except:
5446 doError('No devnames supplied', True) 5823 doError('No devnames supplied', True)
5447 sysvals.setDeviceFilter(val) 5824 sysvals.setDeviceFilter(val)
5825 elif(arg == '-result'):
5826 try:
5827 val = args.next()
5828 except:
5829 doError('No result file supplied', True)
5830 sysvals.result = val
5448 else: 5831 else:
5449 doError('Invalid argument: '+arg, True) 5832 doError('Invalid argument: '+arg, True)
5450 5833
@@ -5454,42 +5837,48 @@ if __name__ == '__main__':
5454 if(sysvals.usecallgraph and sysvals.useprocmon): 5837 if(sysvals.usecallgraph and sysvals.useprocmon):
5455 doError('-proc is not compatible with -f') 5838 doError('-proc is not compatible with -f')
5456 5839
5840 if sysvals.usecallgraph and sysvals.cgskip:
5841 sysvals.vprint('Using cgskip file: %s' % sysvals.cgskip)
5842 sysvals.setCallgraphBlacklist(sysvals.cgskip)
5843
5457 # callgraph size cannot exceed device size 5844 # callgraph size cannot exceed device size
5458 if sysvals.mincglen < sysvals.mindevlen: 5845 if sysvals.mincglen < sysvals.mindevlen:
5459 sysvals.mincglen = sysvals.mindevlen 5846 sysvals.mincglen = sysvals.mindevlen
5460 5847
5461 # just run a utility command and exit 5848 # remove existing buffers before calculating memory
5849 if(sysvals.usecallgraph or sysvals.usedevsrc):
5850 sysvals.fsetVal('16', 'buffer_size_kb')
5462 sysvals.cpuInfo() 5851 sysvals.cpuInfo()
5852
5853 # just run a utility command and exit
5463 if(cmd != ''): 5854 if(cmd != ''):
5464 if(cmd == 'status'): 5855 if(cmd == 'status'):
5465 statusCheck(True) 5856 statusCheck(True)
5466 elif(cmd == 'fpdt'): 5857 elif(cmd == 'fpdt'):
5467 getFPDT(True) 5858 getFPDT(True)
5468 elif(cmd == 'sysinfo'): 5859 elif(cmd == 'sysinfo'):
5469 sysvals.printSystemInfo() 5860 sysvals.printSystemInfo(True)
5470 elif(cmd == 'usbtopo'): 5861 elif(cmd == 'devinfo'):
5471 detectUSB() 5862 deviceInfo()
5472 elif(cmd == 'modes'): 5863 elif(cmd == 'modes'):
5473 print getModes() 5864 print getModes()
5474 elif(cmd == 'flist'): 5865 elif(cmd == 'flist'):
5475 sysvals.getFtraceFilterFunctions(True) 5866 sysvals.getFtraceFilterFunctions(True)
5476 elif(cmd == 'flistall'): 5867 elif(cmd == 'flistall'):
5477 sysvals.getFtraceFilterFunctions(False) 5868 sysvals.getFtraceFilterFunctions(False)
5478 elif(cmd == 'usbauto'):
5479 setUSBDevicesAuto()
5480 elif(cmd == 'summary'): 5869 elif(cmd == 'summary'):
5481 runSummary(outdir, True) 5870 runSummary(sysvals.outdir, True)
5482 sys.exit() 5871 sys.exit()
5483 5872
5484 # if instructed, re-analyze existing data files 5873 # if instructed, re-analyze existing data files
5485 if(sysvals.notestrun): 5874 if(sysvals.notestrun):
5486 rerunTest() 5875 stamp = rerunTest()
5876 sysvals.outputResult(stamp)
5487 sys.exit() 5877 sys.exit()
5488 5878
5489 # verify that we can run a test 5879 # verify that we can run a test
5490 if(not statusCheck()): 5880 if(not statusCheck()):
5491 print('Check FAILED, aborting the test run!') 5881 doError('Check FAILED, aborting the test run!')
5492 sys.exit()
5493 5882
5494 # extract mem modes and convert 5883 # extract mem modes and convert
5495 mode = sysvals.suspendmode 5884 mode = sysvals.suspendmode
@@ -5509,25 +5898,35 @@ if __name__ == '__main__':
5509 5898
5510 sysvals.systemInfo(dmidecode(sysvals.mempath)) 5899 sysvals.systemInfo(dmidecode(sysvals.mempath))
5511 5900
5512 if multitest['run']: 5901 setRuntimeSuspend(True)
5902 if sysvals.display:
5903 call('xset -d :0.0 dpms 0 0 0', shell=True)
5904 call('xset -d :0.0 s off', shell=True)
5905 if sysvals.multitest['run']:
5513 # run multiple tests in a separate subdirectory 5906 # run multiple tests in a separate subdirectory
5514 if not outdir: 5907 if not sysvals.outdir:
5515 s = 'suspend-x%d' % multitest['count'] 5908 s = 'suspend-x%d' % sysvals.multitest['count']
5516 outdir = datetime.now().strftime(s+'-%y%m%d-%H%M%S') 5909 sysvals.outdir = datetime.now().strftime(s+'-%y%m%d-%H%M%S')
5517 if not os.path.isdir(outdir): 5910 if not os.path.isdir(sysvals.outdir):
5518 os.mkdir(outdir) 5911 os.mkdir(sysvals.outdir)
5519 for i in range(multitest['count']): 5912 for i in range(sysvals.multitest['count']):
5520 if(i != 0): 5913 if(i != 0):
5521 print('Waiting %d seconds...' % (multitest['delay'])) 5914 print('Waiting %d seconds...' % (sysvals.multitest['delay']))
5522 time.sleep(multitest['delay']) 5915 time.sleep(sysvals.multitest['delay'])
5523 print('TEST (%d/%d) START' % (i+1, multitest['count'])) 5916 print('TEST (%d/%d) START' % (i+1, sysvals.multitest['count']))
5524 fmt = 'suspend-%y%m%d-%H%M%S' 5917 fmt = 'suspend-%y%m%d-%H%M%S'
5525 sysvals.testdir = os.path.join(outdir, datetime.now().strftime(fmt)) 5918 sysvals.testdir = os.path.join(sysvals.outdir, datetime.now().strftime(fmt))
5526 runTest() 5919 runTest(i+1)
5527 print('TEST (%d/%d) COMPLETE' % (i+1, multitest['count'])) 5920 print('TEST (%d/%d) COMPLETE' % (i+1, sysvals.multitest['count']))
5528 runSummary(outdir, False) 5921 sysvals.logmsg = ''
5922 if not sysvals.skiphtml:
5923 runSummary(sysvals.outdir, False)
5924 sysvals.sudouser(sysvals.outdir)
5529 else: 5925 else:
5530 if outdir: 5926 if sysvals.outdir:
5531 sysvals.testdir = outdir 5927 sysvals.testdir = sysvals.outdir
5532 # run the test in the current directory 5928 # run the test in the current directory
5533 runTest() 5929 runTest()
5930 if sysvals.display:
5931 call('xset -d :0.0 s reset', shell=True)
5932 setRuntimeSuspend(False)