diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-03 13:45:39 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-03 13:45:39 -0400 |
| commit | f2d285669aae656dfeafa0bf25e86bbbc5d22329 (patch) | |
| tree | 4391c45051429c09199d7fd2ca6ca0dd142a5ed6 | |
| parent | be5537542743f72c7cedddd145c17cf7706baa23 (diff) | |
| parent | 103cf0e5799ce024fd28dfab716d7111afe4b117 (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
...
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 | ||
| 201 | What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/s2idle/ | ||
| 202 | Date: March 2018 | ||
| 203 | KernelVersion: v4.17 | ||
| 204 | Contact: Linux power management list <linux-pm@vger.kernel.org> | ||
| 205 | Description: | ||
| 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 | |||
| 211 | What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/s2idle/time | ||
| 212 | Date: March 2018 | ||
| 213 | KernelVersion: v4.17 | ||
| 214 | Contact: Linux power management list <linux-pm@vger.kernel.org> | ||
| 215 | Description: | ||
| 216 | Total time spent by the CPU in suspend-to-idle (with scheduler | ||
| 217 | tick suspended) after requesting this state. | ||
| 218 | |||
| 219 | What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/s2idle/usage | ||
| 220 | Date: March 2018 | ||
| 221 | KernelVersion: v4.17 | ||
| 222 | Contact: Linux power management list <linux-pm@vger.kernel.org> | ||
| 223 | Description: | ||
| 224 | Total number of times this state has been requested by the CPU | ||
| 225 | while entering suspend-to-idle. | ||
| 201 | 226 | ||
| 202 | What: /sys/devices/system/cpu/cpu#/cpufreq/* | 227 | What: /sys/devices/system/cpu/cpu#/cpufreq/* |
| 203 | Date: pre-git history | 228 | Date: 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 | |||
| 291 | What: /sys/power/resume_offset | ||
| 292 | Date: April 2018 | ||
| 293 | Contact: Mario Limonciello <mario.limonciello@dell.com> | ||
| 294 | Description: | ||
| 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 | ||
| 25 | Examples: | 23 | Examples: |
| @@ -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 | ||
| 27 | Swap partition: | ||
| 27 | You need to append resume=/dev/your_swap_partition to kernel command | 28 | You need to append resume=/dev/your_swap_partition to kernel command |
| 28 | line. Then you suspend by | 29 | line or specify it using /sys/power/resume. |
| 30 | |||
| 31 | Swap file: | ||
| 32 | If using a swapfile you can also specify a resume offset using | ||
| 33 | resume_offset=<number> on the kernel command line or specify it | ||
| 34 | in /sys/power/resume_offset. | ||
| 35 | |||
| 36 | After preparing then you suspend by | ||
| 29 | 37 | ||
| 30 | echo shutdown > /sys/power/disk; echo disk > /sys/power/state | 38 | echo 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 | ||
| 295 | static void __device_link_del(struct device_link *link) | 298 | static 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 */ |
| 308 | static void __device_link_del(struct device_link *link) | 313 | static 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 | */ |
| 329 | void device_link_del(struct device_link *link) | 338 | void 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 | ||
| 36 | extern void dev_pm_arm_wake_irq(struct wake_irq *wirq); | 37 | extern 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 | } |
| 117 | EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq); | 118 | EXPORT_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 | ||
| 211 | err_free_irq: | 218 | err_free_irq: |
| 212 | free_irq(irq, wirq); | 219 | free_irq(irq, wirq); |
| 220 | err_free_name: | ||
| 221 | kfree(wirq->name); | ||
| 213 | err_free: | 222 | err_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 | |||
| 45 | config ARM_SCPI_CPUFREQ | 45 | config 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 | ||
| 845 | err_freqfree: | ||
| 846 | kfree(freq_table); | ||
| 847 | err_unreg: | 839 | err_unreg: |
| 848 | acpi_processor_unregister_performance(cpu); | 840 | acpi_processor_unregister_performance(cpu); |
| 849 | err_free_mask: | 841 | err_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 | ||
| 866 | static 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 | |||
| 874 | static int acpi_cpufreq_resume(struct cpufreq_policy *policy) | 875 | static 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 | ||
| 232 | out: | 235 | out: |
| 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 | ||
| 1329 | out_exit_policy: | 1326 | out_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 | ||
| 1332 | out_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 | |||
| 1338 | out_free_policy: | 1336 | out_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 = ¢aur->freq_table[0]; | |
| 363 | ret = cpufreq_table_validate_and_show(policy, ¢aur->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 | } |
| 367 | EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show); | 367 | EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show); |
| 368 | 368 | ||
| 369 | int 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 | |||
| 369 | MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); | 383 | MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); |
| 370 | MODULE_DESCRIPTION("CPUfreq frequency table helpers"); | 384 | MODULE_DESCRIPTION("CPUfreq frequency table helpers"); |
| 371 | MODULE_LICENSE("GPL"); | 385 | MODULE_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[] = { | |||
| 52 | static struct device *cpu_dev; | 52 | static struct device *cpu_dev; |
| 53 | static bool free_opp; | 53 | static bool free_opp; |
| 54 | static struct cpufreq_frequency_table *freq_table; | 54 | static struct cpufreq_frequency_table *freq_table; |
| 55 | static unsigned int max_freq; | ||
| 55 | static unsigned int transition_latency; | 56 | static unsigned int transition_latency; |
| 56 | 57 | ||
| 57 | static u32 *imx6_soc_volt; | 58 | static 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 | ||
| 902 | static struct cpufreq_driver longhaul_driver = { | 903 | static 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 | |||
| 475 | out_free_cpufreq_table: | ||
| 476 | dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table); | ||
| 477 | return ret; | ||
| 478 | } | 469 | } |
| 479 | 470 | ||
| 480 | static int mtk_cpufreq_exit(struct cpufreq_policy *policy) | 471 | static 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 | ||
| 646 | static int powernow_cpu_exit(struct cpufreq_policy *policy) | 647 | static 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) | |||
| 122 | static void count_off_irt(struct powernow_k8_data *data) | 122 | static 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 */ |
| 129 | static void count_off_vst(struct powernow_k8_data *data) | 128 | static 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 | ||
| 813 | static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy) | 813 | static 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 | ||
| 862 | static int powernv_cpufreq_cpu_exit(struct cpufreq_policy *policy) | 857 | static 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 | ||
| 129 | static int cbe_cpufreq_target(struct cpufreq_policy *policy, | 128 | static 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 | ||
| 114 | static void __update_core_freq(struct pxa3xx_freq_info *info) | 116 | static 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, | |||
| 165 | static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) | 165 | static 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 | ||
| 239 | err_nomem1: | ||
| 240 | kfree(table); | ||
| 241 | err_pclk: | 228 | err_pclk: |
| 242 | kfree(data->pclk); | 229 | kfree(data->pclk); |
| 243 | err_nomem2: | 230 | err_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) | |||
| 351 | static int s3c_cpufreq_init(struct cpufreq_policy *policy) | 351 | static 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 | ||
| 181 | out_put_clk: | ||
| 182 | clk_put(priv->clk); | ||
| 183 | out_free_cpufreq_table: | 175 | out_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); |
| 185 | out_free_priv: | 177 | out_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 | ||
| 79 | static struct cpufreq_driver sfi_cpufreq_driver = { | 80 | static 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 | ||
| 149 | static 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 | |||
| 158 | static struct cpufreq_driver sh_cpufreq_driver = { | 159 | static 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 | ||
| 299 | static int us2e_freq_cpu_exit(struct cpufreq_policy *policy) | 300 | static 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 | ||
| 143 | static int us3_freq_cpu_exit(struct cpufreq_policy *policy) | 144 | static 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 | ||
| 402 | static int centrino_cpu_exit(struct cpufreq_policy *policy) | 402 | static 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 | ||
| 272 | static unsigned int speedstep_get(unsigned int cpu) | 274 | static 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, | |||
| 131 | static void enter_s2idle_proper(struct cpuidle_driver *drv, | 131 | static 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 | |||
| 11 | static int __cpuidle poll_idle(struct cpuidle_device *dev, | 15 | static 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) \ | ||
| 335 | static 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 | |||
| 342 | define_show_state_s2idle_ull_function(usage); | ||
| 343 | define_show_state_s2idle_ull_function(time); | ||
| 344 | |||
| 345 | #define define_one_state_s2idle_ro(_name, show) \ | ||
| 346 | static struct cpuidle_state_attr attr_s2idle_##_name = \ | ||
| 347 | __ATTR(_name, 0444, show, NULL) | ||
| 348 | |||
| 349 | define_one_state_s2idle_ro(usage, show_state_s2idle_usage); | ||
| 350 | define_one_state_s2idle_ro(time, show_state_s2idle_time); | ||
| 351 | |||
| 352 | static struct attribute *cpuidle_state_s2idle_attrs[] = { | ||
| 353 | &attr_s2idle_usage.attr, | ||
| 354 | &attr_s2idle_time.attr, | ||
| 355 | NULL | ||
| 356 | }; | ||
| 357 | |||
| 358 | static const struct attribute_group cpuidle_state_s2idle_group = { | ||
| 359 | .name = "s2idle", | ||
| 360 | .attrs = cpuidle_state_s2idle_attrs, | ||
| 361 | }; | ||
| 362 | |||
| 363 | static 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 | |||
| 375 | static 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 | ||
| 381 | static inline void cpuidle_add_s2idle_attr_group(struct cpuidle_state_kobj *kobj) { } | ||
| 382 | static 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 | ||
| 384 | static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i) | 436 | static 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 | ||
| 453 | static int socket_suspend(struct pcmcia_socket *skt) | 453 | static 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; | |||
| 962 | extern struct freq_attr *cpufreq_generic_attr[]; | 962 | extern struct freq_attr *cpufreq_generic_attr[]; |
| 963 | int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, | 963 | int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, |
| 964 | struct cpufreq_frequency_table *table); | 964 | struct cpufreq_frequency_table *table); |
| 965 | int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy); | ||
| 965 | 966 | ||
| 966 | unsigned int cpufreq_generic_get(unsigned int cpu); | 967 | unsigned int cpufreq_generic_get(unsigned int cpu); |
| 967 | int cpufreq_generic_init(struct cpufreq_policy *policy, | 968 | int 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 | ||
| 38 | struct cpuidle_state { | 42 | struct 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 | */ |
| 774 | struct device_link { | 775 | struct 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 | ||
| 1062 | power_attr(resume); | 1062 | power_attr(resume); |
| 1063 | 1063 | ||
| 1064 | static 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 | |||
| 1070 | static 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 | |||
| 1085 | power_attr(resume_offset); | ||
| 1086 | |||
| 1064 | static ssize_t image_size_show(struct kobject *kobj, struct kobj_attribute *attr, | 1087 | static 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 | ||
| 1107 | static struct attribute * g[] = { | 1130 | static 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 | ||
| 8 | install : uninstall | 8 | install : 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 | |||
| 37 | Add the dmesg log to the html output. It will be viewable by | 37 | Add the dmesg log to the html output. It will be viewable by |
| 38 | clicking a button in the timeline. | 38 | clicking a button in the timeline. |
| 39 | .TP | 39 | .TP |
| 40 | \fB-result \fIfile\fR | ||
| 41 | Export a results table to a text file for parsing. | ||
| 42 | .TP | ||
| 40 | \fB-o \fIname\fR | 43 | \fB-o \fIname\fR |
| 41 | Overrides the output subdirectory name when running a new test. | 44 | Overrides the output subdirectory name when running a new test. |
| 42 | Use {date}, {time}, {hostname} for current values. | 45 | Use {date}, {time}, {hostname} for current values. |
| @@ -44,14 +47,14 @@ Use {date}, {time}, {hostname} for current values. | |||
| 44 | e.g. boot-{hostname}-{date}-{time} | 47 | e.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 |
| 48 | Use ftrace to add function detail (default: disabled) | ||
| 49 | .TP | ||
| 50 | \fB-callgraph\fR | ||
| 51 | Use ftrace to create initcall callgraphs (default: disabled). If -func | 51 | Use ftrace to create initcall callgraphs (default: disabled). If -func |
| 52 | is not used there will be one callgraph per initcall. This can produce | 52 | is not used there will be one callgraph per initcall. This can produce |
| 53 | very large outputs, i.e. 10MB - 100MB. | 53 | very large outputs, i.e. 10MB - 100MB. |
| 54 | .TP | 54 | .TP |
| 55 | \fB-fstat\fR | ||
| 56 | Use ftrace to add function detail (default: disabled) | ||
| 57 | .TP | ||
| 55 | \fB-maxdepth \fIlevel\fR | 58 | \fB-maxdepth \fIlevel\fR |
| 56 | limit the callgraph trace depth to \fIlevel\fR (default: 2). This is | 59 | limit the callgraph trace depth to \fIlevel\fR (default: 2). This is |
| 57 | the best way to limit the output size when using -callgraph. | 60 | the 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 | |||
| 67 | argument can be a single function name or a comma delimited list. | 70 | argument 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 | ||
| 74 | Reduce callgraph output in the timeline by skipping over uninteresting | ||
| 75 | functions in the trace, e.g. printk or console_unlock. The functions listed | ||
| 76 | in this file will show up as empty leaves in the callgraph with only the start/end | ||
| 77 | times displayed. | ||
| 78 | (default: none) | ||
| 79 | .TP | ||
| 70 | \fB-timeprec \fIn\fR | 80 | \fB-timeprec \fIn\fR |
| 71 | Number of significant digits in timestamps (0:S, 3:ms, [6:us]) | 81 | Number 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 | |||
| 32 | import shutil | 32 | import shutil |
| 33 | from datetime import datetime, timedelta | 33 | from datetime import datetime, timedelta |
| 34 | from subprocess import call, Popen, PIPE | 34 | from subprocess import call, Popen, PIPE |
| 35 | import analyze_suspend as aslib | 35 | import 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 |
| 43 | class SystemValues(aslib.SystemValues): | 43 | class 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 | ||
| 203 | sysvals = SystemValues() | 200 | sysvals = 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 |
| 277 | def parseKernelLog(): | 285 | def 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 |
| 355 | def parseTraceLog(data): | 371 | def 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 | ||
| 16 | up | ||
| 17 | down_timeout | ||
| 18 | mutex_lock | ||
| 19 | down_read | ||
| 20 | complete_all | ||
| 21 | schedule_timeout | ||
| 22 | wake_up_process | ||
| 23 | msleep | ||
| 24 | __udelay | ||
| 25 | ktime_get | ||
| 26 | |||
| 27 | # console calls | ||
| 28 | printk | ||
| 29 | dev_printk | ||
| 30 | console_unlock | ||
| 31 | |||
| 32 | # memory handling | ||
| 33 | __kmalloc | ||
| 34 | __kmalloc_track_caller | ||
| 35 | kmem_cache_alloc | ||
| 36 | kmem_cache_alloc_trace | ||
| 37 | kmem_cache_free | ||
| 38 | kstrdup | ||
| 39 | kstrdup_const | ||
| 40 | kmalloc_slab | ||
| 41 | new_slab | ||
| 42 | __slab_alloc | ||
| 43 | __slab_free | ||
| 44 | raw_pci_read | ||
| 45 | pci_read | ||
| 46 | alloc_pages_current | ||
| 47 | |||
| 48 | # debugfs and sysfs setup | ||
| 49 | debugfs_remove_recursive | ||
| 50 | debugfs_create_dir | ||
| 51 | debugfs_create_files | ||
| 52 | debugfs_create_dir | ||
| 53 | debugfs_get_inode | ||
| 54 | sysfs_add_file_mode_ns | ||
| 55 | sysfs_add_file | ||
| 56 | sysfs_create_dir_ns | ||
| 57 | sysfs_create_link | ||
| 58 | sysfs_create_group | ||
| 59 | sysfs_create_groups | ||
| 60 | sysfs_create_bin_file | ||
| 61 | dpm_sysfs_add | ||
| 62 | sysfs_create_file_ns | ||
| 63 | sysfs_merge_group | ||
| 64 | sysfs_add_link_to_group | ||
| 65 | sysfs_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) | ||
| 14 | verbose: false | ||
| 15 | |||
| 16 | # Suspend Mode | ||
| 17 | # e.g. standby, mem, freeze, disk (default: mem) | ||
| 18 | mode: mem | ||
| 19 | |||
| 20 | # Automatic Wakeup | ||
| 21 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) | ||
| 22 | rtcwake: 15 | ||
| 23 | |||
| 24 | # Add Logs | ||
| 25 | # add the dmesg and ftrace log to the html output (default: false) | ||
| 26 | addlogs: false | ||
| 27 | |||
| 28 | # Display function calls | ||
| 29 | # graph source functions in the timeline (default: false) | ||
| 30 | dev: true | ||
| 31 | |||
| 32 | # Callgraph | ||
| 33 | # gather detailed ftrace callgraph data on all timeline events (default: false) | ||
| 34 | callgraph: false | ||
| 35 | |||
| 36 | # Back to Back Suspend/Resume | ||
| 37 | # Run two suspend/resumes back to back (default: false) | ||
| 38 | x2: false | ||
| 39 | |||
| 40 | # Back to Back Suspend Delay | ||
| 41 | # Time delay between the two test runs in ms (default: 0 ms) | ||
| 42 | x2delay: 0 | ||
| 43 | |||
| 44 | # Minimum Device Length | ||
| 45 | # graph only devices longer than min in the timeline (default: 0.001 ms) | ||
| 46 | mindev: 1 | ||
| 47 | |||
| 48 | # Minimum Callgraph Length | ||
| 49 | # provide callgraph data for blocks longer than min (default: 0.001 ms) | ||
| 50 | mincg: 1 | ||
| 51 | |||
| 52 | # Suspend/Resume Gap | ||
| 53 | # insert a small visible gap between suspend and resume on the timeline (default: false) | ||
| 54 | srgap: false | ||
| 55 | |||
| 56 | # Output Directory Format | ||
| 57 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values | ||
| 58 | output-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 | ||
| 63 | override-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 | ||
| 68 | override-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 | ||
| 118 | sys_sync: | ||
| 119 | pm_prepare_console: | ||
| 120 | pm_notifier_call_chain: | ||
| 121 | freeze_processes: | ||
| 122 | freeze_kernel_threads: | ||
| 123 | pm_restrict_gfp_mask: | ||
| 124 | acpi_suspend_begin: | ||
| 125 | suspend_console: | ||
| 126 | acpi_pm_prepare: | ||
| 127 | syscore_suspend: | ||
| 128 | arch_enable_nonboot_cpus_end: | ||
| 129 | syscore_resume: | ||
| 130 | acpi_pm_finish: | ||
| 131 | resume_console: | ||
| 132 | acpi_pm_end: | ||
| 133 | pm_restore_gfp_mask: | ||
| 134 | thaw_processes: | ||
| 135 | pm_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 | # | ||
| 181 | msleep: msleep time=%di:s32 | ||
| 182 | schedule_timeout_uninterruptible: schedule_timeout_uninterruptible timeout=%di:s32 | ||
| 183 | schedule_timeout: schedule_timeout timeout=%di:s32 | ||
| 184 | usleep_range: usleep_range min=%di:s32 max=%si:s32 | ||
| 185 | __const_udelay: udelay loops=%di:s32 | ||
| 186 | __mutex_lock_slowpath: mutex_lock_slowpath | ||
| 187 | ata_eh_recover: ata_eh_recover port=+36(%di):s32 | ||
| 188 | acpi_os_stall: | ||
| 189 | acpi_resume_power_resources: | ||
| 190 | acpi_ps_parse_aml: | ||
| 191 | ext4_sync_fs: | ||
| 192 | i915_gem_resume: | ||
| 193 | i915_restore_state: | ||
| 194 | intel_opregion_setup: | ||
| 195 | g4x_pre_enable_dp: | ||
| 196 | vlv_pre_enable_dp: | ||
| 197 | chv_pre_enable_dp: | ||
| 198 | g4x_enable_dp: | ||
| 199 | vlv_enable_dp: | ||
| 200 | intel_hpd_init: | ||
| 201 | intel_opregion_register: | ||
| 202 | intel_dp_detect: | ||
| 203 | intel_hdmi_detect: | ||
| 204 | intel_opregion_init: | ||
| 205 | intel_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) | ||
| 18 | verbose: false | ||
| 19 | |||
| 20 | # Suspend Mode | ||
| 21 | # e.g. standby, mem, freeze, disk (default: mem) | ||
| 22 | mode: mem | ||
| 23 | |||
| 24 | # Output Directory Format | ||
| 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values | ||
| 26 | output-dir: suspend-{hostname}-{date}-{time} | ||
| 27 | |||
| 28 | # Automatic Wakeup | ||
| 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) | ||
| 30 | rtcwake: 15 | ||
| 31 | |||
| 32 | # Add Logs | ||
| 33 | # add the dmesg and ftrace log to the html output (default: false) | ||
| 34 | addlogs: true | ||
| 35 | |||
| 36 | # Suspend/Resume Gap | ||
| 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) | ||
| 38 | srgap: false | ||
| 39 | |||
| 40 | # Skip HTML generation | ||
| 41 | # Only capture the logs, don't generate the html timeline (default: false) | ||
| 42 | skiphtml: false | ||
| 43 | |||
| 44 | # Sync filesystem before suspend | ||
| 45 | # run sync before the test, minimizes sys_sync call time (default: false) | ||
| 46 | sync: 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) | ||
| 58 | result: result.txt | ||
| 59 | |||
| 60 | # Gzip the log files to save space | ||
| 61 | # Gzip the generated log files, and read gzipped log files (default: false) | ||
| 62 | gzip: 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) | ||
| 71 | proc: false | ||
| 72 | |||
| 73 | # Display function calls | ||
| 74 | # graph source functions in the timeline (default: false) | ||
| 75 | dev: 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) | ||
| 83 | x2: false | ||
| 84 | |||
| 85 | # Back to Back Suspend Delay | ||
| 86 | # Time delay between the two test runs in ms (default: 0 ms) | ||
| 87 | x2delay: 0 | ||
| 88 | |||
| 89 | # Pre Suspend Delay | ||
| 90 | # Include an N ms delay before (1st) suspend (default: 0 ms) | ||
| 91 | predelay: 0 | ||
| 92 | |||
| 93 | # Post Resume Delay | ||
| 94 | # Include an N ms delay after (last) resume (default: 0 ms) | ||
| 95 | postdelay: 0 | ||
| 96 | |||
| 97 | # Minimum Device Length | ||
| 98 | # graph only devices longer than min in the timeline (default: 0.001 ms) | ||
| 99 | mindev: 0.001 | ||
| 100 | |||
| 101 | # ---- Debug Options ---- | ||
| 102 | |||
| 103 | # Callgraph | ||
| 104 | # gather detailed ftrace callgraph data on all timeline events (default: false) | ||
| 105 | callgraph: false | ||
| 106 | |||
| 107 | # Callgraph phase filter | ||
| 108 | # Only enable callgraphs for one phase, i.e. resume_noirq (default: all) | ||
| 109 | cgphase: suspend | ||
| 110 | |||
| 111 | # Callgraph x2 test filter | ||
| 112 | # Only enable callgraphs test 0 or 1 when using -x2 (default: 1) | ||
| 113 | cgtest: 0 | ||
| 114 | |||
| 115 | # Expand Callgraph | ||
| 116 | # pre-expand the callgraph data in the html output (default: disabled) | ||
| 117 | expandcg: false | ||
| 118 | |||
| 119 | # Minimum Callgraph Length | ||
| 120 | # provide callgraph data for blocks longer than min (default: 0.001 ms) | ||
| 121 | mincg: 1 | ||
| 122 | |||
| 123 | # Timestamp Precision | ||
| 124 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) | ||
| 125 | timeprec: 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) | ||
| 19 | verbose: false | ||
| 20 | |||
| 21 | # Suspend Mode | ||
| 22 | # e.g. standby, mem, freeze, disk (default: mem) | ||
| 23 | mode: freeze | ||
| 24 | |||
| 25 | # Output Directory Format | ||
| 26 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values | ||
| 27 | output-dir: freeze-{hostname}-{date}-{time}-cg | ||
| 28 | |||
| 29 | # Automatic Wakeup | ||
| 30 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) | ||
| 31 | rtcwake: 15 | ||
| 32 | |||
| 33 | # Add Logs | ||
| 34 | # add the dmesg and ftrace log to the html output (default: false) | ||
| 35 | addlogs: false | ||
| 36 | |||
| 37 | # Suspend/Resume Gap | ||
| 38 | # insert a small visible gap between suspend and resume on the timeline (default: false) | ||
| 39 | srgap: 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) | ||
| 48 | proc: false | ||
| 49 | |||
| 50 | # Display function calls | ||
| 51 | # graph source functions in the timeline (default: false) | ||
| 52 | dev: false | ||
| 53 | |||
| 54 | # Back to Back Suspend/Resume | ||
| 55 | # Run two suspend/resumes back to back (default: false) | ||
| 56 | x2: false | ||
| 57 | |||
| 58 | # Back to Back Suspend Delay | ||
| 59 | # Time delay between the two test runs in ms (default: 0 ms) | ||
| 60 | x2delay: 0 | ||
| 61 | |||
| 62 | # Pre Suspend Delay | ||
| 63 | # Include an N ms delay before (1st) suspend (default: 0 ms) | ||
| 64 | predelay: 0 | ||
| 65 | |||
| 66 | # Post Resume Delay | ||
| 67 | # Include an N ms delay after (last) resume (default: 0 ms) | ||
| 68 | postdelay: 0 | ||
| 69 | |||
| 70 | # Minimum Device Length | ||
| 71 | # graph only devices longer than min in the timeline (default: 0.001 ms) | ||
| 72 | mindev: 1 | ||
| 73 | |||
| 74 | # ---- Debug Options ---- | ||
| 75 | |||
| 76 | # Callgraph | ||
| 77 | # gather detailed ftrace callgraph data on all timeline events (default: false) | ||
| 78 | callgraph: true | ||
| 79 | |||
| 80 | # Expand Callgraph | ||
| 81 | # pre-expand the callgraph data in the html output (default: disabled) | ||
| 82 | expandcg: false | ||
| 83 | |||
| 84 | # Minimum Callgraph Length | ||
| 85 | # provide callgraph data for blocks longer than min (default: 0.001 ms) | ||
| 86 | mincg: 1 | ||
| 87 | |||
| 88 | # Timestamp Precision | ||
| 89 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) | ||
| 90 | timeprec: 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) | ||
| 18 | verbose: false | ||
| 19 | |||
| 20 | # Suspend Mode | ||
| 21 | # e.g. standby, mem, freeze, disk (default: mem) | ||
| 22 | mode: freeze | ||
| 23 | |||
| 24 | # Output Directory Format | ||
| 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values | ||
| 26 | output-dir: freeze-{hostname}-{date}-{time}-dev | ||
| 27 | |||
| 28 | # Automatic Wakeup | ||
| 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) | ||
| 30 | rtcwake: 15 | ||
| 31 | |||
| 32 | # Add Logs | ||
| 33 | # add the dmesg and ftrace log to the html output (default: false) | ||
| 34 | addlogs: false | ||
| 35 | |||
| 36 | # Suspend/Resume Gap | ||
| 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) | ||
| 38 | srgap: 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) | ||
| 47 | proc: false | ||
| 48 | |||
| 49 | # Display function calls | ||
| 50 | # graph source functions in the timeline (default: false) | ||
| 51 | dev: true | ||
| 52 | |||
| 53 | # Back to Back Suspend/Resume | ||
| 54 | # Run two suspend/resumes back to back (default: false) | ||
| 55 | x2: false | ||
| 56 | |||
| 57 | # Back to Back Suspend Delay | ||
| 58 | # Time delay between the two test runs in ms (default: 0 ms) | ||
| 59 | x2delay: 0 | ||
| 60 | |||
| 61 | # Pre Suspend Delay | ||
| 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) | ||
| 63 | predelay: 0 | ||
| 64 | |||
| 65 | # Post Resume Delay | ||
| 66 | # Include an N ms delay after (last) resume (default: 0 ms) | ||
| 67 | postdelay: 0 | ||
| 68 | |||
| 69 | # Minimum Device Length | ||
| 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) | ||
| 71 | mindev: 1 | ||
| 72 | |||
| 73 | # ---- Debug Options ---- | ||
| 74 | |||
| 75 | # Callgraph | ||
| 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) | ||
| 77 | callgraph: false | ||
| 78 | |||
| 79 | # Expand Callgraph | ||
| 80 | # pre-expand the callgraph data in the html output (default: disabled) | ||
| 81 | expandcg: false | ||
| 82 | |||
| 83 | # Minimum Callgraph Length | ||
| 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) | ||
| 85 | mincg: 1 | ||
| 86 | |||
| 87 | # Timestamp Precision | ||
| 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) | ||
| 89 | timeprec: 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) | ||
| 18 | verbose: false | ||
| 19 | |||
| 20 | # Suspend Mode | ||
| 21 | # e.g. standby, mem, freeze, disk (default: mem) | ||
| 22 | mode: freeze | ||
| 23 | |||
| 24 | # Output Directory Format | ||
| 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values | ||
| 26 | output-dir: freeze-{hostname}-{date}-{time} | ||
| 27 | |||
| 28 | # Automatic Wakeup | ||
| 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) | ||
| 30 | rtcwake: 15 | ||
| 31 | |||
| 32 | # Add Logs | ||
| 33 | # add the dmesg and ftrace log to the html output (default: false) | ||
| 34 | addlogs: false | ||
| 35 | |||
| 36 | # Suspend/Resume Gap | ||
| 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) | ||
| 38 | srgap: 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) | ||
| 47 | proc: false | ||
| 48 | |||
| 49 | # Display function calls | ||
| 50 | # graph source functions in the timeline (default: false) | ||
| 51 | dev: false | ||
| 52 | |||
| 53 | # Back to Back Suspend/Resume | ||
| 54 | # Run two suspend/resumes back to back (default: false) | ||
| 55 | x2: false | ||
| 56 | |||
| 57 | # Back to Back Suspend Delay | ||
| 58 | # Time delay between the two test runs in ms (default: 0 ms) | ||
| 59 | x2delay: 0 | ||
| 60 | |||
| 61 | # Pre Suspend Delay | ||
| 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) | ||
| 63 | predelay: 0 | ||
| 64 | |||
| 65 | # Post Resume Delay | ||
| 66 | # Include an N ms delay after (last) resume (default: 0 ms) | ||
| 67 | postdelay: 0 | ||
| 68 | |||
| 69 | # Minimum Device Length | ||
| 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) | ||
| 71 | mindev: 0.001 | ||
| 72 | |||
| 73 | # ---- Debug Options ---- | ||
| 74 | |||
| 75 | # Callgraph | ||
| 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) | ||
| 77 | callgraph: false | ||
| 78 | |||
| 79 | # Expand Callgraph | ||
| 80 | # pre-expand the callgraph data in the html output (default: disabled) | ||
| 81 | expandcg: false | ||
| 82 | |||
| 83 | # Minimum Callgraph Length | ||
| 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) | ||
| 85 | mincg: 1 | ||
| 86 | |||
| 87 | # Timestamp Precision | ||
| 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) | ||
| 89 | timeprec: 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) | ||
| 19 | verbose: false | ||
| 20 | |||
| 21 | # Suspend Mode | ||
| 22 | # e.g. standby, mem, freeze, disk (default: mem) | ||
| 23 | mode: standby | ||
| 24 | |||
| 25 | # Output Directory Format | ||
| 26 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values | ||
| 27 | output-dir: standby-{hostname}-{date}-{time}-cg | ||
| 28 | |||
| 29 | # Automatic Wakeup | ||
| 30 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) | ||
| 31 | rtcwake: 15 | ||
| 32 | |||
| 33 | # Add Logs | ||
| 34 | # add the dmesg and ftrace log to the html output (default: false) | ||
| 35 | addlogs: false | ||
| 36 | |||
| 37 | # Suspend/Resume Gap | ||
| 38 | # insert a small visible gap between suspend and resume on the timeline (default: false) | ||
| 39 | srgap: 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) | ||
| 48 | proc: false | ||
| 49 | |||
| 50 | # Display function calls | ||
| 51 | # graph source functions in the timeline (default: false) | ||
| 52 | dev: false | ||
| 53 | |||
| 54 | # Back to Back Suspend/Resume | ||
| 55 | # Run two suspend/resumes back to back (default: false) | ||
| 56 | x2: false | ||
| 57 | |||
| 58 | # Back to Back Suspend Delay | ||
| 59 | # Time delay between the two test runs in ms (default: 0 ms) | ||
| 60 | x2delay: 0 | ||
| 61 | |||
| 62 | # Pre Suspend Delay | ||
| 63 | # Include an N ms delay before (1st) suspend (default: 0 ms) | ||
| 64 | predelay: 0 | ||
| 65 | |||
| 66 | # Post Resume Delay | ||
| 67 | # Include an N ms delay after (last) resume (default: 0 ms) | ||
| 68 | postdelay: 0 | ||
| 69 | |||
| 70 | # Minimum Device Length | ||
| 71 | # graph only devices longer than min in the timeline (default: 0.001 ms) | ||
| 72 | mindev: 1 | ||
| 73 | |||
| 74 | # ---- Debug Options ---- | ||
| 75 | |||
| 76 | # Callgraph | ||
| 77 | # gather detailed ftrace callgraph data on all timeline events (default: false) | ||
| 78 | callgraph: true | ||
| 79 | |||
| 80 | # Expand Callgraph | ||
| 81 | # pre-expand the callgraph data in the html output (default: disabled) | ||
| 82 | expandcg: false | ||
| 83 | |||
| 84 | # Minimum Callgraph Length | ||
| 85 | # provide callgraph data for blocks longer than min (default: 0.001 ms) | ||
| 86 | mincg: 1 | ||
| 87 | |||
| 88 | # Timestamp Precision | ||
| 89 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) | ||
| 90 | timeprec: 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) | ||
| 18 | verbose: false | ||
| 19 | |||
| 20 | # Suspend Mode | ||
| 21 | # e.g. standby, mem, freeze, disk (default: mem) | ||
| 22 | mode: standby | ||
| 23 | |||
| 24 | # Output Directory Format | ||
| 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values | ||
| 26 | output-dir: standby-{hostname}-{date}-{time}-dev | ||
| 27 | |||
| 28 | # Automatic Wakeup | ||
| 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) | ||
| 30 | rtcwake: 15 | ||
| 31 | |||
| 32 | # Add Logs | ||
| 33 | # add the dmesg and ftrace log to the html output (default: false) | ||
| 34 | addlogs: false | ||
| 35 | |||
| 36 | # Suspend/Resume Gap | ||
| 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) | ||
| 38 | srgap: 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) | ||
| 47 | proc: false | ||
| 48 | |||
| 49 | # Display function calls | ||
| 50 | # graph source functions in the timeline (default: false) | ||
| 51 | dev: true | ||
| 52 | |||
| 53 | # Back to Back Suspend/Resume | ||
| 54 | # Run two suspend/resumes back to back (default: false) | ||
| 55 | x2: false | ||
| 56 | |||
| 57 | # Back to Back Suspend Delay | ||
| 58 | # Time delay between the two test runs in ms (default: 0 ms) | ||
| 59 | x2delay: 0 | ||
| 60 | |||
| 61 | # Pre Suspend Delay | ||
| 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) | ||
| 63 | predelay: 0 | ||
| 64 | |||
| 65 | # Post Resume Delay | ||
| 66 | # Include an N ms delay after (last) resume (default: 0 ms) | ||
| 67 | postdelay: 0 | ||
| 68 | |||
| 69 | # Minimum Device Length | ||
| 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) | ||
| 71 | mindev: 1 | ||
| 72 | |||
| 73 | # ---- Debug Options ---- | ||
| 74 | |||
| 75 | # Callgraph | ||
| 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) | ||
| 77 | callgraph: false | ||
| 78 | |||
| 79 | # Expand Callgraph | ||
| 80 | # pre-expand the callgraph data in the html output (default: disabled) | ||
| 81 | expandcg: false | ||
| 82 | |||
| 83 | # Minimum Callgraph Length | ||
| 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) | ||
| 85 | mincg: 1 | ||
| 86 | |||
| 87 | # Timestamp Precision | ||
| 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) | ||
| 89 | timeprec: 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) | ||
| 18 | verbose: false | ||
| 19 | |||
| 20 | # Suspend Mode | ||
| 21 | # e.g. standby, mem, freeze, disk (default: mem) | ||
| 22 | mode: standby | ||
| 23 | |||
| 24 | # Output Directory Format | ||
| 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values | ||
| 26 | output-dir: standby-{hostname}-{date}-{time} | ||
| 27 | |||
| 28 | # Automatic Wakeup | ||
| 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) | ||
| 30 | rtcwake: 15 | ||
| 31 | |||
| 32 | # Add Logs | ||
| 33 | # add the dmesg and ftrace log to the html output (default: false) | ||
| 34 | addlogs: false | ||
| 35 | |||
| 36 | # Suspend/Resume Gap | ||
| 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) | ||
| 38 | srgap: 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) | ||
| 47 | proc: false | ||
| 48 | |||
| 49 | # Display function calls | ||
| 50 | # graph source functions in the timeline (default: false) | ||
| 51 | dev: false | ||
| 52 | |||
| 53 | # Back to Back Suspend/Resume | ||
| 54 | # Run two suspend/resumes back to back (default: false) | ||
| 55 | x2: false | ||
| 56 | |||
| 57 | # Back to Back Suspend Delay | ||
| 58 | # Time delay between the two test runs in ms (default: 0 ms) | ||
| 59 | x2delay: 0 | ||
| 60 | |||
| 61 | # Pre Suspend Delay | ||
| 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) | ||
| 63 | predelay: 0 | ||
| 64 | |||
| 65 | # Post Resume Delay | ||
| 66 | # Include an N ms delay after (last) resume (default: 0 ms) | ||
| 67 | postdelay: 0 | ||
| 68 | |||
| 69 | # Minimum Device Length | ||
| 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) | ||
| 71 | mindev: 0.001 | ||
| 72 | |||
| 73 | # ---- Debug Options ---- | ||
| 74 | |||
| 75 | # Callgraph | ||
| 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) | ||
| 77 | callgraph: false | ||
| 78 | |||
| 79 | # Expand Callgraph | ||
| 80 | # pre-expand the callgraph data in the html output (default: disabled) | ||
| 81 | expandcg: false | ||
| 82 | |||
| 83 | # Minimum Callgraph Length | ||
| 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) | ||
| 85 | mincg: 1 | ||
| 86 | |||
| 87 | # Timestamp Precision | ||
| 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) | ||
| 89 | timeprec: 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) | ||
| 19 | verbose: false | ||
| 20 | |||
| 21 | # Suspend Mode | ||
| 22 | # e.g. standby, mem, freeze, disk (default: mem) | ||
| 23 | mode: mem | ||
| 24 | |||
| 25 | # Output Directory Format | ||
| 26 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values | ||
| 27 | output-dir: suspend-{hostname}-{date}-{time}-cg | ||
| 28 | |||
| 29 | # Automatic Wakeup | ||
| 30 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) | ||
| 31 | rtcwake: 15 | ||
| 32 | |||
| 33 | # Add Logs | ||
| 34 | # add the dmesg and ftrace log to the html output (default: false) | ||
| 35 | addlogs: false | ||
| 36 | |||
| 37 | # Suspend/Resume Gap | ||
| 38 | # insert a small visible gap between suspend and resume on the timeline (default: false) | ||
| 39 | srgap: 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) | ||
| 48 | proc: false | ||
| 49 | |||
| 50 | # Display function calls | ||
| 51 | # graph source functions in the timeline (default: false) | ||
| 52 | dev: false | ||
| 53 | |||
| 54 | # Back to Back Suspend/Resume | ||
| 55 | # Run two suspend/resumes back to back (default: false) | ||
| 56 | x2: false | ||
| 57 | |||
| 58 | # Back to Back Suspend Delay | ||
| 59 | # Time delay between the two test runs in ms (default: 0 ms) | ||
| 60 | x2delay: 0 | ||
| 61 | |||
| 62 | # Pre Suspend Delay | ||
| 63 | # Include an N ms delay before (1st) suspend (default: 0 ms) | ||
| 64 | predelay: 0 | ||
| 65 | |||
| 66 | # Post Resume Delay | ||
| 67 | # Include an N ms delay after (last) resume (default: 0 ms) | ||
| 68 | postdelay: 0 | ||
| 69 | |||
| 70 | # Minimum Device Length | ||
| 71 | # graph only devices longer than min in the timeline (default: 0.001 ms) | ||
| 72 | mindev: 0.001 | ||
| 73 | |||
| 74 | # ---- Debug Options ---- | ||
| 75 | |||
| 76 | # Callgraph | ||
| 77 | # gather detailed ftrace callgraph data on all timeline events (default: false) | ||
| 78 | callgraph: true | ||
| 79 | |||
| 80 | # Max graph depth | ||
| 81 | # limit the callgraph trace to this depth (default: 0 = all) | ||
| 82 | maxdepth: 5 | ||
| 83 | |||
| 84 | # Expand Callgraph | ||
| 85 | # pre-expand the callgraph data in the html output (default: disabled) | ||
| 86 | expandcg: false | ||
| 87 | |||
| 88 | # Minimum Callgraph Length | ||
| 89 | # provide callgraph data for blocks longer than min (default: 0.001 ms) | ||
| 90 | mincg: 1 | ||
| 91 | |||
| 92 | # Timestamp Precision | ||
| 93 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) | ||
| 94 | timeprec: 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) | ||
| 18 | verbose: false | ||
| 19 | |||
| 20 | # Suspend Mode | ||
| 21 | # e.g. standby, mem, freeze, disk (default: mem) | ||
| 22 | mode: mem | ||
| 23 | |||
| 24 | # Output Directory Format | ||
| 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values | ||
| 26 | output-dir: suspend-{hostname}-{date}-{time}-dev | ||
| 27 | |||
| 28 | # Automatic Wakeup | ||
| 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) | ||
| 30 | rtcwake: 15 | ||
| 31 | |||
| 32 | # Add Logs | ||
| 33 | # add the dmesg and ftrace log to the html output (default: false) | ||
| 34 | addlogs: false | ||
| 35 | |||
| 36 | # Suspend/Resume Gap | ||
| 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) | ||
| 38 | srgap: 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) | ||
| 47 | proc: false | ||
| 48 | |||
| 49 | # Display function calls | ||
| 50 | # graph source functions in the timeline (default: false) | ||
| 51 | dev: true | ||
| 52 | |||
| 53 | # Back to Back Suspend/Resume | ||
| 54 | # Run two suspend/resumes back to back (default: false) | ||
| 55 | x2: false | ||
| 56 | |||
| 57 | # Back to Back Suspend Delay | ||
| 58 | # Time delay between the two test runs in ms (default: 0 ms) | ||
| 59 | x2delay: 0 | ||
| 60 | |||
| 61 | # Pre Suspend Delay | ||
| 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) | ||
| 63 | predelay: 0 | ||
| 64 | |||
| 65 | # Post Resume Delay | ||
| 66 | # Include an N ms delay after (last) resume (default: 0 ms) | ||
| 67 | postdelay: 0 | ||
| 68 | |||
| 69 | # Minimum Device Length | ||
| 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) | ||
| 71 | mindev: 1 | ||
| 72 | |||
| 73 | # ---- Debug Options ---- | ||
| 74 | |||
| 75 | # Callgraph | ||
| 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) | ||
| 77 | callgraph: false | ||
| 78 | |||
| 79 | # Expand Callgraph | ||
| 80 | # pre-expand the callgraph data in the html output (default: disabled) | ||
| 81 | expandcg: false | ||
| 82 | |||
| 83 | # Minimum Callgraph Length | ||
| 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) | ||
| 85 | mincg: 1 | ||
| 86 | |||
| 87 | # Timestamp Precision | ||
| 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) | ||
| 89 | timeprec: 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) | ||
| 18 | verbose: false | ||
| 19 | |||
| 20 | # Suspend Mode | ||
| 21 | # e.g. standby, mem, freeze, disk (default: mem) | ||
| 22 | mode: mem | ||
| 23 | |||
| 24 | # Output Directory Format | ||
| 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values | ||
| 26 | output-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) | ||
| 30 | rtcwake: 15 | ||
| 31 | |||
| 32 | # Add Logs | ||
| 33 | # add the dmesg and ftrace log to the html output (default: false) | ||
| 34 | addlogs: false | ||
| 35 | |||
| 36 | # Suspend/Resume Gap | ||
| 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) | ||
| 38 | srgap: 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) | ||
| 47 | proc: true | ||
| 48 | |||
| 49 | # Display function calls | ||
| 50 | # graph source functions in the timeline (default: false) | ||
| 51 | dev: false | ||
| 52 | |||
| 53 | # Back to Back Suspend/Resume | ||
| 54 | # Run two suspend/resumes back to back (default: false) | ||
| 55 | x2: true | ||
| 56 | |||
| 57 | # Back to Back Suspend Delay | ||
| 58 | # Time delay between the two test runs in ms (default: 0 ms) | ||
| 59 | x2delay: 1000 | ||
| 60 | |||
| 61 | # Pre Suspend Delay | ||
| 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) | ||
| 63 | predelay: 1000 | ||
| 64 | |||
| 65 | # Post Resume Delay | ||
| 66 | # Include an N ms delay after (last) resume (default: 0 ms) | ||
| 67 | postdelay: 1000 | ||
| 68 | |||
| 69 | # Minimum Device Length | ||
| 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) | ||
| 71 | mindev: 1 | ||
| 72 | |||
| 73 | # ---- Debug Options ---- | ||
| 74 | |||
| 75 | # Callgraph | ||
| 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) | ||
| 77 | callgraph: false | ||
| 78 | |||
| 79 | # Expand Callgraph | ||
| 80 | # pre-expand the callgraph data in the html output (default: disabled) | ||
| 81 | expandcg: false | ||
| 82 | |||
| 83 | # Minimum Callgraph Length | ||
| 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) | ||
| 85 | mincg: 1 | ||
| 86 | |||
| 87 | # Timestamp Precision | ||
| 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) | ||
| 89 | timeprec: 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) | ||
| 18 | verbose: false | ||
| 19 | |||
| 20 | # Suspend Mode | ||
| 21 | # e.g. standby, mem, freeze, disk (default: mem) | ||
| 22 | mode: mem | ||
| 23 | |||
| 24 | # Output Directory Format | ||
| 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values | ||
| 26 | output-dir: suspend-{hostname}-{date}-{time} | ||
| 27 | |||
| 28 | # Automatic Wakeup | ||
| 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) | ||
| 30 | rtcwake: 15 | ||
| 31 | |||
| 32 | # Add Logs | ||
| 33 | # add the dmesg and ftrace log to the html output (default: false) | ||
| 34 | addlogs: false | ||
| 35 | |||
| 36 | # Suspend/Resume Gap | ||
| 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) | ||
| 38 | srgap: 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) | ||
| 47 | proc: false | ||
| 48 | |||
| 49 | # Display function calls | ||
| 50 | # graph source functions in the timeline (default: false) | ||
| 51 | dev: false | ||
| 52 | |||
| 53 | # Back to Back Suspend/Resume | ||
| 54 | # Run two suspend/resumes back to back (default: false) | ||
| 55 | x2: false | ||
| 56 | |||
| 57 | # Back to Back Suspend Delay | ||
| 58 | # Time delay between the two test runs in ms (default: 0 ms) | ||
| 59 | x2delay: 0 | ||
| 60 | |||
| 61 | # Pre Suspend Delay | ||
| 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) | ||
| 63 | predelay: 0 | ||
| 64 | |||
| 65 | # Post Resume Delay | ||
| 66 | # Include an N ms delay after (last) resume (default: 0 ms) | ||
| 67 | postdelay: 0 | ||
| 68 | |||
| 69 | # Minimum Device Length | ||
| 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) | ||
| 71 | mindev: 0.001 | ||
| 72 | |||
| 73 | # ---- Debug Options ---- | ||
| 74 | |||
| 75 | # Callgraph | ||
| 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) | ||
| 77 | callgraph: false | ||
| 78 | |||
| 79 | # Expand Callgraph | ||
| 80 | # pre-expand the callgraph data in the html output (default: disabled) | ||
| 81 | expandcg: false | ||
| 82 | |||
| 83 | # Minimum Callgraph Length | ||
| 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) | ||
| 85 | mincg: 1 | ||
| 86 | |||
| 87 | # Timestamp Precision | ||
| 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) | ||
| 89 | timeprec: 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 |
| 53 | Add the dmesg and ftrace logs to the html output. They will be viewable by | 53 | Add the dmesg and ftrace logs to the html output. They will be viewable by |
| 54 | clicking buttons in the timeline. | 54 | clicking buttons in the timeline. |
| 55 | .TP | ||
| 56 | \fB-result \fIfile\fR | ||
| 57 | Export a results table to a text file for parsing. | ||
| 58 | .TP | ||
| 59 | \fB-sync\fR | ||
| 60 | Sync the filesystems before starting the test. This reduces the size of | ||
| 61 | the sys_sync call which happens in the suspend_prepare phase. | ||
| 62 | .TP | ||
| 63 | \fB-rs \fIenable/disable\fR | ||
| 64 | During test, enable/disable runtime suspend for all devices. The test is delayed | ||
| 65 | by 5 seconds to allow runtime suspend changes to occur. The settings are restored | ||
| 66 | after the test is complete. | ||
| 67 | .TP | ||
| 68 | \fB-display \fIon/off\fR | ||
| 69 | Turn the display on or off for the test using the xset command. This helps | ||
| 70 | maintain the consistecy of test data for better comparison. | ||
| 71 | .TP | ||
| 72 | \fB-skiphtml\fR | ||
| 73 | Run 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 | ||
| 78 | Gzip the trace and dmesg logs to save space. The tool can also read in gzipped | ||
| 79 | logs for processing. | ||
| 80 | .TP | ||
| 58 | \fB-cmd \fIstr\fR | 81 | \fB-cmd \fIstr\fR |
| 59 | Run the timeline over a custom suspend command, e.g. pm-suspend. By default | 82 | Run the timeline over a custom suspend command, e.g. pm-suspend. By default |
| 60 | the tool forces suspend via /sys/power/state so this allows testing over | 83 | the 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 | |||
| 114 | which are barely visible in the timeline. | 137 | which are barely visible in the timeline. |
| 115 | The value is a float: e.g. 0.001 represents 1 us. | 138 | The value is a float: e.g. 0.001 represents 1 us. |
| 116 | .TP | 139 | .TP |
| 140 | \fB-cgfilter \fI"func1,func2,..."\fR | ||
| 141 | Reduce callgraph output in the timeline by limiting it to a list of calls. The | ||
| 142 | argument can be a single function name or a comma delimited list. | ||
| 143 | (default: none) | ||
| 144 | .TP | ||
| 145 | \fB-cgskip \fIfile\fR | ||
| 146 | Reduce callgraph timeline size by skipping over uninteresting functions | ||
| 147 | in the trace, e.g. printk or console_unlock. The functions listed | ||
| 148 | in this file will show up as empty leaves in the callgraph with only the start/end | ||
| 149 | times displayed. cgskip.txt is used automatically if found in the path, so | ||
| 150 | use "off" to disable completely (default: cgskip.txt) | ||
| 151 | .TP | ||
| 117 | \fB-cgphase \fIp\fR | 152 | \fB-cgphase \fIp\fR |
| 118 | Only show callgraph data for phase \fIp\fR (e.g. suspend_late). | 153 | Only 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 |
| 124 | Number of significant digits in timestamps (0:S, [3:ms], 6:us). | 159 | Number of significant digits in timestamps (0:S, [3:ms], 6:us). |
| 160 | .TP | ||
| 161 | \fB-bufsize \fIN\fR | ||
| 162 | Set 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 |
| 145 | Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode. | 183 | Print 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 |
| 148 | Print out the current USB topology with power info. | 186 | Print out the pm settings of all devices which support runtime suspend. |
| 149 | .TP | ||
| 150 | \fB-usbauto\fR | ||
| 151 | Enable autosuspend for all connected USB devices. | ||
| 152 | .TP | 187 | .TP |
| 153 | \fB-flist\fR | 188 | \fB-flist\fR |
| 154 | Print the list of ftrace functions currently being captured. Functions | 189 | Print 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 |
| 199 | Execute a standby with a 15 second wakeup. Change the output folder name. | 234 | Execute 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 |
| 203 | Execute a freeze with no wakeup (require keypress). Change output folder name. | 238 | Execute 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 | |||
| 57 | from datetime import datetime | 57 | from datetime import datetime |
| 58 | import struct | 58 | import struct |
| 59 | import ConfigParser | 59 | import ConfigParser |
| 60 | import gzip | ||
| 60 | from threading import Thread | 61 | from threading import Thread |
| 61 | from subprocess import call, Popen, PIPE | 62 | from 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 |
| 69 | class SystemValues: | 70 | class 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 | ||
| 700 | sysvals = SystemValues() | 788 | sysvals = SystemValues() |
| 789 | switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0'] | ||
| 790 | switchoff = ['disable', 'off', 'false', '0'] | ||
| 701 | suspendmodename = { | 791 | suspendmodename = { |
| 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('<', '<').replace('>', '>') | 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 | ||
| 1810 | class DevItem: | 2020 | class 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: | |||
| 2067 | class TestProps: | 2277 | class 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 | ||
| 2194 | def 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 | ||
| 2204 | def doesTraceLogHaveTraceEvents(): | 2414 | def 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 |
| 2444 | def parseTraceLog(): | 2666 | def 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 |
| 2881 | def loadKernelLog(justtext=False): | 3118 | def 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+' → '+cg.name, color, dev['id']) | 3505 | name+' → '+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→</div>\n' | 3622 | html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">{2}→</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('<', '<').replace('>', '>') | 3938 | line = line.replace('<', '<').replace('>', '>') |
| 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 | ||
| 4448 | def 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 | 4575 | def 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 | ||
| 4316 | def 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 | ||
| 4334 | def 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" |
| 4348 | def ms2nice(val): | 4586 | def 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 | 4597 | def 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 |
| 4362 | def detectUSB(): | 4608 | def 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 | ||
| 4960 | def processData(): | 5203 | def 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(): | |||
| 4980 | def rerunTest(): | 5237 | def 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 |
| 4997 | def runTest(): | 5254 | def 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 | ||
| 5015 | def find_in_html(html, strs, div=False): | 5271 | def 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 |
| 5075 | def checkArgBool(value): | 5331 | def 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) |
| 5302 | if __name__ == '__main__': | 5625 | if __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) | ||
