aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-26 20:29:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-26 20:29:07 -0400
commit6453dbdda30428a3c56568c96fe70ea3612f07e2 (patch)
tree9a3c6087a2832c36e8c49296fb05f95b877e0111
parent27b79027bc112a63ad4004eb83c6acacae08a0de (diff)
parentbc841e260c95608921809a2c7481cf6f03bec21a (diff)
Merge tag 'pm-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael Wysocki: "Again, the majority of changes go into the cpufreq subsystem, but there are no big features this time. The cpufreq changes that stand out somewhat are the governor interface rework and improvements related to the handling of frequency tables. Apart from those, there are fixes and new device/CPU IDs in drivers, cleanups and an improvement of the new schedutil governor. Next, there are some changes in the hibernation core, including a fix for a nasty problem related to the MONITOR/MWAIT usage by CPU offline during resume from hibernation, a few core improvements related to memory management during resume, a couple of additional debug features and cleanups. Finally, we have some fixes and cleanups in the devfreq subsystem, generic power domains framework improvements related to system suspend/resume, support for some new chips in intel_idle and in the power capping RAPL driver, a new version of the AnalyzeSuspend utility and some assorted fixes and cleanups. Specifics: - Rework the cpufreq governor interface to make it more straightforward and modify the conservative governor to avoid using transition notifications (Rafael Wysocki). - Rework the handling of frequency tables by the cpufreq core to make it more efficient (Viresh Kumar). - Modify the schedutil governor to reduce the number of wakeups it causes to occur in cases when the CPU frequency doesn't need to be changed (Steve Muckle, Viresh Kumar). - Fix some minor issues and clean up code in the cpufreq core and governors (Rafael Wysocki, Viresh Kumar). - Add Intel Broxton support to the intel_pstate driver (Srinivas Pandruvada). - Fix problems related to the config TDP feature and to the validity of the MSR_HWP_INTERRUPT register in intel_pstate (Jan Kiszka, Srinivas Pandruvada). - Make intel_pstate update the cpu_frequency tracepoint even if the frequency doesn't change to avoid confusing powertop (Rafael Wysocki). - Clean up the usage of __init/__initdata in intel_pstate, mark some of its internal variables as __read_mostly and drop an unused structure element from it (Jisheng Zhang, Carsten Emde). - Clean up the usage of some duplicate MSR symbols in intel_pstate and turbostat (Srinivas Pandruvada). - Update/fix the powernv, s3c24xx and mvebu cpufreq drivers (Akshay Adiga, Viresh Kumar, Ben Dooks). - Fix a regression (introduced during the 4.5 cycle) in the pcc-cpufreq driver by reverting the problematic commit (Andreas Herrmann). - Add support for Intel Denverton to intel_idle, clean up Broxton support in it and make it explicitly non-modular (Jacob Pan, Jan Beulich, Paul Gortmaker). - Add support for Denverton and Ivy Bridge server to the Intel RAPL power capping driver and make it more careful about the handing of MSRs that may not be present (Jacob Pan, Xiaolong Wang). - Fix resume from hibernation on x86-64 by making the CPU offline during resume avoid using MONITOR/MWAIT in the "play dead" loop which may lead to an inadvertent "revival" of a "dead" CPU and a page fault leading to a kernel crash from it (Rafael Wysocki). - Make memory management during resume from hibernation more straightforward (Rafael Wysocki). - Add debug features that should help to detect problems related to hibernation and resume from it (Rafael Wysocki, Chen Yu). - Clean up hibernation core somewhat (Rafael Wysocki). - Prevent KASAN from instrumenting the hibernation core which leads to large numbers of false-positives from it (James Morse). - Prevent PM (hibernate and suspend) notifiers from being called during the cleanup phase if they have not been called during the corresponding preparation phase which is possible if one of the other notifiers returns an error at that time (Lianwei Wang). - Improve suspend-related debug printout in the tasks freezer and clean up suspend-related console handling (Roger Lu, Borislav Petkov). - Update the AnalyzeSuspend script in the kernel sources to version 4.2 (Todd Brandt). - Modify the generic power domains framework to make it handle system suspend/resume better (Ulf Hansson). - Make the runtime PM framework avoid resuming devices synchronously when user space changes the runtime PM settings for them and improve its error reporting (Rafael Wysocki, Linus Walleij). - Fix error paths in devfreq drivers (exynos, exynos-ppmu, exynos-bus) and in the core, make some devfreq code explicitly non-modular and change some of it into tristate (Bartlomiej Zolnierkiewicz, Peter Chen, Paul Gortmaker). - Add DT support to the generic PM clocks management code and make it export some more symbols (Jon Hunter, Paul Gortmaker). - Make the PCI PM core code slightly more robust against possible driver errors (Andy Shevchenko). - Make it possible to change DESTDIR and PREFIX in turbostat (Andy Shevchenko)" * tag 'pm-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (89 commits) Revert "cpufreq: pcc-cpufreq: update default value of cpuinfo_transition_latency" PM / hibernate: Introduce test_resume mode for hibernation cpufreq: export cpufreq_driver_resolve_freq() cpufreq: Disallow ->resolve_freq() for drivers providing ->target_index() PCI / PM: check all fields in pci_set_platform_pm() cpufreq: acpi-cpufreq: use cached frequency mapping when possible cpufreq: schedutil: map raw required frequency to driver frequency cpufreq: add cpufreq_driver_resolve_freq() cpufreq: intel_pstate: Check cpuid for MSR_HWP_INTERRUPT intel_pstate: Update cpu_frequency tracepoint every time cpufreq: intel_pstate: clean remnant struct element PM / tools: scripts: AnalyzeSuspend v4.2 x86 / hibernate: Use hlt_play_dead() when resuming from hibernation cpufreq: powernv: Replacing pstate_id with frequency table index intel_pstate: Fix MSR_CONFIG_TDP_x addressing in core_get_max_pstate() PM / hibernate: Image data protection during restoration PM / hibernate: Add missing braces in __register_nosave_region() PM / hibernate: Clean up comments in snapshot.c PM / hibernate: Clean up function headers in snapshot.c PM / hibernate: Add missing braces in hibernate_setup() ...
-rw-r--r--Documentation/cpu-freq/core.txt4
-rw-r--r--Documentation/cpu-freq/cpu-drivers.txt10
-rw-r--r--Documentation/cpu-freq/pcc-cpufreq.txt4
-rw-r--r--Documentation/kernel-parameters.txt3
-rw-r--r--arch/powerpc/platforms/cell/cpufreq_spudemand.c72
-rw-r--r--arch/x86/include/asm/msr-index.h2
-rw-r--r--arch/x86/include/asm/smp.h1
-rw-r--r--arch/x86/kernel/smpboot.c2
-rw-r--r--arch/x86/power/cpu.c30
-rw-r--r--drivers/base/power/clock_ops.c45
-rw-r--r--drivers/base/power/domain.c301
-rw-r--r--drivers/base/power/runtime.c13
-rw-r--r--drivers/cpufreq/Kconfig13
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c17
-rw-r--r--drivers/cpufreq/amd_freq_sensitivity.c10
-rw-r--r--drivers/cpufreq/cpufreq.c223
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c88
-rw-r--r--drivers/cpufreq/cpufreq_governor.c73
-rw-r--r--drivers/cpufreq/cpufreq_governor.h24
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c38
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.h1
-rw-r--r--drivers/cpufreq/cpufreq_performance.c19
-rw-r--r--drivers/cpufreq/cpufreq_powersave.c19
-rw-r--r--drivers/cpufreq/cpufreq_stats.c157
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c104
-rw-r--r--drivers/cpufreq/davinci-cpufreq.c22
-rw-r--r--drivers/cpufreq/freq_table.c106
-rw-r--r--drivers/cpufreq/intel_pstate.c74
-rw-r--r--drivers/cpufreq/mvebu-cpufreq.c2
-rw-r--r--drivers/cpufreq/pcc-cpufreq.c2
-rw-r--r--drivers/cpufreq/powernv-cpufreq.c181
-rw-r--r--drivers/cpufreq/ppc_cbe_cpufreq_pmi.c3
-rw-r--r--drivers/cpufreq/s3c24xx-cpufreq.c33
-rw-r--r--drivers/cpufreq/s5pv210-cpufreq.c7
-rw-r--r--drivers/devfreq/Kconfig2
-rw-r--r--drivers/devfreq/devfreq-event.c12
-rw-r--r--drivers/devfreq/devfreq.c15
-rw-r--r--drivers/devfreq/event/Kconfig4
-rw-r--r--drivers/devfreq/event/exynos-ppmu.c3
-rw-r--r--drivers/devfreq/exynos-bus.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c23
-rw-r--r--drivers/idle/intel_idle.c107
-rw-r--r--drivers/pci/pci.c4
-rw-r--r--drivers/powercap/intel_rapl.c107
-rw-r--r--drivers/thermal/cpu_cooling.c24
-rw-r--r--include/linux/cpufreq.h289
-rw-r--r--include/linux/pm_clock.h1
-rw-r--r--include/linux/pm_domain.h10
-rw-r--r--include/linux/suspend.h5
-rw-r--r--kernel/power/Makefile2
-rw-r--r--kernel/power/console.c8
-rw-r--r--kernel/power/hibernate.c101
-rw-r--r--kernel/power/main.c11
-rw-r--r--kernel/power/power.h11
-rw-r--r--kernel/power/process.c3
-rw-r--r--kernel/power/snapshot.c940
-rw-r--r--kernel/power/suspend.c10
-rw-r--r--kernel/power/swap.c6
-rw-r--r--kernel/power/user.c14
-rw-r--r--kernel/sched/cpufreq_schedutil.c74
-rw-r--r--kernel/workqueue.c4
-rwxr-xr-xscripts/analyze_suspend.py3641
-rw-r--r--tools/power/x86/turbostat/Makefile4
-rw-r--r--tools/power/x86/turbostat/turbostat.82
-rw-r--r--tools/power/x86/turbostat/turbostat.c2
65 files changed, 4332 insertions, 2821 deletions
diff --git a/Documentation/cpu-freq/core.txt b/Documentation/cpu-freq/core.txt
index ba78e7c2a069..4bc7287806de 100644
--- a/Documentation/cpu-freq/core.txt
+++ b/Documentation/cpu-freq/core.txt
@@ -96,7 +96,7 @@ new - new frequency
96For details about OPP, see Documentation/power/opp.txt 96For details about OPP, see Documentation/power/opp.txt
97 97
98dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with 98dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with
99 cpufreq_frequency_table_cpuinfo which is provided with the list of 99 cpufreq_table_validate_and_show() which is provided with the list of
100 frequencies that are available for operation. This function provides 100 frequencies that are available for operation. This function provides
101 a ready to use conversion routine to translate the OPP layer's internal 101 a ready to use conversion routine to translate the OPP layer's internal
102 information about the available frequencies into a format readily 102 information about the available frequencies into a format readily
@@ -110,7 +110,7 @@ dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with
110 /* Do things */ 110 /* Do things */
111 r = dev_pm_opp_init_cpufreq_table(dev, &freq_table); 111 r = dev_pm_opp_init_cpufreq_table(dev, &freq_table);
112 if (!r) 112 if (!r)
113 cpufreq_frequency_table_cpuinfo(policy, freq_table); 113 cpufreq_table_validate_and_show(policy, freq_table);
114 /* Do other things */ 114 /* Do other things */
115 } 115 }
116 116
diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt
index 14f4e6336d88..772b94fde264 100644
--- a/Documentation/cpu-freq/cpu-drivers.txt
+++ b/Documentation/cpu-freq/cpu-drivers.txt
@@ -231,7 +231,7 @@ if you want to skip one entry in the table, set the frequency to
231CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending 231CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending
232order. 232order.
233 233
234By calling cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, 234By calling cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
235 struct cpufreq_frequency_table *table); 235 struct cpufreq_frequency_table *table);
236the cpuinfo.min_freq and cpuinfo.max_freq values are detected, and 236the cpuinfo.min_freq and cpuinfo.max_freq values are detected, and
237policy->min and policy->max are set to the same values. This is 237policy->min and policy->max are set to the same values. This is
@@ -244,14 +244,12 @@ policy->max, and all other criteria are met. This is helpful for the
244->verify call. 244->verify call.
245 245
246int cpufreq_frequency_table_target(struct cpufreq_policy *policy, 246int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
247 struct cpufreq_frequency_table *table,
248 unsigned int target_freq, 247 unsigned int target_freq,
249 unsigned int relation, 248 unsigned int relation);
250 unsigned int *index);
251 249
252is the corresponding frequency table helper for the ->target 250is the corresponding frequency table helper for the ->target
253stage. Just pass the values to this function, and the unsigned int 251stage. Just pass the values to this function, and this function
254index returns the number of the frequency table entry which contains 252returns the number of the frequency table entry which contains
255the frequency the CPU shall be set to. 253the frequency the CPU shall be set to.
256 254
257The following macros can be used as iterators over cpufreq_frequency_table: 255The following macros can be used as iterators over cpufreq_frequency_table:
diff --git a/Documentation/cpu-freq/pcc-cpufreq.txt b/Documentation/cpu-freq/pcc-cpufreq.txt
index 0a94224ad296..9e3c3b33514c 100644
--- a/Documentation/cpu-freq/pcc-cpufreq.txt
+++ b/Documentation/cpu-freq/pcc-cpufreq.txt
@@ -159,8 +159,8 @@ to be strictly associated with a P-state.
159 159
1602.2 cpuinfo_transition_latency: 1602.2 cpuinfo_transition_latency:
161------------------------------- 161-------------------------------
162The cpuinfo_transition_latency field is CPUFREQ_ETERNAL. The PCC specification 162The cpuinfo_transition_latency field is 0. The PCC specification does
163does not include a field to expose this value currently. 163not include a field to expose this value currently.
164 164
1652.3 cpuinfo_cur_freq: 1652.3 cpuinfo_cur_freq:
166--------------------- 166---------------------
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 724970a25666..118538b548f6 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3598,6 +3598,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
3598 present during boot. 3598 present during boot.
3599 nocompress Don't compress/decompress hibernation images. 3599 nocompress Don't compress/decompress hibernation images.
3600 no Disable hibernation and resume. 3600 no Disable hibernation and resume.
3601 protect_image Turn on image protection during restoration
3602 (that will set all pages holding image data
3603 during restoration read-only).
3601 3604
3602 retain_initrd [RAM] Keep initrd memory after extraction 3605 retain_initrd [RAM] Keep initrd memory after extraction
3603 3606
diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
index 82607d621aca..88301e53f085 100644
--- a/arch/powerpc/platforms/cell/cpufreq_spudemand.c
+++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
@@ -85,61 +85,57 @@ static void spu_gov_cancel_work(struct spu_gov_info_struct *info)
85 cancel_delayed_work_sync(&info->work); 85 cancel_delayed_work_sync(&info->work);
86} 86}
87 87
88static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event) 88static int spu_gov_start(struct cpufreq_policy *policy)
89{ 89{
90 unsigned int cpu = policy->cpu; 90 unsigned int cpu = policy->cpu;
91 struct spu_gov_info_struct *info, *affected_info; 91 struct spu_gov_info_struct *info = &per_cpu(spu_gov_info, cpu);
92 struct spu_gov_info_struct *affected_info;
92 int i; 93 int i;
93 int ret = 0;
94 94
95 info = &per_cpu(spu_gov_info, cpu); 95 if (!cpu_online(cpu)) {
96 96 printk(KERN_ERR "cpu %d is not online\n", cpu);
97 switch (event) { 97 return -EINVAL;
98 case CPUFREQ_GOV_START: 98 }
99 if (!cpu_online(cpu)) {
100 printk(KERN_ERR "cpu %d is not online\n", cpu);
101 ret = -EINVAL;
102 break;
103 }
104 99
105 if (!policy->cur) { 100 if (!policy->cur) {
106 printk(KERN_ERR "no cpu specified in policy\n"); 101 printk(KERN_ERR "no cpu specified in policy\n");
107 ret = -EINVAL; 102 return -EINVAL;
108 break; 103 }
109 }
110 104
111 /* initialize spu_gov_info for all affected cpus */ 105 /* initialize spu_gov_info for all affected cpus */
112 for_each_cpu(i, policy->cpus) { 106 for_each_cpu(i, policy->cpus) {
113 affected_info = &per_cpu(spu_gov_info, i); 107 affected_info = &per_cpu(spu_gov_info, i);
114 affected_info->policy = policy; 108 affected_info->policy = policy;
115 } 109 }
116 110
117 info->poll_int = POLL_TIME; 111 info->poll_int = POLL_TIME;
118 112
119 /* setup timer */ 113 /* setup timer */
120 spu_gov_init_work(info); 114 spu_gov_init_work(info);
121 115
122 break; 116 return 0;
117}
123 118
124 case CPUFREQ_GOV_STOP: 119static void spu_gov_stop(struct cpufreq_policy *policy)
125 /* cancel timer */ 120{
126 spu_gov_cancel_work(info); 121 unsigned int cpu = policy->cpu;
122 struct spu_gov_info_struct *info = &per_cpu(spu_gov_info, cpu);
123 int i;
127 124
128 /* clean spu_gov_info for all affected cpus */ 125 /* cancel timer */
129 for_each_cpu (i, policy->cpus) { 126 spu_gov_cancel_work(info);
130 info = &per_cpu(spu_gov_info, i);
131 info->policy = NULL;
132 }
133 127
134 break; 128 /* clean spu_gov_info for all affected cpus */
129 for_each_cpu (i, policy->cpus) {
130 info = &per_cpu(spu_gov_info, i);
131 info->policy = NULL;
135 } 132 }
136
137 return ret;
138} 133}
139 134
140static struct cpufreq_governor spu_governor = { 135static struct cpufreq_governor spu_governor = {
141 .name = "spudemand", 136 .name = "spudemand",
142 .governor = spu_gov_govern, 137 .start = spu_gov_start,
138 .stop = spu_gov_stop,
143 .owner = THIS_MODULE, 139 .owner = THIS_MODULE,
144}; 140};
145 141
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 5a73a9c62c39..56f4c6676b29 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -64,8 +64,6 @@
64 64
65#define MSR_OFFCORE_RSP_0 0x000001a6 65#define MSR_OFFCORE_RSP_0 0x000001a6
66#define MSR_OFFCORE_RSP_1 0x000001a7 66#define MSR_OFFCORE_RSP_1 0x000001a7
67#define MSR_NHM_TURBO_RATIO_LIMIT 0x000001ad
68#define MSR_IVT_TURBO_RATIO_LIMIT 0x000001ae
69#define MSR_TURBO_RATIO_LIMIT 0x000001ad 67#define MSR_TURBO_RATIO_LIMIT 0x000001ad
70#define MSR_TURBO_RATIO_LIMIT1 0x000001ae 68#define MSR_TURBO_RATIO_LIMIT1 0x000001ae
71#define MSR_TURBO_RATIO_LIMIT2 0x000001af 69#define MSR_TURBO_RATIO_LIMIT2 0x000001af
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index 0576b6157f3a..c9734dc76257 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -135,6 +135,7 @@ int native_cpu_up(unsigned int cpunum, struct task_struct *tidle);
135int native_cpu_disable(void); 135int native_cpu_disable(void);
136int common_cpu_die(unsigned int cpu); 136int common_cpu_die(unsigned int cpu);
137void native_cpu_die(unsigned int cpu); 137void native_cpu_die(unsigned int cpu);
138void hlt_play_dead(void);
138void native_play_dead(void); 139void native_play_dead(void);
139void play_dead_common(void); 140void play_dead_common(void);
140void wbinvd_on_cpu(int cpu); 141void wbinvd_on_cpu(int cpu);
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index d0a51939c150..c93609c97406 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1644,7 +1644,7 @@ static inline void mwait_play_dead(void)
1644 } 1644 }
1645} 1645}
1646 1646
1647static inline void hlt_play_dead(void) 1647void hlt_play_dead(void)
1648{ 1648{
1649 if (__this_cpu_read(cpu_info.x86) >= 4) 1649 if (__this_cpu_read(cpu_info.x86) >= 4)
1650 wbinvd(); 1650 wbinvd();
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index d5f64996394a..b12c26e2e309 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -12,6 +12,7 @@
12#include <linux/export.h> 12#include <linux/export.h>
13#include <linux/smp.h> 13#include <linux/smp.h>
14#include <linux/perf_event.h> 14#include <linux/perf_event.h>
15#include <linux/tboot.h>
15 16
16#include <asm/pgtable.h> 17#include <asm/pgtable.h>
17#include <asm/proto.h> 18#include <asm/proto.h>
@@ -266,6 +267,35 @@ void notrace restore_processor_state(void)
266EXPORT_SYMBOL(restore_processor_state); 267EXPORT_SYMBOL(restore_processor_state);
267#endif 268#endif
268 269
270#if defined(CONFIG_HIBERNATION) && defined(CONFIG_HOTPLUG_CPU)
271static void resume_play_dead(void)
272{
273 play_dead_common();
274 tboot_shutdown(TB_SHUTDOWN_WFS);
275 hlt_play_dead();
276}
277
278int hibernate_resume_nonboot_cpu_disable(void)
279{
280 void (*play_dead)(void) = smp_ops.play_dead;
281 int ret;
282
283 /*
284 * Ensure that MONITOR/MWAIT will not be used in the "play dead" loop
285 * during hibernate image restoration, because it is likely that the
286 * monitored address will be actually written to at that time and then
287 * the "dead" CPU will attempt to execute instructions again, but the
288 * address in its instruction pointer may not be possible to resolve
289 * any more at that point (the page tables used by it previously may
290 * have been overwritten by hibernate image data).
291 */
292 smp_ops.play_dead = resume_play_dead;
293 ret = disable_nonboot_cpus();
294 smp_ops.play_dead = play_dead;
295 return ret;
296}
297#endif
298
269/* 299/*
270 * When bsp_check() is called in hibernate and suspend, cpu hotplug 300 * When bsp_check() is called in hibernate and suspend, cpu hotplug
271 * is disabled already. So it's unnessary to handle race condition between 301 * is disabled already. So it's unnessary to handle race condition between
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index 3657ac1cb801..8e2e4757adcb 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -121,6 +121,7 @@ int pm_clk_add(struct device *dev, const char *con_id)
121{ 121{
122 return __pm_clk_add(dev, con_id, NULL); 122 return __pm_clk_add(dev, con_id, NULL);
123} 123}
124EXPORT_SYMBOL_GPL(pm_clk_add);
124 125
125/** 126/**
126 * pm_clk_add_clk - Start using a device clock for power management. 127 * pm_clk_add_clk - Start using a device clock for power management.
@@ -136,9 +137,42 @@ int pm_clk_add_clk(struct device *dev, struct clk *clk)
136{ 137{
137 return __pm_clk_add(dev, NULL, clk); 138 return __pm_clk_add(dev, NULL, clk);
138} 139}
140EXPORT_SYMBOL_GPL(pm_clk_add_clk);
139 141
140 142
141/** 143/**
144 * of_pm_clk_add_clk - Start using a device clock for power management.
145 * @dev: Device whose clock is going to be used for power management.
146 * @name: Name of clock that is going to be used for power management.
147 *
148 * Add the clock described in the 'clocks' device-tree node that matches
149 * with the 'name' provided, to the list of clocks used for the power
150 * management of @dev. On success, returns 0. Returns a negative error
151 * code if the clock is not found or cannot be added.
152 */
153int of_pm_clk_add_clk(struct device *dev, const char *name)
154{
155 struct clk *clk;
156 int ret;
157
158 if (!dev || !dev->of_node || !name)
159 return -EINVAL;
160
161 clk = of_clk_get_by_name(dev->of_node, name);
162 if (IS_ERR(clk))
163 return PTR_ERR(clk);
164
165 ret = pm_clk_add_clk(dev, clk);
166 if (ret) {
167 clk_put(clk);
168 return ret;
169 }
170
171 return 0;
172}
173EXPORT_SYMBOL_GPL(of_pm_clk_add_clk);
174
175/**
142 * of_pm_clk_add_clks - Start using device clock(s) for power management. 176 * of_pm_clk_add_clks - Start using device clock(s) for power management.
143 * @dev: Device whose clock(s) is going to be used for power management. 177 * @dev: Device whose clock(s) is going to be used for power management.
144 * 178 *
@@ -192,6 +226,7 @@ error:
192 226
193 return ret; 227 return ret;
194} 228}
229EXPORT_SYMBOL_GPL(of_pm_clk_add_clks);
195 230
196/** 231/**
197 * __pm_clk_remove - Destroy PM clock entry. 232 * __pm_clk_remove - Destroy PM clock entry.
@@ -252,6 +287,7 @@ void pm_clk_remove(struct device *dev, const char *con_id)
252 287
253 __pm_clk_remove(ce); 288 __pm_clk_remove(ce);
254} 289}
290EXPORT_SYMBOL_GPL(pm_clk_remove);
255 291
256/** 292/**
257 * pm_clk_remove_clk - Stop using a device clock for power management. 293 * pm_clk_remove_clk - Stop using a device clock for power management.
@@ -285,6 +321,7 @@ void pm_clk_remove_clk(struct device *dev, struct clk *clk)
285 321
286 __pm_clk_remove(ce); 322 __pm_clk_remove(ce);
287} 323}
324EXPORT_SYMBOL_GPL(pm_clk_remove_clk);
288 325
289/** 326/**
290 * pm_clk_init - Initialize a device's list of power management clocks. 327 * pm_clk_init - Initialize a device's list of power management clocks.
@@ -299,6 +336,7 @@ void pm_clk_init(struct device *dev)
299 if (psd) 336 if (psd)
300 INIT_LIST_HEAD(&psd->clock_list); 337 INIT_LIST_HEAD(&psd->clock_list);
301} 338}
339EXPORT_SYMBOL_GPL(pm_clk_init);
302 340
303/** 341/**
304 * pm_clk_create - Create and initialize a device's list of PM clocks. 342 * pm_clk_create - Create and initialize a device's list of PM clocks.
@@ -311,6 +349,7 @@ int pm_clk_create(struct device *dev)
311{ 349{
312 return dev_pm_get_subsys_data(dev); 350 return dev_pm_get_subsys_data(dev);
313} 351}
352EXPORT_SYMBOL_GPL(pm_clk_create);
314 353
315/** 354/**
316 * pm_clk_destroy - Destroy a device's list of power management clocks. 355 * pm_clk_destroy - Destroy a device's list of power management clocks.
@@ -345,6 +384,7 @@ void pm_clk_destroy(struct device *dev)
345 __pm_clk_remove(ce); 384 __pm_clk_remove(ce);
346 } 385 }
347} 386}
387EXPORT_SYMBOL_GPL(pm_clk_destroy);
348 388
349/** 389/**
350 * pm_clk_suspend - Disable clocks in a device's PM clock list. 390 * pm_clk_suspend - Disable clocks in a device's PM clock list.
@@ -375,6 +415,7 @@ int pm_clk_suspend(struct device *dev)
375 415
376 return 0; 416 return 0;
377} 417}
418EXPORT_SYMBOL_GPL(pm_clk_suspend);
378 419
379/** 420/**
380 * pm_clk_resume - Enable clocks in a device's PM clock list. 421 * pm_clk_resume - Enable clocks in a device's PM clock list.
@@ -400,6 +441,7 @@ int pm_clk_resume(struct device *dev)
400 441
401 return 0; 442 return 0;
402} 443}
444EXPORT_SYMBOL_GPL(pm_clk_resume);
403 445
404/** 446/**
405 * pm_clk_notify - Notify routine for device addition and removal. 447 * pm_clk_notify - Notify routine for device addition and removal.
@@ -480,6 +522,7 @@ int pm_clk_runtime_suspend(struct device *dev)
480 522
481 return 0; 523 return 0;
482} 524}
525EXPORT_SYMBOL_GPL(pm_clk_runtime_suspend);
483 526
484int pm_clk_runtime_resume(struct device *dev) 527int pm_clk_runtime_resume(struct device *dev)
485{ 528{
@@ -495,6 +538,7 @@ int pm_clk_runtime_resume(struct device *dev)
495 538
496 return pm_generic_runtime_resume(dev); 539 return pm_generic_runtime_resume(dev);
497} 540}
541EXPORT_SYMBOL_GPL(pm_clk_runtime_resume);
498 542
499#else /* !CONFIG_PM_CLK */ 543#else /* !CONFIG_PM_CLK */
500 544
@@ -598,3 +642,4 @@ void pm_clk_add_notifier(struct bus_type *bus,
598 clknb->nb.notifier_call = pm_clk_notify; 642 clknb->nb.notifier_call = pm_clk_notify;
599 bus_register_notifier(bus, &clknb->nb); 643 bus_register_notifier(bus, &clknb->nb);
600} 644}
645EXPORT_SYMBOL_GPL(pm_clk_add_notifier);
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index de23b648fce3..a1f2aff33997 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -187,8 +187,7 @@ static int genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth)
187 struct gpd_link *link; 187 struct gpd_link *link;
188 int ret = 0; 188 int ret = 0;
189 189
190 if (genpd->status == GPD_STATE_ACTIVE 190 if (genpd->status == GPD_STATE_ACTIVE)
191 || (genpd->prepared_count > 0 && genpd->suspend_power_off))
192 return 0; 191 return 0;
193 192
194 /* 193 /*
@@ -735,82 +734,24 @@ static int pm_genpd_prepare(struct device *dev)
735 734
736 mutex_lock(&genpd->lock); 735 mutex_lock(&genpd->lock);
737 736
738 if (genpd->prepared_count++ == 0) { 737 if (genpd->prepared_count++ == 0)
739 genpd->suspended_count = 0; 738 genpd->suspended_count = 0;
740 genpd->suspend_power_off = genpd->status == GPD_STATE_POWER_OFF;
741 }
742 739
743 mutex_unlock(&genpd->lock); 740 mutex_unlock(&genpd->lock);
744 741
745 if (genpd->suspend_power_off)
746 return 0;
747
748 /*
749 * The PM domain must be in the GPD_STATE_ACTIVE state at this point,
750 * so genpd_poweron() will return immediately, but if the device
751 * is suspended (e.g. it's been stopped by genpd_stop_dev()), we need
752 * to make it operational.
753 */
754 pm_runtime_resume(dev);
755 __pm_runtime_disable(dev, false);
756
757 ret = pm_generic_prepare(dev); 742 ret = pm_generic_prepare(dev);
758 if (ret) { 743 if (ret) {
759 mutex_lock(&genpd->lock); 744 mutex_lock(&genpd->lock);
760 745
761 if (--genpd->prepared_count == 0) 746 genpd->prepared_count--;
762 genpd->suspend_power_off = false;
763 747
764 mutex_unlock(&genpd->lock); 748 mutex_unlock(&genpd->lock);
765 pm_runtime_enable(dev);
766 } 749 }
767 750
768 return ret; 751 return ret;
769} 752}
770 753
771/** 754/**
772 * pm_genpd_suspend - Suspend a device belonging to an I/O PM domain.
773 * @dev: Device to suspend.
774 *
775 * Suspend a device under the assumption that its pm_domain field points to the
776 * domain member of an object of type struct generic_pm_domain representing
777 * a PM domain consisting of I/O devices.
778 */
779static int pm_genpd_suspend(struct device *dev)
780{
781 struct generic_pm_domain *genpd;
782
783 dev_dbg(dev, "%s()\n", __func__);
784
785 genpd = dev_to_genpd(dev);
786 if (IS_ERR(genpd))
787 return -EINVAL;
788
789 return genpd->suspend_power_off ? 0 : pm_generic_suspend(dev);
790}
791
792/**
793 * pm_genpd_suspend_late - Late suspend of a device from an I/O PM domain.
794 * @dev: Device to suspend.
795 *
796 * Carry out a late suspend of a device under the assumption that its
797 * pm_domain field points to the domain member of an object of type
798 * struct generic_pm_domain representing a PM domain consisting of I/O devices.
799 */
800static int pm_genpd_suspend_late(struct device *dev)
801{
802 struct generic_pm_domain *genpd;
803
804 dev_dbg(dev, "%s()\n", __func__);
805
806 genpd = dev_to_genpd(dev);
807 if (IS_ERR(genpd))
808 return -EINVAL;
809
810 return genpd->suspend_power_off ? 0 : pm_generic_suspend_late(dev);
811}
812
813/**
814 * pm_genpd_suspend_noirq - Completion of suspend of device in an I/O PM domain. 755 * pm_genpd_suspend_noirq - Completion of suspend of device in an I/O PM domain.
815 * @dev: Device to suspend. 756 * @dev: Device to suspend.
816 * 757 *
@@ -820,6 +761,7 @@ static int pm_genpd_suspend_late(struct device *dev)
820static int pm_genpd_suspend_noirq(struct device *dev) 761static int pm_genpd_suspend_noirq(struct device *dev)
821{ 762{
822 struct generic_pm_domain *genpd; 763 struct generic_pm_domain *genpd;
764 int ret;
823 765
824 dev_dbg(dev, "%s()\n", __func__); 766 dev_dbg(dev, "%s()\n", __func__);
825 767
@@ -827,11 +769,14 @@ static int pm_genpd_suspend_noirq(struct device *dev)
827 if (IS_ERR(genpd)) 769 if (IS_ERR(genpd))
828 return -EINVAL; 770 return -EINVAL;
829 771
830 if (genpd->suspend_power_off 772 if (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))
831 || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
832 return 0; 773 return 0;
833 774
834 genpd_stop_dev(genpd, dev); 775 if (genpd->dev_ops.stop && genpd->dev_ops.start) {
776 ret = pm_runtime_force_suspend(dev);
777 if (ret)
778 return ret;
779 }
835 780
836 /* 781 /*
837 * Since all of the "noirq" callbacks are executed sequentially, it is 782 * Since all of the "noirq" callbacks are executed sequentially, it is
@@ -853,6 +798,7 @@ static int pm_genpd_suspend_noirq(struct device *dev)
853static int pm_genpd_resume_noirq(struct device *dev) 798static int pm_genpd_resume_noirq(struct device *dev)
854{ 799{
855 struct generic_pm_domain *genpd; 800 struct generic_pm_domain *genpd;
801 int ret = 0;
856 802
857 dev_dbg(dev, "%s()\n", __func__); 803 dev_dbg(dev, "%s()\n", __func__);
858 804
@@ -860,8 +806,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
860 if (IS_ERR(genpd)) 806 if (IS_ERR(genpd))
861 return -EINVAL; 807 return -EINVAL;
862 808
863 if (genpd->suspend_power_off 809 if (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))
864 || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
865 return 0; 810 return 0;
866 811
867 /* 812 /*
@@ -872,93 +817,10 @@ static int pm_genpd_resume_noirq(struct device *dev)
872 pm_genpd_sync_poweron(genpd, true); 817 pm_genpd_sync_poweron(genpd, true);
873 genpd->suspended_count--; 818 genpd->suspended_count--;
874 819
875 return genpd_start_dev(genpd, dev); 820 if (genpd->dev_ops.stop && genpd->dev_ops.start)
876} 821 ret = pm_runtime_force_resume(dev);
877
878/**
879 * pm_genpd_resume_early - Early resume of a device in an I/O PM domain.
880 * @dev: Device to resume.
881 *
882 * Carry out an early resume of a device under the assumption that its
883 * pm_domain field points to the domain member of an object of type
884 * struct generic_pm_domain representing a power domain consisting of I/O
885 * devices.
886 */
887static int pm_genpd_resume_early(struct device *dev)
888{
889 struct generic_pm_domain *genpd;
890
891 dev_dbg(dev, "%s()\n", __func__);
892
893 genpd = dev_to_genpd(dev);
894 if (IS_ERR(genpd))
895 return -EINVAL;
896
897 return genpd->suspend_power_off ? 0 : pm_generic_resume_early(dev);
898}
899
900/**
901 * pm_genpd_resume - Resume of device in an I/O PM domain.
902 * @dev: Device to resume.
903 *
904 * Resume a device under the assumption that its pm_domain field points to the
905 * domain member of an object of type struct generic_pm_domain representing
906 * a power domain consisting of I/O devices.
907 */
908static int pm_genpd_resume(struct device *dev)
909{
910 struct generic_pm_domain *genpd;
911
912 dev_dbg(dev, "%s()\n", __func__);
913
914 genpd = dev_to_genpd(dev);
915 if (IS_ERR(genpd))
916 return -EINVAL;
917
918 return genpd->suspend_power_off ? 0 : pm_generic_resume(dev);
919}
920
921/**
922 * pm_genpd_freeze - Freezing a device in an I/O PM domain.
923 * @dev: Device to freeze.
924 *
925 * Freeze a device under the assumption that its pm_domain field points to the
926 * domain member of an object of type struct generic_pm_domain representing
927 * a power domain consisting of I/O devices.
928 */
929static int pm_genpd_freeze(struct device *dev)
930{
931 struct generic_pm_domain *genpd;
932
933 dev_dbg(dev, "%s()\n", __func__);
934
935 genpd = dev_to_genpd(dev);
936 if (IS_ERR(genpd))
937 return -EINVAL;
938
939 return genpd->suspend_power_off ? 0 : pm_generic_freeze(dev);
940}
941 822
942/** 823 return ret;
943 * pm_genpd_freeze_late - Late freeze of a device in an I/O PM domain.
944 * @dev: Device to freeze.
945 *
946 * Carry out a late freeze of a device under the assumption that its
947 * pm_domain field points to the domain member of an object of type
948 * struct generic_pm_domain representing a power domain consisting of I/O
949 * devices.
950 */
951static int pm_genpd_freeze_late(struct device *dev)
952{
953 struct generic_pm_domain *genpd;
954
955 dev_dbg(dev, "%s()\n", __func__);
956
957 genpd = dev_to_genpd(dev);
958 if (IS_ERR(genpd))
959 return -EINVAL;
960
961 return genpd->suspend_power_off ? 0 : pm_generic_freeze_late(dev);
962} 824}
963 825
964/** 826/**
@@ -973,6 +835,7 @@ static int pm_genpd_freeze_late(struct device *dev)
973static int pm_genpd_freeze_noirq(struct device *dev) 835static int pm_genpd_freeze_noirq(struct device *dev)
974{ 836{
975 struct generic_pm_domain *genpd; 837 struct generic_pm_domain *genpd;
838 int ret = 0;
976 839
977 dev_dbg(dev, "%s()\n", __func__); 840 dev_dbg(dev, "%s()\n", __func__);
978 841
@@ -980,7 +843,10 @@ static int pm_genpd_freeze_noirq(struct device *dev)
980 if (IS_ERR(genpd)) 843 if (IS_ERR(genpd))
981 return -EINVAL; 844 return -EINVAL;
982 845
983 return genpd->suspend_power_off ? 0 : genpd_stop_dev(genpd, dev); 846 if (genpd->dev_ops.stop && genpd->dev_ops.start)
847 ret = pm_runtime_force_suspend(dev);
848
849 return ret;
984} 850}
985 851
986/** 852/**
@@ -993,6 +859,7 @@ static int pm_genpd_freeze_noirq(struct device *dev)
993static int pm_genpd_thaw_noirq(struct device *dev) 859static int pm_genpd_thaw_noirq(struct device *dev)
994{ 860{
995 struct generic_pm_domain *genpd; 861 struct generic_pm_domain *genpd;
862 int ret = 0;
996 863
997 dev_dbg(dev, "%s()\n", __func__); 864 dev_dbg(dev, "%s()\n", __func__);
998 865
@@ -1000,51 +867,10 @@ static int pm_genpd_thaw_noirq(struct device *dev)
1000 if (IS_ERR(genpd)) 867 if (IS_ERR(genpd))
1001 return -EINVAL; 868 return -EINVAL;
1002 869
1003 return genpd->suspend_power_off ? 870 if (genpd->dev_ops.stop && genpd->dev_ops.start)
1004 0 : genpd_start_dev(genpd, dev); 871 ret = pm_runtime_force_resume(dev);
1005}
1006
1007/**
1008 * pm_genpd_thaw_early - Early thaw of device in an I/O PM domain.
1009 * @dev: Device to thaw.
1010 *
1011 * Carry out an early thaw of a device under the assumption that its
1012 * pm_domain field points to the domain member of an object of type
1013 * struct generic_pm_domain representing a power domain consisting of I/O
1014 * devices.
1015 */
1016static int pm_genpd_thaw_early(struct device *dev)
1017{
1018 struct generic_pm_domain *genpd;
1019
1020 dev_dbg(dev, "%s()\n", __func__);
1021
1022 genpd = dev_to_genpd(dev);
1023 if (IS_ERR(genpd))
1024 return -EINVAL;
1025
1026 return genpd->suspend_power_off ? 0 : pm_generic_thaw_early(dev);
1027}
1028
1029/**
1030 * pm_genpd_thaw - Thaw a device belonging to an I/O power domain.
1031 * @dev: Device to thaw.
1032 *
1033 * Thaw a device under the assumption that its pm_domain field points to the
1034 * domain member of an object of type struct generic_pm_domain representing
1035 * a power domain consisting of I/O devices.
1036 */
1037static int pm_genpd_thaw(struct device *dev)
1038{
1039 struct generic_pm_domain *genpd;
1040
1041 dev_dbg(dev, "%s()\n", __func__);
1042 872
1043 genpd = dev_to_genpd(dev); 873 return ret;
1044 if (IS_ERR(genpd))
1045 return -EINVAL;
1046
1047 return genpd->suspend_power_off ? 0 : pm_generic_thaw(dev);
1048} 874}
1049 875
1050/** 876/**
@@ -1057,6 +883,7 @@ static int pm_genpd_thaw(struct device *dev)
1057static int pm_genpd_restore_noirq(struct device *dev) 883static int pm_genpd_restore_noirq(struct device *dev)
1058{ 884{
1059 struct generic_pm_domain *genpd; 885 struct generic_pm_domain *genpd;
886 int ret = 0;
1060 887
1061 dev_dbg(dev, "%s()\n", __func__); 888 dev_dbg(dev, "%s()\n", __func__);
1062 889
@@ -1072,30 +899,20 @@ static int pm_genpd_restore_noirq(struct device *dev)
1072 * At this point suspended_count == 0 means we are being run for the 899 * At this point suspended_count == 0 means we are being run for the
1073 * first time for the given domain in the present cycle. 900 * first time for the given domain in the present cycle.
1074 */ 901 */
1075 if (genpd->suspended_count++ == 0) { 902 if (genpd->suspended_count++ == 0)
1076 /* 903 /*
1077 * The boot kernel might put the domain into arbitrary state, 904 * The boot kernel might put the domain into arbitrary state,
1078 * so make it appear as powered off to pm_genpd_sync_poweron(), 905 * so make it appear as powered off to pm_genpd_sync_poweron(),
1079 * so that it tries to power it on in case it was really off. 906 * so that it tries to power it on in case it was really off.
1080 */ 907 */
1081 genpd->status = GPD_STATE_POWER_OFF; 908 genpd->status = GPD_STATE_POWER_OFF;
1082 if (genpd->suspend_power_off) {
1083 /*
1084 * If the domain was off before the hibernation, make
1085 * sure it will be off going forward.
1086 */
1087 genpd_power_off(genpd, true);
1088
1089 return 0;
1090 }
1091 }
1092
1093 if (genpd->suspend_power_off)
1094 return 0;
1095 909
1096 pm_genpd_sync_poweron(genpd, true); 910 pm_genpd_sync_poweron(genpd, true);
1097 911
1098 return genpd_start_dev(genpd, dev); 912 if (genpd->dev_ops.stop && genpd->dev_ops.start)
913 ret = pm_runtime_force_resume(dev);
914
915 return ret;
1099} 916}
1100 917
1101/** 918/**
@@ -1110,7 +927,6 @@ static int pm_genpd_restore_noirq(struct device *dev)
1110static void pm_genpd_complete(struct device *dev) 927static void pm_genpd_complete(struct device *dev)
1111{ 928{
1112 struct generic_pm_domain *genpd; 929 struct generic_pm_domain *genpd;
1113 bool run_complete;
1114 930
1115 dev_dbg(dev, "%s()\n", __func__); 931 dev_dbg(dev, "%s()\n", __func__);
1116 932
@@ -1118,20 +934,15 @@ static void pm_genpd_complete(struct device *dev)
1118 if (IS_ERR(genpd)) 934 if (IS_ERR(genpd))
1119 return; 935 return;
1120 936
937 pm_generic_complete(dev);
938
1121 mutex_lock(&genpd->lock); 939 mutex_lock(&genpd->lock);
1122 940
1123 run_complete = !genpd->suspend_power_off; 941 genpd->prepared_count--;
1124 if (--genpd->prepared_count == 0) 942 if (!genpd->prepared_count)
1125 genpd->suspend_power_off = false; 943 genpd_queue_power_off_work(genpd);
1126 944
1127 mutex_unlock(&genpd->lock); 945 mutex_unlock(&genpd->lock);
1128
1129 if (run_complete) {
1130 pm_generic_complete(dev);
1131 pm_runtime_set_active(dev);
1132 pm_runtime_enable(dev);
1133 pm_request_idle(dev);
1134 }
1135} 946}
1136 947
1137/** 948/**
@@ -1173,18 +984,10 @@ EXPORT_SYMBOL_GPL(pm_genpd_syscore_poweron);
1173#else /* !CONFIG_PM_SLEEP */ 984#else /* !CONFIG_PM_SLEEP */
1174 985
1175#define pm_genpd_prepare NULL 986#define pm_genpd_prepare NULL
1176#define pm_genpd_suspend NULL
1177#define pm_genpd_suspend_late NULL
1178#define pm_genpd_suspend_noirq NULL 987#define pm_genpd_suspend_noirq NULL
1179#define pm_genpd_resume_early NULL
1180#define pm_genpd_resume_noirq NULL 988#define pm_genpd_resume_noirq NULL
1181#define pm_genpd_resume NULL
1182#define pm_genpd_freeze NULL
1183#define pm_genpd_freeze_late NULL
1184#define pm_genpd_freeze_noirq NULL 989#define pm_genpd_freeze_noirq NULL
1185#define pm_genpd_thaw_early NULL
1186#define pm_genpd_thaw_noirq NULL 990#define pm_genpd_thaw_noirq NULL
1187#define pm_genpd_thaw NULL
1188#define pm_genpd_restore_noirq NULL 991#define pm_genpd_restore_noirq NULL
1189#define pm_genpd_complete NULL 992#define pm_genpd_complete NULL
1190 993
@@ -1455,12 +1258,14 @@ EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain);
1455 * @genpd: PM domain object to initialize. 1258 * @genpd: PM domain object to initialize.
1456 * @gov: PM domain governor to associate with the domain (may be NULL). 1259 * @gov: PM domain governor to associate with the domain (may be NULL).
1457 * @is_off: Initial value of the domain's power_is_off field. 1260 * @is_off: Initial value of the domain's power_is_off field.
1261 *
1262 * Returns 0 on successful initialization, else a negative error code.
1458 */ 1263 */
1459void pm_genpd_init(struct generic_pm_domain *genpd, 1264int pm_genpd_init(struct generic_pm_domain *genpd,
1460 struct dev_power_governor *gov, bool is_off) 1265 struct dev_power_governor *gov, bool is_off)
1461{ 1266{
1462 if (IS_ERR_OR_NULL(genpd)) 1267 if (IS_ERR_OR_NULL(genpd))
1463 return; 1268 return -EINVAL;
1464 1269
1465 INIT_LIST_HEAD(&genpd->master_links); 1270 INIT_LIST_HEAD(&genpd->master_links);
1466 INIT_LIST_HEAD(&genpd->slave_links); 1271 INIT_LIST_HEAD(&genpd->slave_links);
@@ -1476,24 +1281,24 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
1476 genpd->domain.ops.runtime_suspend = genpd_runtime_suspend; 1281 genpd->domain.ops.runtime_suspend = genpd_runtime_suspend;
1477 genpd->domain.ops.runtime_resume = genpd_runtime_resume; 1282 genpd->domain.ops.runtime_resume = genpd_runtime_resume;
1478 genpd->domain.ops.prepare = pm_genpd_prepare; 1283 genpd->domain.ops.prepare = pm_genpd_prepare;
1479 genpd->domain.ops.suspend = pm_genpd_suspend; 1284 genpd->domain.ops.suspend = pm_generic_suspend;
1480 genpd->domain.ops.suspend_late = pm_genpd_suspend_late; 1285 genpd->domain.ops.suspend_late = pm_generic_suspend_late;
1481 genpd->domain.ops.suspend_noirq = pm_genpd_suspend_noirq; 1286 genpd->domain.ops.suspend_noirq = pm_genpd_suspend_noirq;
1482 genpd->domain.ops.resume_noirq = pm_genpd_resume_noirq; 1287 genpd->domain.ops.resume_noirq = pm_genpd_resume_noirq;
1483 genpd->domain.ops.resume_early = pm_genpd_resume_early; 1288 genpd->domain.ops.resume_early = pm_generic_resume_early;
1484 genpd->domain.ops.resume = pm_genpd_resume; 1289 genpd->domain.ops.resume = pm_generic_resume;
1485 genpd->domain.ops.freeze = pm_genpd_freeze; 1290 genpd->domain.ops.freeze = pm_generic_freeze;
1486 genpd->domain.ops.freeze_late = pm_genpd_freeze_late; 1291 genpd->domain.ops.freeze_late = pm_generic_freeze_late;
1487 genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq; 1292 genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq;
1488 genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq; 1293 genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq;
1489 genpd->domain.ops.thaw_early = pm_genpd_thaw_early; 1294 genpd->domain.ops.thaw_early = pm_generic_thaw_early;
1490 genpd->domain.ops.thaw = pm_genpd_thaw; 1295 genpd->domain.ops.thaw = pm_generic_thaw;
1491 genpd->domain.ops.poweroff = pm_genpd_suspend; 1296 genpd->domain.ops.poweroff = pm_generic_poweroff;
1492 genpd->domain.ops.poweroff_late = pm_genpd_suspend_late; 1297 genpd->domain.ops.poweroff_late = pm_generic_poweroff_late;
1493 genpd->domain.ops.poweroff_noirq = pm_genpd_suspend_noirq; 1298 genpd->domain.ops.poweroff_noirq = pm_genpd_suspend_noirq;
1494 genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq; 1299 genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq;
1495 genpd->domain.ops.restore_early = pm_genpd_resume_early; 1300 genpd->domain.ops.restore_early = pm_generic_restore_early;
1496 genpd->domain.ops.restore = pm_genpd_resume; 1301 genpd->domain.ops.restore = pm_generic_restore;
1497 genpd->domain.ops.complete = pm_genpd_complete; 1302 genpd->domain.ops.complete = pm_genpd_complete;
1498 1303
1499 if (genpd->flags & GENPD_FLAG_PM_CLK) { 1304 if (genpd->flags & GENPD_FLAG_PM_CLK) {
@@ -1518,6 +1323,8 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
1518 mutex_lock(&gpd_list_lock); 1323 mutex_lock(&gpd_list_lock);
1519 list_add(&genpd->gpd_list_node, &gpd_list); 1324 list_add(&genpd->gpd_list_node, &gpd_list);
1520 mutex_unlock(&gpd_list_lock); 1325 mutex_unlock(&gpd_list_lock);
1326
1327 return 0;
1521} 1328}
1522EXPORT_SYMBOL_GPL(pm_genpd_init); 1329EXPORT_SYMBOL_GPL(pm_genpd_init);
1523 1330
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index b74690418504..e097d355cc04 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1045,10 +1045,14 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
1045 */ 1045 */
1046 if (!parent->power.disable_depth 1046 if (!parent->power.disable_depth
1047 && !parent->power.ignore_children 1047 && !parent->power.ignore_children
1048 && parent->power.runtime_status != RPM_ACTIVE) 1048 && parent->power.runtime_status != RPM_ACTIVE) {
1049 dev_err(dev, "runtime PM trying to activate child device %s but parent (%s) is not active\n",
1050 dev_name(dev),
1051 dev_name(parent));
1049 error = -EBUSY; 1052 error = -EBUSY;
1050 else if (dev->power.runtime_status == RPM_SUSPENDED) 1053 } else if (dev->power.runtime_status == RPM_SUSPENDED) {
1051 atomic_inc(&parent->power.child_count); 1054 atomic_inc(&parent->power.child_count);
1055 }
1052 1056
1053 spin_unlock(&parent->power.lock); 1057 spin_unlock(&parent->power.lock);
1054 1058
@@ -1256,7 +1260,7 @@ void pm_runtime_allow(struct device *dev)
1256 1260
1257 dev->power.runtime_auto = true; 1261 dev->power.runtime_auto = true;
1258 if (atomic_dec_and_test(&dev->power.usage_count)) 1262 if (atomic_dec_and_test(&dev->power.usage_count))
1259 rpm_idle(dev, RPM_AUTO); 1263 rpm_idle(dev, RPM_AUTO | RPM_ASYNC);
1260 1264
1261 out: 1265 out:
1262 spin_unlock_irq(&dev->power.lock); 1266 spin_unlock_irq(&dev->power.lock);
@@ -1506,6 +1510,9 @@ int pm_runtime_force_resume(struct device *dev)
1506 goto out; 1510 goto out;
1507 } 1511 }
1508 1512
1513 if (!pm_runtime_status_suspended(dev))
1514 goto out;
1515
1509 ret = pm_runtime_set_active(dev); 1516 ret = pm_runtime_set_active(dev);
1510 if (ret) 1517 if (ret)
1511 goto out; 1518 goto out;
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index b7445b6ae5a4..c822d72629d5 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -31,23 +31,18 @@ config CPU_FREQ_BOOST_SW
31 depends on THERMAL 31 depends on THERMAL
32 32
33config CPU_FREQ_STAT 33config CPU_FREQ_STAT
34 tristate "CPU frequency translation statistics" 34 bool "CPU frequency transition statistics"
35 default y 35 default y
36 help 36 help
37 This driver exports CPU frequency statistics information through sysfs 37 Export CPU frequency statistics information through sysfs.
38 file system.
39
40 To compile this driver as a module, choose M here: the
41 module will be called cpufreq_stats.
42 38
43 If in doubt, say N. 39 If in doubt, say N.
44 40
45config CPU_FREQ_STAT_DETAILS 41config CPU_FREQ_STAT_DETAILS
46 bool "CPU frequency translation statistics details" 42 bool "CPU frequency transition statistics details"
47 depends on CPU_FREQ_STAT 43 depends on CPU_FREQ_STAT
48 help 44 help
49 This will show detail CPU frequency translation table in sysfs file 45 Show detailed CPU frequency transition table in sysfs.
50 system.
51 46
52 If in doubt, say N. 47 If in doubt, say N.
53 48
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 32a15052f363..297e9128fe9f 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -468,20 +468,17 @@ unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy,
468 struct acpi_cpufreq_data *data = policy->driver_data; 468 struct acpi_cpufreq_data *data = policy->driver_data;
469 struct acpi_processor_performance *perf; 469 struct acpi_processor_performance *perf;
470 struct cpufreq_frequency_table *entry; 470 struct cpufreq_frequency_table *entry;
471 unsigned int next_perf_state, next_freq, freq; 471 unsigned int next_perf_state, next_freq, index;
472 472
473 /* 473 /*
474 * Find the closest frequency above target_freq. 474 * Find the closest frequency above target_freq.
475 *
476 * The table is sorted in the reverse order with respect to the
477 * frequency and all of the entries are valid (see the initialization).
478 */ 475 */
479 entry = policy->freq_table; 476 if (policy->cached_target_freq == target_freq)
480 do { 477 index = policy->cached_resolved_idx;
481 entry++; 478 else
482 freq = entry->frequency; 479 index = cpufreq_table_find_index_dl(policy, target_freq);
483 } while (freq >= target_freq && freq != CPUFREQ_TABLE_END); 480
484 entry--; 481 entry = &policy->freq_table[index];
485 next_freq = entry->frequency; 482 next_freq = entry->frequency;
486 next_perf_state = entry->driver_data; 483 next_perf_state = entry->driver_data;
487 484
diff --git a/drivers/cpufreq/amd_freq_sensitivity.c b/drivers/cpufreq/amd_freq_sensitivity.c
index 404360cad25c..042023bbbf62 100644
--- a/drivers/cpufreq/amd_freq_sensitivity.c
+++ b/drivers/cpufreq/amd_freq_sensitivity.c
@@ -48,9 +48,8 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy,
48 struct policy_dbs_info *policy_dbs = policy->governor_data; 48 struct policy_dbs_info *policy_dbs = policy->governor_data;
49 struct dbs_data *od_data = policy_dbs->dbs_data; 49 struct dbs_data *od_data = policy_dbs->dbs_data;
50 struct od_dbs_tuners *od_tuners = od_data->tuners; 50 struct od_dbs_tuners *od_tuners = od_data->tuners;
51 struct od_policy_dbs_info *od_info = to_dbs_info(policy_dbs);
52 51
53 if (!od_info->freq_table) 52 if (!policy->freq_table)
54 return freq_next; 53 return freq_next;
55 54
56 rdmsr_on_cpu(policy->cpu, MSR_AMD64_FREQ_SENSITIVITY_ACTUAL, 55 rdmsr_on_cpu(policy->cpu, MSR_AMD64_FREQ_SENSITIVITY_ACTUAL,
@@ -92,10 +91,9 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy,
92 else { 91 else {
93 unsigned int index; 92 unsigned int index;
94 93
95 cpufreq_frequency_table_target(policy, 94 index = cpufreq_table_find_index_h(policy,
96 od_info->freq_table, policy->cur - 1, 95 policy->cur - 1);
97 CPUFREQ_RELATION_H, &index); 96 freq_next = policy->freq_table[index].frequency;
98 freq_next = od_info->freq_table[index].frequency;
99 } 97 }
100 98
101 data->freq_prev = freq_next; 99 data->freq_prev = freq_next;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 5617c7087d77..3dd4884c6f9e 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -74,19 +74,12 @@ static inline bool has_target(void)
74} 74}
75 75
76/* internal prototypes */ 76/* internal prototypes */
77static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
78static unsigned int __cpufreq_get(struct cpufreq_policy *policy); 77static unsigned int __cpufreq_get(struct cpufreq_policy *policy);
78static int cpufreq_init_governor(struct cpufreq_policy *policy);
79static void cpufreq_exit_governor(struct cpufreq_policy *policy);
79static int cpufreq_start_governor(struct cpufreq_policy *policy); 80static int cpufreq_start_governor(struct cpufreq_policy *policy);
80 81static void cpufreq_stop_governor(struct cpufreq_policy *policy);
81static inline void cpufreq_exit_governor(struct cpufreq_policy *policy) 82static void cpufreq_governor_limits(struct cpufreq_policy *policy);
82{
83 (void)cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
84}
85
86static inline void cpufreq_stop_governor(struct cpufreq_policy *policy)
87{
88 (void)cpufreq_governor(policy, CPUFREQ_GOV_STOP);
89}
90 83
91/** 84/**
92 * Two notifier lists: the "policy" list is involved in the 85 * Two notifier lists: the "policy" list is involved in the
@@ -133,15 +126,6 @@ struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
133} 126}
134EXPORT_SYMBOL_GPL(get_governor_parent_kobj); 127EXPORT_SYMBOL_GPL(get_governor_parent_kobj);
135 128
136struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
137{
138 struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
139
140 return policy && !policy_is_inactive(policy) ?
141 policy->freq_table : NULL;
142}
143EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
144
145static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) 129static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
146{ 130{
147 u64 idle_time; 131 u64 idle_time;
@@ -354,6 +338,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
354 pr_debug("FREQ: %lu - CPU: %lu\n", 338 pr_debug("FREQ: %lu - CPU: %lu\n",
355 (unsigned long)freqs->new, (unsigned long)freqs->cpu); 339 (unsigned long)freqs->new, (unsigned long)freqs->cpu);
356 trace_cpu_frequency(freqs->new, freqs->cpu); 340 trace_cpu_frequency(freqs->new, freqs->cpu);
341 cpufreq_stats_record_transition(policy, freqs->new);
357 srcu_notifier_call_chain(&cpufreq_transition_notifier_list, 342 srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
358 CPUFREQ_POSTCHANGE, freqs); 343 CPUFREQ_POSTCHANGE, freqs);
359 if (likely(policy) && likely(policy->cpu == freqs->cpu)) 344 if (likely(policy) && likely(policy->cpu == freqs->cpu))
@@ -507,6 +492,38 @@ void cpufreq_disable_fast_switch(struct cpufreq_policy *policy)
507} 492}
508EXPORT_SYMBOL_GPL(cpufreq_disable_fast_switch); 493EXPORT_SYMBOL_GPL(cpufreq_disable_fast_switch);
509 494
495/**
496 * cpufreq_driver_resolve_freq - Map a target frequency to a driver-supported
497 * one.
498 * @target_freq: target frequency to resolve.
499 *
500 * The target to driver frequency mapping is cached in the policy.
501 *
502 * Return: Lowest driver-supported frequency greater than or equal to the
503 * given target_freq, subject to policy (min/max) and driver limitations.
504 */
505unsigned int cpufreq_driver_resolve_freq(struct cpufreq_policy *policy,
506 unsigned int target_freq)
507{
508 target_freq = clamp_val(target_freq, policy->min, policy->max);
509 policy->cached_target_freq = target_freq;
510
511 if (cpufreq_driver->target_index) {
512 int idx;
513
514 idx = cpufreq_frequency_table_target(policy, target_freq,
515 CPUFREQ_RELATION_L);
516 policy->cached_resolved_idx = idx;
517 return policy->freq_table[idx].frequency;
518 }
519
520 if (cpufreq_driver->resolve_freq)
521 return cpufreq_driver->resolve_freq(policy, target_freq);
522
523 return target_freq;
524}
525EXPORT_SYMBOL_GPL(cpufreq_driver_resolve_freq);
526
510/********************************************************************* 527/*********************************************************************
511 * SYSFS INTERFACE * 528 * SYSFS INTERFACE *
512 *********************************************************************/ 529 *********************************************************************/
@@ -1115,6 +1132,7 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy, bool notify)
1115 CPUFREQ_REMOVE_POLICY, policy); 1132 CPUFREQ_REMOVE_POLICY, policy);
1116 1133
1117 down_write(&policy->rwsem); 1134 down_write(&policy->rwsem);
1135 cpufreq_stats_free_table(policy);
1118 cpufreq_remove_dev_symlink(policy); 1136 cpufreq_remove_dev_symlink(policy);
1119 kobj = &policy->kobj; 1137 kobj = &policy->kobj;
1120 cmp = &policy->kobj_unregister; 1138 cmp = &policy->kobj_unregister;
@@ -1265,13 +1283,12 @@ static int cpufreq_online(unsigned int cpu)
1265 } 1283 }
1266 } 1284 }
1267 1285
1268 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1269 CPUFREQ_START, policy);
1270
1271 if (new_policy) { 1286 if (new_policy) {
1272 ret = cpufreq_add_dev_interface(policy); 1287 ret = cpufreq_add_dev_interface(policy);
1273 if (ret) 1288 if (ret)
1274 goto out_exit_policy; 1289 goto out_exit_policy;
1290
1291 cpufreq_stats_create_table(policy);
1275 blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 1292 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1276 CPUFREQ_CREATE_POLICY, policy); 1293 CPUFREQ_CREATE_POLICY, policy);
1277 1294
@@ -1280,6 +1297,9 @@ static int cpufreq_online(unsigned int cpu)
1280 write_unlock_irqrestore(&cpufreq_driver_lock, flags); 1297 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
1281 } 1298 }
1282 1299
1300 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1301 CPUFREQ_START, policy);
1302
1283 ret = cpufreq_init_policy(policy); 1303 ret = cpufreq_init_policy(policy);
1284 if (ret) { 1304 if (ret) {
1285 pr_err("%s: Failed to initialize policy for cpu: %d (%d)\n", 1305 pr_err("%s: Failed to initialize policy for cpu: %d (%d)\n",
@@ -1556,9 +1576,6 @@ static unsigned int cpufreq_update_current_freq(struct cpufreq_policy *policy)
1556{ 1576{
1557 unsigned int new_freq; 1577 unsigned int new_freq;
1558 1578
1559 if (cpufreq_suspended)
1560 return 0;
1561
1562 new_freq = cpufreq_driver->get(policy->cpu); 1579 new_freq = cpufreq_driver->get(policy->cpu);
1563 if (!new_freq) 1580 if (!new_freq)
1564 return 0; 1581 return 0;
@@ -1864,14 +1881,17 @@ static int __target_intermediate(struct cpufreq_policy *policy,
1864 return ret; 1881 return ret;
1865} 1882}
1866 1883
1867static int __target_index(struct cpufreq_policy *policy, 1884static int __target_index(struct cpufreq_policy *policy, int index)
1868 struct cpufreq_frequency_table *freq_table, int index)
1869{ 1885{
1870 struct cpufreq_freqs freqs = {.old = policy->cur, .flags = 0}; 1886 struct cpufreq_freqs freqs = {.old = policy->cur, .flags = 0};
1871 unsigned int intermediate_freq = 0; 1887 unsigned int intermediate_freq = 0;
1888 unsigned int newfreq = policy->freq_table[index].frequency;
1872 int retval = -EINVAL; 1889 int retval = -EINVAL;
1873 bool notify; 1890 bool notify;
1874 1891
1892 if (newfreq == policy->cur)
1893 return 0;
1894
1875 notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION); 1895 notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION);
1876 if (notify) { 1896 if (notify) {
1877 /* Handle switching to intermediate frequency */ 1897 /* Handle switching to intermediate frequency */
@@ -1886,7 +1906,7 @@ static int __target_index(struct cpufreq_policy *policy,
1886 freqs.old = freqs.new; 1906 freqs.old = freqs.new;
1887 } 1907 }
1888 1908
1889 freqs.new = freq_table[index].frequency; 1909 freqs.new = newfreq;
1890 pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n", 1910 pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
1891 __func__, policy->cpu, freqs.old, freqs.new); 1911 __func__, policy->cpu, freqs.old, freqs.new);
1892 1912
@@ -1923,17 +1943,13 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
1923 unsigned int relation) 1943 unsigned int relation)
1924{ 1944{
1925 unsigned int old_target_freq = target_freq; 1945 unsigned int old_target_freq = target_freq;
1926 struct cpufreq_frequency_table *freq_table; 1946 int index;
1927 int index, retval;
1928 1947
1929 if (cpufreq_disabled()) 1948 if (cpufreq_disabled())
1930 return -ENODEV; 1949 return -ENODEV;
1931 1950
1932 /* Make sure that target_freq is within supported range */ 1951 /* Make sure that target_freq is within supported range */
1933 if (target_freq > policy->max) 1952 target_freq = clamp_val(target_freq, policy->min, policy->max);
1934 target_freq = policy->max;
1935 if (target_freq < policy->min)
1936 target_freq = policy->min;
1937 1953
1938 pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n", 1954 pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
1939 policy->cpu, target_freq, relation, old_target_freq); 1955 policy->cpu, target_freq, relation, old_target_freq);
@@ -1956,23 +1972,9 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
1956 if (!cpufreq_driver->target_index) 1972 if (!cpufreq_driver->target_index)
1957 return -EINVAL; 1973 return -EINVAL;
1958 1974
1959 freq_table = cpufreq_frequency_get_table(policy->cpu); 1975 index = cpufreq_frequency_table_target(policy, target_freq, relation);
1960 if (unlikely(!freq_table)) {
1961 pr_err("%s: Unable to find freq_table\n", __func__);
1962 return -EINVAL;
1963 }
1964
1965 retval = cpufreq_frequency_table_target(policy, freq_table, target_freq,
1966 relation, &index);
1967 if (unlikely(retval)) {
1968 pr_err("%s: Unable to find matching freq\n", __func__);
1969 return retval;
1970 }
1971
1972 if (freq_table[index].frequency == policy->cur)
1973 return 0;
1974 1976
1975 return __target_index(policy, freq_table, index); 1977 return __target_index(policy, index);
1976} 1978}
1977EXPORT_SYMBOL_GPL(__cpufreq_driver_target); 1979EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
1978 1980
@@ -1997,7 +1999,7 @@ __weak struct cpufreq_governor *cpufreq_fallback_governor(void)
1997 return NULL; 1999 return NULL;
1998} 2000}
1999 2001
2000static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) 2002static int cpufreq_init_governor(struct cpufreq_policy *policy)
2001{ 2003{
2002 int ret; 2004 int ret;
2003 2005
@@ -2025,36 +2027,82 @@ static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
2025 } 2027 }
2026 } 2028 }
2027 2029
2028 if (event == CPUFREQ_GOV_POLICY_INIT) 2030 if (!try_module_get(policy->governor->owner))
2029 if (!try_module_get(policy->governor->owner)) 2031 return -EINVAL;
2030 return -EINVAL;
2031
2032 pr_debug("%s: for CPU %u, event %u\n", __func__, policy->cpu, event);
2033 2032
2034 ret = policy->governor->governor(policy, event); 2033 pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
2035 2034
2036 if (event == CPUFREQ_GOV_POLICY_INIT) { 2035 if (policy->governor->init) {
2037 if (ret) 2036 ret = policy->governor->init(policy);
2037 if (ret) {
2038 module_put(policy->governor->owner); 2038 module_put(policy->governor->owner);
2039 else 2039 return ret;
2040 policy->governor->initialized++; 2040 }
2041 } else if (event == CPUFREQ_GOV_POLICY_EXIT) {
2042 policy->governor->initialized--;
2043 module_put(policy->governor->owner);
2044 } 2041 }
2045 2042
2046 return ret; 2043 return 0;
2044}
2045
2046static void cpufreq_exit_governor(struct cpufreq_policy *policy)
2047{
2048 if (cpufreq_suspended || !policy->governor)
2049 return;
2050
2051 pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
2052
2053 if (policy->governor->exit)
2054 policy->governor->exit(policy);
2055
2056 module_put(policy->governor->owner);
2047} 2057}
2048 2058
2049static int cpufreq_start_governor(struct cpufreq_policy *policy) 2059static int cpufreq_start_governor(struct cpufreq_policy *policy)
2050{ 2060{
2051 int ret; 2061 int ret;
2052 2062
2063 if (cpufreq_suspended)
2064 return 0;
2065
2066 if (!policy->governor)
2067 return -EINVAL;
2068
2069 pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
2070
2053 if (cpufreq_driver->get && !cpufreq_driver->setpolicy) 2071 if (cpufreq_driver->get && !cpufreq_driver->setpolicy)
2054 cpufreq_update_current_freq(policy); 2072 cpufreq_update_current_freq(policy);
2055 2073
2056 ret = cpufreq_governor(policy, CPUFREQ_GOV_START); 2074 if (policy->governor->start) {
2057 return ret ? ret : cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); 2075 ret = policy->governor->start(policy);
2076 if (ret)
2077 return ret;
2078 }
2079
2080 if (policy->governor->limits)
2081 policy->governor->limits(policy);
2082
2083 return 0;
2084}
2085
2086static void cpufreq_stop_governor(struct cpufreq_policy *policy)
2087{
2088 if (cpufreq_suspended || !policy->governor)
2089 return;
2090
2091 pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
2092
2093 if (policy->governor->stop)
2094 policy->governor->stop(policy);
2095}
2096
2097static void cpufreq_governor_limits(struct cpufreq_policy *policy)
2098{
2099 if (cpufreq_suspended || !policy->governor)
2100 return;
2101
2102 pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
2103
2104 if (policy->governor->limits)
2105 policy->governor->limits(policy);
2058} 2106}
2059 2107
2060int cpufreq_register_governor(struct cpufreq_governor *governor) 2108int cpufreq_register_governor(struct cpufreq_governor *governor)
@@ -2069,7 +2117,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
2069 2117
2070 mutex_lock(&cpufreq_governor_mutex); 2118 mutex_lock(&cpufreq_governor_mutex);
2071 2119
2072 governor->initialized = 0;
2073 err = -EBUSY; 2120 err = -EBUSY;
2074 if (!find_governor(governor->name)) { 2121 if (!find_governor(governor->name)) {
2075 err = 0; 2122 err = 0;
@@ -2184,6 +2231,8 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
2184 policy->min = new_policy->min; 2231 policy->min = new_policy->min;
2185 policy->max = new_policy->max; 2232 policy->max = new_policy->max;
2186 2233
2234 policy->cached_target_freq = UINT_MAX;
2235
2187 pr_debug("new min and max freqs are %u - %u kHz\n", 2236 pr_debug("new min and max freqs are %u - %u kHz\n",
2188 policy->min, policy->max); 2237 policy->min, policy->max);
2189 2238
@@ -2195,7 +2244,8 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
2195 2244
2196 if (new_policy->governor == policy->governor) { 2245 if (new_policy->governor == policy->governor) {
2197 pr_debug("cpufreq: governor limits update\n"); 2246 pr_debug("cpufreq: governor limits update\n");
2198 return cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); 2247 cpufreq_governor_limits(policy);
2248 return 0;
2199 } 2249 }
2200 2250
2201 pr_debug("governor switch\n"); 2251 pr_debug("governor switch\n");
@@ -2210,7 +2260,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
2210 2260
2211 /* start new governor */ 2261 /* start new governor */
2212 policy->governor = new_policy->governor; 2262 policy->governor = new_policy->governor;
2213 ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT); 2263 ret = cpufreq_init_governor(policy);
2214 if (!ret) { 2264 if (!ret) {
2215 ret = cpufreq_start_governor(policy); 2265 ret = cpufreq_start_governor(policy);
2216 if (!ret) { 2266 if (!ret) {
@@ -2224,7 +2274,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
2224 pr_debug("starting governor %s failed\n", policy->governor->name); 2274 pr_debug("starting governor %s failed\n", policy->governor->name);
2225 if (old_gov) { 2275 if (old_gov) {
2226 policy->governor = old_gov; 2276 policy->governor = old_gov;
2227 if (cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) 2277 if (cpufreq_init_governor(policy))
2228 policy->governor = NULL; 2278 policy->governor = NULL;
2229 else 2279 else
2230 cpufreq_start_governor(policy); 2280 cpufreq_start_governor(policy);
@@ -2309,26 +2359,25 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = {
2309 *********************************************************************/ 2359 *********************************************************************/
2310static int cpufreq_boost_set_sw(int state) 2360static int cpufreq_boost_set_sw(int state)
2311{ 2361{
2312 struct cpufreq_frequency_table *freq_table;
2313 struct cpufreq_policy *policy; 2362 struct cpufreq_policy *policy;
2314 int ret = -EINVAL; 2363 int ret = -EINVAL;
2315 2364
2316 for_each_active_policy(policy) { 2365 for_each_active_policy(policy) {
2317 freq_table = cpufreq_frequency_get_table(policy->cpu); 2366 if (!policy->freq_table)
2318 if (freq_table) { 2367 continue;
2319 ret = cpufreq_frequency_table_cpuinfo(policy, 2368
2320 freq_table); 2369 ret = cpufreq_frequency_table_cpuinfo(policy,
2321 if (ret) { 2370 policy->freq_table);
2322 pr_err("%s: Policy frequency update failed\n", 2371 if (ret) {
2323 __func__); 2372 pr_err("%s: Policy frequency update failed\n",
2324 break; 2373 __func__);
2325 } 2374 break;
2326
2327 down_write(&policy->rwsem);
2328 policy->user_policy.max = policy->max;
2329 cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
2330 up_write(&policy->rwsem);
2331 } 2375 }
2376
2377 down_write(&policy->rwsem);
2378 policy->user_policy.max = policy->max;
2379 cpufreq_governor_limits(policy);
2380 up_write(&policy->rwsem);
2332 } 2381 }
2333 2382
2334 return ret; 2383 return ret;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 316df247e00d..18da4f8051d3 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -17,7 +17,6 @@
17struct cs_policy_dbs_info { 17struct cs_policy_dbs_info {
18 struct policy_dbs_info policy_dbs; 18 struct policy_dbs_info policy_dbs;
19 unsigned int down_skip; 19 unsigned int down_skip;
20 unsigned int requested_freq;
21}; 20};
22 21
23static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs) 22static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs)
@@ -75,19 +74,17 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
75 74
76 /* Check for frequency increase */ 75 /* Check for frequency increase */
77 if (load > dbs_data->up_threshold) { 76 if (load > dbs_data->up_threshold) {
77 unsigned int requested_freq = policy->cur;
78
78 dbs_info->down_skip = 0; 79 dbs_info->down_skip = 0;
79 80
80 /* if we are already at full speed then break out early */ 81 /* if we are already at full speed then break out early */
81 if (dbs_info->requested_freq == policy->max) 82 if (requested_freq == policy->max)
82 goto out; 83 goto out;
83 84
84 dbs_info->requested_freq += get_freq_target(cs_tuners, policy); 85 requested_freq += get_freq_target(cs_tuners, policy);
85
86 if (dbs_info->requested_freq > policy->max)
87 dbs_info->requested_freq = policy->max;
88 86
89 __cpufreq_driver_target(policy, dbs_info->requested_freq, 87 __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H);
90 CPUFREQ_RELATION_H);
91 goto out; 88 goto out;
92 } 89 }
93 90
@@ -98,36 +95,27 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
98 95
99 /* Check for frequency decrease */ 96 /* Check for frequency decrease */
100 if (load < cs_tuners->down_threshold) { 97 if (load < cs_tuners->down_threshold) {
101 unsigned int freq_target; 98 unsigned int freq_target, requested_freq = policy->cur;
102 /* 99 /*
103 * if we cannot reduce the frequency anymore, break out early 100 * if we cannot reduce the frequency anymore, break out early
104 */ 101 */
105 if (policy->cur == policy->min) 102 if (requested_freq == policy->min)
106 goto out; 103 goto out;
107 104
108 freq_target = get_freq_target(cs_tuners, policy); 105 freq_target = get_freq_target(cs_tuners, policy);
109 if (dbs_info->requested_freq > freq_target) 106 if (requested_freq > freq_target)
110 dbs_info->requested_freq -= freq_target; 107 requested_freq -= freq_target;
111 else 108 else
112 dbs_info->requested_freq = policy->min; 109 requested_freq = policy->min;
113 110
114 __cpufreq_driver_target(policy, dbs_info->requested_freq, 111 __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_L);
115 CPUFREQ_RELATION_L);
116 } 112 }
117 113
118 out: 114 out:
119 return dbs_data->sampling_rate; 115 return dbs_data->sampling_rate;
120} 116}
121 117
122static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
123 void *data);
124
125static struct notifier_block cs_cpufreq_notifier_block = {
126 .notifier_call = dbs_cpufreq_notifier,
127};
128
129/************************** sysfs interface ************************/ 118/************************** sysfs interface ************************/
130static struct dbs_governor cs_dbs_gov;
131 119
132static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set, 120static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
133 const char *buf, size_t count) 121 const char *buf, size_t count)
@@ -268,15 +256,13 @@ static void cs_free(struct policy_dbs_info *policy_dbs)
268 kfree(to_dbs_info(policy_dbs)); 256 kfree(to_dbs_info(policy_dbs));
269} 257}
270 258
271static int cs_init(struct dbs_data *dbs_data, bool notify) 259static int cs_init(struct dbs_data *dbs_data)
272{ 260{
273 struct cs_dbs_tuners *tuners; 261 struct cs_dbs_tuners *tuners;
274 262
275 tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); 263 tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
276 if (!tuners) { 264 if (!tuners)
277 pr_err("%s: kzalloc failed\n", __func__);
278 return -ENOMEM; 265 return -ENOMEM;
279 }
280 266
281 tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; 267 tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD;
282 tuners->freq_step = DEF_FREQUENCY_STEP; 268 tuners->freq_step = DEF_FREQUENCY_STEP;
@@ -288,19 +274,11 @@ static int cs_init(struct dbs_data *dbs_data, bool notify)
288 dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * 274 dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
289 jiffies_to_usecs(10); 275 jiffies_to_usecs(10);
290 276
291 if (notify)
292 cpufreq_register_notifier(&cs_cpufreq_notifier_block,
293 CPUFREQ_TRANSITION_NOTIFIER);
294
295 return 0; 277 return 0;
296} 278}
297 279
298static void cs_exit(struct dbs_data *dbs_data, bool notify) 280static void cs_exit(struct dbs_data *dbs_data)
299{ 281{
300 if (notify)
301 cpufreq_unregister_notifier(&cs_cpufreq_notifier_block,
302 CPUFREQ_TRANSITION_NOTIFIER);
303
304 kfree(dbs_data->tuners); 282 kfree(dbs_data->tuners);
305} 283}
306 284
@@ -309,16 +287,10 @@ static void cs_start(struct cpufreq_policy *policy)
309 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data); 287 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
310 288
311 dbs_info->down_skip = 0; 289 dbs_info->down_skip = 0;
312 dbs_info->requested_freq = policy->cur;
313} 290}
314 291
315static struct dbs_governor cs_dbs_gov = { 292static struct dbs_governor cs_governor = {
316 .gov = { 293 .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
317 .name = "conservative",
318 .governor = cpufreq_governor_dbs,
319 .max_transition_latency = TRANSITION_LATENCY_LIMIT,
320 .owner = THIS_MODULE,
321 },
322 .kobj_type = { .default_attrs = cs_attributes }, 294 .kobj_type = { .default_attrs = cs_attributes },
323 .gov_dbs_timer = cs_dbs_timer, 295 .gov_dbs_timer = cs_dbs_timer,
324 .alloc = cs_alloc, 296 .alloc = cs_alloc,
@@ -328,33 +300,7 @@ static struct dbs_governor cs_dbs_gov = {
328 .start = cs_start, 300 .start = cs_start,
329}; 301};
330 302
331#define CPU_FREQ_GOV_CONSERVATIVE (&cs_dbs_gov.gov) 303#define CPU_FREQ_GOV_CONSERVATIVE (&cs_governor.gov)
332
333static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
334 void *data)
335{
336 struct cpufreq_freqs *freq = data;
337 struct cpufreq_policy *policy = cpufreq_cpu_get_raw(freq->cpu);
338 struct cs_policy_dbs_info *dbs_info;
339
340 if (!policy)
341 return 0;
342
343 /* policy isn't governed by conservative governor */
344 if (policy->governor != CPU_FREQ_GOV_CONSERVATIVE)
345 return 0;
346
347 dbs_info = to_dbs_info(policy->governor_data);
348 /*
349 * we only care if our internally tracked freq moves outside the 'valid'
350 * ranges of frequency available to us otherwise we do not change it
351 */
352 if (dbs_info->requested_freq > policy->max
353 || dbs_info->requested_freq < policy->min)
354 dbs_info->requested_freq = freq->new;
355
356 return 0;
357}
358 304
359static int __init cpufreq_gov_dbs_init(void) 305static int __init cpufreq_gov_dbs_init(void)
360{ 306{
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index be498d56dd69..e415349ab31b 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -336,17 +336,6 @@ static inline void gov_clear_update_util(struct cpufreq_policy *policy)
336 synchronize_sched(); 336 synchronize_sched();
337} 337}
338 338
339static void gov_cancel_work(struct cpufreq_policy *policy)
340{
341 struct policy_dbs_info *policy_dbs = policy->governor_data;
342
343 gov_clear_update_util(policy_dbs->policy);
344 irq_work_sync(&policy_dbs->irq_work);
345 cancel_work_sync(&policy_dbs->work);
346 atomic_set(&policy_dbs->work_count, 0);
347 policy_dbs->work_in_progress = false;
348}
349
350static struct policy_dbs_info *alloc_policy_dbs_info(struct cpufreq_policy *policy, 339static struct policy_dbs_info *alloc_policy_dbs_info(struct cpufreq_policy *policy,
351 struct dbs_governor *gov) 340 struct dbs_governor *gov)
352{ 341{
@@ -389,7 +378,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
389 gov->free(policy_dbs); 378 gov->free(policy_dbs);
390} 379}
391 380
392static int cpufreq_governor_init(struct cpufreq_policy *policy) 381int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
393{ 382{
394 struct dbs_governor *gov = dbs_governor_of(policy); 383 struct dbs_governor *gov = dbs_governor_of(policy);
395 struct dbs_data *dbs_data; 384 struct dbs_data *dbs_data;
@@ -429,7 +418,7 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
429 418
430 gov_attr_set_init(&dbs_data->attr_set, &policy_dbs->list); 419 gov_attr_set_init(&dbs_data->attr_set, &policy_dbs->list);
431 420
432 ret = gov->init(dbs_data, !policy->governor->initialized); 421 ret = gov->init(dbs_data);
433 if (ret) 422 if (ret)
434 goto free_policy_dbs_info; 423 goto free_policy_dbs_info;
435 424
@@ -458,13 +447,13 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
458 goto out; 447 goto out;
459 448
460 /* Failure, so roll back. */ 449 /* Failure, so roll back. */
461 pr_err("cpufreq: Governor initialization failed (dbs_data kobject init error %d)\n", ret); 450 pr_err("initialization failed (dbs_data kobject init error %d)\n", ret);
462 451
463 policy->governor_data = NULL; 452 policy->governor_data = NULL;
464 453
465 if (!have_governor_per_policy()) 454 if (!have_governor_per_policy())
466 gov->gdbs_data = NULL; 455 gov->gdbs_data = NULL;
467 gov->exit(dbs_data, !policy->governor->initialized); 456 gov->exit(dbs_data);
468 kfree(dbs_data); 457 kfree(dbs_data);
469 458
470free_policy_dbs_info: 459free_policy_dbs_info:
@@ -474,8 +463,9 @@ out:
474 mutex_unlock(&gov_dbs_data_mutex); 463 mutex_unlock(&gov_dbs_data_mutex);
475 return ret; 464 return ret;
476} 465}
466EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_init);
477 467
478static int cpufreq_governor_exit(struct cpufreq_policy *policy) 468void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy)
479{ 469{
480 struct dbs_governor *gov = dbs_governor_of(policy); 470 struct dbs_governor *gov = dbs_governor_of(policy);
481 struct policy_dbs_info *policy_dbs = policy->governor_data; 471 struct policy_dbs_info *policy_dbs = policy->governor_data;
@@ -493,17 +483,17 @@ static int cpufreq_governor_exit(struct cpufreq_policy *policy)
493 if (!have_governor_per_policy()) 483 if (!have_governor_per_policy())
494 gov->gdbs_data = NULL; 484 gov->gdbs_data = NULL;
495 485
496 gov->exit(dbs_data, policy->governor->initialized == 1); 486 gov->exit(dbs_data);
497 kfree(dbs_data); 487 kfree(dbs_data);
498 } 488 }
499 489
500 free_policy_dbs_info(policy_dbs, gov); 490 free_policy_dbs_info(policy_dbs, gov);
501 491
502 mutex_unlock(&gov_dbs_data_mutex); 492 mutex_unlock(&gov_dbs_data_mutex);
503 return 0;
504} 493}
494EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_exit);
505 495
506static int cpufreq_governor_start(struct cpufreq_policy *policy) 496int cpufreq_dbs_governor_start(struct cpufreq_policy *policy)
507{ 497{
508 struct dbs_governor *gov = dbs_governor_of(policy); 498 struct dbs_governor *gov = dbs_governor_of(policy);
509 struct policy_dbs_info *policy_dbs = policy->governor_data; 499 struct policy_dbs_info *policy_dbs = policy->governor_data;
@@ -539,47 +529,28 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy)
539 gov_set_update_util(policy_dbs, sampling_rate); 529 gov_set_update_util(policy_dbs, sampling_rate);
540 return 0; 530 return 0;
541} 531}
532EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_start);
542 533
543static int cpufreq_governor_stop(struct cpufreq_policy *policy) 534void cpufreq_dbs_governor_stop(struct cpufreq_policy *policy)
544{ 535{
545 gov_cancel_work(policy); 536 struct policy_dbs_info *policy_dbs = policy->governor_data;
546 return 0; 537
538 gov_clear_update_util(policy_dbs->policy);
539 irq_work_sync(&policy_dbs->irq_work);
540 cancel_work_sync(&policy_dbs->work);
541 atomic_set(&policy_dbs->work_count, 0);
542 policy_dbs->work_in_progress = false;
547} 543}
544EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_stop);
548 545
549static int cpufreq_governor_limits(struct cpufreq_policy *policy) 546void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy)
550{ 547{
551 struct policy_dbs_info *policy_dbs = policy->governor_data; 548 struct policy_dbs_info *policy_dbs = policy->governor_data;
552 549
553 mutex_lock(&policy_dbs->timer_mutex); 550 mutex_lock(&policy_dbs->timer_mutex);
554 551 cpufreq_policy_apply_limits(policy);
555 if (policy->max < policy->cur)
556 __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
557 else if (policy->min > policy->cur)
558 __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
559
560 gov_update_sample_delay(policy_dbs, 0); 552 gov_update_sample_delay(policy_dbs, 0);
561 553
562 mutex_unlock(&policy_dbs->timer_mutex); 554 mutex_unlock(&policy_dbs->timer_mutex);
563
564 return 0;
565}
566
567int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event)
568{
569 if (event == CPUFREQ_GOV_POLICY_INIT) {
570 return cpufreq_governor_init(policy);
571 } else if (policy->governor_data) {
572 switch (event) {
573 case CPUFREQ_GOV_POLICY_EXIT:
574 return cpufreq_governor_exit(policy);
575 case CPUFREQ_GOV_START:
576 return cpufreq_governor_start(policy);
577 case CPUFREQ_GOV_STOP:
578 return cpufreq_governor_stop(policy);
579 case CPUFREQ_GOV_LIMITS:
580 return cpufreq_governor_limits(policy);
581 }
582 }
583 return -EINVAL;
584} 555}
585EXPORT_SYMBOL_GPL(cpufreq_governor_dbs); 556EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_limits);
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 34eb214b6d57..ef1037e9c92b 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -138,8 +138,8 @@ struct dbs_governor {
138 unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy); 138 unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy);
139 struct policy_dbs_info *(*alloc)(void); 139 struct policy_dbs_info *(*alloc)(void);
140 void (*free)(struct policy_dbs_info *policy_dbs); 140 void (*free)(struct policy_dbs_info *policy_dbs);
141 int (*init)(struct dbs_data *dbs_data, bool notify); 141 int (*init)(struct dbs_data *dbs_data);
142 void (*exit)(struct dbs_data *dbs_data, bool notify); 142 void (*exit)(struct dbs_data *dbs_data);
143 void (*start)(struct cpufreq_policy *policy); 143 void (*start)(struct cpufreq_policy *policy);
144}; 144};
145 145
@@ -148,6 +148,25 @@ static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy
148 return container_of(policy->governor, struct dbs_governor, gov); 148 return container_of(policy->governor, struct dbs_governor, gov);
149} 149}
150 150
151/* Governor callback routines */
152int cpufreq_dbs_governor_init(struct cpufreq_policy *policy);
153void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy);
154int cpufreq_dbs_governor_start(struct cpufreq_policy *policy);
155void cpufreq_dbs_governor_stop(struct cpufreq_policy *policy);
156void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy);
157
158#define CPUFREQ_DBS_GOVERNOR_INITIALIZER(_name_) \
159 { \
160 .name = _name_, \
161 .max_transition_latency = TRANSITION_LATENCY_LIMIT, \
162 .owner = THIS_MODULE, \
163 .init = cpufreq_dbs_governor_init, \
164 .exit = cpufreq_dbs_governor_exit, \
165 .start = cpufreq_dbs_governor_start, \
166 .stop = cpufreq_dbs_governor_stop, \
167 .limits = cpufreq_dbs_governor_limits, \
168 }
169
151/* Governor specific operations */ 170/* Governor specific operations */
152struct od_ops { 171struct od_ops {
153 unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy, 172 unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
@@ -155,7 +174,6 @@ struct od_ops {
155}; 174};
156 175
157unsigned int dbs_update(struct cpufreq_policy *policy); 176unsigned int dbs_update(struct cpufreq_policy *policy);
158int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event);
159void od_register_powersave_bias_handler(unsigned int (*f) 177void od_register_powersave_bias_handler(unsigned int (*f)
160 (struct cpufreq_policy *, unsigned int, unsigned int), 178 (struct cpufreq_policy *, unsigned int, unsigned int),
161 unsigned int powersave_bias); 179 unsigned int powersave_bias);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 300163430516..3a1f49f5f4c6 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -65,34 +65,30 @@ static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy,
65{ 65{
66 unsigned int freq_req, freq_reduc, freq_avg; 66 unsigned int freq_req, freq_reduc, freq_avg;
67 unsigned int freq_hi, freq_lo; 67 unsigned int freq_hi, freq_lo;
68 unsigned int index = 0; 68 unsigned int index;
69 unsigned int delay_hi_us; 69 unsigned int delay_hi_us;
70 struct policy_dbs_info *policy_dbs = policy->governor_data; 70 struct policy_dbs_info *policy_dbs = policy->governor_data;
71 struct od_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs); 71 struct od_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
72 struct dbs_data *dbs_data = policy_dbs->dbs_data; 72 struct dbs_data *dbs_data = policy_dbs->dbs_data;
73 struct od_dbs_tuners *od_tuners = dbs_data->tuners; 73 struct od_dbs_tuners *od_tuners = dbs_data->tuners;
74 struct cpufreq_frequency_table *freq_table = policy->freq_table;
74 75
75 if (!dbs_info->freq_table) { 76 if (!freq_table) {
76 dbs_info->freq_lo = 0; 77 dbs_info->freq_lo = 0;
77 dbs_info->freq_lo_delay_us = 0; 78 dbs_info->freq_lo_delay_us = 0;
78 return freq_next; 79 return freq_next;
79 } 80 }
80 81
81 cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next, 82 index = cpufreq_frequency_table_target(policy, freq_next, relation);
82 relation, &index); 83 freq_req = freq_table[index].frequency;
83 freq_req = dbs_info->freq_table[index].frequency;
84 freq_reduc = freq_req * od_tuners->powersave_bias / 1000; 84 freq_reduc = freq_req * od_tuners->powersave_bias / 1000;
85 freq_avg = freq_req - freq_reduc; 85 freq_avg = freq_req - freq_reduc;
86 86
87 /* Find freq bounds for freq_avg in freq_table */ 87 /* Find freq bounds for freq_avg in freq_table */
88 index = 0; 88 index = cpufreq_table_find_index_h(policy, freq_avg);
89 cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, 89 freq_lo = freq_table[index].frequency;
90 CPUFREQ_RELATION_H, &index); 90 index = cpufreq_table_find_index_l(policy, freq_avg);
91 freq_lo = dbs_info->freq_table[index].frequency; 91 freq_hi = freq_table[index].frequency;
92 index = 0;
93 cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg,
94 CPUFREQ_RELATION_L, &index);
95 freq_hi = dbs_info->freq_table[index].frequency;
96 92
97 /* Find out how long we have to be in hi and lo freqs */ 93 /* Find out how long we have to be in hi and lo freqs */
98 if (freq_hi == freq_lo) { 94 if (freq_hi == freq_lo) {
@@ -113,7 +109,6 @@ static void ondemand_powersave_bias_init(struct cpufreq_policy *policy)
113{ 109{
114 struct od_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data); 110 struct od_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
115 111
116 dbs_info->freq_table = cpufreq_frequency_get_table(policy->cpu);
117 dbs_info->freq_lo = 0; 112 dbs_info->freq_lo = 0;
118} 113}
119 114
@@ -361,17 +356,15 @@ static void od_free(struct policy_dbs_info *policy_dbs)
361 kfree(to_dbs_info(policy_dbs)); 356 kfree(to_dbs_info(policy_dbs));
362} 357}
363 358
364static int od_init(struct dbs_data *dbs_data, bool notify) 359static int od_init(struct dbs_data *dbs_data)
365{ 360{
366 struct od_dbs_tuners *tuners; 361 struct od_dbs_tuners *tuners;
367 u64 idle_time; 362 u64 idle_time;
368 int cpu; 363 int cpu;
369 364
370 tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); 365 tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
371 if (!tuners) { 366 if (!tuners)
372 pr_err("%s: kzalloc failed\n", __func__);
373 return -ENOMEM; 367 return -ENOMEM;
374 }
375 368
376 cpu = get_cpu(); 369 cpu = get_cpu();
377 idle_time = get_cpu_idle_time_us(cpu, NULL); 370 idle_time = get_cpu_idle_time_us(cpu, NULL);
@@ -402,7 +395,7 @@ static int od_init(struct dbs_data *dbs_data, bool notify)
402 return 0; 395 return 0;
403} 396}
404 397
405static void od_exit(struct dbs_data *dbs_data, bool notify) 398static void od_exit(struct dbs_data *dbs_data)
406{ 399{
407 kfree(dbs_data->tuners); 400 kfree(dbs_data->tuners);
408} 401}
@@ -420,12 +413,7 @@ static struct od_ops od_ops = {
420}; 413};
421 414
422static struct dbs_governor od_dbs_gov = { 415static struct dbs_governor od_dbs_gov = {
423 .gov = { 416 .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("ondemand"),
424 .name = "ondemand",
425 .governor = cpufreq_governor_dbs,
426 .max_transition_latency = TRANSITION_LATENCY_LIMIT,
427 .owner = THIS_MODULE,
428 },
429 .kobj_type = { .default_attrs = od_attributes }, 417 .kobj_type = { .default_attrs = od_attributes },
430 .gov_dbs_timer = od_dbs_timer, 418 .gov_dbs_timer = od_dbs_timer,
431 .alloc = od_alloc, 419 .alloc = od_alloc,
diff --git a/drivers/cpufreq/cpufreq_ondemand.h b/drivers/cpufreq/cpufreq_ondemand.h
index f0121db3cd9e..640ea4e97106 100644
--- a/drivers/cpufreq/cpufreq_ondemand.h
+++ b/drivers/cpufreq/cpufreq_ondemand.h
@@ -13,7 +13,6 @@
13 13
14struct od_policy_dbs_info { 14struct od_policy_dbs_info {
15 struct policy_dbs_info policy_dbs; 15 struct policy_dbs_info policy_dbs;
16 struct cpufreq_frequency_table *freq_table;
17 unsigned int freq_lo; 16 unsigned int freq_lo;
18 unsigned int freq_lo_delay_us; 17 unsigned int freq_lo_delay_us;
19 unsigned int freq_hi_delay_us; 18 unsigned int freq_hi_delay_us;
diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c
index af9f4b96f5a8..dafb679adc58 100644
--- a/drivers/cpufreq/cpufreq_performance.c
+++ b/drivers/cpufreq/cpufreq_performance.c
@@ -16,27 +16,16 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/module.h> 17#include <linux/module.h>
18 18
19static int cpufreq_governor_performance(struct cpufreq_policy *policy, 19static void cpufreq_gov_performance_limits(struct cpufreq_policy *policy)
20 unsigned int event)
21{ 20{
22 switch (event) { 21 pr_debug("setting to %u kHz\n", policy->max);
23 case CPUFREQ_GOV_START: 22 __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
24 case CPUFREQ_GOV_LIMITS:
25 pr_debug("setting to %u kHz because of event %u\n",
26 policy->max, event);
27 __cpufreq_driver_target(policy, policy->max,
28 CPUFREQ_RELATION_H);
29 break;
30 default:
31 break;
32 }
33 return 0;
34} 23}
35 24
36static struct cpufreq_governor cpufreq_gov_performance = { 25static struct cpufreq_governor cpufreq_gov_performance = {
37 .name = "performance", 26 .name = "performance",
38 .governor = cpufreq_governor_performance,
39 .owner = THIS_MODULE, 27 .owner = THIS_MODULE,
28 .limits = cpufreq_gov_performance_limits,
40}; 29};
41 30
42static int __init cpufreq_gov_performance_init(void) 31static int __init cpufreq_gov_performance_init(void)
diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c
index b8b400232a74..78a651038faf 100644
--- a/drivers/cpufreq/cpufreq_powersave.c
+++ b/drivers/cpufreq/cpufreq_powersave.c
@@ -16,26 +16,15 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/module.h> 17#include <linux/module.h>
18 18
19static int cpufreq_governor_powersave(struct cpufreq_policy *policy, 19static void cpufreq_gov_powersave_limits(struct cpufreq_policy *policy)
20 unsigned int event)
21{ 20{
22 switch (event) { 21 pr_debug("setting to %u kHz\n", policy->min);
23 case CPUFREQ_GOV_START: 22 __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
24 case CPUFREQ_GOV_LIMITS:
25 pr_debug("setting to %u kHz because of event %u\n",
26 policy->min, event);
27 __cpufreq_driver_target(policy, policy->min,
28 CPUFREQ_RELATION_L);
29 break;
30 default:
31 break;
32 }
33 return 0;
34} 23}
35 24
36static struct cpufreq_governor cpufreq_gov_powersave = { 25static struct cpufreq_governor cpufreq_gov_powersave = {
37 .name = "powersave", 26 .name = "powersave",
38 .governor = cpufreq_governor_powersave, 27 .limits = cpufreq_gov_powersave_limits,
39 .owner = THIS_MODULE, 28 .owner = THIS_MODULE,
40}; 29};
41 30
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 5e370a30a964..06d3abdffd3a 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -15,7 +15,7 @@
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/cputime.h> 16#include <linux/cputime.h>
17 17
18static spinlock_t cpufreq_stats_lock; 18static DEFINE_SPINLOCK(cpufreq_stats_lock);
19 19
20struct cpufreq_stats { 20struct cpufreq_stats {
21 unsigned int total_trans; 21 unsigned int total_trans;
@@ -52,6 +52,9 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
52 ssize_t len = 0; 52 ssize_t len = 0;
53 int i; 53 int i;
54 54
55 if (policy->fast_switch_enabled)
56 return 0;
57
55 cpufreq_stats_update(stats); 58 cpufreq_stats_update(stats);
56 for (i = 0; i < stats->state_num; i++) { 59 for (i = 0; i < stats->state_num; i++) {
57 len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i], 60 len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i],
@@ -68,6 +71,9 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
68 ssize_t len = 0; 71 ssize_t len = 0;
69 int i, j; 72 int i, j;
70 73
74 if (policy->fast_switch_enabled)
75 return 0;
76
71 len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n"); 77 len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
72 len += snprintf(buf + len, PAGE_SIZE - len, " : "); 78 len += snprintf(buf + len, PAGE_SIZE - len, " : ");
73 for (i = 0; i < stats->state_num; i++) { 79 for (i = 0; i < stats->state_num; i++) {
@@ -130,7 +136,7 @@ static int freq_table_get_index(struct cpufreq_stats *stats, unsigned int freq)
130 return -1; 136 return -1;
131} 137}
132 138
133static void __cpufreq_stats_free_table(struct cpufreq_policy *policy) 139void cpufreq_stats_free_table(struct cpufreq_policy *policy)
134{ 140{
135 struct cpufreq_stats *stats = policy->stats; 141 struct cpufreq_stats *stats = policy->stats;
136 142
@@ -146,39 +152,25 @@ static void __cpufreq_stats_free_table(struct cpufreq_policy *policy)
146 policy->stats = NULL; 152 policy->stats = NULL;
147} 153}
148 154
149static void cpufreq_stats_free_table(unsigned int cpu) 155void cpufreq_stats_create_table(struct cpufreq_policy *policy)
150{
151 struct cpufreq_policy *policy;
152
153 policy = cpufreq_cpu_get(cpu);
154 if (!policy)
155 return;
156
157 __cpufreq_stats_free_table(policy);
158
159 cpufreq_cpu_put(policy);
160}
161
162static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
163{ 156{
164 unsigned int i = 0, count = 0, ret = -ENOMEM; 157 unsigned int i = 0, count = 0, ret = -ENOMEM;
165 struct cpufreq_stats *stats; 158 struct cpufreq_stats *stats;
166 unsigned int alloc_size; 159 unsigned int alloc_size;
167 unsigned int cpu = policy->cpu;
168 struct cpufreq_frequency_table *pos, *table; 160 struct cpufreq_frequency_table *pos, *table;
169 161
170 /* We need cpufreq table for creating stats table */ 162 /* We need cpufreq table for creating stats table */
171 table = cpufreq_frequency_get_table(cpu); 163 table = policy->freq_table;
172 if (unlikely(!table)) 164 if (unlikely(!table))
173 return 0; 165 return;
174 166
175 /* stats already initialized */ 167 /* stats already initialized */
176 if (policy->stats) 168 if (policy->stats)
177 return -EEXIST; 169 return;
178 170
179 stats = kzalloc(sizeof(*stats), GFP_KERNEL); 171 stats = kzalloc(sizeof(*stats), GFP_KERNEL);
180 if (!stats) 172 if (!stats)
181 return -ENOMEM; 173 return;
182 174
183 /* Find total allocation size */ 175 /* Find total allocation size */
184 cpufreq_for_each_valid_entry(pos, table) 176 cpufreq_for_each_valid_entry(pos, table)
@@ -215,80 +207,32 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
215 policy->stats = stats; 207 policy->stats = stats;
216 ret = sysfs_create_group(&policy->kobj, &stats_attr_group); 208 ret = sysfs_create_group(&policy->kobj, &stats_attr_group);
217 if (!ret) 209 if (!ret)
218 return 0; 210 return;
219 211
220 /* We failed, release resources */ 212 /* We failed, release resources */
221 policy->stats = NULL; 213 policy->stats = NULL;
222 kfree(stats->time_in_state); 214 kfree(stats->time_in_state);
223free_stat: 215free_stat:
224 kfree(stats); 216 kfree(stats);
225
226 return ret;
227}
228
229static void cpufreq_stats_create_table(unsigned int cpu)
230{
231 struct cpufreq_policy *policy;
232
233 /*
234 * "likely(!policy)" because normally cpufreq_stats will be registered
235 * before cpufreq driver
236 */
237 policy = cpufreq_cpu_get(cpu);
238 if (likely(!policy))
239 return;
240
241 __cpufreq_stats_create_table(policy);
242
243 cpufreq_cpu_put(policy);
244} 217}
245 218
246static int cpufreq_stat_notifier_policy(struct notifier_block *nb, 219void cpufreq_stats_record_transition(struct cpufreq_policy *policy,
247 unsigned long val, void *data) 220 unsigned int new_freq)
248{ 221{
249 int ret = 0; 222 struct cpufreq_stats *stats = policy->stats;
250 struct cpufreq_policy *policy = data;
251
252 if (val == CPUFREQ_CREATE_POLICY)
253 ret = __cpufreq_stats_create_table(policy);
254 else if (val == CPUFREQ_REMOVE_POLICY)
255 __cpufreq_stats_free_table(policy);
256
257 return ret;
258}
259
260static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
261 unsigned long val, void *data)
262{
263 struct cpufreq_freqs *freq = data;
264 struct cpufreq_policy *policy = cpufreq_cpu_get(freq->cpu);
265 struct cpufreq_stats *stats;
266 int old_index, new_index; 223 int old_index, new_index;
267 224
268 if (!policy) { 225 if (!stats) {
269 pr_err("%s: No policy found\n", __func__);
270 return 0;
271 }
272
273 if (val != CPUFREQ_POSTCHANGE)
274 goto put_policy;
275
276 if (!policy->stats) {
277 pr_debug("%s: No stats found\n", __func__); 226 pr_debug("%s: No stats found\n", __func__);
278 goto put_policy; 227 return;
279 } 228 }
280 229
281 stats = policy->stats;
282
283 old_index = stats->last_index; 230 old_index = stats->last_index;
284 new_index = freq_table_get_index(stats, freq->new); 231 new_index = freq_table_get_index(stats, new_freq);
285 232
286 /* We can't do stats->time_in_state[-1]= .. */ 233 /* We can't do stats->time_in_state[-1]= .. */
287 if (old_index == -1 || new_index == -1) 234 if (old_index == -1 || new_index == -1 || old_index == new_index)
288 goto put_policy; 235 return;
289
290 if (old_index == new_index)
291 goto put_policy;
292 236
293 cpufreq_stats_update(stats); 237 cpufreq_stats_update(stats);
294 238
@@ -297,61 +241,4 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
297 stats->trans_table[old_index * stats->max_state + new_index]++; 241 stats->trans_table[old_index * stats->max_state + new_index]++;
298#endif 242#endif
299 stats->total_trans++; 243 stats->total_trans++;
300
301put_policy:
302 cpufreq_cpu_put(policy);
303 return 0;
304} 244}
305
306static struct notifier_block notifier_policy_block = {
307 .notifier_call = cpufreq_stat_notifier_policy
308};
309
310static struct notifier_block notifier_trans_block = {
311 .notifier_call = cpufreq_stat_notifier_trans
312};
313
314static int __init cpufreq_stats_init(void)
315{
316 int ret;
317 unsigned int cpu;
318
319 spin_lock_init(&cpufreq_stats_lock);
320 ret = cpufreq_register_notifier(&notifier_policy_block,
321 CPUFREQ_POLICY_NOTIFIER);
322 if (ret)
323 return ret;
324
325 for_each_online_cpu(cpu)
326 cpufreq_stats_create_table(cpu);
327
328 ret = cpufreq_register_notifier(&notifier_trans_block,
329 CPUFREQ_TRANSITION_NOTIFIER);
330 if (ret) {
331 cpufreq_unregister_notifier(&notifier_policy_block,
332 CPUFREQ_POLICY_NOTIFIER);
333 for_each_online_cpu(cpu)
334 cpufreq_stats_free_table(cpu);
335 return ret;
336 }
337
338 return 0;
339}
340static void __exit cpufreq_stats_exit(void)
341{
342 unsigned int cpu;
343
344 cpufreq_unregister_notifier(&notifier_policy_block,
345 CPUFREQ_POLICY_NOTIFIER);
346 cpufreq_unregister_notifier(&notifier_trans_block,
347 CPUFREQ_TRANSITION_NOTIFIER);
348 for_each_online_cpu(cpu)
349 cpufreq_stats_free_table(cpu);
350}
351
352MODULE_AUTHOR("Zou Nan hai <nanhai.zou@intel.com>");
353MODULE_DESCRIPTION("Export cpufreq stats via sysfs");
354MODULE_LICENSE("GPL");
355
356module_init(cpufreq_stats_init);
357module_exit(cpufreq_stats_exit);
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 9f3dec9a3f36..bd897e3e134d 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -65,66 +65,66 @@ static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy)
65 return 0; 65 return 0;
66} 66}
67 67
68static int cpufreq_governor_userspace(struct cpufreq_policy *policy, 68static void cpufreq_userspace_policy_exit(struct cpufreq_policy *policy)
69 unsigned int event) 69{
70 mutex_lock(&userspace_mutex);
71 kfree(policy->governor_data);
72 policy->governor_data = NULL;
73 mutex_unlock(&userspace_mutex);
74}
75
76static int cpufreq_userspace_policy_start(struct cpufreq_policy *policy)
70{ 77{
71 unsigned int *setspeed = policy->governor_data; 78 unsigned int *setspeed = policy->governor_data;
72 unsigned int cpu = policy->cpu;
73 int rc = 0;
74 79
75 if (event == CPUFREQ_GOV_POLICY_INIT) 80 BUG_ON(!policy->cur);
76 return cpufreq_userspace_policy_init(policy); 81 pr_debug("started managing cpu %u\n", policy->cpu);
77 82
78 if (!setspeed) 83 mutex_lock(&userspace_mutex);
79 return -EINVAL; 84 per_cpu(cpu_is_managed, policy->cpu) = 1;
80 85 *setspeed = policy->cur;
81 switch (event) { 86 mutex_unlock(&userspace_mutex);
82 case CPUFREQ_GOV_POLICY_EXIT: 87 return 0;
83 mutex_lock(&userspace_mutex); 88}
84 policy->governor_data = NULL; 89
85 kfree(setspeed); 90static void cpufreq_userspace_policy_stop(struct cpufreq_policy *policy)
86 mutex_unlock(&userspace_mutex); 91{
87 break; 92 unsigned int *setspeed = policy->governor_data;
88 case CPUFREQ_GOV_START: 93
89 BUG_ON(!policy->cur); 94 pr_debug("managing cpu %u stopped\n", policy->cpu);
90 pr_debug("started managing cpu %u\n", cpu); 95
91 96 mutex_lock(&userspace_mutex);
92 mutex_lock(&userspace_mutex); 97 per_cpu(cpu_is_managed, policy->cpu) = 0;
93 per_cpu(cpu_is_managed, cpu) = 1; 98 *setspeed = 0;
94 *setspeed = policy->cur; 99 mutex_unlock(&userspace_mutex);
95 mutex_unlock(&userspace_mutex); 100}
96 break; 101
97 case CPUFREQ_GOV_STOP: 102static void cpufreq_userspace_policy_limits(struct cpufreq_policy *policy)
98 pr_debug("managing cpu %u stopped\n", cpu); 103{
99 104 unsigned int *setspeed = policy->governor_data;
100 mutex_lock(&userspace_mutex); 105
101 per_cpu(cpu_is_managed, cpu) = 0; 106 mutex_lock(&userspace_mutex);
102 *setspeed = 0; 107
103 mutex_unlock(&userspace_mutex); 108 pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n",
104 break; 109 policy->cpu, policy->min, policy->max, policy->cur, *setspeed);
105 case CPUFREQ_GOV_LIMITS: 110
106 mutex_lock(&userspace_mutex); 111 if (policy->max < *setspeed)
107 pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n", 112 __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
108 cpu, policy->min, policy->max, policy->cur, *setspeed); 113 else if (policy->min > *setspeed)
109 114 __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
110 if (policy->max < *setspeed) 115 else
111 __cpufreq_driver_target(policy, policy->max, 116 __cpufreq_driver_target(policy, *setspeed, CPUFREQ_RELATION_L);
112 CPUFREQ_RELATION_H); 117
113 else if (policy->min > *setspeed) 118 mutex_unlock(&userspace_mutex);
114 __cpufreq_driver_target(policy, policy->min,
115 CPUFREQ_RELATION_L);
116 else
117 __cpufreq_driver_target(policy, *setspeed,
118 CPUFREQ_RELATION_L);
119 mutex_unlock(&userspace_mutex);
120 break;
121 }
122 return rc;
123} 119}
124 120
125static struct cpufreq_governor cpufreq_gov_userspace = { 121static struct cpufreq_governor cpufreq_gov_userspace = {
126 .name = "userspace", 122 .name = "userspace",
127 .governor = cpufreq_governor_userspace, 123 .init = cpufreq_userspace_policy_init,
124 .exit = cpufreq_userspace_policy_exit,
125 .start = cpufreq_userspace_policy_start,
126 .stop = cpufreq_userspace_policy_stop,
127 .limits = cpufreq_userspace_policy_limits,
128 .store_setspeed = cpufreq_set, 128 .store_setspeed = cpufreq_set,
129 .show_setspeed = show_speed, 129 .show_setspeed = show_speed,
130 .owner = THIS_MODULE, 130 .owner = THIS_MODULE,
diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c
index 7e336d20c184..b95a872800ec 100644
--- a/drivers/cpufreq/davinci-cpufreq.c
+++ b/drivers/cpufreq/davinci-cpufreq.c
@@ -38,26 +38,6 @@ struct davinci_cpufreq {
38}; 38};
39static struct davinci_cpufreq cpufreq; 39static struct davinci_cpufreq cpufreq;
40 40
41static int davinci_verify_speed(struct cpufreq_policy *policy)
42{
43 struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
44 struct cpufreq_frequency_table *freq_table = pdata->freq_table;
45 struct clk *armclk = cpufreq.armclk;
46
47 if (freq_table)
48 return cpufreq_frequency_table_verify(policy, freq_table);
49
50 if (policy->cpu)
51 return -EINVAL;
52
53 cpufreq_verify_within_cpu_limits(policy);
54 policy->min = clk_round_rate(armclk, policy->min * 1000) / 1000;
55 policy->max = clk_round_rate(armclk, policy->max * 1000) / 1000;
56 cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
57 policy->cpuinfo.max_freq);
58 return 0;
59}
60
61static int davinci_target(struct cpufreq_policy *policy, unsigned int idx) 41static int davinci_target(struct cpufreq_policy *policy, unsigned int idx)
62{ 42{
63 struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; 43 struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
@@ -121,7 +101,7 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
121 101
122static struct cpufreq_driver davinci_driver = { 102static struct cpufreq_driver davinci_driver = {
123 .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, 103 .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
124 .verify = davinci_verify_speed, 104 .verify = cpufreq_generic_frequency_table_verify,
125 .target_index = davinci_target, 105 .target_index = davinci_target,
126 .get = cpufreq_generic_get, 106 .get = cpufreq_generic_get,
127 .init = davinci_cpu_init, 107 .init = davinci_cpu_init,
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index a8f1daffc9bc..3bbbf9e6960c 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -63,8 +63,6 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
63 else 63 else
64 return 0; 64 return 0;
65} 65}
66EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
67
68 66
69int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, 67int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
70 struct cpufreq_frequency_table *table) 68 struct cpufreq_frequency_table *table)
@@ -108,20 +106,16 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
108 */ 106 */
109int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy) 107int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
110{ 108{
111 struct cpufreq_frequency_table *table = 109 if (!policy->freq_table)
112 cpufreq_frequency_get_table(policy->cpu);
113 if (!table)
114 return -ENODEV; 110 return -ENODEV;
115 111
116 return cpufreq_frequency_table_verify(policy, table); 112 return cpufreq_frequency_table_verify(policy, policy->freq_table);
117} 113}
118EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify); 114EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify);
119 115
120int cpufreq_frequency_table_target(struct cpufreq_policy *policy, 116int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
121 struct cpufreq_frequency_table *table, 117 unsigned int target_freq,
122 unsigned int target_freq, 118 unsigned int relation)
123 unsigned int relation,
124 unsigned int *index)
125{ 119{
126 struct cpufreq_frequency_table optimal = { 120 struct cpufreq_frequency_table optimal = {
127 .driver_data = ~0, 121 .driver_data = ~0,
@@ -132,7 +126,9 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
132 .frequency = 0, 126 .frequency = 0,
133 }; 127 };
134 struct cpufreq_frequency_table *pos; 128 struct cpufreq_frequency_table *pos;
129 struct cpufreq_frequency_table *table = policy->freq_table;
135 unsigned int freq, diff, i = 0; 130 unsigned int freq, diff, i = 0;
131 int index;
136 132
137 pr_debug("request for target %u kHz (relation: %u) for cpu %u\n", 133 pr_debug("request for target %u kHz (relation: %u) for cpu %u\n",
138 target_freq, relation, policy->cpu); 134 target_freq, relation, policy->cpu);
@@ -196,25 +192,26 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
196 } 192 }
197 } 193 }
198 if (optimal.driver_data > i) { 194 if (optimal.driver_data > i) {
199 if (suboptimal.driver_data > i) 195 if (suboptimal.driver_data > i) {
200 return -EINVAL; 196 WARN(1, "Invalid frequency table: %d\n", policy->cpu);
201 *index = suboptimal.driver_data; 197 return 0;
202 } else 198 }
203 *index = optimal.driver_data;
204 199
205 pr_debug("target index is %u, freq is:%u kHz\n", *index, 200 index = suboptimal.driver_data;
206 table[*index].frequency); 201 } else
202 index = optimal.driver_data;
207 203
208 return 0; 204 pr_debug("target index is %u, freq is:%u kHz\n", index,
205 table[index].frequency);
206 return index;
209} 207}
210EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); 208EXPORT_SYMBOL_GPL(cpufreq_table_index_unsorted);
211 209
212int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, 210int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
213 unsigned int freq) 211 unsigned int freq)
214{ 212{
215 struct cpufreq_frequency_table *pos, *table; 213 struct cpufreq_frequency_table *pos, *table = policy->freq_table;
216 214
217 table = cpufreq_frequency_get_table(policy->cpu);
218 if (unlikely(!table)) { 215 if (unlikely(!table)) {
219 pr_debug("%s: Unable to find frequency table\n", __func__); 216 pr_debug("%s: Unable to find frequency table\n", __func__);
220 return -ENOENT; 217 return -ENOENT;
@@ -300,15 +297,72 @@ struct freq_attr *cpufreq_generic_attr[] = {
300}; 297};
301EXPORT_SYMBOL_GPL(cpufreq_generic_attr); 298EXPORT_SYMBOL_GPL(cpufreq_generic_attr);
302 299
300static int set_freq_table_sorted(struct cpufreq_policy *policy)
301{
302 struct cpufreq_frequency_table *pos, *table = policy->freq_table;
303 struct cpufreq_frequency_table *prev = NULL;
304 int ascending = 0;
305
306 policy->freq_table_sorted = CPUFREQ_TABLE_UNSORTED;
307
308 cpufreq_for_each_valid_entry(pos, table) {
309 if (!prev) {
310 prev = pos;
311 continue;
312 }
313
314 if (pos->frequency == prev->frequency) {
315 pr_warn("Duplicate freq-table entries: %u\n",
316 pos->frequency);
317 return -EINVAL;
318 }
319
320 /* Frequency increased from prev to pos */
321 if (pos->frequency > prev->frequency) {
322 /* But frequency was decreasing earlier */
323 if (ascending < 0) {
324 pr_debug("Freq table is unsorted\n");
325 return 0;
326 }
327
328 ascending++;
329 } else {
330 /* Frequency decreased from prev to pos */
331
332 /* But frequency was increasing earlier */
333 if (ascending > 0) {
334 pr_debug("Freq table is unsorted\n");
335 return 0;
336 }
337
338 ascending--;
339 }
340
341 prev = pos;
342 }
343
344 if (ascending > 0)
345 policy->freq_table_sorted = CPUFREQ_TABLE_SORTED_ASCENDING;
346 else
347 policy->freq_table_sorted = CPUFREQ_TABLE_SORTED_DESCENDING;
348
349 pr_debug("Freq table is sorted in %s order\n",
350 ascending > 0 ? "ascending" : "descending");
351
352 return 0;
353}
354
303int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, 355int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
304 struct cpufreq_frequency_table *table) 356 struct cpufreq_frequency_table *table)
305{ 357{
306 int ret = cpufreq_frequency_table_cpuinfo(policy, table); 358 int ret;
307 359
308 if (!ret) 360 ret = cpufreq_frequency_table_cpuinfo(policy, table);
309 policy->freq_table = table; 361 if (ret)
362 return ret;
310 363
311 return ret; 364 policy->freq_table = table;
365 return set_freq_table_sorted(policy);
312} 366}
313EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show); 367EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
314 368
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 28690b284846..9ec033b4f2d9 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -97,7 +97,6 @@ static inline u64 div_ext_fp(u64 x, u64 y)
97 * read from MPERF MSR between last and current sample 97 * read from MPERF MSR between last and current sample
98 * @tsc: Difference of time stamp counter between last and 98 * @tsc: Difference of time stamp counter between last and
99 * current sample 99 * current sample
100 * @freq: Effective frequency calculated from APERF/MPERF
101 * @time: Current time from scheduler 100 * @time: Current time from scheduler
102 * 101 *
103 * This structure is used in the cpudata structure to store performance sample 102 * This structure is used in the cpudata structure to store performance sample
@@ -109,7 +108,6 @@ struct sample {
109 u64 aperf; 108 u64 aperf;
110 u64 mperf; 109 u64 mperf;
111 u64 tsc; 110 u64 tsc;
112 int freq;
113 u64 time; 111 u64 time;
114}; 112};
115 113
@@ -282,9 +280,9 @@ struct cpu_defaults {
282static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu); 280static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu);
283static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu); 281static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu);
284 282
285static struct pstate_adjust_policy pid_params; 283static struct pstate_adjust_policy pid_params __read_mostly;
286static struct pstate_funcs pstate_funcs; 284static struct pstate_funcs pstate_funcs __read_mostly;
287static int hwp_active; 285static int hwp_active __read_mostly;
288 286
289#ifdef CONFIG_ACPI 287#ifdef CONFIG_ACPI
290static bool acpi_ppc; 288static bool acpi_ppc;
@@ -808,7 +806,8 @@ static void __init intel_pstate_sysfs_expose_params(void)
808static void intel_pstate_hwp_enable(struct cpudata *cpudata) 806static void intel_pstate_hwp_enable(struct cpudata *cpudata)
809{ 807{
810 /* First disable HWP notification interrupt as we don't process them */ 808 /* First disable HWP notification interrupt as we don't process them */
811 wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x00); 809 if (static_cpu_has(X86_FEATURE_HWP_NOTIFY))
810 wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x00);
812 811
813 wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1); 812 wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1);
814} 813}
@@ -945,7 +944,7 @@ static int core_get_max_pstate(void)
945 if (err) 944 if (err)
946 goto skip_tar; 945 goto skip_tar;
947 946
948 tdp_msr = MSR_CONFIG_TDP_NOMINAL + tdp_ctrl; 947 tdp_msr = MSR_CONFIG_TDP_NOMINAL + (tdp_ctrl & 0x3);
949 err = rdmsrl_safe(tdp_msr, &tdp_ratio); 948 err = rdmsrl_safe(tdp_msr, &tdp_ratio);
950 if (err) 949 if (err)
951 goto skip_tar; 950 goto skip_tar;
@@ -973,7 +972,7 @@ static int core_get_turbo_pstate(void)
973 u64 value; 972 u64 value;
974 int nont, ret; 973 int nont, ret;
975 974
976 rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value); 975 rdmsrl(MSR_TURBO_RATIO_LIMIT, value);
977 nont = core_get_max_pstate(); 976 nont = core_get_max_pstate();
978 ret = (value) & 255; 977 ret = (value) & 255;
979 if (ret <= nont) 978 if (ret <= nont)
@@ -1002,7 +1001,7 @@ static int knl_get_turbo_pstate(void)
1002 u64 value; 1001 u64 value;
1003 int nont, ret; 1002 int nont, ret;
1004 1003
1005 rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value); 1004 rdmsrl(MSR_TURBO_RATIO_LIMIT, value);
1006 nont = core_get_max_pstate(); 1005 nont = core_get_max_pstate();
1007 ret = (((value) >> 8) & 0xFF); 1006 ret = (((value) >> 8) & 0xFF);
1008 if (ret <= nont) 1007 if (ret <= nont)
@@ -1092,6 +1091,26 @@ static struct cpu_defaults knl_params = {
1092 }, 1091 },
1093}; 1092};
1094 1093
1094static struct cpu_defaults bxt_params = {
1095 .pid_policy = {
1096 .sample_rate_ms = 10,
1097 .deadband = 0,
1098 .setpoint = 60,
1099 .p_gain_pct = 14,
1100 .d_gain_pct = 0,
1101 .i_gain_pct = 4,
1102 },
1103 .funcs = {
1104 .get_max = core_get_max_pstate,
1105 .get_max_physical = core_get_max_pstate_physical,
1106 .get_min = core_get_min_pstate,
1107 .get_turbo = core_get_turbo_pstate,
1108 .get_scaling = core_get_scaling,
1109 .get_val = core_get_val,
1110 .get_target_pstate = get_target_pstate_use_cpu_load,
1111 },
1112};
1113
1095static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) 1114static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
1096{ 1115{
1097 int max_perf = cpu->pstate.turbo_pstate; 1116 int max_perf = cpu->pstate.turbo_pstate;
@@ -1114,17 +1133,12 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
1114 *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf); 1133 *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
1115} 1134}
1116 1135
1117static inline void intel_pstate_record_pstate(struct cpudata *cpu, int pstate)
1118{
1119 trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
1120 cpu->pstate.current_pstate = pstate;
1121}
1122
1123static void intel_pstate_set_min_pstate(struct cpudata *cpu) 1136static void intel_pstate_set_min_pstate(struct cpudata *cpu)
1124{ 1137{
1125 int pstate = cpu->pstate.min_pstate; 1138 int pstate = cpu->pstate.min_pstate;
1126 1139
1127 intel_pstate_record_pstate(cpu, pstate); 1140 trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
1141 cpu->pstate.current_pstate = pstate;
1128 /* 1142 /*
1129 * Generally, there is no guarantee that this code will always run on 1143 * Generally, there is no guarantee that this code will always run on
1130 * the CPU being updated, so force the register update to run on the 1144 * the CPU being updated, so force the register update to run on the
@@ -1284,10 +1298,11 @@ static inline void intel_pstate_update_pstate(struct cpudata *cpu, int pstate)
1284 1298
1285 intel_pstate_get_min_max(cpu, &min_perf, &max_perf); 1299 intel_pstate_get_min_max(cpu, &min_perf, &max_perf);
1286 pstate = clamp_t(int, pstate, min_perf, max_perf); 1300 pstate = clamp_t(int, pstate, min_perf, max_perf);
1301 trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
1287 if (pstate == cpu->pstate.current_pstate) 1302 if (pstate == cpu->pstate.current_pstate)
1288 return; 1303 return;
1289 1304
1290 intel_pstate_record_pstate(cpu, pstate); 1305 cpu->pstate.current_pstate = pstate;
1291 wrmsrl(MSR_IA32_PERF_CTL, pstate_funcs.get_val(cpu, pstate)); 1306 wrmsrl(MSR_IA32_PERF_CTL, pstate_funcs.get_val(cpu, pstate));
1292} 1307}
1293 1308
@@ -1352,11 +1367,12 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
1352 ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, core_params), 1367 ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, core_params),
1353 ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_params), 1368 ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_params),
1354 ICPU(INTEL_FAM6_XEON_PHI_KNL, knl_params), 1369 ICPU(INTEL_FAM6_XEON_PHI_KNL, knl_params),
1370 ICPU(INTEL_FAM6_ATOM_GOLDMONT, bxt_params),
1355 {} 1371 {}
1356}; 1372};
1357MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); 1373MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
1358 1374
1359static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] = { 1375static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = {
1360 ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_params), 1376 ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_params),
1361 {} 1377 {}
1362}; 1378};
@@ -1576,12 +1592,12 @@ static struct cpufreq_driver intel_pstate_driver = {
1576 .name = "intel_pstate", 1592 .name = "intel_pstate",
1577}; 1593};
1578 1594
1579static int __initdata no_load; 1595static int no_load __initdata;
1580static int __initdata no_hwp; 1596static int no_hwp __initdata;
1581static int __initdata hwp_only; 1597static int hwp_only __initdata;
1582static unsigned int force_load; 1598static unsigned int force_load __initdata;
1583 1599
1584static int intel_pstate_msrs_not_valid(void) 1600static int __init intel_pstate_msrs_not_valid(void)
1585{ 1601{
1586 if (!pstate_funcs.get_max() || 1602 if (!pstate_funcs.get_max() ||
1587 !pstate_funcs.get_min() || 1603 !pstate_funcs.get_min() ||
@@ -1591,7 +1607,7 @@ static int intel_pstate_msrs_not_valid(void)
1591 return 0; 1607 return 0;
1592} 1608}
1593 1609
1594static void copy_pid_params(struct pstate_adjust_policy *policy) 1610static void __init copy_pid_params(struct pstate_adjust_policy *policy)
1595{ 1611{
1596 pid_params.sample_rate_ms = policy->sample_rate_ms; 1612 pid_params.sample_rate_ms = policy->sample_rate_ms;
1597 pid_params.sample_rate_ns = pid_params.sample_rate_ms * NSEC_PER_MSEC; 1613 pid_params.sample_rate_ns = pid_params.sample_rate_ms * NSEC_PER_MSEC;
@@ -1602,7 +1618,7 @@ static void copy_pid_params(struct pstate_adjust_policy *policy)
1602 pid_params.setpoint = policy->setpoint; 1618 pid_params.setpoint = policy->setpoint;
1603} 1619}
1604 1620
1605static void copy_cpu_funcs(struct pstate_funcs *funcs) 1621static void __init copy_cpu_funcs(struct pstate_funcs *funcs)
1606{ 1622{
1607 pstate_funcs.get_max = funcs->get_max; 1623 pstate_funcs.get_max = funcs->get_max;
1608 pstate_funcs.get_max_physical = funcs->get_max_physical; 1624 pstate_funcs.get_max_physical = funcs->get_max_physical;
@@ -1617,7 +1633,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs)
1617 1633
1618#ifdef CONFIG_ACPI 1634#ifdef CONFIG_ACPI
1619 1635
1620static bool intel_pstate_no_acpi_pss(void) 1636static bool __init intel_pstate_no_acpi_pss(void)
1621{ 1637{
1622 int i; 1638 int i;
1623 1639
@@ -1646,7 +1662,7 @@ static bool intel_pstate_no_acpi_pss(void)
1646 return true; 1662 return true;
1647} 1663}
1648 1664
1649static bool intel_pstate_has_acpi_ppc(void) 1665static bool __init intel_pstate_has_acpi_ppc(void)
1650{ 1666{
1651 int i; 1667 int i;
1652 1668
@@ -1674,7 +1690,7 @@ struct hw_vendor_info {
1674}; 1690};
1675 1691
1676/* Hardware vendor-specific info that has its own power management modes */ 1692/* Hardware vendor-specific info that has its own power management modes */
1677static struct hw_vendor_info vendor_info[] = { 1693static struct hw_vendor_info vendor_info[] __initdata = {
1678 {1, "HP ", "ProLiant", PSS}, 1694 {1, "HP ", "ProLiant", PSS},
1679 {1, "ORACLE", "X4-2 ", PPC}, 1695 {1, "ORACLE", "X4-2 ", PPC},
1680 {1, "ORACLE", "X4-2L ", PPC}, 1696 {1, "ORACLE", "X4-2L ", PPC},
@@ -1693,7 +1709,7 @@ static struct hw_vendor_info vendor_info[] = {
1693 {0, "", ""}, 1709 {0, "", ""},
1694}; 1710};
1695 1711
1696static bool intel_pstate_platform_pwr_mgmt_exists(void) 1712static bool __init intel_pstate_platform_pwr_mgmt_exists(void)
1697{ 1713{
1698 struct acpi_table_header hdr; 1714 struct acpi_table_header hdr;
1699 struct hw_vendor_info *v_info; 1715 struct hw_vendor_info *v_info;
diff --git a/drivers/cpufreq/mvebu-cpufreq.c b/drivers/cpufreq/mvebu-cpufreq.c
index e920889b9ac2..ed915ee85dd9 100644
--- a/drivers/cpufreq/mvebu-cpufreq.c
+++ b/drivers/cpufreq/mvebu-cpufreq.c
@@ -70,7 +70,7 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
70 continue; 70 continue;
71 } 71 }
72 72
73 clk = clk_get(cpu_dev, 0); 73 clk = clk_get(cpu_dev, NULL);
74 if (IS_ERR(clk)) { 74 if (IS_ERR(clk)) {
75 pr_err("Cannot get clock for CPU %d\n", cpu); 75 pr_err("Cannot get clock for CPU %d\n", cpu);
76 return PTR_ERR(clk); 76 return PTR_ERR(clk);
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c
index a7ecb9a84c15..3f0ce2ae35ee 100644
--- a/drivers/cpufreq/pcc-cpufreq.c
+++ b/drivers/cpufreq/pcc-cpufreq.c
@@ -555,8 +555,6 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
555 policy->min = policy->cpuinfo.min_freq = 555 policy->min = policy->cpuinfo.min_freq =
556 ioread32(&pcch_hdr->minimum_frequency) * 1000; 556 ioread32(&pcch_hdr->minimum_frequency) * 1000;
557 557
558 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
559
560 pr_debug("init: policy->max is %d, policy->min is %d\n", 558 pr_debug("init: policy->max is %d, policy->min is %d\n",
561 policy->max, policy->min); 559 policy->max, policy->min);
562out: 560out:
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 6bd715b7f11c..87796e0864e9 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -64,12 +64,14 @@
64/** 64/**
65 * struct global_pstate_info - Per policy data structure to maintain history of 65 * struct global_pstate_info - Per policy data structure to maintain history of
66 * global pstates 66 * global pstates
67 * @highest_lpstate: The local pstate from which we are ramping down 67 * @highest_lpstate_idx: The local pstate index from which we are
68 * ramping down
68 * @elapsed_time: Time in ms spent in ramping down from 69 * @elapsed_time: Time in ms spent in ramping down from
69 * highest_lpstate 70 * highest_lpstate_idx
70 * @last_sampled_time: Time from boot in ms when global pstates were 71 * @last_sampled_time: Time from boot in ms when global pstates were
71 * last set 72 * last set
72 * @last_lpstate,last_gpstate: Last set values for local and global pstates 73 * @last_lpstate_idx, Last set value of local pstate and global
74 * last_gpstate_idx pstate in terms of cpufreq table index
73 * @timer: Is used for ramping down if cpu goes idle for 75 * @timer: Is used for ramping down if cpu goes idle for
74 * a long time with global pstate held high 76 * a long time with global pstate held high
75 * @gpstate_lock: A spinlock to maintain synchronization between 77 * @gpstate_lock: A spinlock to maintain synchronization between
@@ -77,11 +79,11 @@
77 * governer's target_index calls 79 * governer's target_index calls
78 */ 80 */
79struct global_pstate_info { 81struct global_pstate_info {
80 int highest_lpstate; 82 int highest_lpstate_idx;
81 unsigned int elapsed_time; 83 unsigned int elapsed_time;
82 unsigned int last_sampled_time; 84 unsigned int last_sampled_time;
83 int last_lpstate; 85 int last_lpstate_idx;
84 int last_gpstate; 86 int last_gpstate_idx;
85 spinlock_t gpstate_lock; 87 spinlock_t gpstate_lock;
86 struct timer_list timer; 88 struct timer_list timer;
87}; 89};
@@ -124,29 +126,47 @@ static int nr_chips;
124static DEFINE_PER_CPU(struct chip *, chip_info); 126static DEFINE_PER_CPU(struct chip *, chip_info);
125 127
126/* 128/*
127 * Note: The set of pstates consists of contiguous integers, the 129 * Note:
128 * smallest of which is indicated by powernv_pstate_info.min, the 130 * The set of pstates consists of contiguous integers.
129 * largest of which is indicated by powernv_pstate_info.max. 131 * powernv_pstate_info stores the index of the frequency table for
132 * max, min and nominal frequencies. It also stores number of
133 * available frequencies.
130 * 134 *
131 * The nominal pstate is the highest non-turbo pstate in this 135 * powernv_pstate_info.nominal indicates the index to the highest
132 * platform. This is indicated by powernv_pstate_info.nominal. 136 * non-turbo frequency.
133 */ 137 */
134static struct powernv_pstate_info { 138static struct powernv_pstate_info {
135 int min; 139 unsigned int min;
136 int max; 140 unsigned int max;
137 int nominal; 141 unsigned int nominal;
138 int nr_pstates; 142 unsigned int nr_pstates;
139} powernv_pstate_info; 143} powernv_pstate_info;
140 144
145/* Use following macros for conversions between pstate_id and index */
146static inline int idx_to_pstate(unsigned int i)
147{
148 return powernv_freqs[i].driver_data;
149}
150
151static inline unsigned int pstate_to_idx(int pstate)
152{
153 /*
154 * abs() is deliberately used so that is works with
155 * both monotonically increasing and decreasing
156 * pstate values
157 */
158 return abs(pstate - idx_to_pstate(powernv_pstate_info.max));
159}
160
141static inline void reset_gpstates(struct cpufreq_policy *policy) 161static inline void reset_gpstates(struct cpufreq_policy *policy)
142{ 162{
143 struct global_pstate_info *gpstates = policy->driver_data; 163 struct global_pstate_info *gpstates = policy->driver_data;
144 164
145 gpstates->highest_lpstate = 0; 165 gpstates->highest_lpstate_idx = 0;
146 gpstates->elapsed_time = 0; 166 gpstates->elapsed_time = 0;
147 gpstates->last_sampled_time = 0; 167 gpstates->last_sampled_time = 0;
148 gpstates->last_lpstate = 0; 168 gpstates->last_lpstate_idx = 0;
149 gpstates->last_gpstate = 0; 169 gpstates->last_gpstate_idx = 0;
150} 170}
151 171
152/* 172/*
@@ -156,9 +176,10 @@ static inline void reset_gpstates(struct cpufreq_policy *policy)
156static int init_powernv_pstates(void) 176static int init_powernv_pstates(void)
157{ 177{
158 struct device_node *power_mgt; 178 struct device_node *power_mgt;
159 int i, pstate_min, pstate_max, pstate_nominal, nr_pstates = 0; 179 int i, nr_pstates = 0;
160 const __be32 *pstate_ids, *pstate_freqs; 180 const __be32 *pstate_ids, *pstate_freqs;
161 u32 len_ids, len_freqs; 181 u32 len_ids, len_freqs;
182 u32 pstate_min, pstate_max, pstate_nominal;
162 183
163 power_mgt = of_find_node_by_path("/ibm,opal/power-mgt"); 184 power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
164 if (!power_mgt) { 185 if (!power_mgt) {
@@ -208,6 +229,7 @@ static int init_powernv_pstates(void)
208 return -ENODEV; 229 return -ENODEV;
209 } 230 }
210 231
232 powernv_pstate_info.nr_pstates = nr_pstates;
211 pr_debug("NR PStates %d\n", nr_pstates); 233 pr_debug("NR PStates %d\n", nr_pstates);
212 for (i = 0; i < nr_pstates; i++) { 234 for (i = 0; i < nr_pstates; i++) {
213 u32 id = be32_to_cpu(pstate_ids[i]); 235 u32 id = be32_to_cpu(pstate_ids[i]);
@@ -216,15 +238,17 @@ static int init_powernv_pstates(void)
216 pr_debug("PState id %d freq %d MHz\n", id, freq); 238 pr_debug("PState id %d freq %d MHz\n", id, freq);
217 powernv_freqs[i].frequency = freq * 1000; /* kHz */ 239 powernv_freqs[i].frequency = freq * 1000; /* kHz */
218 powernv_freqs[i].driver_data = id; 240 powernv_freqs[i].driver_data = id;
241
242 if (id == pstate_max)
243 powernv_pstate_info.max = i;
244 else if (id == pstate_nominal)
245 powernv_pstate_info.nominal = i;
246 else if (id == pstate_min)
247 powernv_pstate_info.min = i;
219 } 248 }
249
220 /* End of list marker entry */ 250 /* End of list marker entry */
221 powernv_freqs[i].frequency = CPUFREQ_TABLE_END; 251 powernv_freqs[i].frequency = CPUFREQ_TABLE_END;
222
223 powernv_pstate_info.min = pstate_min;
224 powernv_pstate_info.max = pstate_max;
225 powernv_pstate_info.nominal = pstate_nominal;
226 powernv_pstate_info.nr_pstates = nr_pstates;
227
228 return 0; 252 return 0;
229} 253}
230 254
@@ -233,12 +257,12 @@ static unsigned int pstate_id_to_freq(int pstate_id)
233{ 257{
234 int i; 258 int i;
235 259
236 i = powernv_pstate_info.max - pstate_id; 260 i = pstate_to_idx(pstate_id);
237 if (i >= powernv_pstate_info.nr_pstates || i < 0) { 261 if (i >= powernv_pstate_info.nr_pstates || i < 0) {
238 pr_warn("PState id %d outside of PState table, " 262 pr_warn("PState id %d outside of PState table, "
239 "reporting nominal id %d instead\n", 263 "reporting nominal id %d instead\n",
240 pstate_id, powernv_pstate_info.nominal); 264 pstate_id, idx_to_pstate(powernv_pstate_info.nominal));
241 i = powernv_pstate_info.max - powernv_pstate_info.nominal; 265 i = powernv_pstate_info.nominal;
242 } 266 }
243 267
244 return powernv_freqs[i].frequency; 268 return powernv_freqs[i].frequency;
@@ -252,7 +276,7 @@ static ssize_t cpuinfo_nominal_freq_show(struct cpufreq_policy *policy,
252 char *buf) 276 char *buf)
253{ 277{
254 return sprintf(buf, "%u\n", 278 return sprintf(buf, "%u\n",
255 pstate_id_to_freq(powernv_pstate_info.nominal)); 279 powernv_freqs[powernv_pstate_info.nominal].frequency);
256} 280}
257 281
258struct freq_attr cpufreq_freq_attr_cpuinfo_nominal_freq = 282struct freq_attr cpufreq_freq_attr_cpuinfo_nominal_freq =
@@ -426,7 +450,7 @@ static void set_pstate(void *data)
426 */ 450 */
427static inline unsigned int get_nominal_index(void) 451static inline unsigned int get_nominal_index(void)
428{ 452{
429 return powernv_pstate_info.max - powernv_pstate_info.nominal; 453 return powernv_pstate_info.nominal;
430} 454}
431 455
432static void powernv_cpufreq_throttle_check(void *data) 456static void powernv_cpufreq_throttle_check(void *data)
@@ -435,20 +459,22 @@ static void powernv_cpufreq_throttle_check(void *data)
435 unsigned int cpu = smp_processor_id(); 459 unsigned int cpu = smp_processor_id();
436 unsigned long pmsr; 460 unsigned long pmsr;
437 int pmsr_pmax; 461 int pmsr_pmax;
462 unsigned int pmsr_pmax_idx;
438 463
439 pmsr = get_pmspr(SPRN_PMSR); 464 pmsr = get_pmspr(SPRN_PMSR);
440 chip = this_cpu_read(chip_info); 465 chip = this_cpu_read(chip_info);
441 466
442 /* Check for Pmax Capping */ 467 /* Check for Pmax Capping */
443 pmsr_pmax = (s8)PMSR_MAX(pmsr); 468 pmsr_pmax = (s8)PMSR_MAX(pmsr);
444 if (pmsr_pmax != powernv_pstate_info.max) { 469 pmsr_pmax_idx = pstate_to_idx(pmsr_pmax);
470 if (pmsr_pmax_idx != powernv_pstate_info.max) {
445 if (chip->throttled) 471 if (chip->throttled)
446 goto next; 472 goto next;
447 chip->throttled = true; 473 chip->throttled = true;
448 if (pmsr_pmax < powernv_pstate_info.nominal) { 474 if (pmsr_pmax_idx > powernv_pstate_info.nominal) {
449 pr_warn_once("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n", 475 pr_warn_once("CPU %d on Chip %u has Pmax(%d) reduced below nominal frequency(%d)\n",
450 cpu, chip->id, pmsr_pmax, 476 cpu, chip->id, pmsr_pmax,
451 powernv_pstate_info.nominal); 477 idx_to_pstate(powernv_pstate_info.nominal));
452 chip->throttle_sub_turbo++; 478 chip->throttle_sub_turbo++;
453 } else { 479 } else {
454 chip->throttle_turbo++; 480 chip->throttle_turbo++;
@@ -484,34 +510,35 @@ next:
484 510
485/** 511/**
486 * calc_global_pstate - Calculate global pstate 512 * calc_global_pstate - Calculate global pstate
487 * @elapsed_time: Elapsed time in milliseconds 513 * @elapsed_time: Elapsed time in milliseconds
488 * @local_pstate: New local pstate 514 * @local_pstate_idx: New local pstate
489 * @highest_lpstate: pstate from which its ramping down 515 * @highest_lpstate_idx: pstate from which its ramping down
490 * 516 *
491 * Finds the appropriate global pstate based on the pstate from which its 517 * Finds the appropriate global pstate based on the pstate from which its
492 * ramping down and the time elapsed in ramping down. It follows a quadratic 518 * ramping down and the time elapsed in ramping down. It follows a quadratic
493 * equation which ensures that it reaches ramping down to pmin in 5sec. 519 * equation which ensures that it reaches ramping down to pmin in 5sec.
494 */ 520 */
495static inline int calc_global_pstate(unsigned int elapsed_time, 521static inline int calc_global_pstate(unsigned int elapsed_time,
496 int highest_lpstate, int local_pstate) 522 int highest_lpstate_idx,
523 int local_pstate_idx)
497{ 524{
498 int pstate_diff; 525 int index_diff;
499 526
500 /* 527 /*
501 * Using ramp_down_percent we get the percentage of rampdown 528 * Using ramp_down_percent we get the percentage of rampdown
502 * that we are expecting to be dropping. Difference between 529 * that we are expecting to be dropping. Difference between
503 * highest_lpstate and powernv_pstate_info.min will give a absolute 530 * highest_lpstate_idx and powernv_pstate_info.min will give a absolute
504 * number of how many pstates we will drop eventually by the end of 531 * number of how many pstates we will drop eventually by the end of
505 * 5 seconds, then just scale it get the number pstates to be dropped. 532 * 5 seconds, then just scale it get the number pstates to be dropped.
506 */ 533 */
507 pstate_diff = ((int)ramp_down_percent(elapsed_time) * 534 index_diff = ((int)ramp_down_percent(elapsed_time) *
508 (highest_lpstate - powernv_pstate_info.min)) / 100; 535 (powernv_pstate_info.min - highest_lpstate_idx)) / 100;
509 536
510 /* Ensure that global pstate is >= to local pstate */ 537 /* Ensure that global pstate is >= to local pstate */
511 if (highest_lpstate - pstate_diff < local_pstate) 538 if (highest_lpstate_idx + index_diff >= local_pstate_idx)
512 return local_pstate; 539 return local_pstate_idx;
513 else 540 else
514 return highest_lpstate - pstate_diff; 541 return highest_lpstate_idx + index_diff;
515} 542}
516 543
517static inline void queue_gpstate_timer(struct global_pstate_info *gpstates) 544static inline void queue_gpstate_timer(struct global_pstate_info *gpstates)
@@ -546,7 +573,7 @@ void gpstate_timer_handler(unsigned long data)
546{ 573{
547 struct cpufreq_policy *policy = (struct cpufreq_policy *)data; 574 struct cpufreq_policy *policy = (struct cpufreq_policy *)data;
548 struct global_pstate_info *gpstates = policy->driver_data; 575 struct global_pstate_info *gpstates = policy->driver_data;
549 int gpstate_id; 576 int gpstate_idx;
550 unsigned int time_diff = jiffies_to_msecs(jiffies) 577 unsigned int time_diff = jiffies_to_msecs(jiffies)
551 - gpstates->last_sampled_time; 578 - gpstates->last_sampled_time;
552 struct powernv_smp_call_data freq_data; 579 struct powernv_smp_call_data freq_data;
@@ -556,29 +583,29 @@ void gpstate_timer_handler(unsigned long data)
556 583
557 gpstates->last_sampled_time += time_diff; 584 gpstates->last_sampled_time += time_diff;
558 gpstates->elapsed_time += time_diff; 585 gpstates->elapsed_time += time_diff;
559 freq_data.pstate_id = gpstates->last_lpstate; 586 freq_data.pstate_id = idx_to_pstate(gpstates->last_lpstate_idx);
560 587
561 if ((gpstates->last_gpstate == freq_data.pstate_id) || 588 if ((gpstates->last_gpstate_idx == gpstates->last_lpstate_idx) ||
562 (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME)) { 589 (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME)) {
563 gpstate_id = freq_data.pstate_id; 590 gpstate_idx = pstate_to_idx(freq_data.pstate_id);
564 reset_gpstates(policy); 591 reset_gpstates(policy);
565 gpstates->highest_lpstate = freq_data.pstate_id; 592 gpstates->highest_lpstate_idx = gpstate_idx;
566 } else { 593 } else {
567 gpstate_id = calc_global_pstate(gpstates->elapsed_time, 594 gpstate_idx = calc_global_pstate(gpstates->elapsed_time,
568 gpstates->highest_lpstate, 595 gpstates->highest_lpstate_idx,
569 freq_data.pstate_id); 596 freq_data.pstate_id);
570 } 597 }
571 598
572 /* 599 /*
573 * If local pstate is equal to global pstate, rampdown is over 600 * If local pstate is equal to global pstate, rampdown is over
574 * So timer is not required to be queued. 601 * So timer is not required to be queued.
575 */ 602 */
576 if (gpstate_id != freq_data.pstate_id) 603 if (gpstate_idx != gpstates->last_lpstate_idx)
577 queue_gpstate_timer(gpstates); 604 queue_gpstate_timer(gpstates);
578 605
579 freq_data.gpstate_id = gpstate_id; 606 freq_data.gpstate_id = idx_to_pstate(gpstate_idx);
580 gpstates->last_gpstate = freq_data.gpstate_id; 607 gpstates->last_gpstate_idx = pstate_to_idx(freq_data.gpstate_id);
581 gpstates->last_lpstate = freq_data.pstate_id; 608 gpstates->last_lpstate_idx = pstate_to_idx(freq_data.pstate_id);
582 609
583 spin_unlock(&gpstates->gpstate_lock); 610 spin_unlock(&gpstates->gpstate_lock);
584 611
@@ -595,7 +622,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
595 unsigned int new_index) 622 unsigned int new_index)
596{ 623{
597 struct powernv_smp_call_data freq_data; 624 struct powernv_smp_call_data freq_data;
598 unsigned int cur_msec, gpstate_id; 625 unsigned int cur_msec, gpstate_idx;
599 struct global_pstate_info *gpstates = policy->driver_data; 626 struct global_pstate_info *gpstates = policy->driver_data;
600 627
601 if (unlikely(rebooting) && new_index != get_nominal_index()) 628 if (unlikely(rebooting) && new_index != get_nominal_index())
@@ -607,15 +634,15 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
607 cur_msec = jiffies_to_msecs(get_jiffies_64()); 634 cur_msec = jiffies_to_msecs(get_jiffies_64());
608 635
609 spin_lock(&gpstates->gpstate_lock); 636 spin_lock(&gpstates->gpstate_lock);
610 freq_data.pstate_id = powernv_freqs[new_index].driver_data; 637 freq_data.pstate_id = idx_to_pstate(new_index);
611 638
612 if (!gpstates->last_sampled_time) { 639 if (!gpstates->last_sampled_time) {
613 gpstate_id = freq_data.pstate_id; 640 gpstate_idx = new_index;
614 gpstates->highest_lpstate = freq_data.pstate_id; 641 gpstates->highest_lpstate_idx = new_index;
615 goto gpstates_done; 642 goto gpstates_done;
616 } 643 }
617 644
618 if (gpstates->last_gpstate > freq_data.pstate_id) { 645 if (gpstates->last_gpstate_idx < new_index) {
619 gpstates->elapsed_time += cur_msec - 646 gpstates->elapsed_time += cur_msec -
620 gpstates->last_sampled_time; 647 gpstates->last_sampled_time;
621 648
@@ -626,34 +653,34 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
626 */ 653 */
627 if (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME) { 654 if (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME) {
628 reset_gpstates(policy); 655 reset_gpstates(policy);
629 gpstates->highest_lpstate = freq_data.pstate_id; 656 gpstates->highest_lpstate_idx = new_index;
630 gpstate_id = freq_data.pstate_id; 657 gpstate_idx = new_index;
631 } else { 658 } else {
632 /* Elaspsed_time is less than 5 seconds, continue to rampdown */ 659 /* Elaspsed_time is less than 5 seconds, continue to rampdown */
633 gpstate_id = calc_global_pstate(gpstates->elapsed_time, 660 gpstate_idx = calc_global_pstate(gpstates->elapsed_time,
634 gpstates->highest_lpstate, 661 gpstates->highest_lpstate_idx,
635 freq_data.pstate_id); 662 new_index);
636 } 663 }
637 } else { 664 } else {
638 reset_gpstates(policy); 665 reset_gpstates(policy);
639 gpstates->highest_lpstate = freq_data.pstate_id; 666 gpstates->highest_lpstate_idx = new_index;
640 gpstate_id = freq_data.pstate_id; 667 gpstate_idx = new_index;
641 } 668 }
642 669
643 /* 670 /*
644 * If local pstate is equal to global pstate, rampdown is over 671 * If local pstate is equal to global pstate, rampdown is over
645 * So timer is not required to be queued. 672 * So timer is not required to be queued.
646 */ 673 */
647 if (gpstate_id != freq_data.pstate_id) 674 if (gpstate_idx != new_index)
648 queue_gpstate_timer(gpstates); 675 queue_gpstate_timer(gpstates);
649 else 676 else
650 del_timer_sync(&gpstates->timer); 677 del_timer_sync(&gpstates->timer);
651 678
652gpstates_done: 679gpstates_done:
653 freq_data.gpstate_id = gpstate_id; 680 freq_data.gpstate_id = idx_to_pstate(gpstate_idx);
654 gpstates->last_sampled_time = cur_msec; 681 gpstates->last_sampled_time = cur_msec;
655 gpstates->last_gpstate = freq_data.gpstate_id; 682 gpstates->last_gpstate_idx = gpstate_idx;
656 gpstates->last_lpstate = freq_data.pstate_id; 683 gpstates->last_lpstate_idx = new_index;
657 684
658 spin_unlock(&gpstates->gpstate_lock); 685 spin_unlock(&gpstates->gpstate_lock);
659 686
@@ -759,9 +786,7 @@ void powernv_cpufreq_work_fn(struct work_struct *work)
759 struct cpufreq_policy policy; 786 struct cpufreq_policy policy;
760 787
761 cpufreq_get_policy(&policy, cpu); 788 cpufreq_get_policy(&policy, cpu);
762 cpufreq_frequency_table_target(&policy, policy.freq_table, 789 index = cpufreq_table_find_index_c(&policy, policy.cur);
763 policy.cur,
764 CPUFREQ_RELATION_C, &index);
765 powernv_cpufreq_target_index(&policy, index); 790 powernv_cpufreq_target_index(&policy, index);
766 cpumask_andnot(&mask, &mask, policy.cpus); 791 cpumask_andnot(&mask, &mask, policy.cpus);
767 } 792 }
@@ -847,8 +872,8 @@ static void powernv_cpufreq_stop_cpu(struct cpufreq_policy *policy)
847 struct powernv_smp_call_data freq_data; 872 struct powernv_smp_call_data freq_data;
848 struct global_pstate_info *gpstates = policy->driver_data; 873 struct global_pstate_info *gpstates = policy->driver_data;
849 874
850 freq_data.pstate_id = powernv_pstate_info.min; 875 freq_data.pstate_id = idx_to_pstate(powernv_pstate_info.min);
851 freq_data.gpstate_id = powernv_pstate_info.min; 876 freq_data.gpstate_id = idx_to_pstate(powernv_pstate_info.min);
852 smp_call_function_single(policy->cpu, set_pstate, &freq_data, 1); 877 smp_call_function_single(policy->cpu, set_pstate, &freq_data, 1);
853 del_timer_sync(&gpstates->timer); 878 del_timer_sync(&gpstates->timer);
854} 879}
diff --git a/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c b/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c
index 7c4cd5c634f2..dc112481a408 100644
--- a/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c
+++ b/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c
@@ -94,7 +94,7 @@ static int pmi_notifier(struct notifier_block *nb,
94 unsigned long event, void *data) 94 unsigned long event, void *data)
95{ 95{
96 struct cpufreq_policy *policy = data; 96 struct cpufreq_policy *policy = data;
97 struct cpufreq_frequency_table *cbe_freqs; 97 struct cpufreq_frequency_table *cbe_freqs = policy->freq_table;
98 u8 node; 98 u8 node;
99 99
100 /* Should this really be called for CPUFREQ_ADJUST and CPUFREQ_NOTIFY 100 /* Should this really be called for CPUFREQ_ADJUST and CPUFREQ_NOTIFY
@@ -103,7 +103,6 @@ static int pmi_notifier(struct notifier_block *nb,
103 if (event == CPUFREQ_START) 103 if (event == CPUFREQ_START)
104 return 0; 104 return 0;
105 105
106 cbe_freqs = cpufreq_frequency_get_table(policy->cpu);
107 node = cbe_cpu_to_node(policy->cpu); 106 node = cbe_cpu_to_node(policy->cpu);
108 107
109 pr_debug("got notified, event=%lu, node=%u\n", event, node); 108 pr_debug("got notified, event=%lu, node=%u\n", event, node);
diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c
index ae8eaed77b70..7b596fa38ad2 100644
--- a/drivers/cpufreq/s3c24xx-cpufreq.c
+++ b/drivers/cpufreq/s3c24xx-cpufreq.c
@@ -293,12 +293,8 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
293 __func__, policy, target_freq, relation); 293 __func__, policy, target_freq, relation);
294 294
295 if (ftab) { 295 if (ftab) {
296 if (cpufreq_frequency_table_target(policy, ftab, 296 index = cpufreq_frequency_table_target(policy, target_freq,
297 target_freq, relation, 297 relation);
298 &index)) {
299 s3c_freq_dbg("%s: table failed\n", __func__);
300 return -EINVAL;
301 }
302 298
303 s3c_freq_dbg("%s: adjust %d to entry %d (%u)\n", __func__, 299 s3c_freq_dbg("%s: adjust %d to entry %d (%u)\n", __func__,
304 target_freq, index, ftab[index].frequency); 300 target_freq, index, ftab[index].frequency);
@@ -315,7 +311,6 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
315 pll = NULL; 311 pll = NULL;
316 } else { 312 } else {
317 struct cpufreq_policy tmp_policy; 313 struct cpufreq_policy tmp_policy;
318 int ret;
319 314
320 /* we keep the cpu pll table in Hz, to ensure we get an 315 /* we keep the cpu pll table in Hz, to ensure we get an
321 * accurate value for the PLL output. */ 316 * accurate value for the PLL output. */
@@ -323,20 +318,14 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
323 tmp_policy.min = policy->min * 1000; 318 tmp_policy.min = policy->min * 1000;
324 tmp_policy.max = policy->max * 1000; 319 tmp_policy.max = policy->max * 1000;
325 tmp_policy.cpu = policy->cpu; 320 tmp_policy.cpu = policy->cpu;
321 tmp_policy.freq_table = pll_reg;
326 322
327 /* cpufreq_frequency_table_target uses a pointer to 'index' 323 /* cpufreq_frequency_table_target returns the index
328 * which is the number of the table entry, not the value of 324 * of the table entry, not the value of
329 * the table entry's index field. */ 325 * the table entry's index field. */
330 326
331 ret = cpufreq_frequency_table_target(&tmp_policy, pll_reg, 327 index = cpufreq_frequency_table_target(&tmp_policy, target_freq,
332 target_freq, relation, 328 relation);
333 &index);
334
335 if (ret < 0) {
336 pr_err("%s: no PLL available\n", __func__);
337 goto err_notpossible;
338 }
339
340 pll = pll_reg + index; 329 pll = pll_reg + index;
341 330
342 s3c_freq_dbg("%s: target %u => %u\n", 331 s3c_freq_dbg("%s: target %u => %u\n",
@@ -346,10 +335,6 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
346 } 335 }
347 336
348 return s3c_cpufreq_settarget(policy, target_freq, pll); 337 return s3c_cpufreq_settarget(policy, target_freq, pll);
349
350 err_notpossible:
351 pr_err("no compatible settings for %d\n", target_freq);
352 return -EINVAL;
353} 338}
354 339
355struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name) 340struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name)
@@ -571,11 +556,7 @@ static int s3c_cpufreq_build_freq(void)
571{ 556{
572 int size, ret; 557 int size, ret;
573 558
574 if (!cpu_cur.info->calc_freqtable)
575 return -EINVAL;
576
577 kfree(ftab); 559 kfree(ftab);
578 ftab = NULL;
579 560
580 size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0); 561 size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0);
581 size++; 562 size++;
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index 06d85917b6d5..9e07588ea9f5 100644
--- a/drivers/cpufreq/s5pv210-cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -246,12 +246,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
246 new_freq = s5pv210_freq_table[index].frequency; 246 new_freq = s5pv210_freq_table[index].frequency;
247 247
248 /* Finding current running level index */ 248 /* Finding current running level index */
249 if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, 249 priv_index = cpufreq_table_find_index_h(policy, old_freq);
250 old_freq, CPUFREQ_RELATION_H,
251 &priv_index)) {
252 ret = -EINVAL;
253 goto exit;
254 }
255 250
256 arm_volt = dvs_conf[index].arm_volt; 251 arm_volt = dvs_conf[index].arm_volt;
257 int_volt = dvs_conf[index].int_volt; 252 int_volt = dvs_conf[index].int_volt;
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 78dac0e9da11..a5be56ec57f2 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -75,7 +75,7 @@ config DEVFREQ_GOV_PASSIVE
75comment "DEVFREQ Drivers" 75comment "DEVFREQ Drivers"
76 76
77config ARM_EXYNOS_BUS_DEVFREQ 77config ARM_EXYNOS_BUS_DEVFREQ
78 bool "ARM EXYNOS Generic Memory Bus DEVFREQ Driver" 78 tristate "ARM EXYNOS Generic Memory Bus DEVFREQ Driver"
79 depends on ARCH_EXYNOS 79 depends on ARCH_EXYNOS
80 select DEVFREQ_GOV_SIMPLE_ONDEMAND 80 select DEVFREQ_GOV_SIMPLE_ONDEMAND
81 select DEVFREQ_GOV_PASSIVE 81 select DEVFREQ_GOV_PASSIVE
diff --git a/drivers/devfreq/devfreq-event.c b/drivers/devfreq/devfreq-event.c
index 39b048eda2ce..9aea2c7ecbe6 100644
--- a/drivers/devfreq/devfreq-event.c
+++ b/drivers/devfreq/devfreq-event.c
@@ -15,7 +15,7 @@
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/module.h> 18#include <linux/export.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/list.h> 20#include <linux/list.h>
21#include <linux/of.h> 21#include <linux/of.h>
@@ -481,13 +481,3 @@ static int __init devfreq_event_init(void)
481 return 0; 481 return 0;
482} 482}
483subsys_initcall(devfreq_event_init); 483subsys_initcall(devfreq_event_init);
484
485static void __exit devfreq_event_exit(void)
486{
487 class_destroy(devfreq_event_class);
488}
489module_exit(devfreq_event_exit);
490
491MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
492MODULE_DESCRIPTION("DEVFREQ-Event class support");
493MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index e92418facc92..478006b7764a 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -15,7 +15,7 @@
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/module.h> 18#include <linux/export.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/stat.h> 20#include <linux/stat.h>
21#include <linux/pm_opp.h> 21#include <linux/pm_opp.h>
@@ -707,10 +707,12 @@ struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index)
707 if (devfreq->dev.parent 707 if (devfreq->dev.parent
708 && devfreq->dev.parent->of_node == node) { 708 && devfreq->dev.parent->of_node == node) {
709 mutex_unlock(&devfreq_list_lock); 709 mutex_unlock(&devfreq_list_lock);
710 of_node_put(node);
710 return devfreq; 711 return devfreq;
711 } 712 }
712 } 713 }
713 mutex_unlock(&devfreq_list_lock); 714 mutex_unlock(&devfreq_list_lock);
715 of_node_put(node);
714 716
715 return ERR_PTR(-EPROBE_DEFER); 717 return ERR_PTR(-EPROBE_DEFER);
716} 718}
@@ -1199,13 +1201,6 @@ static int __init devfreq_init(void)
1199} 1201}
1200subsys_initcall(devfreq_init); 1202subsys_initcall(devfreq_init);
1201 1203
1202static void __exit devfreq_exit(void)
1203{
1204 class_destroy(devfreq_class);
1205 destroy_workqueue(devfreq_wq);
1206}
1207module_exit(devfreq_exit);
1208
1209/* 1204/*
1210 * The followings are helper functions for devfreq user device drivers with 1205 * The followings are helper functions for devfreq user device drivers with
1211 * OPP framework. 1206 * OPP framework.
@@ -1471,7 +1466,3 @@ void devm_devfreq_unregister_notifier(struct device *dev,
1471 devm_devfreq_dev_match, devfreq)); 1466 devm_devfreq_dev_match, devfreq));
1472} 1467}
1473EXPORT_SYMBOL(devm_devfreq_unregister_notifier); 1468EXPORT_SYMBOL(devm_devfreq_unregister_notifier);
1474
1475MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
1476MODULE_DESCRIPTION("devfreq class support");
1477MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig
index 1e8b4f469f38..eb6f74a2b6b9 100644
--- a/drivers/devfreq/event/Kconfig
+++ b/drivers/devfreq/event/Kconfig
@@ -14,7 +14,7 @@ menuconfig PM_DEVFREQ_EVENT
14if PM_DEVFREQ_EVENT 14if PM_DEVFREQ_EVENT
15 15
16config DEVFREQ_EVENT_EXYNOS_NOCP 16config DEVFREQ_EVENT_EXYNOS_NOCP
17 bool "EXYNOS NoC (Network On Chip) Probe DEVFREQ event Driver" 17 tristate "EXYNOS NoC (Network On Chip) Probe DEVFREQ event Driver"
18 depends on ARCH_EXYNOS 18 depends on ARCH_EXYNOS
19 select PM_OPP 19 select PM_OPP
20 help 20 help
@@ -22,7 +22,7 @@ config DEVFREQ_EVENT_EXYNOS_NOCP
22 (Network on Chip) Probe counters to measure the bandwidth of AXI bus. 22 (Network on Chip) Probe counters to measure the bandwidth of AXI bus.
23 23
24config DEVFREQ_EVENT_EXYNOS_PPMU 24config DEVFREQ_EVENT_EXYNOS_PPMU
25 bool "EXYNOS PPMU (Platform Performance Monitoring Unit) DEVFREQ event Driver" 25 tristate "EXYNOS PPMU (Platform Performance Monitoring Unit) DEVFREQ event Driver"
26 depends on ARCH_EXYNOS 26 depends on ARCH_EXYNOS
27 select PM_OPP 27 select PM_OPP
28 help 28 help
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c
index f312485f1451..845bf25fb9fb 100644
--- a/drivers/devfreq/event/exynos-ppmu.c
+++ b/drivers/devfreq/event/exynos-ppmu.c
@@ -482,7 +482,8 @@ static int exynos_ppmu_probe(struct platform_device *pdev)
482 if (!info->edev) { 482 if (!info->edev) {
483 dev_err(&pdev->dev, 483 dev_err(&pdev->dev,
484 "failed to allocate memory devfreq-event devices\n"); 484 "failed to allocate memory devfreq-event devices\n");
485 return -ENOMEM; 485 ret = -ENOMEM;
486 goto err;
486 } 487 }
487 edev = info->edev; 488 edev = info->edev;
488 platform_set_drvdata(pdev, info); 489 platform_set_drvdata(pdev, info);
diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index 2363d0a189b7..29866f7e6d7e 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -383,7 +383,7 @@ err_clk:
383static int exynos_bus_probe(struct platform_device *pdev) 383static int exynos_bus_probe(struct platform_device *pdev)
384{ 384{
385 struct device *dev = &pdev->dev; 385 struct device *dev = &pdev->dev;
386 struct device_node *np = dev->of_node; 386 struct device_node *np = dev->of_node, *node;
387 struct devfreq_dev_profile *profile; 387 struct devfreq_dev_profile *profile;
388 struct devfreq_simple_ondemand_data *ondemand_data; 388 struct devfreq_simple_ondemand_data *ondemand_data;
389 struct devfreq_passive_data *passive_data; 389 struct devfreq_passive_data *passive_data;
@@ -407,7 +407,7 @@ static int exynos_bus_probe(struct platform_device *pdev)
407 /* Parse the device-tree to get the resource information */ 407 /* Parse the device-tree to get the resource information */
408 ret = exynos_bus_parse_of(np, bus); 408 ret = exynos_bus_parse_of(np, bus);
409 if (ret < 0) 409 if (ret < 0)
410 goto err; 410 return ret;
411 411
412 profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL); 412 profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
413 if (!profile) { 413 if (!profile) {
@@ -415,10 +415,13 @@ static int exynos_bus_probe(struct platform_device *pdev)
415 goto err; 415 goto err;
416 } 416 }
417 417
418 if (of_parse_phandle(dev->of_node, "devfreq", 0)) 418 node = of_parse_phandle(dev->of_node, "devfreq", 0);
419 if (node) {
420 of_node_put(node);
419 goto passive; 421 goto passive;
420 else 422 } else {
421 ret = exynos_bus_parent_parse_of(np, bus); 423 ret = exynos_bus_parent_parse_of(np, bus);
424 }
422 425
423 if (ret < 0) 426 if (ret < 0)
424 goto err; 427 goto err;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
index 252edba16e36..892d60fb225b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
@@ -421,29 +421,6 @@ static int acp_suspend(void *handle)
421 421
422static int acp_resume(void *handle) 422static int acp_resume(void *handle)
423{ 423{
424 int i, ret;
425 struct acp_pm_domain *apd;
426 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
427
428 /* return early if no ACP */
429 if (!adev->acp.acp_genpd)
430 return 0;
431
432 /* SMU block will power on ACP irrespective of ACP runtime status.
433 * Power off explicitly based on genpd ACP runtime status so that ACP
434 * hw and ACP-genpd status are in sync.
435 * 'suspend_power_off' represents "Power status before system suspend"
436 */
437 if (adev->acp.acp_genpd->gpd.suspend_power_off == true) {
438 apd = container_of(&adev->acp.acp_genpd->gpd,
439 struct acp_pm_domain, gpd);
440
441 for (i = 4; i >= 0 ; i--) {
442 ret = acp_suspend_tile(apd->cgs_dev, ACP_TILE_P1 + i);
443 if (ret)
444 pr_err("ACP tile %d tile suspend failed\n", i);
445 }
446 }
447 return 0; 424 return 0;
448} 425}
449 426
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index b5dd41d13d3d..9b2ef248788d 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -46,8 +46,6 @@
46 * to avoid complications with the lapic timer workaround. 46 * to avoid complications with the lapic timer workaround.
47 * Have not seen issues with suspend, but may need same workaround here. 47 * Have not seen issues with suspend, but may need same workaround here.
48 * 48 *
49 * There is currently no kernel-based automatic probing/loading mechanism
50 * if the driver is built as a module.
51 */ 49 */
52 50
53/* un-comment DEBUG to enable pr_debug() statements */ 51/* un-comment DEBUG to enable pr_debug() statements */
@@ -60,7 +58,7 @@
60#include <linux/sched.h> 58#include <linux/sched.h>
61#include <linux/notifier.h> 59#include <linux/notifier.h>
62#include <linux/cpu.h> 60#include <linux/cpu.h>
63#include <linux/module.h> 61#include <linux/moduleparam.h>
64#include <asm/cpu_device_id.h> 62#include <asm/cpu_device_id.h>
65#include <asm/intel-family.h> 63#include <asm/intel-family.h>
66#include <asm/mwait.h> 64#include <asm/mwait.h>
@@ -828,6 +826,35 @@ static struct cpuidle_state bxt_cstates[] = {
828 .enter = NULL } 826 .enter = NULL }
829}; 827};
830 828
829static struct cpuidle_state dnv_cstates[] = {
830 {
831 .name = "C1-DNV",
832 .desc = "MWAIT 0x00",
833 .flags = MWAIT2flg(0x00),
834 .exit_latency = 2,
835 .target_residency = 2,
836 .enter = &intel_idle,
837 .enter_freeze = intel_idle_freeze, },
838 {
839 .name = "C1E-DNV",
840 .desc = "MWAIT 0x01",
841 .flags = MWAIT2flg(0x01),
842 .exit_latency = 10,
843 .target_residency = 20,
844 .enter = &intel_idle,
845 .enter_freeze = intel_idle_freeze, },
846 {
847 .name = "C6-DNV",
848 .desc = "MWAIT 0x20",
849 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
850 .exit_latency = 50,
851 .target_residency = 500,
852 .enter = &intel_idle,
853 .enter_freeze = intel_idle_freeze, },
854 {
855 .enter = NULL }
856};
857
831/** 858/**
832 * intel_idle 859 * intel_idle
833 * @dev: cpuidle_device 860 * @dev: cpuidle_device
@@ -1017,6 +1044,11 @@ static const struct idle_cpu idle_cpu_bxt = {
1017 .disable_promotion_to_c1e = true, 1044 .disable_promotion_to_c1e = true,
1018}; 1045};
1019 1046
1047static const struct idle_cpu idle_cpu_dnv = {
1048 .state_table = dnv_cstates,
1049 .disable_promotion_to_c1e = true,
1050};
1051
1020#define ICPU(model, cpu) \ 1052#define ICPU(model, cpu) \
1021 { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } 1053 { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu }
1022 1054
@@ -1053,9 +1085,9 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
1053 ICPU(INTEL_FAM6_SKYLAKE_X, idle_cpu_skx), 1085 ICPU(INTEL_FAM6_SKYLAKE_X, idle_cpu_skx),
1054 ICPU(INTEL_FAM6_XEON_PHI_KNL, idle_cpu_knl), 1086 ICPU(INTEL_FAM6_XEON_PHI_KNL, idle_cpu_knl),
1055 ICPU(INTEL_FAM6_ATOM_GOLDMONT, idle_cpu_bxt), 1087 ICPU(INTEL_FAM6_ATOM_GOLDMONT, idle_cpu_bxt),
1088 ICPU(INTEL_FAM6_ATOM_DENVERTON, idle_cpu_dnv),
1056 {} 1089 {}
1057}; 1090};
1058MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
1059 1091
1060/* 1092/*
1061 * intel_idle_probe() 1093 * intel_idle_probe()
@@ -1155,7 +1187,10 @@ static unsigned long long irtl_2_usec(unsigned long long irtl)
1155{ 1187{
1156 unsigned long long ns; 1188 unsigned long long ns;
1157 1189
1158 ns = irtl_ns_units[(irtl >> 10) & 0x3]; 1190 if (!irtl)
1191 return 0;
1192
1193 ns = irtl_ns_units[(irtl >> 10) & 0x7];
1159 1194
1160 return div64_u64((irtl & 0x3FF) * ns, 1000); 1195 return div64_u64((irtl & 0x3FF) * ns, 1000);
1161} 1196}
@@ -1168,43 +1203,39 @@ static unsigned long long irtl_2_usec(unsigned long long irtl)
1168static void bxt_idle_state_table_update(void) 1203static void bxt_idle_state_table_update(void)
1169{ 1204{
1170 unsigned long long msr; 1205 unsigned long long msr;
1206 unsigned int usec;
1171 1207
1172 rdmsrl(MSR_PKGC6_IRTL, msr); 1208 rdmsrl(MSR_PKGC6_IRTL, msr);
1173 if (msr) { 1209 usec = irtl_2_usec(msr);
1174 unsigned int usec = irtl_2_usec(msr); 1210 if (usec) {
1175
1176 bxt_cstates[2].exit_latency = usec; 1211 bxt_cstates[2].exit_latency = usec;
1177 bxt_cstates[2].target_residency = usec; 1212 bxt_cstates[2].target_residency = usec;
1178 } 1213 }
1179 1214
1180 rdmsrl(MSR_PKGC7_IRTL, msr); 1215 rdmsrl(MSR_PKGC7_IRTL, msr);
1181 if (msr) { 1216 usec = irtl_2_usec(msr);
1182 unsigned int usec = irtl_2_usec(msr); 1217 if (usec) {
1183
1184 bxt_cstates[3].exit_latency = usec; 1218 bxt_cstates[3].exit_latency = usec;
1185 bxt_cstates[3].target_residency = usec; 1219 bxt_cstates[3].target_residency = usec;
1186 } 1220 }
1187 1221
1188 rdmsrl(MSR_PKGC8_IRTL, msr); 1222 rdmsrl(MSR_PKGC8_IRTL, msr);
1189 if (msr) { 1223 usec = irtl_2_usec(msr);
1190 unsigned int usec = irtl_2_usec(msr); 1224 if (usec) {
1191
1192 bxt_cstates[4].exit_latency = usec; 1225 bxt_cstates[4].exit_latency = usec;
1193 bxt_cstates[4].target_residency = usec; 1226 bxt_cstates[4].target_residency = usec;
1194 } 1227 }
1195 1228
1196 rdmsrl(MSR_PKGC9_IRTL, msr); 1229 rdmsrl(MSR_PKGC9_IRTL, msr);
1197 if (msr) { 1230 usec = irtl_2_usec(msr);
1198 unsigned int usec = irtl_2_usec(msr); 1231 if (usec) {
1199
1200 bxt_cstates[5].exit_latency = usec; 1232 bxt_cstates[5].exit_latency = usec;
1201 bxt_cstates[5].target_residency = usec; 1233 bxt_cstates[5].target_residency = usec;
1202 } 1234 }
1203 1235
1204 rdmsrl(MSR_PKGC10_IRTL, msr); 1236 rdmsrl(MSR_PKGC10_IRTL, msr);
1205 if (msr) { 1237 usec = irtl_2_usec(msr);
1206 unsigned int usec = irtl_2_usec(msr); 1238 if (usec) {
1207
1208 bxt_cstates[6].exit_latency = usec; 1239 bxt_cstates[6].exit_latency = usec;
1209 bxt_cstates[6].target_residency = usec; 1240 bxt_cstates[6].target_residency = usec;
1210 } 1241 }
@@ -1416,34 +1447,12 @@ static int __init intel_idle_init(void)
1416 1447
1417 return 0; 1448 return 0;
1418} 1449}
1450device_initcall(intel_idle_init);
1419 1451
1420static void __exit intel_idle_exit(void) 1452/*
1421{ 1453 * We are not really modular, but we used to support that. Meaning we also
1422 struct cpuidle_device *dev; 1454 * support "intel_idle.max_cstate=..." at boot and also a read-only export of
1423 int i; 1455 * it at /sys/module/intel_idle/parameters/max_cstate -- so using module_param
1424 1456 * is the easiest way (currently) to continue doing that.
1425 cpu_notifier_register_begin(); 1457 */
1426
1427 if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
1428 on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
1429 __unregister_cpu_notifier(&cpu_hotplug_notifier);
1430
1431 for_each_possible_cpu(i) {
1432 dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
1433 cpuidle_unregister_device(dev);
1434 }
1435
1436 cpu_notifier_register_done();
1437
1438 cpuidle_unregister_driver(&intel_idle_driver);
1439 free_percpu(intel_idle_cpuidle_devices);
1440}
1441
1442module_init(intel_idle_init);
1443module_exit(intel_idle_exit);
1444
1445module_param(max_cstate, int, 0444); 1458module_param(max_cstate, int, 0444);
1446
1447MODULE_AUTHOR("Len Brown <len.brown@intel.com>");
1448MODULE_DESCRIPTION("Cpuidle driver for Intel Hardware v" INTEL_IDLE_VERSION);
1449MODULE_LICENSE("GPL");
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index c8b4dbdd1bdd..badbddc683f0 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -530,8 +530,8 @@ static const struct pci_platform_pm_ops *pci_platform_pm;
530 530
531int pci_set_platform_pm(const struct pci_platform_pm_ops *ops) 531int pci_set_platform_pm(const struct pci_platform_pm_ops *ops)
532{ 532{
533 if (!ops->is_manageable || !ops->set_state || !ops->choose_state 533 if (!ops->is_manageable || !ops->set_state || !ops->choose_state ||
534 || !ops->sleep_wake) 534 !ops->sleep_wake || !ops->run_wake || !ops->need_resume)
535 return -EINVAL; 535 return -EINVAL;
536 pci_platform_pm = ops; 536 pci_platform_pm = ops;
537 return 0; 537 return 0;
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
index 2e8f2be5b6f9..fbab29dfa793 100644
--- a/drivers/powercap/intel_rapl.c
+++ b/drivers/powercap/intel_rapl.c
@@ -336,14 +336,14 @@ static int release_zone(struct powercap_zone *power_zone)
336 336
337static int find_nr_power_limit(struct rapl_domain *rd) 337static int find_nr_power_limit(struct rapl_domain *rd)
338{ 338{
339 int i; 339 int i, nr_pl = 0;
340 340
341 for (i = 0; i < NR_POWER_LIMITS; i++) { 341 for (i = 0; i < NR_POWER_LIMITS; i++) {
342 if (rd->rpl[i].name == NULL) 342 if (rd->rpl[i].name)
343 break; 343 nr_pl++;
344 } 344 }
345 345
346 return i; 346 return nr_pl;
347} 347}
348 348
349static int set_domain_enable(struct powercap_zone *power_zone, bool mode) 349static int set_domain_enable(struct powercap_zone *power_zone, bool mode)
@@ -426,15 +426,38 @@ static const struct powercap_zone_ops zone_ops[] = {
426 }, 426 },
427}; 427};
428 428
429static int set_power_limit(struct powercap_zone *power_zone, int id, 429
430/*
431 * Constraint index used by powercap can be different than power limit (PL)
432 * index in that some PLs maybe missing due to non-existant MSRs. So we
433 * need to convert here by finding the valid PLs only (name populated).
434 */
435static int contraint_to_pl(struct rapl_domain *rd, int cid)
436{
437 int i, j;
438
439 for (i = 0, j = 0; i < NR_POWER_LIMITS; i++) {
440 if ((rd->rpl[i].name) && j++ == cid) {
441 pr_debug("%s: index %d\n", __func__, i);
442 return i;
443 }
444 }
445
446 return -EINVAL;
447}
448
449static int set_power_limit(struct powercap_zone *power_zone, int cid,
430 u64 power_limit) 450 u64 power_limit)
431{ 451{
432 struct rapl_domain *rd; 452 struct rapl_domain *rd;
433 struct rapl_package *rp; 453 struct rapl_package *rp;
434 int ret = 0; 454 int ret = 0;
455 int id;
435 456
436 get_online_cpus(); 457 get_online_cpus();
437 rd = power_zone_to_rapl_domain(power_zone); 458 rd = power_zone_to_rapl_domain(power_zone);
459 id = contraint_to_pl(rd, cid);
460
438 rp = rd->rp; 461 rp = rd->rp;
439 462
440 if (rd->state & DOMAIN_STATE_BIOS_LOCKED) { 463 if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
@@ -461,16 +484,18 @@ set_exit:
461 return ret; 484 return ret;
462} 485}
463 486
464static int get_current_power_limit(struct powercap_zone *power_zone, int id, 487static int get_current_power_limit(struct powercap_zone *power_zone, int cid,
465 u64 *data) 488 u64 *data)
466{ 489{
467 struct rapl_domain *rd; 490 struct rapl_domain *rd;
468 u64 val; 491 u64 val;
469 int prim; 492 int prim;
470 int ret = 0; 493 int ret = 0;
494 int id;
471 495
472 get_online_cpus(); 496 get_online_cpus();
473 rd = power_zone_to_rapl_domain(power_zone); 497 rd = power_zone_to_rapl_domain(power_zone);
498 id = contraint_to_pl(rd, cid);
474 switch (rd->rpl[id].prim_id) { 499 switch (rd->rpl[id].prim_id) {
475 case PL1_ENABLE: 500 case PL1_ENABLE:
476 prim = POWER_LIMIT1; 501 prim = POWER_LIMIT1;
@@ -492,14 +517,17 @@ static int get_current_power_limit(struct powercap_zone *power_zone, int id,
492 return ret; 517 return ret;
493} 518}
494 519
495static int set_time_window(struct powercap_zone *power_zone, int id, 520static int set_time_window(struct powercap_zone *power_zone, int cid,
496 u64 window) 521 u64 window)
497{ 522{
498 struct rapl_domain *rd; 523 struct rapl_domain *rd;
499 int ret = 0; 524 int ret = 0;
525 int id;
500 526
501 get_online_cpus(); 527 get_online_cpus();
502 rd = power_zone_to_rapl_domain(power_zone); 528 rd = power_zone_to_rapl_domain(power_zone);
529 id = contraint_to_pl(rd, cid);
530
503 switch (rd->rpl[id].prim_id) { 531 switch (rd->rpl[id].prim_id) {
504 case PL1_ENABLE: 532 case PL1_ENABLE:
505 rapl_write_data_raw(rd, TIME_WINDOW1, window); 533 rapl_write_data_raw(rd, TIME_WINDOW1, window);
@@ -514,14 +542,17 @@ static int set_time_window(struct powercap_zone *power_zone, int id,
514 return ret; 542 return ret;
515} 543}
516 544
517static int get_time_window(struct powercap_zone *power_zone, int id, u64 *data) 545static int get_time_window(struct powercap_zone *power_zone, int cid, u64 *data)
518{ 546{
519 struct rapl_domain *rd; 547 struct rapl_domain *rd;
520 u64 val; 548 u64 val;
521 int ret = 0; 549 int ret = 0;
550 int id;
522 551
523 get_online_cpus(); 552 get_online_cpus();
524 rd = power_zone_to_rapl_domain(power_zone); 553 rd = power_zone_to_rapl_domain(power_zone);
554 id = contraint_to_pl(rd, cid);
555
525 switch (rd->rpl[id].prim_id) { 556 switch (rd->rpl[id].prim_id) {
526 case PL1_ENABLE: 557 case PL1_ENABLE:
527 ret = rapl_read_data_raw(rd, TIME_WINDOW1, true, &val); 558 ret = rapl_read_data_raw(rd, TIME_WINDOW1, true, &val);
@@ -540,15 +571,17 @@ static int get_time_window(struct powercap_zone *power_zone, int id, u64 *data)
540 return ret; 571 return ret;
541} 572}
542 573
543static const char *get_constraint_name(struct powercap_zone *power_zone, int id) 574static const char *get_constraint_name(struct powercap_zone *power_zone, int cid)
544{ 575{
545 struct rapl_power_limit *rpl;
546 struct rapl_domain *rd; 576 struct rapl_domain *rd;
577 int id;
547 578
548 rd = power_zone_to_rapl_domain(power_zone); 579 rd = power_zone_to_rapl_domain(power_zone);
549 rpl = (struct rapl_power_limit *) &rd->rpl[id]; 580 id = contraint_to_pl(rd, cid);
581 if (id >= 0)
582 return rd->rpl[id].name;
550 583
551 return rpl->name; 584 return NULL;
552} 585}
553 586
554 587
@@ -1101,6 +1134,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
1101 RAPL_CPU(INTEL_FAM6_SANDYBRIDGE_X, rapl_defaults_core), 1134 RAPL_CPU(INTEL_FAM6_SANDYBRIDGE_X, rapl_defaults_core),
1102 1135
1103 RAPL_CPU(INTEL_FAM6_IVYBRIDGE, rapl_defaults_core), 1136 RAPL_CPU(INTEL_FAM6_IVYBRIDGE, rapl_defaults_core),
1137 RAPL_CPU(INTEL_FAM6_IVYBRIDGE_X, rapl_defaults_core),
1104 1138
1105 RAPL_CPU(INTEL_FAM6_HASWELL_CORE, rapl_defaults_core), 1139 RAPL_CPU(INTEL_FAM6_HASWELL_CORE, rapl_defaults_core),
1106 RAPL_CPU(INTEL_FAM6_HASWELL_ULT, rapl_defaults_core), 1140 RAPL_CPU(INTEL_FAM6_HASWELL_ULT, rapl_defaults_core),
@@ -1123,6 +1157,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
1123 RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD1, rapl_defaults_tng), 1157 RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD1, rapl_defaults_tng),
1124 RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD2, rapl_defaults_ann), 1158 RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD2, rapl_defaults_ann),
1125 RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT, rapl_defaults_core), 1159 RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT, rapl_defaults_core),
1160 RAPL_CPU(INTEL_FAM6_ATOM_DENVERTON, rapl_defaults_core),
1126 1161
1127 RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL, rapl_defaults_hsw_server), 1162 RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL, rapl_defaults_hsw_server),
1128 {} 1163 {}
@@ -1381,6 +1416,37 @@ static int rapl_check_domain(int cpu, int domain)
1381 return 0; 1416 return 0;
1382} 1417}
1383 1418
1419
1420/*
1421 * Check if power limits are available. Two cases when they are not available:
1422 * 1. Locked by BIOS, in this case we still provide read-only access so that
1423 * users can see what limit is set by the BIOS.
1424 * 2. Some CPUs make some domains monitoring only which means PLx MSRs may not
1425 * exist at all. In this case, we do not show the contraints in powercap.
1426 *
1427 * Called after domains are detected and initialized.
1428 */
1429static void rapl_detect_powerlimit(struct rapl_domain *rd)
1430{
1431 u64 val64;
1432 int i;
1433
1434 /* check if the domain is locked by BIOS, ignore if MSR doesn't exist */
1435 if (!rapl_read_data_raw(rd, FW_LOCK, false, &val64)) {
1436 if (val64) {
1437 pr_info("RAPL package %d domain %s locked by BIOS\n",
1438 rd->rp->id, rd->name);
1439 rd->state |= DOMAIN_STATE_BIOS_LOCKED;
1440 }
1441 }
1442 /* check if power limit MSRs exists, otherwise domain is monitoring only */
1443 for (i = 0; i < NR_POWER_LIMITS; i++) {
1444 int prim = rd->rpl[i].prim_id;
1445 if (rapl_read_data_raw(rd, prim, false, &val64))
1446 rd->rpl[i].name = NULL;
1447 }
1448}
1449
1384/* Detect active and valid domains for the given CPU, caller must 1450/* Detect active and valid domains for the given CPU, caller must
1385 * ensure the CPU belongs to the targeted package and CPU hotlug is disabled. 1451 * ensure the CPU belongs to the targeted package and CPU hotlug is disabled.
1386 */ 1452 */
@@ -1389,7 +1455,6 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
1389 int i; 1455 int i;
1390 int ret = 0; 1456 int ret = 0;
1391 struct rapl_domain *rd; 1457 struct rapl_domain *rd;
1392 u64 locked;
1393 1458
1394 for (i = 0; i < RAPL_DOMAIN_MAX; i++) { 1459 for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
1395 /* use physical package id to read counters */ 1460 /* use physical package id to read counters */
@@ -1400,7 +1465,7 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
1400 } 1465 }
1401 rp->nr_domains = bitmap_weight(&rp->domain_map, RAPL_DOMAIN_MAX); 1466 rp->nr_domains = bitmap_weight(&rp->domain_map, RAPL_DOMAIN_MAX);
1402 if (!rp->nr_domains) { 1467 if (!rp->nr_domains) {
1403 pr_err("no valid rapl domains found in package %d\n", rp->id); 1468 pr_debug("no valid rapl domains found in package %d\n", rp->id);
1404 ret = -ENODEV; 1469 ret = -ENODEV;
1405 goto done; 1470 goto done;
1406 } 1471 }
@@ -1414,17 +1479,9 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
1414 } 1479 }
1415 rapl_init_domains(rp); 1480 rapl_init_domains(rp);
1416 1481
1417 for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) { 1482 for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++)
1418 /* check if the domain is locked by BIOS */ 1483 rapl_detect_powerlimit(rd);
1419 ret = rapl_read_data_raw(rd, FW_LOCK, false, &locked); 1484
1420 if (ret)
1421 return ret;
1422 if (locked) {
1423 pr_info("RAPL package %d domain %s locked by BIOS\n",
1424 rp->id, rd->name);
1425 rd->state |= DOMAIN_STATE_BIOS_LOCKED;
1426 }
1427 }
1428 1485
1429 1486
1430done: 1487done:
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 5b4b47ed948b..3788ed74c9ab 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -787,22 +787,34 @@ __cpufreq_cooling_register(struct device_node *np,
787 const struct cpumask *clip_cpus, u32 capacitance, 787 const struct cpumask *clip_cpus, u32 capacitance,
788 get_static_t plat_static_func) 788 get_static_t plat_static_func)
789{ 789{
790 struct cpufreq_policy *policy;
790 struct thermal_cooling_device *cool_dev; 791 struct thermal_cooling_device *cool_dev;
791 struct cpufreq_cooling_device *cpufreq_dev; 792 struct cpufreq_cooling_device *cpufreq_dev;
792 char dev_name[THERMAL_NAME_LENGTH]; 793 char dev_name[THERMAL_NAME_LENGTH];
793 struct cpufreq_frequency_table *pos, *table; 794 struct cpufreq_frequency_table *pos, *table;
795 struct cpumask temp_mask;
794 unsigned int freq, i, num_cpus; 796 unsigned int freq, i, num_cpus;
795 int ret; 797 int ret;
796 798
797 table = cpufreq_frequency_get_table(cpumask_first(clip_cpus)); 799 cpumask_and(&temp_mask, clip_cpus, cpu_online_mask);
800 policy = cpufreq_cpu_get(cpumask_first(&temp_mask));
801 if (!policy) {
802 pr_debug("%s: CPUFreq policy not found\n", __func__);
803 return ERR_PTR(-EPROBE_DEFER);
804 }
805
806 table = policy->freq_table;
798 if (!table) { 807 if (!table) {
799 pr_debug("%s: CPUFreq table not found\n", __func__); 808 pr_debug("%s: CPUFreq table not found\n", __func__);
800 return ERR_PTR(-EPROBE_DEFER); 809 cool_dev = ERR_PTR(-ENODEV);
810 goto put_policy;
801 } 811 }
802 812
803 cpufreq_dev = kzalloc(sizeof(*cpufreq_dev), GFP_KERNEL); 813 cpufreq_dev = kzalloc(sizeof(*cpufreq_dev), GFP_KERNEL);
804 if (!cpufreq_dev) 814 if (!cpufreq_dev) {
805 return ERR_PTR(-ENOMEM); 815 cool_dev = ERR_PTR(-ENOMEM);
816 goto put_policy;
817 }
806 818
807 num_cpus = cpumask_weight(clip_cpus); 819 num_cpus = cpumask_weight(clip_cpus);
808 cpufreq_dev->time_in_idle = kcalloc(num_cpus, 820 cpufreq_dev->time_in_idle = kcalloc(num_cpus,
@@ -892,7 +904,7 @@ __cpufreq_cooling_register(struct device_node *np,
892 CPUFREQ_POLICY_NOTIFIER); 904 CPUFREQ_POLICY_NOTIFIER);
893 mutex_unlock(&cooling_cpufreq_lock); 905 mutex_unlock(&cooling_cpufreq_lock);
894 906
895 return cool_dev; 907 goto put_policy;
896 908
897remove_idr: 909remove_idr:
898 release_idr(&cpufreq_idr, cpufreq_dev->id); 910 release_idr(&cpufreq_idr, cpufreq_dev->id);
@@ -906,6 +918,8 @@ free_time_in_idle:
906 kfree(cpufreq_dev->time_in_idle); 918 kfree(cpufreq_dev->time_in_idle);
907free_cdev: 919free_cdev:
908 kfree(cpufreq_dev); 920 kfree(cpufreq_dev);
921put_policy:
922 cpufreq_cpu_put(policy);
909 923
910 return cool_dev; 924 return cool_dev;
911} 925}
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 4e81e08db752..631ba33bbe9f 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -36,6 +36,12 @@
36 36
37struct cpufreq_governor; 37struct cpufreq_governor;
38 38
39enum cpufreq_table_sorting {
40 CPUFREQ_TABLE_UNSORTED,
41 CPUFREQ_TABLE_SORTED_ASCENDING,
42 CPUFREQ_TABLE_SORTED_DESCENDING
43};
44
39struct cpufreq_freqs { 45struct cpufreq_freqs {
40 unsigned int cpu; /* cpu nr */ 46 unsigned int cpu; /* cpu nr */
41 unsigned int old; 47 unsigned int old;
@@ -87,6 +93,7 @@ struct cpufreq_policy {
87 93
88 struct cpufreq_user_policy user_policy; 94 struct cpufreq_user_policy user_policy;
89 struct cpufreq_frequency_table *freq_table; 95 struct cpufreq_frequency_table *freq_table;
96 enum cpufreq_table_sorting freq_table_sorted;
90 97
91 struct list_head policy_list; 98 struct list_head policy_list;
92 struct kobject kobj; 99 struct kobject kobj;
@@ -113,6 +120,10 @@ struct cpufreq_policy {
113 bool fast_switch_possible; 120 bool fast_switch_possible;
114 bool fast_switch_enabled; 121 bool fast_switch_enabled;
115 122
123 /* Cached frequency lookup from cpufreq_driver_resolve_freq. */
124 unsigned int cached_target_freq;
125 int cached_resolved_idx;
126
116 /* Synchronization for frequency transitions */ 127 /* Synchronization for frequency transitions */
117 bool transition_ongoing; /* Tracks transition status */ 128 bool transition_ongoing; /* Tracks transition status */
118 spinlock_t transition_lock; 129 spinlock_t transition_lock;
@@ -185,6 +196,18 @@ static inline unsigned int cpufreq_quick_get_max(unsigned int cpu)
185static inline void disable_cpufreq(void) { } 196static inline void disable_cpufreq(void) { }
186#endif 197#endif
187 198
199#ifdef CONFIG_CPU_FREQ_STAT
200void cpufreq_stats_create_table(struct cpufreq_policy *policy);
201void cpufreq_stats_free_table(struct cpufreq_policy *policy);
202void cpufreq_stats_record_transition(struct cpufreq_policy *policy,
203 unsigned int new_freq);
204#else
205static inline void cpufreq_stats_create_table(struct cpufreq_policy *policy) { }
206static inline void cpufreq_stats_free_table(struct cpufreq_policy *policy) { }
207static inline void cpufreq_stats_record_transition(struct cpufreq_policy *policy,
208 unsigned int new_freq) { }
209#endif /* CONFIG_CPU_FREQ_STAT */
210
188/********************************************************************* 211/*********************************************************************
189 * CPUFREQ DRIVER INTERFACE * 212 * CPUFREQ DRIVER INTERFACE *
190 *********************************************************************/ 213 *********************************************************************/
@@ -251,6 +274,16 @@ struct cpufreq_driver {
251 unsigned int index); 274 unsigned int index);
252 unsigned int (*fast_switch)(struct cpufreq_policy *policy, 275 unsigned int (*fast_switch)(struct cpufreq_policy *policy,
253 unsigned int target_freq); 276 unsigned int target_freq);
277
278 /*
279 * Caches and returns the lowest driver-supported frequency greater than
280 * or equal to the target frequency, subject to any driver limitations.
281 * Does not set the frequency. Only to be implemented for drivers with
282 * target().
283 */
284 unsigned int (*resolve_freq)(struct cpufreq_policy *policy,
285 unsigned int target_freq);
286
254 /* 287 /*
255 * Only for drivers with target_index() and CPUFREQ_ASYNC_NOTIFICATION 288 * Only for drivers with target_index() and CPUFREQ_ASYNC_NOTIFICATION
256 * unset. 289 * unset.
@@ -455,18 +488,13 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div,
455#define MIN_LATENCY_MULTIPLIER (20) 488#define MIN_LATENCY_MULTIPLIER (20)
456#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) 489#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000)
457 490
458/* Governor Events */
459#define CPUFREQ_GOV_START 1
460#define CPUFREQ_GOV_STOP 2
461#define CPUFREQ_GOV_LIMITS 3
462#define CPUFREQ_GOV_POLICY_INIT 4
463#define CPUFREQ_GOV_POLICY_EXIT 5
464
465struct cpufreq_governor { 491struct cpufreq_governor {
466 char name[CPUFREQ_NAME_LEN]; 492 char name[CPUFREQ_NAME_LEN];
467 int initialized; 493 int (*init)(struct cpufreq_policy *policy);
468 int (*governor) (struct cpufreq_policy *policy, 494 void (*exit)(struct cpufreq_policy *policy);
469 unsigned int event); 495 int (*start)(struct cpufreq_policy *policy);
496 void (*stop)(struct cpufreq_policy *policy);
497 void (*limits)(struct cpufreq_policy *policy);
470 ssize_t (*show_setspeed) (struct cpufreq_policy *policy, 498 ssize_t (*show_setspeed) (struct cpufreq_policy *policy,
471 char *buf); 499 char *buf);
472 int (*store_setspeed) (struct cpufreq_policy *policy, 500 int (*store_setspeed) (struct cpufreq_policy *policy,
@@ -487,12 +515,22 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
487int __cpufreq_driver_target(struct cpufreq_policy *policy, 515int __cpufreq_driver_target(struct cpufreq_policy *policy,
488 unsigned int target_freq, 516 unsigned int target_freq,
489 unsigned int relation); 517 unsigned int relation);
518unsigned int cpufreq_driver_resolve_freq(struct cpufreq_policy *policy,
519 unsigned int target_freq);
490int cpufreq_register_governor(struct cpufreq_governor *governor); 520int cpufreq_register_governor(struct cpufreq_governor *governor);
491void cpufreq_unregister_governor(struct cpufreq_governor *governor); 521void cpufreq_unregister_governor(struct cpufreq_governor *governor);
492 522
493struct cpufreq_governor *cpufreq_default_governor(void); 523struct cpufreq_governor *cpufreq_default_governor(void);
494struct cpufreq_governor *cpufreq_fallback_governor(void); 524struct cpufreq_governor *cpufreq_fallback_governor(void);
495 525
526static inline void cpufreq_policy_apply_limits(struct cpufreq_policy *policy)
527{
528 if (policy->max < policy->cur)
529 __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
530 else if (policy->min > policy->cur)
531 __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
532}
533
496/* Governor attribute set */ 534/* Governor attribute set */
497struct gov_attr_set { 535struct gov_attr_set {
498 struct kobject kobj; 536 struct kobject kobj;
@@ -582,11 +620,9 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
582 struct cpufreq_frequency_table *table); 620 struct cpufreq_frequency_table *table);
583int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy); 621int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy);
584 622
585int cpufreq_frequency_table_target(struct cpufreq_policy *policy, 623int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
586 struct cpufreq_frequency_table *table, 624 unsigned int target_freq,
587 unsigned int target_freq, 625 unsigned int relation);
588 unsigned int relation,
589 unsigned int *index);
590int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, 626int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
591 unsigned int freq); 627 unsigned int freq);
592 628
@@ -597,6 +633,227 @@ int cpufreq_boost_trigger_state(int state);
597int cpufreq_boost_enabled(void); 633int cpufreq_boost_enabled(void);
598int cpufreq_enable_boost_support(void); 634int cpufreq_enable_boost_support(void);
599bool policy_has_boost_freq(struct cpufreq_policy *policy); 635bool policy_has_boost_freq(struct cpufreq_policy *policy);
636
637/* Find lowest freq at or above target in a table in ascending order */
638static inline int cpufreq_table_find_index_al(struct cpufreq_policy *policy,
639 unsigned int target_freq)
640{
641 struct cpufreq_frequency_table *table = policy->freq_table;
642 unsigned int freq;
643 int i, best = -1;
644
645 for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
646 freq = table[i].frequency;
647
648 if (freq >= target_freq)
649 return i;
650
651 best = i;
652 }
653
654 return best;
655}
656
657/* Find lowest freq at or above target in a table in descending order */
658static inline int cpufreq_table_find_index_dl(struct cpufreq_policy *policy,
659 unsigned int target_freq)
660{
661 struct cpufreq_frequency_table *table = policy->freq_table;
662 unsigned int freq;
663 int i, best = -1;
664
665 for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
666 freq = table[i].frequency;
667
668 if (freq == target_freq)
669 return i;
670
671 if (freq > target_freq) {
672 best = i;
673 continue;
674 }
675
676 /* No freq found above target_freq */
677 if (best == -1)
678 return i;
679
680 return best;
681 }
682
683 return best;
684}
685
686/* Works only on sorted freq-tables */
687static inline int cpufreq_table_find_index_l(struct cpufreq_policy *policy,
688 unsigned int target_freq)
689{
690 target_freq = clamp_val(target_freq, policy->min, policy->max);
691
692 if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
693 return cpufreq_table_find_index_al(policy, target_freq);
694 else
695 return cpufreq_table_find_index_dl(policy, target_freq);
696}
697
698/* Find highest freq at or below target in a table in ascending order */
699static inline int cpufreq_table_find_index_ah(struct cpufreq_policy *policy,
700 unsigned int target_freq)
701{
702 struct cpufreq_frequency_table *table = policy->freq_table;
703 unsigned int freq;
704 int i, best = -1;
705
706 for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
707 freq = table[i].frequency;
708
709 if (freq == target_freq)
710 return i;
711
712 if (freq < target_freq) {
713 best = i;
714 continue;
715 }
716
717 /* No freq found below target_freq */
718 if (best == -1)
719 return i;
720
721 return best;
722 }
723
724 return best;
725}
726
727/* Find highest freq at or below target in a table in descending order */
728static inline int cpufreq_table_find_index_dh(struct cpufreq_policy *policy,
729 unsigned int target_freq)
730{
731 struct cpufreq_frequency_table *table = policy->freq_table;
732 unsigned int freq;
733 int i, best = -1;
734
735 for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
736 freq = table[i].frequency;
737
738 if (freq <= target_freq)
739 return i;
740
741 best = i;
742 }
743
744 return best;
745}
746
747/* Works only on sorted freq-tables */
748static inline int cpufreq_table_find_index_h(struct cpufreq_policy *policy,
749 unsigned int target_freq)
750{
751 target_freq = clamp_val(target_freq, policy->min, policy->max);
752
753 if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
754 return cpufreq_table_find_index_ah(policy, target_freq);
755 else
756 return cpufreq_table_find_index_dh(policy, target_freq);
757}
758
759/* Find closest freq to target in a table in ascending order */
760static inline int cpufreq_table_find_index_ac(struct cpufreq_policy *policy,
761 unsigned int target_freq)
762{
763 struct cpufreq_frequency_table *table = policy->freq_table;
764 unsigned int freq;
765 int i, best = -1;
766
767 for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
768 freq = table[i].frequency;
769
770 if (freq == target_freq)
771 return i;
772
773 if (freq < target_freq) {
774 best = i;
775 continue;
776 }
777
778 /* No freq found below target_freq */
779 if (best == -1)
780 return i;
781
782 /* Choose the closest freq */
783 if (target_freq - table[best].frequency > freq - target_freq)
784 return i;
785
786 return best;
787 }
788
789 return best;
790}
791
792/* Find closest freq to target in a table in descending order */
793static inline int cpufreq_table_find_index_dc(struct cpufreq_policy *policy,
794 unsigned int target_freq)
795{
796 struct cpufreq_frequency_table *table = policy->freq_table;
797 unsigned int freq;
798 int i, best = -1;
799
800 for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
801 freq = table[i].frequency;
802
803 if (freq == target_freq)
804 return i;
805
806 if (freq > target_freq) {
807 best = i;
808 continue;
809 }
810
811 /* No freq found above target_freq */
812 if (best == -1)
813 return i;
814
815 /* Choose the closest freq */
816 if (table[best].frequency - target_freq > target_freq - freq)
817 return i;
818
819 return best;
820 }
821
822 return best;
823}
824
825/* Works only on sorted freq-tables */
826static inline int cpufreq_table_find_index_c(struct cpufreq_policy *policy,
827 unsigned int target_freq)
828{
829 target_freq = clamp_val(target_freq, policy->min, policy->max);
830
831 if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
832 return cpufreq_table_find_index_ac(policy, target_freq);
833 else
834 return cpufreq_table_find_index_dc(policy, target_freq);
835}
836
837static inline int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
838 unsigned int target_freq,
839 unsigned int relation)
840{
841 if (unlikely(policy->freq_table_sorted == CPUFREQ_TABLE_UNSORTED))
842 return cpufreq_table_index_unsorted(policy, target_freq,
843 relation);
844
845 switch (relation) {
846 case CPUFREQ_RELATION_L:
847 return cpufreq_table_find_index_l(policy, target_freq);
848 case CPUFREQ_RELATION_H:
849 return cpufreq_table_find_index_h(policy, target_freq);
850 case CPUFREQ_RELATION_C:
851 return cpufreq_table_find_index_c(policy, target_freq);
852 default:
853 pr_err("%s: Invalid relation: %d\n", __func__, relation);
854 return -EINVAL;
855 }
856}
600#else 857#else
601static inline int cpufreq_boost_trigger_state(int state) 858static inline int cpufreq_boost_trigger_state(int state)
602{ 859{
@@ -617,8 +874,6 @@ static inline bool policy_has_boost_freq(struct cpufreq_policy *policy)
617 return false; 874 return false;
618} 875}
619#endif 876#endif
620/* the following funtion is for cpufreq core use only */
621struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
622 877
623/* the following are really really optional */ 878/* the following are really really optional */
624extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs; 879extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
diff --git a/include/linux/pm_clock.h b/include/linux/pm_clock.h
index 308d6044f153..09779b0ae720 100644
--- a/include/linux/pm_clock.h
+++ b/include/linux/pm_clock.h
@@ -42,6 +42,7 @@ extern int pm_clk_create(struct device *dev);
42extern void pm_clk_destroy(struct device *dev); 42extern void pm_clk_destroy(struct device *dev);
43extern int pm_clk_add(struct device *dev, const char *con_id); 43extern int pm_clk_add(struct device *dev, const char *con_id);
44extern int pm_clk_add_clk(struct device *dev, struct clk *clk); 44extern int pm_clk_add_clk(struct device *dev, struct clk *clk);
45extern int of_pm_clk_add_clk(struct device *dev, const char *name);
45extern int of_pm_clk_add_clks(struct device *dev); 46extern int of_pm_clk_add_clks(struct device *dev);
46extern void pm_clk_remove(struct device *dev, const char *con_id); 47extern void pm_clk_remove(struct device *dev, const char *con_id);
47extern void pm_clk_remove_clk(struct device *dev, struct clk *clk); 48extern void pm_clk_remove_clk(struct device *dev, struct clk *clk);
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 39285c7bd3f5..31fec858088c 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -57,7 +57,6 @@ struct generic_pm_domain {
57 unsigned int device_count; /* Number of devices */ 57 unsigned int device_count; /* Number of devices */
58 unsigned int suspended_count; /* System suspend device counter */ 58 unsigned int suspended_count; /* System suspend device counter */
59 unsigned int prepared_count; /* Suspend counter of prepared devices */ 59 unsigned int prepared_count; /* Suspend counter of prepared devices */
60 bool suspend_power_off; /* Power status before system suspend */
61 int (*power_off)(struct generic_pm_domain *domain); 60 int (*power_off)(struct generic_pm_domain *domain);
62 int (*power_on)(struct generic_pm_domain *domain); 61 int (*power_on)(struct generic_pm_domain *domain);
63 struct gpd_dev_ops dev_ops; 62 struct gpd_dev_ops dev_ops;
@@ -128,8 +127,8 @@ extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
128 struct generic_pm_domain *new_subdomain); 127 struct generic_pm_domain *new_subdomain);
129extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, 128extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
130 struct generic_pm_domain *target); 129 struct generic_pm_domain *target);
131extern void pm_genpd_init(struct generic_pm_domain *genpd, 130extern int pm_genpd_init(struct generic_pm_domain *genpd,
132 struct dev_power_governor *gov, bool is_off); 131 struct dev_power_governor *gov, bool is_off);
133 132
134extern struct dev_power_governor simple_qos_governor; 133extern struct dev_power_governor simple_qos_governor;
135extern struct dev_power_governor pm_domain_always_on_gov; 134extern struct dev_power_governor pm_domain_always_on_gov;
@@ -164,9 +163,10 @@ static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
164{ 163{
165 return -ENOSYS; 164 return -ENOSYS;
166} 165}
167static inline void pm_genpd_init(struct generic_pm_domain *genpd, 166static inline int pm_genpd_init(struct generic_pm_domain *genpd,
168 struct dev_power_governor *gov, bool is_off) 167 struct dev_power_governor *gov, bool is_off)
169{ 168{
169 return -ENOSYS;
170} 170}
171#endif 171#endif
172 172
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 8b6ec7ef0854..7693e39b14fe 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -18,12 +18,11 @@ static inline void pm_set_vt_switch(int do_switch)
18#endif 18#endif
19 19
20#ifdef CONFIG_VT_CONSOLE_SLEEP 20#ifdef CONFIG_VT_CONSOLE_SLEEP
21extern int pm_prepare_console(void); 21extern void pm_prepare_console(void);
22extern void pm_restore_console(void); 22extern void pm_restore_console(void);
23#else 23#else
24static inline int pm_prepare_console(void) 24static inline void pm_prepare_console(void)
25{ 25{
26 return 0;
27} 26}
28 27
29static inline void pm_restore_console(void) 28static inline void pm_restore_console(void)
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index cb880a14cc39..eb4f717705ba 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -1,6 +1,8 @@
1 1
2ccflags-$(CONFIG_PM_DEBUG) := -DDEBUG 2ccflags-$(CONFIG_PM_DEBUG) := -DDEBUG
3 3
4KASAN_SANITIZE_snapshot.o := n
5
4obj-y += qos.o 6obj-y += qos.o
5obj-$(CONFIG_PM) += main.o 7obj-$(CONFIG_PM) += main.o
6obj-$(CONFIG_VT_CONSOLE_SLEEP) += console.o 8obj-$(CONFIG_VT_CONSOLE_SLEEP) += console.o
diff --git a/kernel/power/console.c b/kernel/power/console.c
index aba9c545a0e3..0e781798b0b3 100644
--- a/kernel/power/console.c
+++ b/kernel/power/console.c
@@ -126,17 +126,17 @@ out:
126 return ret; 126 return ret;
127} 127}
128 128
129int pm_prepare_console(void) 129void pm_prepare_console(void)
130{ 130{
131 if (!pm_vt_switch()) 131 if (!pm_vt_switch())
132 return 0; 132 return;
133 133
134 orig_fgconsole = vt_move_to_console(SUSPEND_CONSOLE, 1); 134 orig_fgconsole = vt_move_to_console(SUSPEND_CONSOLE, 1);
135 if (orig_fgconsole < 0) 135 if (orig_fgconsole < 0)
136 return 1; 136 return;
137 137
138 orig_kmsg = vt_kmsg_redirect(SUSPEND_CONSOLE); 138 orig_kmsg = vt_kmsg_redirect(SUSPEND_CONSOLE);
139 return 0; 139 return;
140} 140}
141 141
142void pm_restore_console(void) 142void pm_restore_console(void)
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 9021387c6ff4..a881c6a7ba74 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -52,6 +52,7 @@ enum {
52#ifdef CONFIG_SUSPEND 52#ifdef CONFIG_SUSPEND
53 HIBERNATION_SUSPEND, 53 HIBERNATION_SUSPEND,
54#endif 54#endif
55 HIBERNATION_TEST_RESUME,
55 /* keep last */ 56 /* keep last */
56 __HIBERNATION_AFTER_LAST 57 __HIBERNATION_AFTER_LAST
57}; 58};
@@ -409,6 +410,11 @@ int hibernation_snapshot(int platform_mode)
409 goto Close; 410 goto Close;
410} 411}
411 412
413int __weak hibernate_resume_nonboot_cpu_disable(void)
414{
415 return disable_nonboot_cpus();
416}
417
412/** 418/**
413 * resume_target_kernel - Restore system state from a hibernation image. 419 * resume_target_kernel - Restore system state from a hibernation image.
414 * @platform_mode: Whether or not to use the platform driver. 420 * @platform_mode: Whether or not to use the platform driver.
@@ -433,7 +439,7 @@ static int resume_target_kernel(bool platform_mode)
433 if (error) 439 if (error)
434 goto Cleanup; 440 goto Cleanup;
435 441
436 error = disable_nonboot_cpus(); 442 error = hibernate_resume_nonboot_cpu_disable();
437 if (error) 443 if (error)
438 goto Enable_cpus; 444 goto Enable_cpus;
439 445
@@ -642,12 +648,39 @@ static void power_down(void)
642 cpu_relax(); 648 cpu_relax();
643} 649}
644 650
651static int load_image_and_restore(void)
652{
653 int error;
654 unsigned int flags;
655
656 pr_debug("PM: Loading hibernation image.\n");
657
658 lock_device_hotplug();
659 error = create_basic_memory_bitmaps();
660 if (error)
661 goto Unlock;
662
663 error = swsusp_read(&flags);
664 swsusp_close(FMODE_READ);
665 if (!error)
666 hibernation_restore(flags & SF_PLATFORM_MODE);
667
668 printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
669 swsusp_free();
670 free_basic_memory_bitmaps();
671 Unlock:
672 unlock_device_hotplug();
673
674 return error;
675}
676
645/** 677/**
646 * hibernate - Carry out system hibernation, including saving the image. 678 * hibernate - Carry out system hibernation, including saving the image.
647 */ 679 */
648int hibernate(void) 680int hibernate(void)
649{ 681{
650 int error; 682 int error, nr_calls = 0;
683 bool snapshot_test = false;
651 684
652 if (!hibernation_available()) { 685 if (!hibernation_available()) {
653 pr_debug("PM: Hibernation not available.\n"); 686 pr_debug("PM: Hibernation not available.\n");
@@ -662,9 +695,11 @@ int hibernate(void)
662 } 695 }
663 696
664 pm_prepare_console(); 697 pm_prepare_console();
665 error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE); 698 error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls);
666 if (error) 699 if (error) {
700 nr_calls--;
667 goto Exit; 701 goto Exit;
702 }
668 703
669 printk(KERN_INFO "PM: Syncing filesystems ... "); 704 printk(KERN_INFO "PM: Syncing filesystems ... ");
670 sys_sync(); 705 sys_sync();
@@ -697,8 +732,12 @@ int hibernate(void)
697 pr_debug("PM: writing image.\n"); 732 pr_debug("PM: writing image.\n");
698 error = swsusp_write(flags); 733 error = swsusp_write(flags);
699 swsusp_free(); 734 swsusp_free();
700 if (!error) 735 if (!error) {
701 power_down(); 736 if (hibernation_mode == HIBERNATION_TEST_RESUME)
737 snapshot_test = true;
738 else
739 power_down();
740 }
702 in_suspend = 0; 741 in_suspend = 0;
703 pm_restore_gfp_mask(); 742 pm_restore_gfp_mask();
704 } else { 743 } else {
@@ -709,12 +748,18 @@ int hibernate(void)
709 free_basic_memory_bitmaps(); 748 free_basic_memory_bitmaps();
710 Thaw: 749 Thaw:
711 unlock_device_hotplug(); 750 unlock_device_hotplug();
751 if (snapshot_test) {
752 pr_debug("PM: Checking hibernation image\n");
753 error = swsusp_check();
754 if (!error)
755 error = load_image_and_restore();
756 }
712 thaw_processes(); 757 thaw_processes();
713 758
714 /* Don't bother checking whether freezer_test_done is true */ 759 /* Don't bother checking whether freezer_test_done is true */
715 freezer_test_done = false; 760 freezer_test_done = false;
716 Exit: 761 Exit:
717 pm_notifier_call_chain(PM_POST_HIBERNATION); 762 __pm_notifier_call_chain(PM_POST_HIBERNATION, nr_calls, NULL);
718 pm_restore_console(); 763 pm_restore_console();
719 atomic_inc(&snapshot_device_available); 764 atomic_inc(&snapshot_device_available);
720 Unlock: 765 Unlock:
@@ -740,8 +785,7 @@ int hibernate(void)
740 */ 785 */
741static int software_resume(void) 786static int software_resume(void)
742{ 787{
743 int error; 788 int error, nr_calls = 0;
744 unsigned int flags;
745 789
746 /* 790 /*
747 * If the user said "noresume".. bail out early. 791 * If the user said "noresume".. bail out early.
@@ -827,35 +871,20 @@ static int software_resume(void)
827 } 871 }
828 872
829 pm_prepare_console(); 873 pm_prepare_console();
830 error = pm_notifier_call_chain(PM_RESTORE_PREPARE); 874 error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls);
831 if (error) 875 if (error) {
876 nr_calls--;
832 goto Close_Finish; 877 goto Close_Finish;
878 }
833 879
834 pr_debug("PM: Preparing processes for restore.\n"); 880 pr_debug("PM: Preparing processes for restore.\n");
835 error = freeze_processes(); 881 error = freeze_processes();
836 if (error) 882 if (error)
837 goto Close_Finish; 883 goto Close_Finish;
838 884 error = load_image_and_restore();
839 pr_debug("PM: Loading hibernation image.\n");
840
841 lock_device_hotplug();
842 error = create_basic_memory_bitmaps();
843 if (error)
844 goto Thaw;
845
846 error = swsusp_read(&flags);
847 swsusp_close(FMODE_READ);
848 if (!error)
849 hibernation_restore(flags & SF_PLATFORM_MODE);
850
851 printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
852 swsusp_free();
853 free_basic_memory_bitmaps();
854 Thaw:
855 unlock_device_hotplug();
856 thaw_processes(); 885 thaw_processes();
857 Finish: 886 Finish:
858 pm_notifier_call_chain(PM_POST_RESTORE); 887 __pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
859 pm_restore_console(); 888 pm_restore_console();
860 atomic_inc(&snapshot_device_available); 889 atomic_inc(&snapshot_device_available);
861 /* For success case, the suspend path will release the lock */ 890 /* For success case, the suspend path will release the lock */
@@ -878,6 +907,7 @@ static const char * const hibernation_modes[] = {
878#ifdef CONFIG_SUSPEND 907#ifdef CONFIG_SUSPEND
879 [HIBERNATION_SUSPEND] = "suspend", 908 [HIBERNATION_SUSPEND] = "suspend",
880#endif 909#endif
910 [HIBERNATION_TEST_RESUME] = "test_resume",
881}; 911};
882 912
883/* 913/*
@@ -924,6 +954,7 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
924#ifdef CONFIG_SUSPEND 954#ifdef CONFIG_SUSPEND
925 case HIBERNATION_SUSPEND: 955 case HIBERNATION_SUSPEND:
926#endif 956#endif
957 case HIBERNATION_TEST_RESUME:
927 break; 958 break;
928 case HIBERNATION_PLATFORM: 959 case HIBERNATION_PLATFORM:
929 if (hibernation_ops) 960 if (hibernation_ops)
@@ -970,6 +1001,7 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
970#ifdef CONFIG_SUSPEND 1001#ifdef CONFIG_SUSPEND
971 case HIBERNATION_SUSPEND: 1002 case HIBERNATION_SUSPEND:
972#endif 1003#endif
1004 case HIBERNATION_TEST_RESUME:
973 hibernation_mode = mode; 1005 hibernation_mode = mode;
974 break; 1006 break;
975 case HIBERNATION_PLATFORM: 1007 case HIBERNATION_PLATFORM:
@@ -1115,13 +1147,16 @@ static int __init resume_offset_setup(char *str)
1115 1147
1116static int __init hibernate_setup(char *str) 1148static int __init hibernate_setup(char *str)
1117{ 1149{
1118 if (!strncmp(str, "noresume", 8)) 1150 if (!strncmp(str, "noresume", 8)) {
1119 noresume = 1; 1151 noresume = 1;
1120 else if (!strncmp(str, "nocompress", 10)) 1152 } else if (!strncmp(str, "nocompress", 10)) {
1121 nocompress = 1; 1153 nocompress = 1;
1122 else if (!strncmp(str, "no", 2)) { 1154 } else if (!strncmp(str, "no", 2)) {
1123 noresume = 1; 1155 noresume = 1;
1124 nohibernate = 1; 1156 nohibernate = 1;
1157 } else if (IS_ENABLED(CONFIG_DEBUG_RODATA)
1158 && !strncmp(str, "protect_image", 13)) {
1159 enable_restore_image_protection();
1125 } 1160 }
1126 return 1; 1161 return 1;
1127} 1162}
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 27946975eff0..5ea50b1b7595 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -38,12 +38,19 @@ int unregister_pm_notifier(struct notifier_block *nb)
38} 38}
39EXPORT_SYMBOL_GPL(unregister_pm_notifier); 39EXPORT_SYMBOL_GPL(unregister_pm_notifier);
40 40
41int pm_notifier_call_chain(unsigned long val) 41int __pm_notifier_call_chain(unsigned long val, int nr_to_call, int *nr_calls)
42{ 42{
43 int ret = blocking_notifier_call_chain(&pm_chain_head, val, NULL); 43 int ret;
44
45 ret = __blocking_notifier_call_chain(&pm_chain_head, val, NULL,
46 nr_to_call, nr_calls);
44 47
45 return notifier_to_errno(ret); 48 return notifier_to_errno(ret);
46} 49}
50int pm_notifier_call_chain(unsigned long val)
51{
52 return __pm_notifier_call_chain(val, -1, NULL);
53}
47 54
48/* If set, devices may be suspended and resumed asynchronously. */ 55/* If set, devices may be suspended and resumed asynchronously. */
49int pm_async_enabled = 1; 56int pm_async_enabled = 1;
diff --git a/kernel/power/power.h b/kernel/power/power.h
index efe1b3b17c88..242d8b827dd5 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -38,6 +38,8 @@ static inline char *check_image_kernel(struct swsusp_info *info)
38} 38}
39#endif /* CONFIG_ARCH_HIBERNATION_HEADER */ 39#endif /* CONFIG_ARCH_HIBERNATION_HEADER */
40 40
41extern int hibernate_resume_nonboot_cpu_disable(void);
42
41/* 43/*
42 * Keep some memory free so that I/O operations can succeed without paging 44 * Keep some memory free so that I/O operations can succeed without paging
43 * [Might this be more than 4 MB?] 45 * [Might this be more than 4 MB?]
@@ -59,6 +61,13 @@ extern int hibernation_snapshot(int platform_mode);
59extern int hibernation_restore(int platform_mode); 61extern int hibernation_restore(int platform_mode);
60extern int hibernation_platform_enter(void); 62extern int hibernation_platform_enter(void);
61 63
64#ifdef CONFIG_DEBUG_RODATA
65/* kernel/power/snapshot.c */
66extern void enable_restore_image_protection(void);
67#else
68static inline void enable_restore_image_protection(void) {}
69#endif /* CONFIG_DEBUG_RODATA */
70
62#else /* !CONFIG_HIBERNATION */ 71#else /* !CONFIG_HIBERNATION */
63 72
64static inline void hibernate_reserved_size_init(void) {} 73static inline void hibernate_reserved_size_init(void) {}
@@ -200,6 +209,8 @@ static inline void suspend_test_finish(const char *label) {}
200 209
201#ifdef CONFIG_PM_SLEEP 210#ifdef CONFIG_PM_SLEEP
202/* kernel/power/main.c */ 211/* kernel/power/main.c */
212extern int __pm_notifier_call_chain(unsigned long val, int nr_to_call,
213 int *nr_calls);
203extern int pm_notifier_call_chain(unsigned long val); 214extern int pm_notifier_call_chain(unsigned long val);
204#endif 215#endif
205 216
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 0c2ee9761d57..8f27d5a8adf6 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -89,6 +89,9 @@ static int try_to_freeze_tasks(bool user_only)
89 elapsed_msecs / 1000, elapsed_msecs % 1000, 89 elapsed_msecs / 1000, elapsed_msecs % 1000,
90 todo - wq_busy, wq_busy); 90 todo - wq_busy, wq_busy);
91 91
92 if (wq_busy)
93 show_workqueue_state();
94
92 if (!wakeup) { 95 if (!wakeup) {
93 read_lock(&tasklist_lock); 96 read_lock(&tasklist_lock);
94 for_each_process_thread(g, p) { 97 for_each_process_thread(g, p) {
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 3a970604308f..d90df926b59f 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -38,6 +38,43 @@
38 38
39#include "power.h" 39#include "power.h"
40 40
41#ifdef CONFIG_DEBUG_RODATA
42static bool hibernate_restore_protection;
43static bool hibernate_restore_protection_active;
44
45void enable_restore_image_protection(void)
46{
47 hibernate_restore_protection = true;
48}
49
50static inline void hibernate_restore_protection_begin(void)
51{
52 hibernate_restore_protection_active = hibernate_restore_protection;
53}
54
55static inline void hibernate_restore_protection_end(void)
56{
57 hibernate_restore_protection_active = false;
58}
59
60static inline void hibernate_restore_protect_page(void *page_address)
61{
62 if (hibernate_restore_protection_active)
63 set_memory_ro((unsigned long)page_address, 1);
64}
65
66static inline void hibernate_restore_unprotect_page(void *page_address)
67{
68 if (hibernate_restore_protection_active)
69 set_memory_rw((unsigned long)page_address, 1);
70}
71#else
72static inline void hibernate_restore_protection_begin(void) {}
73static inline void hibernate_restore_protection_end(void) {}
74static inline void hibernate_restore_protect_page(void *page_address) {}
75static inline void hibernate_restore_unprotect_page(void *page_address) {}
76#endif /* CONFIG_DEBUG_RODATA */
77
41static int swsusp_page_is_free(struct page *); 78static int swsusp_page_is_free(struct page *);
42static void swsusp_set_page_forbidden(struct page *); 79static void swsusp_set_page_forbidden(struct page *);
43static void swsusp_unset_page_forbidden(struct page *); 80static void swsusp_unset_page_forbidden(struct page *);
@@ -67,25 +104,32 @@ void __init hibernate_image_size_init(void)
67 image_size = ((totalram_pages * 2) / 5) * PAGE_SIZE; 104 image_size = ((totalram_pages * 2) / 5) * PAGE_SIZE;
68} 105}
69 106
70/* List of PBEs needed for restoring the pages that were allocated before 107/*
108 * List of PBEs needed for restoring the pages that were allocated before
71 * the suspend and included in the suspend image, but have also been 109 * the suspend and included in the suspend image, but have also been
72 * allocated by the "resume" kernel, so their contents cannot be written 110 * allocated by the "resume" kernel, so their contents cannot be written
73 * directly to their "original" page frames. 111 * directly to their "original" page frames.
74 */ 112 */
75struct pbe *restore_pblist; 113struct pbe *restore_pblist;
76 114
77/* Pointer to an auxiliary buffer (1 page) */ 115/* struct linked_page is used to build chains of pages */
78static void *buffer;
79 116
80/** 117#define LINKED_PAGE_DATA_SIZE (PAGE_SIZE - sizeof(void *))
81 * @safe_needed - on resume, for storing the PBE list and the image, 118
82 * we can only use memory pages that do not conflict with the pages 119struct linked_page {
83 * used before suspend. The unsafe pages have PageNosaveFree set 120 struct linked_page *next;
84 * and we count them using unsafe_pages. 121 char data[LINKED_PAGE_DATA_SIZE];
85 * 122} __packed;
86 * Each allocated image page is marked as PageNosave and PageNosaveFree 123
87 * so that swsusp_free() can release it. 124/*
125 * List of "safe" pages (ie. pages that were not used by the image kernel
126 * before hibernation) that may be used as temporary storage for image kernel
127 * memory contents.
88 */ 128 */
129static struct linked_page *safe_pages_list;
130
131/* Pointer to an auxiliary buffer (1 page) */
132static void *buffer;
89 133
90#define PG_ANY 0 134#define PG_ANY 0
91#define PG_SAFE 1 135#define PG_SAFE 1
@@ -94,6 +138,19 @@ static void *buffer;
94 138
95static unsigned int allocated_unsafe_pages; 139static unsigned int allocated_unsafe_pages;
96 140
141/**
142 * get_image_page - Allocate a page for a hibernation image.
143 * @gfp_mask: GFP mask for the allocation.
144 * @safe_needed: Get pages that were not used before hibernation (restore only)
145 *
146 * During image restoration, for storing the PBE list and the image data, we can
147 * only use memory pages that do not conflict with the pages used before
148 * hibernation. The "unsafe" pages have PageNosaveFree set and we count them
149 * using allocated_unsafe_pages.
150 *
151 * Each allocated image page is marked as PageNosave and PageNosaveFree so that
152 * swsusp_free() can release it.
153 */
97static void *get_image_page(gfp_t gfp_mask, int safe_needed) 154static void *get_image_page(gfp_t gfp_mask, int safe_needed)
98{ 155{
99 void *res; 156 void *res;
@@ -113,9 +170,21 @@ static void *get_image_page(gfp_t gfp_mask, int safe_needed)
113 return res; 170 return res;
114} 171}
115 172
173static void *__get_safe_page(gfp_t gfp_mask)
174{
175 if (safe_pages_list) {
176 void *ret = safe_pages_list;
177
178 safe_pages_list = safe_pages_list->next;
179 memset(ret, 0, PAGE_SIZE);
180 return ret;
181 }
182 return get_image_page(gfp_mask, PG_SAFE);
183}
184
116unsigned long get_safe_page(gfp_t gfp_mask) 185unsigned long get_safe_page(gfp_t gfp_mask)
117{ 186{
118 return (unsigned long)get_image_page(gfp_mask, PG_SAFE); 187 return (unsigned long)__get_safe_page(gfp_mask);
119} 188}
120 189
121static struct page *alloc_image_page(gfp_t gfp_mask) 190static struct page *alloc_image_page(gfp_t gfp_mask)
@@ -130,11 +199,22 @@ static struct page *alloc_image_page(gfp_t gfp_mask)
130 return page; 199 return page;
131} 200}
132 201
202static void recycle_safe_page(void *page_address)
203{
204 struct linked_page *lp = page_address;
205
206 lp->next = safe_pages_list;
207 safe_pages_list = lp;
208}
209
133/** 210/**
134 * free_image_page - free page represented by @addr, allocated with 211 * free_image_page - Free a page allocated for hibernation image.
135 * get_image_page (page flags set by it must be cleared) 212 * @addr: Address of the page to free.
213 * @clear_nosave_free: If set, clear the PageNosaveFree bit for the page.
214 *
215 * The page to free should have been allocated by get_image_page() (page flags
216 * set by it are affected).
136 */ 217 */
137
138static inline void free_image_page(void *addr, int clear_nosave_free) 218static inline void free_image_page(void *addr, int clear_nosave_free)
139{ 219{
140 struct page *page; 220 struct page *page;
@@ -150,17 +230,8 @@ static inline void free_image_page(void *addr, int clear_nosave_free)
150 __free_page(page); 230 __free_page(page);
151} 231}
152 232
153/* struct linked_page is used to build chains of pages */ 233static inline void free_list_of_pages(struct linked_page *list,
154 234 int clear_page_nosave)
155#define LINKED_PAGE_DATA_SIZE (PAGE_SIZE - sizeof(void *))
156
157struct linked_page {
158 struct linked_page *next;
159 char data[LINKED_PAGE_DATA_SIZE];
160} __packed;
161
162static inline void
163free_list_of_pages(struct linked_page *list, int clear_page_nosave)
164{ 235{
165 while (list) { 236 while (list) {
166 struct linked_page *lp = list->next; 237 struct linked_page *lp = list->next;
@@ -170,30 +241,28 @@ free_list_of_pages(struct linked_page *list, int clear_page_nosave)
170 } 241 }
171} 242}
172 243
173/** 244/*
174 * struct chain_allocator is used for allocating small objects out of 245 * struct chain_allocator is used for allocating small objects out of
175 * a linked list of pages called 'the chain'. 246 * a linked list of pages called 'the chain'.
176 * 247 *
177 * The chain grows each time when there is no room for a new object in 248 * The chain grows each time when there is no room for a new object in
178 * the current page. The allocated objects cannot be freed individually. 249 * the current page. The allocated objects cannot be freed individually.
179 * It is only possible to free them all at once, by freeing the entire 250 * It is only possible to free them all at once, by freeing the entire
180 * chain. 251 * chain.
181 * 252 *
182 * NOTE: The chain allocator may be inefficient if the allocated objects 253 * NOTE: The chain allocator may be inefficient if the allocated objects
183 * are not much smaller than PAGE_SIZE. 254 * are not much smaller than PAGE_SIZE.
184 */ 255 */
185
186struct chain_allocator { 256struct chain_allocator {
187 struct linked_page *chain; /* the chain */ 257 struct linked_page *chain; /* the chain */
188 unsigned int used_space; /* total size of objects allocated out 258 unsigned int used_space; /* total size of objects allocated out
189 * of the current page 259 of the current page */
190 */
191 gfp_t gfp_mask; /* mask for allocating pages */ 260 gfp_t gfp_mask; /* mask for allocating pages */
192 int safe_needed; /* if set, only "safe" pages are allocated */ 261 int safe_needed; /* if set, only "safe" pages are allocated */
193}; 262};
194 263
195static void 264static void chain_init(struct chain_allocator *ca, gfp_t gfp_mask,
196chain_init(struct chain_allocator *ca, gfp_t gfp_mask, int safe_needed) 265 int safe_needed)
197{ 266{
198 ca->chain = NULL; 267 ca->chain = NULL;
199 ca->used_space = LINKED_PAGE_DATA_SIZE; 268 ca->used_space = LINKED_PAGE_DATA_SIZE;
@@ -208,7 +277,8 @@ static void *chain_alloc(struct chain_allocator *ca, unsigned int size)
208 if (LINKED_PAGE_DATA_SIZE - ca->used_space < size) { 277 if (LINKED_PAGE_DATA_SIZE - ca->used_space < size) {
209 struct linked_page *lp; 278 struct linked_page *lp;
210 279
211 lp = get_image_page(ca->gfp_mask, ca->safe_needed); 280 lp = ca->safe_needed ? __get_safe_page(ca->gfp_mask) :
281 get_image_page(ca->gfp_mask, PG_ANY);
212 if (!lp) 282 if (!lp)
213 return NULL; 283 return NULL;
214 284
@@ -222,44 +292,44 @@ static void *chain_alloc(struct chain_allocator *ca, unsigned int size)
222} 292}
223 293
224/** 294/**
225 * Data types related to memory bitmaps. 295 * Data types related to memory bitmaps.
226 * 296 *
227 * Memory bitmap is a structure consiting of many linked lists of 297 * Memory bitmap is a structure consiting of many linked lists of
228 * objects. The main list's elements are of type struct zone_bitmap 298 * objects. The main list's elements are of type struct zone_bitmap
229 * and each of them corresonds to one zone. For each zone bitmap 299 * and each of them corresonds to one zone. For each zone bitmap
230 * object there is a list of objects of type struct bm_block that 300 * object there is a list of objects of type struct bm_block that
231 * represent each blocks of bitmap in which information is stored. 301 * represent each blocks of bitmap in which information is stored.
232 * 302 *
233 * struct memory_bitmap contains a pointer to the main list of zone 303 * struct memory_bitmap contains a pointer to the main list of zone
234 * bitmap objects, a struct bm_position used for browsing the bitmap, 304 * bitmap objects, a struct bm_position used for browsing the bitmap,
235 * and a pointer to the list of pages used for allocating all of the 305 * and a pointer to the list of pages used for allocating all of the
236 * zone bitmap objects and bitmap block objects. 306 * zone bitmap objects and bitmap block objects.
237 * 307 *
238 * NOTE: It has to be possible to lay out the bitmap in memory 308 * NOTE: It has to be possible to lay out the bitmap in memory
239 * using only allocations of order 0. Additionally, the bitmap is 309 * using only allocations of order 0. Additionally, the bitmap is
240 * designed to work with arbitrary number of zones (this is over the 310 * designed to work with arbitrary number of zones (this is over the
241 * top for now, but let's avoid making unnecessary assumptions ;-). 311 * top for now, but let's avoid making unnecessary assumptions ;-).
242 * 312 *
243 * struct zone_bitmap contains a pointer to a list of bitmap block 313 * struct zone_bitmap contains a pointer to a list of bitmap block
244 * objects and a pointer to the bitmap block object that has been 314 * objects and a pointer to the bitmap block object that has been
245 * most recently used for setting bits. Additionally, it contains the 315 * most recently used for setting bits. Additionally, it contains the
246 * pfns that correspond to the start and end of the represented zone. 316 * PFNs that correspond to the start and end of the represented zone.
247 * 317 *
248 * struct bm_block contains a pointer to the memory page in which 318 * struct bm_block contains a pointer to the memory page in which
249 * information is stored (in the form of a block of bitmap) 319 * information is stored (in the form of a block of bitmap)
250 * It also contains the pfns that correspond to the start and end of 320 * It also contains the pfns that correspond to the start and end of
251 * the represented memory area. 321 * the represented memory area.
252 * 322 *
253 * The memory bitmap is organized as a radix tree to guarantee fast random 323 * The memory bitmap is organized as a radix tree to guarantee fast random
254 * access to the bits. There is one radix tree for each zone (as returned 324 * access to the bits. There is one radix tree for each zone (as returned
255 * from create_mem_extents). 325 * from create_mem_extents).
256 * 326 *
257 * One radix tree is represented by one struct mem_zone_bm_rtree. There are 327 * One radix tree is represented by one struct mem_zone_bm_rtree. There are
258 * two linked lists for the nodes of the tree, one for the inner nodes and 328 * two linked lists for the nodes of the tree, one for the inner nodes and
259 * one for the leave nodes. The linked leave nodes are used for fast linear 329 * one for the leave nodes. The linked leave nodes are used for fast linear
260 * access of the memory bitmap. 330 * access of the memory bitmap.
261 * 331 *
262 * The struct rtree_node represents one node of the radix tree. 332 * The struct rtree_node represents one node of the radix tree.
263 */ 333 */
264 334
265#define BM_END_OF_MAP (~0UL) 335#define BM_END_OF_MAP (~0UL)
@@ -305,9 +375,8 @@ struct bm_position {
305struct memory_bitmap { 375struct memory_bitmap {
306 struct list_head zones; 376 struct list_head zones;
307 struct linked_page *p_list; /* list of pages used to store zone 377 struct linked_page *p_list; /* list of pages used to store zone
308 * bitmap objects and bitmap block 378 bitmap objects and bitmap block
309 * objects 379 objects */
310 */
311 struct bm_position cur; /* most recently used bit position */ 380 struct bm_position cur; /* most recently used bit position */
312}; 381};
313 382
@@ -321,12 +390,12 @@ struct memory_bitmap {
321#endif 390#endif
322#define BM_RTREE_LEVEL_MASK ((1UL << BM_RTREE_LEVEL_SHIFT) - 1) 391#define BM_RTREE_LEVEL_MASK ((1UL << BM_RTREE_LEVEL_SHIFT) - 1)
323 392
324/* 393/**
325 * alloc_rtree_node - Allocate a new node and add it to the radix tree. 394 * alloc_rtree_node - Allocate a new node and add it to the radix tree.
326 * 395 *
327 * This function is used to allocate inner nodes as well as the 396 * This function is used to allocate inner nodes as well as the
328 * leave nodes of the radix tree. It also adds the node to the 397 * leave nodes of the radix tree. It also adds the node to the
329 * corresponding linked list passed in by the *list parameter. 398 * corresponding linked list passed in by the *list parameter.
330 */ 399 */
331static struct rtree_node *alloc_rtree_node(gfp_t gfp_mask, int safe_needed, 400static struct rtree_node *alloc_rtree_node(gfp_t gfp_mask, int safe_needed,
332 struct chain_allocator *ca, 401 struct chain_allocator *ca,
@@ -347,12 +416,12 @@ static struct rtree_node *alloc_rtree_node(gfp_t gfp_mask, int safe_needed,
347 return node; 416 return node;
348} 417}
349 418
350/* 419/**
351 * add_rtree_block - Add a new leave node to the radix tree 420 * add_rtree_block - Add a new leave node to the radix tree.
352 * 421 *
353 * The leave nodes need to be allocated in order to keep the leaves 422 * The leave nodes need to be allocated in order to keep the leaves
354 * linked list in order. This is guaranteed by the zone->blocks 423 * linked list in order. This is guaranteed by the zone->blocks
355 * counter. 424 * counter.
356 */ 425 */
357static int add_rtree_block(struct mem_zone_bm_rtree *zone, gfp_t gfp_mask, 426static int add_rtree_block(struct mem_zone_bm_rtree *zone, gfp_t gfp_mask,
358 int safe_needed, struct chain_allocator *ca) 427 int safe_needed, struct chain_allocator *ca)
@@ -417,17 +486,18 @@ static int add_rtree_block(struct mem_zone_bm_rtree *zone, gfp_t gfp_mask,
417static void free_zone_bm_rtree(struct mem_zone_bm_rtree *zone, 486static void free_zone_bm_rtree(struct mem_zone_bm_rtree *zone,
418 int clear_nosave_free); 487 int clear_nosave_free);
419 488
420/* 489/**
421 * create_zone_bm_rtree - create a radix tree for one zone 490 * create_zone_bm_rtree - Create a radix tree for one zone.
422 * 491 *
423 * Allocated the mem_zone_bm_rtree structure and initializes it. 492 * Allocated the mem_zone_bm_rtree structure and initializes it.
424 * This function also allocated and builds the radix tree for the 493 * This function also allocated and builds the radix tree for the
425 * zone. 494 * zone.
426 */ 495 */
427static struct mem_zone_bm_rtree * 496static struct mem_zone_bm_rtree *create_zone_bm_rtree(gfp_t gfp_mask,
428create_zone_bm_rtree(gfp_t gfp_mask, int safe_needed, 497 int safe_needed,
429 struct chain_allocator *ca, 498 struct chain_allocator *ca,
430 unsigned long start, unsigned long end) 499 unsigned long start,
500 unsigned long end)
431{ 501{
432 struct mem_zone_bm_rtree *zone; 502 struct mem_zone_bm_rtree *zone;
433 unsigned int i, nr_blocks; 503 unsigned int i, nr_blocks;
@@ -454,12 +524,12 @@ create_zone_bm_rtree(gfp_t gfp_mask, int safe_needed,
454 return zone; 524 return zone;
455} 525}
456 526
457/* 527/**
458 * free_zone_bm_rtree - Free the memory of the radix tree 528 * free_zone_bm_rtree - Free the memory of the radix tree.
459 * 529 *
460 * Free all node pages of the radix tree. The mem_zone_bm_rtree 530 * Free all node pages of the radix tree. The mem_zone_bm_rtree
461 * structure itself is not freed here nor are the rtree_node 531 * structure itself is not freed here nor are the rtree_node
462 * structs. 532 * structs.
463 */ 533 */
464static void free_zone_bm_rtree(struct mem_zone_bm_rtree *zone, 534static void free_zone_bm_rtree(struct mem_zone_bm_rtree *zone,
465 int clear_nosave_free) 535 int clear_nosave_free)
@@ -492,8 +562,8 @@ struct mem_extent {
492}; 562};
493 563
494/** 564/**
495 * free_mem_extents - free a list of memory extents 565 * free_mem_extents - Free a list of memory extents.
496 * @list - list of extents to empty 566 * @list: List of extents to free.
497 */ 567 */
498static void free_mem_extents(struct list_head *list) 568static void free_mem_extents(struct list_head *list)
499{ 569{
@@ -506,10 +576,11 @@ static void free_mem_extents(struct list_head *list)
506} 576}
507 577
508/** 578/**
509 * create_mem_extents - create a list of memory extents representing 579 * create_mem_extents - Create a list of memory extents.
510 * contiguous ranges of PFNs 580 * @list: List to put the extents into.
511 * @list - list to put the extents into 581 * @gfp_mask: Mask to use for memory allocations.
512 * @gfp_mask - mask to use for memory allocations 582 *
583 * The extents represent contiguous ranges of PFNs.
513 */ 584 */
514static int create_mem_extents(struct list_head *list, gfp_t gfp_mask) 585static int create_mem_extents(struct list_head *list, gfp_t gfp_mask)
515{ 586{
@@ -565,10 +636,10 @@ static int create_mem_extents(struct list_head *list, gfp_t gfp_mask)
565} 636}
566 637
567/** 638/**
568 * memory_bm_create - allocate memory for a memory bitmap 639 * memory_bm_create - Allocate memory for a memory bitmap.
569 */ 640 */
570static int 641static int memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask,
571memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed) 642 int safe_needed)
572{ 643{
573 struct chain_allocator ca; 644 struct chain_allocator ca;
574 struct list_head mem_extents; 645 struct list_head mem_extents;
@@ -607,8 +678,9 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed)
607} 678}
608 679
609/** 680/**
610 * memory_bm_free - free memory occupied by the memory bitmap @bm 681 * memory_bm_free - Free memory occupied by the memory bitmap.
611 */ 682 * @bm: Memory bitmap.
683 */
612static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free) 684static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free)
613{ 685{
614 struct mem_zone_bm_rtree *zone; 686 struct mem_zone_bm_rtree *zone;
@@ -622,14 +694,13 @@ static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free)
622} 694}
623 695
624/** 696/**
625 * memory_bm_find_bit - Find the bit for pfn in the memory 697 * memory_bm_find_bit - Find the bit for a given PFN in a memory bitmap.
626 * bitmap
627 * 698 *
628 * Find the bit in the bitmap @bm that corresponds to given pfn. 699 * Find the bit in memory bitmap @bm that corresponds to the given PFN.
629 * The cur.zone, cur.block and cur.node_pfn member of @bm are 700 * The cur.zone, cur.block and cur.node_pfn members of @bm are updated.
630 * updated. 701 *
631 * It walks the radix tree to find the page which contains the bit for 702 * Walk the radix tree to find the page containing the bit that represents @pfn
632 * pfn and returns the bit position in **addr and *bit_nr. 703 * and return the position of the bit in @addr and @bit_nr.
633 */ 704 */
634static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, 705static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
635 void **addr, unsigned int *bit_nr) 706 void **addr, unsigned int *bit_nr)
@@ -658,10 +729,9 @@ static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
658 729
659zone_found: 730zone_found:
660 /* 731 /*
661 * We have a zone. Now walk the radix tree to find the leave 732 * We have found the zone. Now walk the radix tree to find the leaf node
662 * node for our pfn. 733 * for our PFN.
663 */ 734 */
664
665 node = bm->cur.node; 735 node = bm->cur.node;
666 if (((pfn - zone->start_pfn) & ~BM_BLOCK_MASK) == bm->cur.node_pfn) 736 if (((pfn - zone->start_pfn) & ~BM_BLOCK_MASK) == bm->cur.node_pfn)
667 goto node_found; 737 goto node_found;
@@ -754,14 +824,14 @@ static bool memory_bm_pfn_present(struct memory_bitmap *bm, unsigned long pfn)
754} 824}
755 825
756/* 826/*
757 * rtree_next_node - Jumps to the next leave node 827 * rtree_next_node - Jump to the next leaf node.
758 * 828 *
759 * Sets the position to the beginning of the next node in the 829 * Set the position to the beginning of the next node in the
760 * memory bitmap. This is either the next node in the current 830 * memory bitmap. This is either the next node in the current
761 * zone's radix tree or the first node in the radix tree of the 831 * zone's radix tree or the first node in the radix tree of the
762 * next zone. 832 * next zone.
763 * 833 *
764 * Returns true if there is a next node, false otherwise. 834 * Return true if there is a next node, false otherwise.
765 */ 835 */
766static bool rtree_next_node(struct memory_bitmap *bm) 836static bool rtree_next_node(struct memory_bitmap *bm)
767{ 837{
@@ -790,14 +860,15 @@ static bool rtree_next_node(struct memory_bitmap *bm)
790} 860}
791 861
792/** 862/**
793 * memory_bm_rtree_next_pfn - Find the next set bit in the bitmap @bm 863 * memory_bm_rtree_next_pfn - Find the next set bit in a memory bitmap.
864 * @bm: Memory bitmap.
794 * 865 *
795 * Starting from the last returned position this function searches 866 * Starting from the last returned position this function searches for the next
796 * for the next set bit in the memory bitmap and returns its 867 * set bit in @bm and returns the PFN represented by it. If no more bits are
797 * number. If no more bit is set BM_END_OF_MAP is returned. 868 * set, BM_END_OF_MAP is returned.
798 * 869 *
799 * It is required to run memory_bm_position_reset() before the 870 * It is required to run memory_bm_position_reset() before the first call to
800 * first call to this function. 871 * this function for the given memory bitmap.
801 */ 872 */
802static unsigned long memory_bm_next_pfn(struct memory_bitmap *bm) 873static unsigned long memory_bm_next_pfn(struct memory_bitmap *bm)
803{ 874{
@@ -819,11 +890,10 @@ static unsigned long memory_bm_next_pfn(struct memory_bitmap *bm)
819 return BM_END_OF_MAP; 890 return BM_END_OF_MAP;
820} 891}
821 892
822/** 893/*
823 * This structure represents a range of page frames the contents of which 894 * This structure represents a range of page frames the contents of which
824 * should not be saved during the suspend. 895 * should not be saved during hibernation.
825 */ 896 */
826
827struct nosave_region { 897struct nosave_region {
828 struct list_head list; 898 struct list_head list;
829 unsigned long start_pfn; 899 unsigned long start_pfn;
@@ -832,15 +902,42 @@ struct nosave_region {
832 902
833static LIST_HEAD(nosave_regions); 903static LIST_HEAD(nosave_regions);
834 904
905static void recycle_zone_bm_rtree(struct mem_zone_bm_rtree *zone)
906{
907 struct rtree_node *node;
908
909 list_for_each_entry(node, &zone->nodes, list)
910 recycle_safe_page(node->data);
911
912 list_for_each_entry(node, &zone->leaves, list)
913 recycle_safe_page(node->data);
914}
915
916static void memory_bm_recycle(struct memory_bitmap *bm)
917{
918 struct mem_zone_bm_rtree *zone;
919 struct linked_page *p_list;
920
921 list_for_each_entry(zone, &bm->zones, list)
922 recycle_zone_bm_rtree(zone);
923
924 p_list = bm->p_list;
925 while (p_list) {
926 struct linked_page *lp = p_list;
927
928 p_list = lp->next;
929 recycle_safe_page(lp);
930 }
931}
932
835/** 933/**
836 * register_nosave_region - register a range of page frames the contents 934 * register_nosave_region - Register a region of unsaveable memory.
837 * of which should not be saved during the suspend (to be used in the early 935 *
838 * initialization code) 936 * Register a range of page frames the contents of which should not be saved
937 * during hibernation (to be used in the early initialization code).
839 */ 938 */
840 939void __init __register_nosave_region(unsigned long start_pfn,
841void __init 940 unsigned long end_pfn, int use_kmalloc)
842__register_nosave_region(unsigned long start_pfn, unsigned long end_pfn,
843 int use_kmalloc)
844{ 941{
845 struct nosave_region *region; 942 struct nosave_region *region;
846 943
@@ -857,12 +954,13 @@ __register_nosave_region(unsigned long start_pfn, unsigned long end_pfn,
857 } 954 }
858 } 955 }
859 if (use_kmalloc) { 956 if (use_kmalloc) {
860 /* during init, this shouldn't fail */ 957 /* During init, this shouldn't fail */
861 region = kmalloc(sizeof(struct nosave_region), GFP_KERNEL); 958 region = kmalloc(sizeof(struct nosave_region), GFP_KERNEL);
862 BUG_ON(!region); 959 BUG_ON(!region);
863 } else 960 } else {
864 /* This allocation cannot fail */ 961 /* This allocation cannot fail */
865 region = memblock_virt_alloc(sizeof(struct nosave_region), 0); 962 region = memblock_virt_alloc(sizeof(struct nosave_region), 0);
963 }
866 region->start_pfn = start_pfn; 964 region->start_pfn = start_pfn;
867 region->end_pfn = end_pfn; 965 region->end_pfn = end_pfn;
868 list_add_tail(&region->list, &nosave_regions); 966 list_add_tail(&region->list, &nosave_regions);
@@ -923,10 +1021,12 @@ static void swsusp_unset_page_forbidden(struct page *page)
923} 1021}
924 1022
925/** 1023/**
926 * mark_nosave_pages - set bits corresponding to the page frames the 1024 * mark_nosave_pages - Mark pages that should not be saved.
927 * contents of which should not be saved in a given bitmap. 1025 * @bm: Memory bitmap.
1026 *
1027 * Set the bits in @bm that correspond to the page frames the contents of which
1028 * should not be saved.
928 */ 1029 */
929
930static void mark_nosave_pages(struct memory_bitmap *bm) 1030static void mark_nosave_pages(struct memory_bitmap *bm)
931{ 1031{
932 struct nosave_region *region; 1032 struct nosave_region *region;
@@ -956,13 +1056,13 @@ static void mark_nosave_pages(struct memory_bitmap *bm)
956} 1056}
957 1057
958/** 1058/**
959 * create_basic_memory_bitmaps - create bitmaps needed for marking page 1059 * create_basic_memory_bitmaps - Create bitmaps to hold basic page information.
960 * frames that should not be saved and free page frames. The pointers 1060 *
961 * forbidden_pages_map and free_pages_map are only modified if everything 1061 * Create bitmaps needed for marking page frames that should not be saved and
962 * goes well, because we don't want the bits to be used before both bitmaps 1062 * free page frames. The forbidden_pages_map and free_pages_map pointers are
963 * are set up. 1063 * only modified if everything goes well, because we don't want the bits to be
1064 * touched before both bitmaps are set up.
964 */ 1065 */
965
966int create_basic_memory_bitmaps(void) 1066int create_basic_memory_bitmaps(void)
967{ 1067{
968 struct memory_bitmap *bm1, *bm2; 1068 struct memory_bitmap *bm1, *bm2;
@@ -1007,12 +1107,12 @@ int create_basic_memory_bitmaps(void)
1007} 1107}
1008 1108
1009/** 1109/**
1010 * free_basic_memory_bitmaps - free memory bitmaps allocated by 1110 * free_basic_memory_bitmaps - Free memory bitmaps holding basic information.
1011 * create_basic_memory_bitmaps(). The auxiliary pointers are necessary 1111 *
1012 * so that the bitmaps themselves are not referred to while they are being 1112 * Free memory bitmaps allocated by create_basic_memory_bitmaps(). The
1013 * freed. 1113 * auxiliary pointers are necessary so that the bitmaps themselves are not
1114 * referred to while they are being freed.
1014 */ 1115 */
1015
1016void free_basic_memory_bitmaps(void) 1116void free_basic_memory_bitmaps(void)
1017{ 1117{
1018 struct memory_bitmap *bm1, *bm2; 1118 struct memory_bitmap *bm1, *bm2;
@@ -1033,11 +1133,13 @@ void free_basic_memory_bitmaps(void)
1033} 1133}
1034 1134
1035/** 1135/**
1036 * snapshot_additional_pages - estimate the number of additional pages 1136 * snapshot_additional_pages - Estimate the number of extra pages needed.
1037 * be needed for setting up the suspend image data structures for given 1137 * @zone: Memory zone to carry out the computation for.
1038 * zone (usually the returned value is greater than the exact number) 1138 *
1139 * Estimate the number of additional pages needed for setting up a hibernation
1140 * image data structures for @zone (usually, the returned value is greater than
1141 * the exact number).
1039 */ 1142 */
1040
1041unsigned int snapshot_additional_pages(struct zone *zone) 1143unsigned int snapshot_additional_pages(struct zone *zone)
1042{ 1144{
1043 unsigned int rtree, nodes; 1145 unsigned int rtree, nodes;
@@ -1055,10 +1157,10 @@ unsigned int snapshot_additional_pages(struct zone *zone)
1055 1157
1056#ifdef CONFIG_HIGHMEM 1158#ifdef CONFIG_HIGHMEM
1057/** 1159/**
1058 * count_free_highmem_pages - compute the total number of free highmem 1160 * count_free_highmem_pages - Compute the total number of free highmem pages.
1059 * pages, system-wide. 1161 *
1162 * The returned number is system-wide.
1060 */ 1163 */
1061
1062static unsigned int count_free_highmem_pages(void) 1164static unsigned int count_free_highmem_pages(void)
1063{ 1165{
1064 struct zone *zone; 1166 struct zone *zone;
@@ -1072,11 +1174,12 @@ static unsigned int count_free_highmem_pages(void)
1072} 1174}
1073 1175
1074/** 1176/**
1075 * saveable_highmem_page - Determine whether a highmem page should be 1177 * saveable_highmem_page - Check if a highmem page is saveable.
1076 * included in the suspend image.
1077 * 1178 *
1078 * We should save the page if it isn't Nosave or NosaveFree, or Reserved, 1179 * Determine whether a highmem page should be included in a hibernation image.
1079 * and it isn't a part of a free chunk of pages. 1180 *
1181 * We should save the page if it isn't Nosave or NosaveFree, or Reserved,
1182 * and it isn't part of a free chunk of pages.
1080 */ 1183 */
1081static struct page *saveable_highmem_page(struct zone *zone, unsigned long pfn) 1184static struct page *saveable_highmem_page(struct zone *zone, unsigned long pfn)
1082{ 1185{
@@ -1102,10 +1205,8 @@ static struct page *saveable_highmem_page(struct zone *zone, unsigned long pfn)
1102} 1205}
1103 1206
1104/** 1207/**
1105 * count_highmem_pages - compute the total number of saveable highmem 1208 * count_highmem_pages - Compute the total number of saveable highmem pages.
1106 * pages.
1107 */ 1209 */
1108
1109static unsigned int count_highmem_pages(void) 1210static unsigned int count_highmem_pages(void)
1110{ 1211{
1111 struct zone *zone; 1212 struct zone *zone;
@@ -1133,12 +1234,14 @@ static inline void *saveable_highmem_page(struct zone *z, unsigned long p)
1133#endif /* CONFIG_HIGHMEM */ 1234#endif /* CONFIG_HIGHMEM */
1134 1235
1135/** 1236/**
1136 * saveable_page - Determine whether a non-highmem page should be included 1237 * saveable_page - Check if the given page is saveable.
1137 * in the suspend image.
1138 * 1238 *
1139 * We should save the page if it isn't Nosave, and is not in the range 1239 * Determine whether a non-highmem page should be included in a hibernation
1140 * of pages statically defined as 'unsaveable', and it isn't a part of 1240 * image.
1141 * a free chunk of pages. 1241 *
1242 * We should save the page if it isn't Nosave, and is not in the range
1243 * of pages statically defined as 'unsaveable', and it isn't part of
1244 * a free chunk of pages.
1142 */ 1245 */
1143static struct page *saveable_page(struct zone *zone, unsigned long pfn) 1246static struct page *saveable_page(struct zone *zone, unsigned long pfn)
1144{ 1247{
@@ -1167,10 +1270,8 @@ static struct page *saveable_page(struct zone *zone, unsigned long pfn)
1167} 1270}
1168 1271
1169/** 1272/**
1170 * count_data_pages - compute the total number of saveable non-highmem 1273 * count_data_pages - Compute the total number of saveable non-highmem pages.
1171 * pages.
1172 */ 1274 */
1173
1174static unsigned int count_data_pages(void) 1275static unsigned int count_data_pages(void)
1175{ 1276{
1176 struct zone *zone; 1277 struct zone *zone;
@@ -1190,7 +1291,8 @@ static unsigned int count_data_pages(void)
1190 return n; 1291 return n;
1191} 1292}
1192 1293
1193/* This is needed, because copy_page and memcpy are not usable for copying 1294/*
1295 * This is needed, because copy_page and memcpy are not usable for copying
1194 * task structs. 1296 * task structs.
1195 */ 1297 */
1196static inline void do_copy_page(long *dst, long *src) 1298static inline void do_copy_page(long *dst, long *src)
@@ -1201,12 +1303,12 @@ static inline void do_copy_page(long *dst, long *src)
1201 *dst++ = *src++; 1303 *dst++ = *src++;
1202} 1304}
1203 1305
1204
1205/** 1306/**
1206 * safe_copy_page - check if the page we are going to copy is marked as 1307 * safe_copy_page - Copy a page in a safe way.
1207 * present in the kernel page tables (this always is the case if 1308 *
1208 * CONFIG_DEBUG_PAGEALLOC is not set and in that case 1309 * Check if the page we are going to copy is marked as present in the kernel
1209 * kernel_page_present() always returns 'true'). 1310 * page tables (this always is the case if CONFIG_DEBUG_PAGEALLOC is not set
1311 * and in that case kernel_page_present() always returns 'true').
1210 */ 1312 */
1211static void safe_copy_page(void *dst, struct page *s_page) 1313static void safe_copy_page(void *dst, struct page *s_page)
1212{ 1314{
@@ -1219,10 +1321,8 @@ static void safe_copy_page(void *dst, struct page *s_page)
1219 } 1321 }
1220} 1322}
1221 1323
1222
1223#ifdef CONFIG_HIGHMEM 1324#ifdef CONFIG_HIGHMEM
1224static inline struct page * 1325static inline struct page *page_is_saveable(struct zone *zone, unsigned long pfn)
1225page_is_saveable(struct zone *zone, unsigned long pfn)
1226{ 1326{
1227 return is_highmem(zone) ? 1327 return is_highmem(zone) ?
1228 saveable_highmem_page(zone, pfn) : saveable_page(zone, pfn); 1328 saveable_highmem_page(zone, pfn) : saveable_page(zone, pfn);
@@ -1243,7 +1343,8 @@ static void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
1243 kunmap_atomic(src); 1343 kunmap_atomic(src);
1244 } else { 1344 } else {
1245 if (PageHighMem(d_page)) { 1345 if (PageHighMem(d_page)) {
1246 /* Page pointed to by src may contain some kernel 1346 /*
1347 * The page pointed to by src may contain some kernel
1247 * data modified by kmap_atomic() 1348 * data modified by kmap_atomic()
1248 */ 1349 */
1249 safe_copy_page(buffer, s_page); 1350 safe_copy_page(buffer, s_page);
@@ -1265,8 +1366,8 @@ static inline void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
1265} 1366}
1266#endif /* CONFIG_HIGHMEM */ 1367#endif /* CONFIG_HIGHMEM */
1267 1368
1268static void 1369static void copy_data_pages(struct memory_bitmap *copy_bm,
1269copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm) 1370 struct memory_bitmap *orig_bm)
1270{ 1371{
1271 struct zone *zone; 1372 struct zone *zone;
1272 unsigned long pfn; 1373 unsigned long pfn;
@@ -1315,12 +1416,11 @@ static struct memory_bitmap orig_bm;
1315static struct memory_bitmap copy_bm; 1416static struct memory_bitmap copy_bm;
1316 1417
1317/** 1418/**
1318 * swsusp_free - free pages allocated for the suspend. 1419 * swsusp_free - Free pages allocated for hibernation image.
1319 * 1420 *
1320 * Suspend pages are alocated before the atomic copy is made, so we 1421 * Image pages are alocated before snapshot creation, so they need to be
1321 * need to release them after the resume. 1422 * released after resume.
1322 */ 1423 */
1323
1324void swsusp_free(void) 1424void swsusp_free(void)
1325{ 1425{
1326 unsigned long fb_pfn, fr_pfn; 1426 unsigned long fb_pfn, fr_pfn;
@@ -1351,6 +1451,7 @@ loop:
1351 1451
1352 memory_bm_clear_current(forbidden_pages_map); 1452 memory_bm_clear_current(forbidden_pages_map);
1353 memory_bm_clear_current(free_pages_map); 1453 memory_bm_clear_current(free_pages_map);
1454 hibernate_restore_unprotect_page(page_address(page));
1354 __free_page(page); 1455 __free_page(page);
1355 goto loop; 1456 goto loop;
1356 } 1457 }
@@ -1362,6 +1463,7 @@ out:
1362 buffer = NULL; 1463 buffer = NULL;
1363 alloc_normal = 0; 1464 alloc_normal = 0;
1364 alloc_highmem = 0; 1465 alloc_highmem = 0;
1466 hibernate_restore_protection_end();
1365} 1467}
1366 1468
1367/* Helper functions used for the shrinking of memory. */ 1469/* Helper functions used for the shrinking of memory. */
@@ -1369,7 +1471,7 @@ out:
1369#define GFP_IMAGE (GFP_KERNEL | __GFP_NOWARN) 1471#define GFP_IMAGE (GFP_KERNEL | __GFP_NOWARN)
1370 1472
1371/** 1473/**
1372 * preallocate_image_pages - Allocate a number of pages for hibernation image 1474 * preallocate_image_pages - Allocate a number of pages for hibernation image.
1373 * @nr_pages: Number of page frames to allocate. 1475 * @nr_pages: Number of page frames to allocate.
1374 * @mask: GFP flags to use for the allocation. 1476 * @mask: GFP flags to use for the allocation.
1375 * 1477 *
@@ -1419,7 +1521,7 @@ static unsigned long preallocate_image_highmem(unsigned long nr_pages)
1419} 1521}
1420 1522
1421/** 1523/**
1422 * __fraction - Compute (an approximation of) x * (multiplier / base) 1524 * __fraction - Compute (an approximation of) x * (multiplier / base).
1423 */ 1525 */
1424static unsigned long __fraction(u64 x, u64 multiplier, u64 base) 1526static unsigned long __fraction(u64 x, u64 multiplier, u64 base)
1425{ 1527{
@@ -1429,8 +1531,8 @@ static unsigned long __fraction(u64 x, u64 multiplier, u64 base)
1429} 1531}
1430 1532
1431static unsigned long preallocate_highmem_fraction(unsigned long nr_pages, 1533static unsigned long preallocate_highmem_fraction(unsigned long nr_pages,
1432 unsigned long highmem, 1534 unsigned long highmem,
1433 unsigned long total) 1535 unsigned long total)
1434{ 1536{
1435 unsigned long alloc = __fraction(nr_pages, highmem, total); 1537 unsigned long alloc = __fraction(nr_pages, highmem, total);
1436 1538
@@ -1443,15 +1545,15 @@ static inline unsigned long preallocate_image_highmem(unsigned long nr_pages)
1443} 1545}
1444 1546
1445static inline unsigned long preallocate_highmem_fraction(unsigned long nr_pages, 1547static inline unsigned long preallocate_highmem_fraction(unsigned long nr_pages,
1446 unsigned long highmem, 1548 unsigned long highmem,
1447 unsigned long total) 1549 unsigned long total)
1448{ 1550{
1449 return 0; 1551 return 0;
1450} 1552}
1451#endif /* CONFIG_HIGHMEM */ 1553#endif /* CONFIG_HIGHMEM */
1452 1554
1453/** 1555/**
1454 * free_unnecessary_pages - Release preallocated pages not needed for the image 1556 * free_unnecessary_pages - Release preallocated pages not needed for the image.
1455 */ 1557 */
1456static unsigned long free_unnecessary_pages(void) 1558static unsigned long free_unnecessary_pages(void)
1457{ 1559{
@@ -1505,7 +1607,7 @@ static unsigned long free_unnecessary_pages(void)
1505} 1607}
1506 1608
1507/** 1609/**
1508 * minimum_image_size - Estimate the minimum acceptable size of an image 1610 * minimum_image_size - Estimate the minimum acceptable size of an image.
1509 * @saveable: Number of saveable pages in the system. 1611 * @saveable: Number of saveable pages in the system.
1510 * 1612 *
1511 * We want to avoid attempting to free too much memory too hard, so estimate the 1613 * We want to avoid attempting to free too much memory too hard, so estimate the
@@ -1535,7 +1637,7 @@ static unsigned long minimum_image_size(unsigned long saveable)
1535} 1637}
1536 1638
1537/** 1639/**
1538 * hibernate_preallocate_memory - Preallocate memory for hibernation image 1640 * hibernate_preallocate_memory - Preallocate memory for hibernation image.
1539 * 1641 *
1540 * To create a hibernation image it is necessary to make a copy of every page 1642 * To create a hibernation image it is necessary to make a copy of every page
1541 * frame in use. We also need a number of page frames to be free during 1643 * frame in use. We also need a number of page frames to be free during
@@ -1708,10 +1810,11 @@ int hibernate_preallocate_memory(void)
1708 1810
1709#ifdef CONFIG_HIGHMEM 1811#ifdef CONFIG_HIGHMEM
1710/** 1812/**
1711 * count_pages_for_highmem - compute the number of non-highmem pages 1813 * count_pages_for_highmem - Count non-highmem pages needed for copying highmem.
1712 * that will be necessary for creating copies of highmem pages. 1814 *
1713 */ 1815 * Compute the number of non-highmem pages that will be necessary for creating
1714 1816 * copies of highmem pages.
1817 */
1715static unsigned int count_pages_for_highmem(unsigned int nr_highmem) 1818static unsigned int count_pages_for_highmem(unsigned int nr_highmem)
1716{ 1819{
1717 unsigned int free_highmem = count_free_highmem_pages() + alloc_highmem; 1820 unsigned int free_highmem = count_free_highmem_pages() + alloc_highmem;
@@ -1724,15 +1827,12 @@ static unsigned int count_pages_for_highmem(unsigned int nr_highmem)
1724 return nr_highmem; 1827 return nr_highmem;
1725} 1828}
1726#else 1829#else
1727static unsigned int 1830static unsigned int count_pages_for_highmem(unsigned int nr_highmem) { return 0; }
1728count_pages_for_highmem(unsigned int nr_highmem) { return 0; }
1729#endif /* CONFIG_HIGHMEM */ 1831#endif /* CONFIG_HIGHMEM */
1730 1832
1731/** 1833/**
1732 * enough_free_mem - Make sure we have enough free memory for the 1834 * enough_free_mem - Check if there is enough free memory for the image.
1733 * snapshot image.
1734 */ 1835 */
1735
1736static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem) 1836static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem)
1737{ 1837{
1738 struct zone *zone; 1838 struct zone *zone;
@@ -1751,10 +1851,11 @@ static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem)
1751 1851
1752#ifdef CONFIG_HIGHMEM 1852#ifdef CONFIG_HIGHMEM
1753/** 1853/**
1754 * get_highmem_buffer - if there are some highmem pages in the suspend 1854 * get_highmem_buffer - Allocate a buffer for highmem pages.
1755 * image, we may need the buffer to copy them and/or load their data. 1855 *
1856 * If there are some highmem pages in the hibernation image, we may need a
1857 * buffer to copy them and/or load their data.
1756 */ 1858 */
1757
1758static inline int get_highmem_buffer(int safe_needed) 1859static inline int get_highmem_buffer(int safe_needed)
1759{ 1860{
1760 buffer = get_image_page(GFP_ATOMIC | __GFP_COLD, safe_needed); 1861 buffer = get_image_page(GFP_ATOMIC | __GFP_COLD, safe_needed);
@@ -1762,13 +1863,13 @@ static inline int get_highmem_buffer(int safe_needed)
1762} 1863}
1763 1864
1764/** 1865/**
1765 * alloc_highmem_image_pages - allocate some highmem pages for the image. 1866 * alloc_highmem_image_pages - Allocate some highmem pages for the image.
1766 * Try to allocate as many pages as needed, but if the number of free 1867 *
1767 * highmem pages is lesser than that, allocate them all. 1868 * Try to allocate as many pages as needed, but if the number of free highmem
1869 * pages is less than that, allocate them all.
1768 */ 1870 */
1769 1871static inline unsigned int alloc_highmem_pages(struct memory_bitmap *bm,
1770static inline unsigned int 1872 unsigned int nr_highmem)
1771alloc_highmem_pages(struct memory_bitmap *bm, unsigned int nr_highmem)
1772{ 1873{
1773 unsigned int to_alloc = count_free_highmem_pages(); 1874 unsigned int to_alloc = count_free_highmem_pages();
1774 1875
@@ -1787,25 +1888,24 @@ alloc_highmem_pages(struct memory_bitmap *bm, unsigned int nr_highmem)
1787#else 1888#else
1788static inline int get_highmem_buffer(int safe_needed) { return 0; } 1889static inline int get_highmem_buffer(int safe_needed) { return 0; }
1789 1890
1790static inline unsigned int 1891static inline unsigned int alloc_highmem_pages(struct memory_bitmap *bm,
1791alloc_highmem_pages(struct memory_bitmap *bm, unsigned int n) { return 0; } 1892 unsigned int n) { return 0; }
1792#endif /* CONFIG_HIGHMEM */ 1893#endif /* CONFIG_HIGHMEM */
1793 1894
1794/** 1895/**
1795 * swsusp_alloc - allocate memory for the suspend image 1896 * swsusp_alloc - Allocate memory for hibernation image.
1796 * 1897 *
1797 * We first try to allocate as many highmem pages as there are 1898 * We first try to allocate as many highmem pages as there are
1798 * saveable highmem pages in the system. If that fails, we allocate 1899 * saveable highmem pages in the system. If that fails, we allocate
1799 * non-highmem pages for the copies of the remaining highmem ones. 1900 * non-highmem pages for the copies of the remaining highmem ones.
1800 * 1901 *
1801 * In this approach it is likely that the copies of highmem pages will 1902 * In this approach it is likely that the copies of highmem pages will
1802 * also be located in the high memory, because of the way in which 1903 * also be located in the high memory, because of the way in which
1803 * copy_data_pages() works. 1904 * copy_data_pages() works.
1804 */ 1905 */
1805 1906static int swsusp_alloc(struct memory_bitmap *orig_bm,
1806static int 1907 struct memory_bitmap *copy_bm,
1807swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm, 1908 unsigned int nr_pages, unsigned int nr_highmem)
1808 unsigned int nr_pages, unsigned int nr_highmem)
1809{ 1909{
1810 if (nr_highmem > 0) { 1910 if (nr_highmem > 0) {
1811 if (get_highmem_buffer(PG_ANY)) 1911 if (get_highmem_buffer(PG_ANY))
@@ -1855,7 +1955,8 @@ asmlinkage __visible int swsusp_save(void)
1855 return -ENOMEM; 1955 return -ENOMEM;
1856 } 1956 }
1857 1957
1858 /* During allocating of suspend pagedir, new cold pages may appear. 1958 /*
1959 * During allocating of suspend pagedir, new cold pages may appear.
1859 * Kill them. 1960 * Kill them.
1860 */ 1961 */
1861 drain_local_pages(NULL); 1962 drain_local_pages(NULL);
@@ -1918,12 +2019,14 @@ static int init_header(struct swsusp_info *info)
1918} 2019}
1919 2020
1920/** 2021/**
1921 * pack_pfns - pfns corresponding to the set bits found in the bitmap @bm 2022 * pack_pfns - Prepare PFNs for saving.
1922 * are stored in the array @buf[] (1 page at a time) 2023 * @bm: Memory bitmap.
2024 * @buf: Memory buffer to store the PFNs in.
2025 *
2026 * PFNs corresponding to set bits in @bm are stored in the area of memory
2027 * pointed to by @buf (1 page at a time).
1923 */ 2028 */
1924 2029static inline void pack_pfns(unsigned long *buf, struct memory_bitmap *bm)
1925static inline void
1926pack_pfns(unsigned long *buf, struct memory_bitmap *bm)
1927{ 2030{
1928 int j; 2031 int j;
1929 2032
@@ -1937,22 +2040,21 @@ pack_pfns(unsigned long *buf, struct memory_bitmap *bm)
1937} 2040}
1938 2041
1939/** 2042/**
1940 * snapshot_read_next - used for reading the system memory snapshot. 2043 * snapshot_read_next - Get the address to read the next image page from.
2044 * @handle: Snapshot handle to be used for the reading.
1941 * 2045 *
1942 * On the first call to it @handle should point to a zeroed 2046 * On the first call, @handle should point to a zeroed snapshot_handle
1943 * snapshot_handle structure. The structure gets updated and a pointer 2047 * structure. The structure gets populated then and a pointer to it should be
1944 * to it should be passed to this function every next time. 2048 * passed to this function every next time.
1945 * 2049 *
1946 * On success the function returns a positive number. Then, the caller 2050 * On success, the function returns a positive number. Then, the caller
1947 * is allowed to read up to the returned number of bytes from the memory 2051 * is allowed to read up to the returned number of bytes from the memory
1948 * location computed by the data_of() macro. 2052 * location computed by the data_of() macro.
1949 * 2053 *
1950 * The function returns 0 to indicate the end of data stream condition, 2054 * The function returns 0 to indicate the end of the data stream condition,
1951 * and a negative number is returned on error. In such cases the 2055 * and negative numbers are returned on errors. If that happens, the structure
1952 * structure pointed to by @handle is not updated and should not be used 2056 * pointed to by @handle is not updated and should not be used any more.
1953 * any more.
1954 */ 2057 */
1955
1956int snapshot_read_next(struct snapshot_handle *handle) 2058int snapshot_read_next(struct snapshot_handle *handle)
1957{ 2059{
1958 if (handle->cur > nr_meta_pages + nr_copy_pages) 2060 if (handle->cur > nr_meta_pages + nr_copy_pages)
@@ -1981,7 +2083,8 @@ int snapshot_read_next(struct snapshot_handle *handle)
1981 2083
1982 page = pfn_to_page(memory_bm_next_pfn(&copy_bm)); 2084 page = pfn_to_page(memory_bm_next_pfn(&copy_bm));
1983 if (PageHighMem(page)) { 2085 if (PageHighMem(page)) {
1984 /* Highmem pages are copied to the buffer, 2086 /*
2087 * Highmem pages are copied to the buffer,
1985 * because we can't return with a kmapped 2088 * because we can't return with a kmapped
1986 * highmem page (we may not be called again). 2089 * highmem page (we may not be called again).
1987 */ 2090 */
@@ -1999,53 +2102,41 @@ int snapshot_read_next(struct snapshot_handle *handle)
1999 return PAGE_SIZE; 2102 return PAGE_SIZE;
2000} 2103}
2001 2104
2002/** 2105static void duplicate_memory_bitmap(struct memory_bitmap *dst,
2003 * mark_unsafe_pages - mark the pages that cannot be used for storing 2106 struct memory_bitmap *src)
2004 * the image during resume, because they conflict with the pages that
2005 * had been used before suspend
2006 */
2007
2008static int mark_unsafe_pages(struct memory_bitmap *bm)
2009{ 2107{
2010 struct zone *zone; 2108 unsigned long pfn;
2011 unsigned long pfn, max_zone_pfn;
2012 2109
2013 /* Clear page flags */ 2110 memory_bm_position_reset(src);
2014 for_each_populated_zone(zone) { 2111 pfn = memory_bm_next_pfn(src);
2015 max_zone_pfn = zone_end_pfn(zone); 2112 while (pfn != BM_END_OF_MAP) {
2016 for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) 2113 memory_bm_set_bit(dst, pfn);
2017 if (pfn_valid(pfn)) 2114 pfn = memory_bm_next_pfn(src);
2018 swsusp_unset_page_free(pfn_to_page(pfn));
2019 } 2115 }
2020
2021 /* Mark pages that correspond to the "original" pfns as "unsafe" */
2022 memory_bm_position_reset(bm);
2023 do {
2024 pfn = memory_bm_next_pfn(bm);
2025 if (likely(pfn != BM_END_OF_MAP)) {
2026 if (likely(pfn_valid(pfn)))
2027 swsusp_set_page_free(pfn_to_page(pfn));
2028 else
2029 return -EFAULT;
2030 }
2031 } while (pfn != BM_END_OF_MAP);
2032
2033 allocated_unsafe_pages = 0;
2034
2035 return 0;
2036} 2116}
2037 2117
2038static void 2118/**
2039duplicate_memory_bitmap(struct memory_bitmap *dst, struct memory_bitmap *src) 2119 * mark_unsafe_pages - Mark pages that were used before hibernation.
2120 *
2121 * Mark the pages that cannot be used for storing the image during restoration,
2122 * because they conflict with the pages that had been used before hibernation.
2123 */
2124static void mark_unsafe_pages(struct memory_bitmap *bm)
2040{ 2125{
2041 unsigned long pfn; 2126 unsigned long pfn;
2042 2127
2043 memory_bm_position_reset(src); 2128 /* Clear the "free"/"unsafe" bit for all PFNs */
2044 pfn = memory_bm_next_pfn(src); 2129 memory_bm_position_reset(free_pages_map);
2130 pfn = memory_bm_next_pfn(free_pages_map);
2045 while (pfn != BM_END_OF_MAP) { 2131 while (pfn != BM_END_OF_MAP) {
2046 memory_bm_set_bit(dst, pfn); 2132 memory_bm_clear_current(free_pages_map);
2047 pfn = memory_bm_next_pfn(src); 2133 pfn = memory_bm_next_pfn(free_pages_map);
2048 } 2134 }
2135
2136 /* Mark pages that correspond to the "original" PFNs as "unsafe" */
2137 duplicate_memory_bitmap(free_pages_map, bm);
2138
2139 allocated_unsafe_pages = 0;
2049} 2140}
2050 2141
2051static int check_header(struct swsusp_info *info) 2142static int check_header(struct swsusp_info *info)
@@ -2063,11 +2154,9 @@ static int check_header(struct swsusp_info *info)
2063} 2154}
2064 2155
2065/** 2156/**
2066 * load header - check the image header and copy data from it 2157 * load header - Check the image header and copy the data from it.
2067 */ 2158 */
2068 2159static int load_header(struct swsusp_info *info)
2069static int
2070load_header(struct swsusp_info *info)
2071{ 2160{
2072 int error; 2161 int error;
2073 2162
@@ -2081,8 +2170,12 @@ load_header(struct swsusp_info *info)
2081} 2170}
2082 2171
2083/** 2172/**
2084 * unpack_orig_pfns - for each element of @buf[] (1 page at a time) set 2173 * unpack_orig_pfns - Set bits corresponding to given PFNs in a memory bitmap.
2085 * the corresponding bit in the memory bitmap @bm 2174 * @bm: Memory bitmap.
2175 * @buf: Area of memory containing the PFNs.
2176 *
2177 * For each element of the array pointed to by @buf (1 page at a time), set the
2178 * corresponding bit in @bm.
2086 */ 2179 */
2087static int unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm) 2180static int unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm)
2088{ 2181{
@@ -2095,7 +2188,7 @@ static int unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm)
2095 /* Extract and buffer page key for data page (s390 only). */ 2188 /* Extract and buffer page key for data page (s390 only). */
2096 page_key_memorize(buf + j); 2189 page_key_memorize(buf + j);
2097 2190
2098 if (memory_bm_pfn_present(bm, buf[j])) 2191 if (pfn_valid(buf[j]) && memory_bm_pfn_present(bm, buf[j]))
2099 memory_bm_set_bit(bm, buf[j]); 2192 memory_bm_set_bit(bm, buf[j]);
2100 else 2193 else
2101 return -EFAULT; 2194 return -EFAULT;
@@ -2104,13 +2197,9 @@ static int unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm)
2104 return 0; 2197 return 0;
2105} 2198}
2106 2199
2107/* List of "safe" pages that may be used to store data loaded from the suspend
2108 * image
2109 */
2110static struct linked_page *safe_pages_list;
2111
2112#ifdef CONFIG_HIGHMEM 2200#ifdef CONFIG_HIGHMEM
2113/* struct highmem_pbe is used for creating the list of highmem pages that 2201/*
2202 * struct highmem_pbe is used for creating the list of highmem pages that
2114 * should be restored atomically during the resume from disk, because the page 2203 * should be restored atomically during the resume from disk, because the page
2115 * frames they have occupied before the suspend are in use. 2204 * frames they have occupied before the suspend are in use.
2116 */ 2205 */
@@ -2120,7 +2209,8 @@ struct highmem_pbe {
2120 struct highmem_pbe *next; 2209 struct highmem_pbe *next;
2121}; 2210};
2122 2211
2123/* List of highmem PBEs needed for restoring the highmem pages that were 2212/*
2213 * List of highmem PBEs needed for restoring the highmem pages that were
2124 * allocated before the suspend and included in the suspend image, but have 2214 * allocated before the suspend and included in the suspend image, but have
2125 * also been allocated by the "resume" kernel, so their contents cannot be 2215 * also been allocated by the "resume" kernel, so their contents cannot be
2126 * written directly to their "original" page frames. 2216 * written directly to their "original" page frames.
@@ -2128,11 +2218,11 @@ struct highmem_pbe {
2128static struct highmem_pbe *highmem_pblist; 2218static struct highmem_pbe *highmem_pblist;
2129 2219
2130/** 2220/**
2131 * count_highmem_image_pages - compute the number of highmem pages in the 2221 * count_highmem_image_pages - Compute the number of highmem pages in the image.
2132 * suspend image. The bits in the memory bitmap @bm that correspond to the 2222 * @bm: Memory bitmap.
2133 * image pages are assumed to be set. 2223 *
2224 * The bits in @bm that correspond to image pages are assumed to be set.
2134 */ 2225 */
2135
2136static unsigned int count_highmem_image_pages(struct memory_bitmap *bm) 2226static unsigned int count_highmem_image_pages(struct memory_bitmap *bm)
2137{ 2227{
2138 unsigned long pfn; 2228 unsigned long pfn;
@@ -2149,24 +2239,25 @@ static unsigned int count_highmem_image_pages(struct memory_bitmap *bm)
2149 return cnt; 2239 return cnt;
2150} 2240}
2151 2241
2152/**
2153 * prepare_highmem_image - try to allocate as many highmem pages as
2154 * there are highmem image pages (@nr_highmem_p points to the variable
2155 * containing the number of highmem image pages). The pages that are
2156 * "safe" (ie. will not be overwritten when the suspend image is
2157 * restored) have the corresponding bits set in @bm (it must be
2158 * unitialized).
2159 *
2160 * NOTE: This function should not be called if there are no highmem
2161 * image pages.
2162 */
2163
2164static unsigned int safe_highmem_pages; 2242static unsigned int safe_highmem_pages;
2165 2243
2166static struct memory_bitmap *safe_highmem_bm; 2244static struct memory_bitmap *safe_highmem_bm;
2167 2245
2168static int 2246/**
2169prepare_highmem_image(struct memory_bitmap *bm, unsigned int *nr_highmem_p) 2247 * prepare_highmem_image - Allocate memory for loading highmem data from image.
2248 * @bm: Pointer to an uninitialized memory bitmap structure.
2249 * @nr_highmem_p: Pointer to the number of highmem image pages.
2250 *
2251 * Try to allocate as many highmem pages as there are highmem image pages
2252 * (@nr_highmem_p points to the variable containing the number of highmem image
2253 * pages). The pages that are "safe" (ie. will not be overwritten when the
2254 * hibernation image is restored entirely) have the corresponding bits set in
2255 * @bm (it must be unitialized).
2256 *
2257 * NOTE: This function should not be called if there are no highmem image pages.
2258 */
2259static int prepare_highmem_image(struct memory_bitmap *bm,
2260 unsigned int *nr_highmem_p)
2170{ 2261{
2171 unsigned int to_alloc; 2262 unsigned int to_alloc;
2172 2263
@@ -2201,39 +2292,42 @@ prepare_highmem_image(struct memory_bitmap *bm, unsigned int *nr_highmem_p)
2201 return 0; 2292 return 0;
2202} 2293}
2203 2294
2295static struct page *last_highmem_page;
2296
2204/** 2297/**
2205 * get_highmem_page_buffer - for given highmem image page find the buffer 2298 * get_highmem_page_buffer - Prepare a buffer to store a highmem image page.
2206 * that suspend_write_next() should set for its caller to write to.
2207 * 2299 *
2208 * If the page is to be saved to its "original" page frame or a copy of 2300 * For a given highmem image page get a buffer that suspend_write_next() should
2209 * the page is to be made in the highmem, @buffer is returned. Otherwise, 2301 * return to its caller to write to.
2210 * the copy of the page is to be made in normal memory, so the address of
2211 * the copy is returned.
2212 * 2302 *
2213 * If @buffer is returned, the caller of suspend_write_next() will write 2303 * If the page is to be saved to its "original" page frame or a copy of
2214 * the page's contents to @buffer, so they will have to be copied to the 2304 * the page is to be made in the highmem, @buffer is returned. Otherwise,
2215 * right location on the next call to suspend_write_next() and it is done 2305 * the copy of the page is to be made in normal memory, so the address of
2216 * with the help of copy_last_highmem_page(). For this purpose, if 2306 * the copy is returned.
2217 * @buffer is returned, @last_highmem page is set to the page to which 2307 *
2218 * the data will have to be copied from @buffer. 2308 * If @buffer is returned, the caller of suspend_write_next() will write
2309 * the page's contents to @buffer, so they will have to be copied to the
2310 * right location on the next call to suspend_write_next() and it is done
2311 * with the help of copy_last_highmem_page(). For this purpose, if
2312 * @buffer is returned, @last_highmem_page is set to the page to which
2313 * the data will have to be copied from @buffer.
2219 */ 2314 */
2220 2315static void *get_highmem_page_buffer(struct page *page,
2221static struct page *last_highmem_page; 2316 struct chain_allocator *ca)
2222
2223static void *
2224get_highmem_page_buffer(struct page *page, struct chain_allocator *ca)
2225{ 2317{
2226 struct highmem_pbe *pbe; 2318 struct highmem_pbe *pbe;
2227 void *kaddr; 2319 void *kaddr;
2228 2320
2229 if (swsusp_page_is_forbidden(page) && swsusp_page_is_free(page)) { 2321 if (swsusp_page_is_forbidden(page) && swsusp_page_is_free(page)) {
2230 /* We have allocated the "original" page frame and we can 2322 /*
2323 * We have allocated the "original" page frame and we can
2231 * use it directly to store the loaded page. 2324 * use it directly to store the loaded page.
2232 */ 2325 */
2233 last_highmem_page = page; 2326 last_highmem_page = page;
2234 return buffer; 2327 return buffer;
2235 } 2328 }
2236 /* The "original" page frame has not been allocated and we have to 2329 /*
2330 * The "original" page frame has not been allocated and we have to
2237 * use a "safe" page frame to store the loaded page. 2331 * use a "safe" page frame to store the loaded page.
2238 */ 2332 */
2239 pbe = chain_alloc(ca, sizeof(struct highmem_pbe)); 2333 pbe = chain_alloc(ca, sizeof(struct highmem_pbe));
@@ -2263,11 +2357,12 @@ get_highmem_page_buffer(struct page *page, struct chain_allocator *ca)
2263} 2357}
2264 2358
2265/** 2359/**
2266 * copy_last_highmem_page - copy the contents of a highmem image from 2360 * copy_last_highmem_page - Copy most the most recent highmem image page.
2267 * @buffer, where the caller of snapshot_write_next() has place them, 2361 *
2268 * to the right location represented by @last_highmem_page . 2362 * Copy the contents of a highmem image from @buffer, where the caller of
2363 * snapshot_write_next() has stored them, to the right location represented by
2364 * @last_highmem_page .
2269 */ 2365 */
2270
2271static void copy_last_highmem_page(void) 2366static void copy_last_highmem_page(void)
2272{ 2367{
2273 if (last_highmem_page) { 2368 if (last_highmem_page) {
@@ -2294,17 +2389,13 @@ static inline void free_highmem_data(void)
2294 free_image_page(buffer, PG_UNSAFE_CLEAR); 2389 free_image_page(buffer, PG_UNSAFE_CLEAR);
2295} 2390}
2296#else 2391#else
2297static unsigned int 2392static unsigned int count_highmem_image_pages(struct memory_bitmap *bm) { return 0; }
2298count_highmem_image_pages(struct memory_bitmap *bm) { return 0; }
2299 2393
2300static inline int 2394static inline int prepare_highmem_image(struct memory_bitmap *bm,
2301prepare_highmem_image(struct memory_bitmap *bm, unsigned int *nr_highmem_p) 2395 unsigned int *nr_highmem_p) { return 0; }
2302{
2303 return 0;
2304}
2305 2396
2306static inline void * 2397static inline void *get_highmem_page_buffer(struct page *page,
2307get_highmem_page_buffer(struct page *page, struct chain_allocator *ca) 2398 struct chain_allocator *ca)
2308{ 2399{
2309 return ERR_PTR(-EINVAL); 2400 return ERR_PTR(-EINVAL);
2310} 2401}
@@ -2314,27 +2405,27 @@ static inline int last_highmem_page_copied(void) { return 1; }
2314static inline void free_highmem_data(void) {} 2405static inline void free_highmem_data(void) {}
2315#endif /* CONFIG_HIGHMEM */ 2406#endif /* CONFIG_HIGHMEM */
2316 2407
2408#define PBES_PER_LINKED_PAGE (LINKED_PAGE_DATA_SIZE / sizeof(struct pbe))
2409
2317/** 2410/**
2318 * prepare_image - use the memory bitmap @bm to mark the pages that will 2411 * prepare_image - Make room for loading hibernation image.
2319 * be overwritten in the process of restoring the system memory state 2412 * @new_bm: Unitialized memory bitmap structure.
2320 * from the suspend image ("unsafe" pages) and allocate memory for the 2413 * @bm: Memory bitmap with unsafe pages marked.
2321 * image. 2414 *
2415 * Use @bm to mark the pages that will be overwritten in the process of
2416 * restoring the system memory state from the suspend image ("unsafe" pages)
2417 * and allocate memory for the image.
2322 * 2418 *
2323 * The idea is to allocate a new memory bitmap first and then allocate 2419 * The idea is to allocate a new memory bitmap first and then allocate
2324 * as many pages as needed for the image data, but not to assign these 2420 * as many pages as needed for image data, but without specifying what those
2325 * pages to specific tasks initially. Instead, we just mark them as 2421 * pages will be used for just yet. Instead, we mark them all as allocated and
2326 * allocated and create a lists of "safe" pages that will be used 2422 * create a lists of "safe" pages to be used later. On systems with high
2327 * later. On systems with high memory a list of "safe" highmem pages is 2423 * memory a list of "safe" highmem pages is created too.
2328 * also created.
2329 */ 2424 */
2330 2425static int prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
2331#define PBES_PER_LINKED_PAGE (LINKED_PAGE_DATA_SIZE / sizeof(struct pbe))
2332
2333static int
2334prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
2335{ 2426{
2336 unsigned int nr_pages, nr_highmem; 2427 unsigned int nr_pages, nr_highmem;
2337 struct linked_page *sp_list, *lp; 2428 struct linked_page *lp;
2338 int error; 2429 int error;
2339 2430
2340 /* If there is no highmem, the buffer will not be necessary */ 2431 /* If there is no highmem, the buffer will not be necessary */
@@ -2342,9 +2433,7 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
2342 buffer = NULL; 2433 buffer = NULL;
2343 2434
2344 nr_highmem = count_highmem_image_pages(bm); 2435 nr_highmem = count_highmem_image_pages(bm);
2345 error = mark_unsafe_pages(bm); 2436 mark_unsafe_pages(bm);
2346 if (error)
2347 goto Free;
2348 2437
2349 error = memory_bm_create(new_bm, GFP_ATOMIC, PG_SAFE); 2438 error = memory_bm_create(new_bm, GFP_ATOMIC, PG_SAFE);
2350 if (error) 2439 if (error)
@@ -2357,14 +2446,15 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
2357 if (error) 2446 if (error)
2358 goto Free; 2447 goto Free;
2359 } 2448 }
2360 /* Reserve some safe pages for potential later use. 2449 /*
2450 * Reserve some safe pages for potential later use.
2361 * 2451 *
2362 * NOTE: This way we make sure there will be enough safe pages for the 2452 * NOTE: This way we make sure there will be enough safe pages for the
2363 * chain_alloc() in get_buffer(). It is a bit wasteful, but 2453 * chain_alloc() in get_buffer(). It is a bit wasteful, but
2364 * nr_copy_pages cannot be greater than 50% of the memory anyway. 2454 * nr_copy_pages cannot be greater than 50% of the memory anyway.
2455 *
2456 * nr_copy_pages cannot be less than allocated_unsafe_pages too.
2365 */ 2457 */
2366 sp_list = NULL;
2367 /* nr_copy_pages cannot be lesser than allocated_unsafe_pages */
2368 nr_pages = nr_copy_pages - nr_highmem - allocated_unsafe_pages; 2458 nr_pages = nr_copy_pages - nr_highmem - allocated_unsafe_pages;
2369 nr_pages = DIV_ROUND_UP(nr_pages, PBES_PER_LINKED_PAGE); 2459 nr_pages = DIV_ROUND_UP(nr_pages, PBES_PER_LINKED_PAGE);
2370 while (nr_pages > 0) { 2460 while (nr_pages > 0) {
@@ -2373,12 +2463,11 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
2373 error = -ENOMEM; 2463 error = -ENOMEM;
2374 goto Free; 2464 goto Free;
2375 } 2465 }
2376 lp->next = sp_list; 2466 lp->next = safe_pages_list;
2377 sp_list = lp; 2467 safe_pages_list = lp;
2378 nr_pages--; 2468 nr_pages--;
2379 } 2469 }
2380 /* Preallocate memory for the image */ 2470 /* Preallocate memory for the image */
2381 safe_pages_list = NULL;
2382 nr_pages = nr_copy_pages - nr_highmem - allocated_unsafe_pages; 2471 nr_pages = nr_copy_pages - nr_highmem - allocated_unsafe_pages;
2383 while (nr_pages > 0) { 2472 while (nr_pages > 0) {
2384 lp = (struct linked_page *)get_zeroed_page(GFP_ATOMIC); 2473 lp = (struct linked_page *)get_zeroed_page(GFP_ATOMIC);
@@ -2396,12 +2485,6 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
2396 swsusp_set_page_free(virt_to_page(lp)); 2485 swsusp_set_page_free(virt_to_page(lp));
2397 nr_pages--; 2486 nr_pages--;
2398 } 2487 }
2399 /* Free the reserved safe pages so that chain_alloc() can use them */
2400 while (sp_list) {
2401 lp = sp_list->next;
2402 free_image_page(sp_list, PG_UNSAFE_CLEAR);
2403 sp_list = lp;
2404 }
2405 return 0; 2488 return 0;
2406 2489
2407 Free: 2490 Free:
@@ -2410,10 +2493,11 @@ prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
2410} 2493}
2411 2494
2412/** 2495/**
2413 * get_buffer - compute the address that snapshot_write_next() should 2496 * get_buffer - Get the address to store the next image data page.
2414 * set for its caller to write to. 2497 *
2498 * Get the address that snapshot_write_next() should return to its caller to
2499 * write to.
2415 */ 2500 */
2416
2417static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca) 2501static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca)
2418{ 2502{
2419 struct pbe *pbe; 2503 struct pbe *pbe;
@@ -2428,12 +2512,14 @@ static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca)
2428 return get_highmem_page_buffer(page, ca); 2512 return get_highmem_page_buffer(page, ca);
2429 2513
2430 if (swsusp_page_is_forbidden(page) && swsusp_page_is_free(page)) 2514 if (swsusp_page_is_forbidden(page) && swsusp_page_is_free(page))
2431 /* We have allocated the "original" page frame and we can 2515 /*
2516 * We have allocated the "original" page frame and we can
2432 * use it directly to store the loaded page. 2517 * use it directly to store the loaded page.
2433 */ 2518 */
2434 return page_address(page); 2519 return page_address(page);
2435 2520
2436 /* The "original" page frame has not been allocated and we have to 2521 /*
2522 * The "original" page frame has not been allocated and we have to
2437 * use a "safe" page frame to store the loaded page. 2523 * use a "safe" page frame to store the loaded page.
2438 */ 2524 */
2439 pbe = chain_alloc(ca, sizeof(struct pbe)); 2525 pbe = chain_alloc(ca, sizeof(struct pbe));
@@ -2450,22 +2536,21 @@ static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca)
2450} 2536}
2451 2537
2452/** 2538/**
2453 * snapshot_write_next - used for writing the system memory snapshot. 2539 * snapshot_write_next - Get the address to store the next image page.
2540 * @handle: Snapshot handle structure to guide the writing.
2454 * 2541 *
2455 * On the first call to it @handle should point to a zeroed 2542 * On the first call, @handle should point to a zeroed snapshot_handle
2456 * snapshot_handle structure. The structure gets updated and a pointer 2543 * structure. The structure gets populated then and a pointer to it should be
2457 * to it should be passed to this function every next time. 2544 * passed to this function every next time.
2458 * 2545 *
2459 * On success the function returns a positive number. Then, the caller 2546 * On success, the function returns a positive number. Then, the caller
2460 * is allowed to write up to the returned number of bytes to the memory 2547 * is allowed to write up to the returned number of bytes to the memory
2461 * location computed by the data_of() macro. 2548 * location computed by the data_of() macro.
2462 * 2549 *
2463 * The function returns 0 to indicate the "end of file" condition, 2550 * The function returns 0 to indicate the "end of file" condition. Negative
2464 * and a negative number is returned on error. In such cases the 2551 * numbers are returned on errors, in which cases the structure pointed to by
2465 * structure pointed to by @handle is not updated and should not be used 2552 * @handle is not updated and should not be used any more.
2466 * any more.
2467 */ 2553 */
2468
2469int snapshot_write_next(struct snapshot_handle *handle) 2554int snapshot_write_next(struct snapshot_handle *handle)
2470{ 2555{
2471 static struct chain_allocator ca; 2556 static struct chain_allocator ca;
@@ -2491,6 +2576,8 @@ int snapshot_write_next(struct snapshot_handle *handle)
2491 if (error) 2576 if (error)
2492 return error; 2577 return error;
2493 2578
2579 safe_pages_list = NULL;
2580
2494 error = memory_bm_create(&copy_bm, GFP_ATOMIC, PG_ANY); 2581 error = memory_bm_create(&copy_bm, GFP_ATOMIC, PG_ANY);
2495 if (error) 2582 if (error)
2496 return error; 2583 return error;
@@ -2500,6 +2587,7 @@ int snapshot_write_next(struct snapshot_handle *handle)
2500 if (error) 2587 if (error)
2501 return error; 2588 return error;
2502 2589
2590 hibernate_restore_protection_begin();
2503 } else if (handle->cur <= nr_meta_pages + 1) { 2591 } else if (handle->cur <= nr_meta_pages + 1) {
2504 error = unpack_orig_pfns(buffer, &copy_bm); 2592 error = unpack_orig_pfns(buffer, &copy_bm);
2505 if (error) 2593 if (error)
@@ -2522,6 +2610,7 @@ int snapshot_write_next(struct snapshot_handle *handle)
2522 copy_last_highmem_page(); 2610 copy_last_highmem_page();
2523 /* Restore page key for data page (s390 only). */ 2611 /* Restore page key for data page (s390 only). */
2524 page_key_write(handle->buffer); 2612 page_key_write(handle->buffer);
2613 hibernate_restore_protect_page(handle->buffer);
2525 handle->buffer = get_buffer(&orig_bm, &ca); 2614 handle->buffer = get_buffer(&orig_bm, &ca);
2526 if (IS_ERR(handle->buffer)) 2615 if (IS_ERR(handle->buffer))
2527 return PTR_ERR(handle->buffer); 2616 return PTR_ERR(handle->buffer);
@@ -2533,22 +2622,23 @@ int snapshot_write_next(struct snapshot_handle *handle)
2533} 2622}
2534 2623
2535/** 2624/**
2536 * snapshot_write_finalize - must be called after the last call to 2625 * snapshot_write_finalize - Complete the loading of a hibernation image.
2537 * snapshot_write_next() in case the last page in the image happens 2626 *
2538 * to be a highmem page and its contents should be stored in the 2627 * Must be called after the last call to snapshot_write_next() in case the last
2539 * highmem. Additionally, it releases the memory that will not be 2628 * page in the image happens to be a highmem page and its contents should be
2540 * used any more. 2629 * stored in highmem. Additionally, it recycles bitmap memory that's not
2630 * necessary any more.
2541 */ 2631 */
2542
2543void snapshot_write_finalize(struct snapshot_handle *handle) 2632void snapshot_write_finalize(struct snapshot_handle *handle)
2544{ 2633{
2545 copy_last_highmem_page(); 2634 copy_last_highmem_page();
2546 /* Restore page key for data page (s390 only). */ 2635 /* Restore page key for data page (s390 only). */
2547 page_key_write(handle->buffer); 2636 page_key_write(handle->buffer);
2548 page_key_free(); 2637 page_key_free();
2549 /* Free only if we have loaded the image entirely */ 2638 hibernate_restore_protect_page(handle->buffer);
2639 /* Do that only if we have loaded the image entirely */
2550 if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages) { 2640 if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages) {
2551 memory_bm_free(&orig_bm, PG_UNSAFE_CLEAR); 2641 memory_bm_recycle(&orig_bm);
2552 free_highmem_data(); 2642 free_highmem_data();
2553 } 2643 }
2554} 2644}
@@ -2561,8 +2651,8 @@ int snapshot_image_loaded(struct snapshot_handle *handle)
2561 2651
2562#ifdef CONFIG_HIGHMEM 2652#ifdef CONFIG_HIGHMEM
2563/* Assumes that @buf is ready and points to a "safe" page */ 2653/* Assumes that @buf is ready and points to a "safe" page */
2564static inline void 2654static inline void swap_two_pages_data(struct page *p1, struct page *p2,
2565swap_two_pages_data(struct page *p1, struct page *p2, void *buf) 2655 void *buf)
2566{ 2656{
2567 void *kaddr1, *kaddr2; 2657 void *kaddr1, *kaddr2;
2568 2658
@@ -2576,15 +2666,15 @@ swap_two_pages_data(struct page *p1, struct page *p2, void *buf)
2576} 2666}
2577 2667
2578/** 2668/**
2579 * restore_highmem - for each highmem page that was allocated before 2669 * restore_highmem - Put highmem image pages into their original locations.
2580 * the suspend and included in the suspend image, and also has been 2670 *
2581 * allocated by the "resume" kernel swap its current (ie. "before 2671 * For each highmem page that was in use before hibernation and is included in
2582 * resume") contents with the previous (ie. "before suspend") one. 2672 * the image, and also has been allocated by the "restore" kernel, swap its
2673 * current contents with the previous (ie. "before hibernation") ones.
2583 * 2674 *
2584 * If the resume eventually fails, we can call this function once 2675 * If the restore eventually fails, we can call this function once again and
2585 * again and restore the "before resume" highmem state. 2676 * restore the highmem state as seen by the restore kernel.
2586 */ 2677 */
2587
2588int restore_highmem(void) 2678int restore_highmem(void)
2589{ 2679{
2590 struct highmem_pbe *pbe = highmem_pblist; 2680 struct highmem_pbe *pbe = highmem_pblist;
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 5b70d64b871e..0acab9d7f96f 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -266,16 +266,18 @@ static int suspend_test(int level)
266 */ 266 */
267static int suspend_prepare(suspend_state_t state) 267static int suspend_prepare(suspend_state_t state)
268{ 268{
269 int error; 269 int error, nr_calls = 0;
270 270
271 if (!sleep_state_supported(state)) 271 if (!sleep_state_supported(state))
272 return -EPERM; 272 return -EPERM;
273 273
274 pm_prepare_console(); 274 pm_prepare_console();
275 275
276 error = pm_notifier_call_chain(PM_SUSPEND_PREPARE); 276 error = __pm_notifier_call_chain(PM_SUSPEND_PREPARE, -1, &nr_calls);
277 if (error) 277 if (error) {
278 nr_calls--;
278 goto Finish; 279 goto Finish;
280 }
279 281
280 trace_suspend_resume(TPS("freeze_processes"), 0, true); 282 trace_suspend_resume(TPS("freeze_processes"), 0, true);
281 error = suspend_freeze_processes(); 283 error = suspend_freeze_processes();
@@ -286,7 +288,7 @@ static int suspend_prepare(suspend_state_t state)
286 suspend_stats.failed_freeze++; 288 suspend_stats.failed_freeze++;
287 dpm_save_failed_step(SUSPEND_FREEZE); 289 dpm_save_failed_step(SUSPEND_FREEZE);
288 Finish: 290 Finish:
289 pm_notifier_call_chain(PM_POST_SUSPEND); 291 __pm_notifier_call_chain(PM_POST_SUSPEND, nr_calls, NULL);
290 pm_restore_console(); 292 pm_restore_console();
291 return error; 293 return error;
292} 294}
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index c1aaac431055..a3b1e617bcdc 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -350,6 +350,12 @@ static int swsusp_swap_check(void)
350 if (res < 0) 350 if (res < 0)
351 blkdev_put(hib_resume_bdev, FMODE_WRITE); 351 blkdev_put(hib_resume_bdev, FMODE_WRITE);
352 352
353 /*
354 * Update the resume device to the one actually used,
355 * so the test_resume mode can use it in case it is
356 * invoked from hibernate() to test the snapshot.
357 */
358 swsusp_resume_device = hib_resume_bdev->bd_dev;
353 return res; 359 return res;
354} 360}
355 361
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 526e8911460a..35310b627388 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -47,7 +47,7 @@ atomic_t snapshot_device_available = ATOMIC_INIT(1);
47static int snapshot_open(struct inode *inode, struct file *filp) 47static int snapshot_open(struct inode *inode, struct file *filp)
48{ 48{
49 struct snapshot_data *data; 49 struct snapshot_data *data;
50 int error; 50 int error, nr_calls = 0;
51 51
52 if (!hibernation_available()) 52 if (!hibernation_available())
53 return -EPERM; 53 return -EPERM;
@@ -74,9 +74,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
74 swap_type_of(swsusp_resume_device, 0, NULL) : -1; 74 swap_type_of(swsusp_resume_device, 0, NULL) : -1;
75 data->mode = O_RDONLY; 75 data->mode = O_RDONLY;
76 data->free_bitmaps = false; 76 data->free_bitmaps = false;
77 error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE); 77 error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls);
78 if (error) 78 if (error)
79 pm_notifier_call_chain(PM_POST_HIBERNATION); 79 __pm_notifier_call_chain(PM_POST_HIBERNATION, --nr_calls, NULL);
80 } else { 80 } else {
81 /* 81 /*
82 * Resuming. We may need to wait for the image device to 82 * Resuming. We may need to wait for the image device to
@@ -86,13 +86,15 @@ static int snapshot_open(struct inode *inode, struct file *filp)
86 86
87 data->swap = -1; 87 data->swap = -1;
88 data->mode = O_WRONLY; 88 data->mode = O_WRONLY;
89 error = pm_notifier_call_chain(PM_RESTORE_PREPARE); 89 error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls);
90 if (!error) { 90 if (!error) {
91 error = create_basic_memory_bitmaps(); 91 error = create_basic_memory_bitmaps();
92 data->free_bitmaps = !error; 92 data->free_bitmaps = !error;
93 } 93 } else
94 nr_calls--;
95
94 if (error) 96 if (error)
95 pm_notifier_call_chain(PM_POST_RESTORE); 97 __pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
96 } 98 }
97 if (error) 99 if (error)
98 atomic_inc(&snapshot_device_available); 100 atomic_inc(&snapshot_device_available);
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 14c4aa25cc45..a84641b222c1 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -47,6 +47,8 @@ struct sugov_cpu {
47 struct update_util_data update_util; 47 struct update_util_data update_util;
48 struct sugov_policy *sg_policy; 48 struct sugov_policy *sg_policy;
49 49
50 unsigned int cached_raw_freq;
51
50 /* The fields below are only needed when sharing a policy. */ 52 /* The fields below are only needed when sharing a policy. */
51 unsigned long util; 53 unsigned long util;
52 unsigned long max; 54 unsigned long max;
@@ -106,7 +108,7 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time,
106 108
107/** 109/**
108 * get_next_freq - Compute a new frequency for a given cpufreq policy. 110 * get_next_freq - Compute a new frequency for a given cpufreq policy.
109 * @policy: cpufreq policy object to compute the new frequency for. 111 * @sg_cpu: schedutil cpu object to compute the new frequency for.
110 * @util: Current CPU utilization. 112 * @util: Current CPU utilization.
111 * @max: CPU capacity. 113 * @max: CPU capacity.
112 * 114 *
@@ -121,14 +123,25 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time,
121 * next_freq = C * curr_freq * util_raw / max 123 * next_freq = C * curr_freq * util_raw / max
122 * 124 *
123 * Take C = 1.25 for the frequency tipping point at (util / max) = 0.8. 125 * Take C = 1.25 for the frequency tipping point at (util / max) = 0.8.
126 *
127 * The lowest driver-supported frequency which is equal or greater than the raw
128 * next_freq (as calculated above) is returned, subject to policy min/max and
129 * cpufreq driver limitations.
124 */ 130 */
125static unsigned int get_next_freq(struct cpufreq_policy *policy, 131static unsigned int get_next_freq(struct sugov_cpu *sg_cpu, unsigned long util,
126 unsigned long util, unsigned long max) 132 unsigned long max)
127{ 133{
134 struct sugov_policy *sg_policy = sg_cpu->sg_policy;
135 struct cpufreq_policy *policy = sg_policy->policy;
128 unsigned int freq = arch_scale_freq_invariant() ? 136 unsigned int freq = arch_scale_freq_invariant() ?
129 policy->cpuinfo.max_freq : policy->cur; 137 policy->cpuinfo.max_freq : policy->cur;
130 138
131 return (freq + (freq >> 2)) * util / max; 139 freq = (freq + (freq >> 2)) * util / max;
140
141 if (freq == sg_cpu->cached_raw_freq && sg_policy->next_freq != UINT_MAX)
142 return sg_policy->next_freq;
143 sg_cpu->cached_raw_freq = freq;
144 return cpufreq_driver_resolve_freq(policy, freq);
132} 145}
133 146
134static void sugov_update_single(struct update_util_data *hook, u64 time, 147static void sugov_update_single(struct update_util_data *hook, u64 time,
@@ -143,13 +156,14 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
143 return; 156 return;
144 157
145 next_f = util == ULONG_MAX ? policy->cpuinfo.max_freq : 158 next_f = util == ULONG_MAX ? policy->cpuinfo.max_freq :
146 get_next_freq(policy, util, max); 159 get_next_freq(sg_cpu, util, max);
147 sugov_update_commit(sg_policy, time, next_f); 160 sugov_update_commit(sg_policy, time, next_f);
148} 161}
149 162
150static unsigned int sugov_next_freq_shared(struct sugov_policy *sg_policy, 163static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu,
151 unsigned long util, unsigned long max) 164 unsigned long util, unsigned long max)
152{ 165{
166 struct sugov_policy *sg_policy = sg_cpu->sg_policy;
153 struct cpufreq_policy *policy = sg_policy->policy; 167 struct cpufreq_policy *policy = sg_policy->policy;
154 unsigned int max_f = policy->cpuinfo.max_freq; 168 unsigned int max_f = policy->cpuinfo.max_freq;
155 u64 last_freq_update_time = sg_policy->last_freq_update_time; 169 u64 last_freq_update_time = sg_policy->last_freq_update_time;
@@ -189,7 +203,7 @@ static unsigned int sugov_next_freq_shared(struct sugov_policy *sg_policy,
189 } 203 }
190 } 204 }
191 205
192 return get_next_freq(policy, util, max); 206 return get_next_freq(sg_cpu, util, max);
193} 207}
194 208
195static void sugov_update_shared(struct update_util_data *hook, u64 time, 209static void sugov_update_shared(struct update_util_data *hook, u64 time,
@@ -206,7 +220,7 @@ static void sugov_update_shared(struct update_util_data *hook, u64 time,
206 sg_cpu->last_update = time; 220 sg_cpu->last_update = time;
207 221
208 if (sugov_should_update_freq(sg_policy, time)) { 222 if (sugov_should_update_freq(sg_policy, time)) {
209 next_f = sugov_next_freq_shared(sg_policy, util, max); 223 next_f = sugov_next_freq_shared(sg_cpu, util, max);
210 sugov_update_commit(sg_policy, time, next_f); 224 sugov_update_commit(sg_policy, time, next_f);
211 } 225 }
212 226
@@ -394,7 +408,7 @@ static int sugov_init(struct cpufreq_policy *policy)
394 return ret; 408 return ret;
395} 409}
396 410
397static int sugov_exit(struct cpufreq_policy *policy) 411static void sugov_exit(struct cpufreq_policy *policy)
398{ 412{
399 struct sugov_policy *sg_policy = policy->governor_data; 413 struct sugov_policy *sg_policy = policy->governor_data;
400 struct sugov_tunables *tunables = sg_policy->tunables; 414 struct sugov_tunables *tunables = sg_policy->tunables;
@@ -412,7 +426,6 @@ static int sugov_exit(struct cpufreq_policy *policy)
412 mutex_unlock(&global_tunables_lock); 426 mutex_unlock(&global_tunables_lock);
413 427
414 sugov_policy_free(sg_policy); 428 sugov_policy_free(sg_policy);
415 return 0;
416} 429}
417 430
418static int sugov_start(struct cpufreq_policy *policy) 431static int sugov_start(struct cpufreq_policy *policy)
@@ -434,6 +447,7 @@ static int sugov_start(struct cpufreq_policy *policy)
434 sg_cpu->util = ULONG_MAX; 447 sg_cpu->util = ULONG_MAX;
435 sg_cpu->max = 0; 448 sg_cpu->max = 0;
436 sg_cpu->last_update = 0; 449 sg_cpu->last_update = 0;
450 sg_cpu->cached_raw_freq = 0;
437 cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util, 451 cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
438 sugov_update_shared); 452 sugov_update_shared);
439 } else { 453 } else {
@@ -444,7 +458,7 @@ static int sugov_start(struct cpufreq_policy *policy)
444 return 0; 458 return 0;
445} 459}
446 460
447static int sugov_stop(struct cpufreq_policy *policy) 461static void sugov_stop(struct cpufreq_policy *policy)
448{ 462{
449 struct sugov_policy *sg_policy = policy->governor_data; 463 struct sugov_policy *sg_policy = policy->governor_data;
450 unsigned int cpu; 464 unsigned int cpu;
@@ -456,53 +470,29 @@ static int sugov_stop(struct cpufreq_policy *policy)
456 470
457 irq_work_sync(&sg_policy->irq_work); 471 irq_work_sync(&sg_policy->irq_work);
458 cancel_work_sync(&sg_policy->work); 472 cancel_work_sync(&sg_policy->work);
459 return 0;
460} 473}
461 474
462static int sugov_limits(struct cpufreq_policy *policy) 475static void sugov_limits(struct cpufreq_policy *policy)
463{ 476{
464 struct sugov_policy *sg_policy = policy->governor_data; 477 struct sugov_policy *sg_policy = policy->governor_data;
465 478
466 if (!policy->fast_switch_enabled) { 479 if (!policy->fast_switch_enabled) {
467 mutex_lock(&sg_policy->work_lock); 480 mutex_lock(&sg_policy->work_lock);
468 481 cpufreq_policy_apply_limits(policy);
469 if (policy->max < policy->cur)
470 __cpufreq_driver_target(policy, policy->max,
471 CPUFREQ_RELATION_H);
472 else if (policy->min > policy->cur)
473 __cpufreq_driver_target(policy, policy->min,
474 CPUFREQ_RELATION_L);
475
476 mutex_unlock(&sg_policy->work_lock); 482 mutex_unlock(&sg_policy->work_lock);
477 } 483 }
478 484
479 sg_policy->need_freq_update = true; 485 sg_policy->need_freq_update = true;
480 return 0;
481}
482
483int sugov_governor(struct cpufreq_policy *policy, unsigned int event)
484{
485 if (event == CPUFREQ_GOV_POLICY_INIT) {
486 return sugov_init(policy);
487 } else if (policy->governor_data) {
488 switch (event) {
489 case CPUFREQ_GOV_POLICY_EXIT:
490 return sugov_exit(policy);
491 case CPUFREQ_GOV_START:
492 return sugov_start(policy);
493 case CPUFREQ_GOV_STOP:
494 return sugov_stop(policy);
495 case CPUFREQ_GOV_LIMITS:
496 return sugov_limits(policy);
497 }
498 }
499 return -EINVAL;
500} 486}
501 487
502static struct cpufreq_governor schedutil_gov = { 488static struct cpufreq_governor schedutil_gov = {
503 .name = "schedutil", 489 .name = "schedutil",
504 .governor = sugov_governor,
505 .owner = THIS_MODULE, 490 .owner = THIS_MODULE,
491 .init = sugov_init,
492 .exit = sugov_exit,
493 .start = sugov_start,
494 .stop = sugov_stop,
495 .limits = sugov_limits,
506}; 496};
507 497
508static int __init sugov_module_init(void) 498static int __init sugov_module_init(void)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 97e7b793df35..d12bd958077e 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -4369,8 +4369,8 @@ static void show_pwq(struct pool_workqueue *pwq)
4369/** 4369/**
4370 * show_workqueue_state - dump workqueue state 4370 * show_workqueue_state - dump workqueue state
4371 * 4371 *
4372 * Called from a sysrq handler and prints out all busy workqueues and 4372 * Called from a sysrq handler or try_to_freeze_tasks() and prints out
4373 * pools. 4373 * all busy workqueues and pools.
4374 */ 4374 */
4375void show_workqueue_state(void) 4375void show_workqueue_state(void)
4376{ 4376{
diff --git a/scripts/analyze_suspend.py b/scripts/analyze_suspend.py
index 93e1fd40f430..a0ba48fa2c5e 100755
--- a/scripts/analyze_suspend.py
+++ b/scripts/analyze_suspend.py
@@ -19,6 +19,17 @@
19# Authors: 19# Authors:
20# Todd Brandt <todd.e.brandt@linux.intel.com> 20# Todd Brandt <todd.e.brandt@linux.intel.com>
21# 21#
22# Links:
23# Home Page
24# https://01.org/suspendresume
25# Source repo
26# https://github.com/01org/suspendresume
27# Documentation
28# Getting Started
29# https://01.org/suspendresume/documentation/getting-started
30# Command List:
31# https://01.org/suspendresume/documentation/command-list
32#
22# Description: 33# Description:
23# This tool is designed to assist kernel and OS developers in optimizing 34# This tool is designed to assist kernel and OS developers in optimizing
24# their linux stack's suspend/resume time. Using a kernel image built 35# their linux stack's suspend/resume time. Using a kernel image built
@@ -35,6 +46,8 @@
35# CONFIG_FTRACE=y 46# CONFIG_FTRACE=y
36# CONFIG_FUNCTION_TRACER=y 47# CONFIG_FUNCTION_TRACER=y
37# CONFIG_FUNCTION_GRAPH_TRACER=y 48# CONFIG_FUNCTION_GRAPH_TRACER=y
49# CONFIG_KPROBES=y
50# CONFIG_KPROBES_ON_FTRACE=y
38# 51#
39# For kernel versions older than 3.15: 52# For kernel versions older than 3.15:
40# The following additional kernel parameters are required: 53# The following additional kernel parameters are required:
@@ -52,6 +65,7 @@ import re
52import platform 65import platform
53from datetime import datetime 66from datetime import datetime
54import struct 67import struct
68import ConfigParser
55 69
56# ----------------- CLASSES -------------------- 70# ----------------- CLASSES --------------------
57 71
@@ -60,8 +74,15 @@ import struct
60# A global, single-instance container used to 74# A global, single-instance container used to
61# store system values and test parameters 75# store system values and test parameters
62class SystemValues: 76class SystemValues:
63 version = 3.0 77 ansi = False
78 version = '4.2'
64 verbose = False 79 verbose = False
80 addlogs = False
81 mindevlen = 0.001
82 mincglen = 1.0
83 srgap = 0
84 cgexp = False
85 outdir = ''
65 testdir = '.' 86 testdir = '.'
66 tpath = '/sys/kernel/debug/tracing/' 87 tpath = '/sys/kernel/debug/tracing/'
67 fpdtpath = '/sys/firmware/acpi/tables/FPDT' 88 fpdtpath = '/sys/firmware/acpi/tables/FPDT'
@@ -71,26 +92,21 @@ class SystemValues:
71 'device_pm_callback_end', 92 'device_pm_callback_end',
72 'device_pm_callback_start' 93 'device_pm_callback_start'
73 ] 94 ]
74 modename = { 95 testcommand = ''
75 'freeze': 'Suspend-To-Idle (S0)',
76 'standby': 'Power-On Suspend (S1)',
77 'mem': 'Suspend-to-RAM (S3)',
78 'disk': 'Suspend-to-disk (S4)'
79 }
80 mempath = '/dev/mem' 96 mempath = '/dev/mem'
81 powerfile = '/sys/power/state' 97 powerfile = '/sys/power/state'
82 suspendmode = 'mem' 98 suspendmode = 'mem'
83 hostname = 'localhost' 99 hostname = 'localhost'
84 prefix = 'test' 100 prefix = 'test'
85 teststamp = '' 101 teststamp = ''
102 dmesgstart = 0.0
86 dmesgfile = '' 103 dmesgfile = ''
87 ftracefile = '' 104 ftracefile = ''
88 htmlfile = '' 105 htmlfile = ''
106 embedded = False
89 rtcwake = False 107 rtcwake = False
90 rtcwaketime = 10 108 rtcwaketime = 10
91 rtcpath = '' 109 rtcpath = ''
92 android = False
93 adb = 'adb'
94 devicefilter = [] 110 devicefilter = []
95 stamp = 0 111 stamp = 0
96 execcount = 1 112 execcount = 1
@@ -98,16 +114,90 @@ class SystemValues:
98 usecallgraph = False 114 usecallgraph = False
99 usetraceevents = False 115 usetraceevents = False
100 usetraceeventsonly = False 116 usetraceeventsonly = False
117 usetracemarkers = True
118 usekprobes = True
119 usedevsrc = False
101 notestrun = False 120 notestrun = False
102 altdevname = dict() 121 devprops = dict()
103 postresumetime = 0 122 postresumetime = 0
123 devpropfmt = '# Device Properties: .*'
104 tracertypefmt = '# tracer: (?P<t>.*)' 124 tracertypefmt = '# tracer: (?P<t>.*)'
105 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$' 125 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$'
106 postresumefmt = '# post resume time (?P<t>[0-9]*)$' 126 postresumefmt = '# post resume time (?P<t>[0-9]*)$'
107 stampfmt = '# suspend-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\ 127 stampfmt = '# suspend-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\
108 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\ 128 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\
109 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$' 129 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
130 kprobecolor = 'rgba(204,204,204,0.5)'
131 synccolor = 'rgba(204,204,204,0.5)'
132 debugfuncs = []
133 tracefuncs = {
134 'sys_sync': dict(),
135 'pm_prepare_console': dict(),
136 'pm_notifier_call_chain': dict(),
137 'freeze_processes': dict(),
138 'freeze_kernel_threads': dict(),
139 'pm_restrict_gfp_mask': dict(),
140 'acpi_suspend_begin': dict(),
141 'suspend_console': dict(),
142 'acpi_pm_prepare': dict(),
143 'syscore_suspend': dict(),
144 'arch_enable_nonboot_cpus_end': dict(),
145 'syscore_resume': dict(),
146 'acpi_pm_finish': dict(),
147 'resume_console': dict(),
148 'acpi_pm_end': dict(),
149 'pm_restore_gfp_mask': dict(),
150 'thaw_processes': dict(),
151 'pm_restore_console': dict(),
152 'CPU_OFF': {
153 'func':'_cpu_down',
154 'args_x86_64': {'cpu':'%di:s32'},
155 'format': 'CPU_OFF[{cpu}]',
156 'mask': 'CPU_.*_DOWN'
157 },
158 'CPU_ON': {
159 'func':'_cpu_up',
160 'args_x86_64': {'cpu':'%di:s32'},
161 'format': 'CPU_ON[{cpu}]',
162 'mask': 'CPU_.*_UP'
163 },
164 }
165 dev_tracefuncs = {
166 # general wait/delay/sleep
167 'msleep': { 'args_x86_64': {'time':'%di:s32'} },
168 'udelay': { 'func':'__const_udelay', 'args_x86_64': {'loops':'%di:s32'} },
169 'acpi_os_stall': dict(),
170 # ACPI
171 'acpi_resume_power_resources': dict(),
172 'acpi_ps_parse_aml': dict(),
173 # filesystem
174 'ext4_sync_fs': dict(),
175 # ATA
176 'ata_eh_recover': { 'args_x86_64': {'port':'+36(%di):s32'} },
177 # i915
178 'i915_gem_restore_gtt_mappings': dict(),
179 'intel_opregion_setup': dict(),
180 'intel_dp_detect': dict(),
181 'intel_hdmi_detect': dict(),
182 'intel_opregion_init': dict(),
183 }
184 kprobes_postresume = [
185 {
186 'name': 'ataportrst',
187 'func': 'ata_eh_recover',
188 'args': {'port':'+36(%di):s32'},
189 'format': 'ata{port}_port_reset',
190 'mask': 'ata.*_port_reset'
191 }
192 ]
193 kprobes = dict()
194 timeformat = '%.3f'
110 def __init__(self): 195 def __init__(self):
196 # if this is a phoronix test run, set some default options
197 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ):
198 self.embedded = True
199 self.addlogs = True
200 self.htmlfile = os.environ['LOG_FILE']
111 self.hostname = platform.node() 201 self.hostname = platform.node()
112 if(self.hostname == ''): 202 if(self.hostname == ''):
113 self.hostname = 'localhost' 203 self.hostname = 'localhost'
@@ -118,6 +208,12 @@ class SystemValues:
118 if os.path.exists(rtc) and os.path.exists(rtc+'/date') and \ 208 if os.path.exists(rtc) and os.path.exists(rtc+'/date') and \
119 os.path.exists(rtc+'/time') and os.path.exists(rtc+'/wakealarm'): 209 os.path.exists(rtc+'/time') and os.path.exists(rtc+'/wakealarm'):
120 self.rtcpath = rtc 210 self.rtcpath = rtc
211 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()):
212 self.ansi = True
213 def setPrecision(self, num):
214 if num < 0 or num > 6:
215 return
216 self.timeformat = '%.{0}f'.format(num)
121 def setOutputFile(self): 217 def setOutputFile(self):
122 if((self.htmlfile == '') and (self.dmesgfile != '')): 218 if((self.htmlfile == '') and (self.dmesgfile != '')):
123 m = re.match('(?P<name>.*)_dmesg\.txt$', self.dmesgfile) 219 m = re.match('(?P<name>.*)_dmesg\.txt$', self.dmesgfile)
@@ -129,32 +225,37 @@ class SystemValues:
129 self.htmlfile = m.group('name')+'.html' 225 self.htmlfile = m.group('name')+'.html'
130 if(self.htmlfile == ''): 226 if(self.htmlfile == ''):
131 self.htmlfile = 'output.html' 227 self.htmlfile = 'output.html'
132 def initTestOutput(self, subdir): 228 def initTestOutput(self, subdir, testpath=''):
133 if(not self.android): 229 self.prefix = self.hostname
134 self.prefix = self.hostname 230 v = open('/proc/version', 'r').read().strip()
135 v = open('/proc/version', 'r').read().strip() 231 kver = string.split(v)[2]
136 kver = string.split(v)[2] 232 n = datetime.now()
137 else: 233 testtime = n.strftime('suspend-%m%d%y-%H%M%S')
138 self.prefix = 'android' 234 if not testpath:
139 v = os.popen(self.adb+' shell cat /proc/version').read().strip() 235 testpath = n.strftime('suspend-%y%m%d-%H%M%S')
140 kver = string.split(v)[2]
141 testtime = datetime.now().strftime('suspend-%m%d%y-%H%M%S')
142 if(subdir != "."): 236 if(subdir != "."):
143 self.testdir = subdir+"/"+testtime 237 self.testdir = subdir+"/"+testpath
144 else: 238 else:
145 self.testdir = testtime 239 self.testdir = testpath
146 self.teststamp = \ 240 self.teststamp = \
147 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver 241 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver
242 if(self.embedded):
243 self.dmesgfile = \
244 '/tmp/'+testtime+'_'+self.suspendmode+'_dmesg.txt'
245 self.ftracefile = \
246 '/tmp/'+testtime+'_'+self.suspendmode+'_ftrace.txt'
247 return
148 self.dmesgfile = \ 248 self.dmesgfile = \
149 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt' 249 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt'
150 self.ftracefile = \ 250 self.ftracefile = \
151 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt' 251 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt'
152 self.htmlfile = \ 252 self.htmlfile = \
153 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html' 253 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html'
154 os.mkdir(self.testdir) 254 if not os.path.isdir(self.testdir):
255 os.mkdir(self.testdir)
155 def setDeviceFilter(self, devnames): 256 def setDeviceFilter(self, devnames):
156 self.devicefilter = string.split(devnames) 257 self.devicefilter = string.split(devnames)
157 def rtcWakeAlarm(self): 258 def rtcWakeAlarmOn(self):
158 os.system('echo 0 > '+self.rtcpath+'/wakealarm') 259 os.system('echo 0 > '+self.rtcpath+'/wakealarm')
159 outD = open(self.rtcpath+'/date', 'r').read().strip() 260 outD = open(self.rtcpath+'/date', 'r').read().strip()
160 outT = open(self.rtcpath+'/time', 'r').read().strip() 261 outT = open(self.rtcpath+'/time', 'r').read().strip()
@@ -172,9 +273,361 @@ class SystemValues:
172 nowtime = int(datetime.now().strftime('%s')) 273 nowtime = int(datetime.now().strftime('%s'))
173 alarm = nowtime + self.rtcwaketime 274 alarm = nowtime + self.rtcwaketime
174 os.system('echo %d > %s/wakealarm' % (alarm, self.rtcpath)) 275 os.system('echo %d > %s/wakealarm' % (alarm, self.rtcpath))
276 def rtcWakeAlarmOff(self):
277 os.system('echo 0 > %s/wakealarm' % self.rtcpath)
278 def initdmesg(self):
279 # get the latest time stamp from the dmesg log
280 fp = os.popen('dmesg')
281 ktime = '0'
282 for line in fp:
283 line = line.replace('\r\n', '')
284 idx = line.find('[')
285 if idx > 1:
286 line = line[idx:]
287 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
288 if(m):
289 ktime = m.group('ktime')
290 fp.close()
291 self.dmesgstart = float(ktime)
292 def getdmesg(self):
293 # store all new dmesg lines since initdmesg was called
294 fp = os.popen('dmesg')
295 op = open(self.dmesgfile, 'a')
296 for line in fp:
297 line = line.replace('\r\n', '')
298 idx = line.find('[')
299 if idx > 1:
300 line = line[idx:]
301 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
302 if(not m):
303 continue
304 ktime = float(m.group('ktime'))
305 if ktime > self.dmesgstart:
306 op.write(line)
307 fp.close()
308 op.close()
309 def addFtraceFilterFunctions(self, file):
310 fp = open(file)
311 list = fp.read().split('\n')
312 fp.close()
313 for i in list:
314 if len(i) < 2:
315 continue
316 self.tracefuncs[i] = dict()
317 def getFtraceFilterFunctions(self, current):
318 rootCheck(True)
319 if not current:
320 os.system('cat '+self.tpath+'available_filter_functions')
321 return
322 fp = open(self.tpath+'available_filter_functions')
323 master = fp.read().split('\n')
324 fp.close()
325 if len(self.debugfuncs) > 0:
326 for i in self.debugfuncs:
327 if i in master:
328 print i
329 else:
330 print self.colorText(i)
331 else:
332 for i in self.tracefuncs:
333 if 'func' in self.tracefuncs[i]:
334 i = self.tracefuncs[i]['func']
335 if i in master:
336 print i
337 else:
338 print self.colorText(i)
339 def setFtraceFilterFunctions(self, list):
340 fp = open(self.tpath+'available_filter_functions')
341 master = fp.read().split('\n')
342 fp.close()
343 flist = ''
344 for i in list:
345 if i not in master:
346 continue
347 if ' [' in i:
348 flist += i.split(' ')[0]+'\n'
349 else:
350 flist += i+'\n'
351 fp = open(self.tpath+'set_graph_function', 'w')
352 fp.write(flist)
353 fp.close()
354 def kprobeMatch(self, name, target):
355 if name not in self.kprobes:
356 return False
357 if re.match(self.kprobes[name]['mask'], target):
358 return True
359 return False
360 def basicKprobe(self, name):
361 self.kprobes[name] = {'name': name,'func': name,'args': dict(),'format': name,'mask': name}
362 def defaultKprobe(self, name, kdata):
363 k = kdata
364 for field in ['name', 'format', 'mask', 'func']:
365 if field not in k:
366 k[field] = name
367 archargs = 'args_'+platform.machine()
368 if archargs in k:
369 k['args'] = k[archargs]
370 else:
371 k['args'] = dict()
372 k['format'] = name
373 self.kprobes[name] = k
374 def kprobeColor(self, name):
375 if name not in self.kprobes or 'color' not in self.kprobes[name]:
376 return ''
377 return self.kprobes[name]['color']
378 def kprobeDisplayName(self, name, dataraw):
379 if name not in self.kprobes:
380 self.basicKprobe(name)
381 data = ''
382 quote=0
383 # first remvoe any spaces inside quotes, and the quotes
384 for c in dataraw:
385 if c == '"':
386 quote = (quote + 1) % 2
387 if quote and c == ' ':
388 data += '_'
389 elif c != '"':
390 data += c
391 fmt, args = self.kprobes[name]['format'], self.kprobes[name]['args']
392 arglist = dict()
393 # now process the args
394 for arg in sorted(args):
395 arglist[arg] = ''
396 m = re.match('.* '+arg+'=(?P<arg>.*) ', data);
397 if m:
398 arglist[arg] = m.group('arg')
399 else:
400 m = re.match('.* '+arg+'=(?P<arg>.*)', data);
401 if m:
402 arglist[arg] = m.group('arg')
403 out = fmt.format(**arglist)
404 out = out.replace(' ', '_').replace('"', '')
405 return out
406 def kprobeText(self, kprobe):
407 name, fmt, func, args = kprobe['name'], kprobe['format'], kprobe['func'], kprobe['args']
408 if re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', func):
409 doError('Kprobe "%s" has format info in the function name "%s"' % (name, func), False)
410 for arg in re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', fmt):
411 if arg not in args:
412 doError('Kprobe "%s" is missing argument "%s"' % (name, arg), False)
413 val = 'p:%s_cal %s' % (name, func)
414 for i in sorted(args):
415 val += ' %s=%s' % (i, args[i])
416 val += '\nr:%s_ret %s $retval\n' % (name, func)
417 return val
418 def addKprobes(self):
419 # first test each kprobe
420 print('INITIALIZING KPROBES...')
421 rejects = []
422 for name in sorted(self.kprobes):
423 if not self.testKprobe(self.kprobes[name]):
424 rejects.append(name)
425 # remove all failed ones from the list
426 for name in rejects:
427 vprint('Skipping KPROBE: %s' % name)
428 self.kprobes.pop(name)
429 self.fsetVal('', 'kprobe_events')
430 kprobeevents = ''
431 # set the kprobes all at once
432 for kp in self.kprobes:
433 val = self.kprobeText(self.kprobes[kp])
434 vprint('Adding KPROBE: %s\n%s' % (kp, val.strip()))
435 kprobeevents += self.kprobeText(self.kprobes[kp])
436 self.fsetVal(kprobeevents, 'kprobe_events')
437 # verify that the kprobes were set as ordered
438 check = self.fgetVal('kprobe_events')
439 linesout = len(kprobeevents.split('\n'))
440 linesack = len(check.split('\n'))
441 if linesack < linesout:
442 # if not, try appending the kprobes 1 by 1
443 for kp in self.kprobes:
444 kprobeevents = self.kprobeText(self.kprobes[kp])
445 self.fsetVal(kprobeevents, 'kprobe_events', 'a')
446 self.fsetVal('1', 'events/kprobes/enable')
447 def testKprobe(self, kprobe):
448 kprobeevents = self.kprobeText(kprobe)
449 if not kprobeevents:
450 return False
451 try:
452 self.fsetVal(kprobeevents, 'kprobe_events')
453 check = self.fgetVal('kprobe_events')
454 except:
455 return False
456 linesout = len(kprobeevents.split('\n'))
457 linesack = len(check.split('\n'))
458 if linesack < linesout:
459 return False
460 return True
461 def fsetVal(self, val, path, mode='w'):
462 file = self.tpath+path
463 if not os.path.exists(file):
464 return False
465 try:
466 fp = open(file, mode)
467 fp.write(val)
468 fp.close()
469 except:
470 pass
471 return True
472 def fgetVal(self, path):
473 file = self.tpath+path
474 res = ''
475 if not os.path.exists(file):
476 return res
477 try:
478 fp = open(file, 'r')
479 res = fp.read()
480 fp.close()
481 except:
482 pass
483 return res
484 def cleanupFtrace(self):
485 if(self.usecallgraph or self.usetraceevents):
486 self.fsetVal('0', 'events/kprobes/enable')
487 self.fsetVal('', 'kprobe_events')
488 def setupAllKprobes(self):
489 for name in self.tracefuncs:
490 self.defaultKprobe(name, self.tracefuncs[name])
491 for name in self.dev_tracefuncs:
492 self.defaultKprobe(name, self.dev_tracefuncs[name])
493 def isCallgraphFunc(self, name):
494 if len(self.debugfuncs) < 1 and self.suspendmode == 'command':
495 return True
496 if name in self.debugfuncs:
497 return True
498 funclist = []
499 for i in self.tracefuncs:
500 if 'func' in self.tracefuncs[i]:
501 funclist.append(self.tracefuncs[i]['func'])
502 else:
503 funclist.append(i)
504 if name in funclist:
505 return True
506 return False
507 def initFtrace(self, testing=False):
508 tp = self.tpath
509 print('INITIALIZING FTRACE...')
510 # turn trace off
511 self.fsetVal('0', 'tracing_on')
512 self.cleanupFtrace()
513 # set the trace clock to global
514 self.fsetVal('global', 'trace_clock')
515 # set trace buffer to a huge value
516 self.fsetVal('nop', 'current_tracer')
517 self.fsetVal('100000', 'buffer_size_kb')
518 # go no further if this is just a status check
519 if testing:
520 return
521 if self.usekprobes:
522 # add tracefunc kprobes so long as were not using full callgraph
523 if(not self.usecallgraph or len(self.debugfuncs) > 0):
524 for name in self.tracefuncs:
525 self.defaultKprobe(name, self.tracefuncs[name])
526 if self.usedevsrc:
527 for name in self.dev_tracefuncs:
528 self.defaultKprobe(name, self.dev_tracefuncs[name])
529 else:
530 self.usedevsrc = False
531 self.addKprobes()
532 # initialize the callgraph trace, unless this is an x2 run
533 if(self.usecallgraph):
534 # set trace type
535 self.fsetVal('function_graph', 'current_tracer')
536 self.fsetVal('', 'set_ftrace_filter')
537 # set trace format options
538 self.fsetVal('print-parent', 'trace_options')
539 self.fsetVal('funcgraph-abstime', 'trace_options')
540 self.fsetVal('funcgraph-cpu', 'trace_options')
541 self.fsetVal('funcgraph-duration', 'trace_options')
542 self.fsetVal('funcgraph-proc', 'trace_options')
543 self.fsetVal('funcgraph-tail', 'trace_options')
544 self.fsetVal('nofuncgraph-overhead', 'trace_options')
545 self.fsetVal('context-info', 'trace_options')
546 self.fsetVal('graph-time', 'trace_options')
547 self.fsetVal('0', 'max_graph_depth')
548 if len(self.debugfuncs) > 0:
549 self.setFtraceFilterFunctions(self.debugfuncs)
550 elif self.suspendmode == 'command':
551 self.fsetVal('', 'set_graph_function')
552 else:
553 cf = ['dpm_run_callback']
554 if(self.usetraceeventsonly):
555 cf += ['dpm_prepare', 'dpm_complete']
556 for fn in self.tracefuncs:
557 if 'func' in self.tracefuncs[fn]:
558 cf.append(self.tracefuncs[fn]['func'])
559 else:
560 cf.append(fn)
561 self.setFtraceFilterFunctions(cf)
562 if(self.usetraceevents):
563 # turn trace events on
564 events = iter(self.traceevents)
565 for e in events:
566 self.fsetVal('1', 'events/power/'+e+'/enable')
567 # clear the trace buffer
568 self.fsetVal('', 'trace')
569 def verifyFtrace(self):
570 # files needed for any trace data
571 files = ['buffer_size_kb', 'current_tracer', 'trace', 'trace_clock',
572 'trace_marker', 'trace_options', 'tracing_on']
573 # files needed for callgraph trace data
574 tp = self.tpath
575 if(self.usecallgraph):
576 files += [
577 'available_filter_functions',
578 'set_ftrace_filter',
579 'set_graph_function'
580 ]
581 for f in files:
582 if(os.path.exists(tp+f) == False):
583 return False
584 return True
585 def verifyKprobes(self):
586 # files needed for kprobes to work
587 files = ['kprobe_events', 'events']
588 tp = self.tpath
589 for f in files:
590 if(os.path.exists(tp+f) == False):
591 return False
592 return True
593 def colorText(self, str):
594 if not self.ansi:
595 return str
596 return '\x1B[31;40m'+str+'\x1B[m'
175 597
176sysvals = SystemValues() 598sysvals = SystemValues()
177 599
600# Class: DevProps
601# Description:
602# Simple class which holds property values collected
603# for all the devices used in the timeline.
604class DevProps:
605 syspath = ''
606 altname = ''
607 async = True
608 xtraclass = ''
609 xtrainfo = ''
610 def out(self, dev):
611 return '%s,%s,%d;' % (dev, self.altname, self.async)
612 def debug(self, dev):
613 print '%s:\n\taltname = %s\n\t async = %s' % (dev, self.altname, self.async)
614 def altName(self, dev):
615 if not self.altname or self.altname == dev:
616 return dev
617 return '%s [%s]' % (self.altname, dev)
618 def xtraClass(self):
619 if self.xtraclass:
620 return ' '+self.xtraclass
621 if not self.async:
622 return ' sync'
623 return ''
624 def xtraInfo(self):
625 if self.xtraclass:
626 return ' '+self.xtraclass
627 if self.async:
628 return ' async'
629 return ' sync'
630
178# Class: DeviceNode 631# Class: DeviceNode
179# Description: 632# Description:
180# A container used to create a device hierachy, with a single root node 633# A container used to create a device hierachy, with a single root node
@@ -228,6 +681,7 @@ class Data:
228 html_device_id = 0 681 html_device_id = 0
229 stamp = 0 682 stamp = 0
230 outfile = '' 683 outfile = ''
684 dev_ubiquitous = ['msleep', 'udelay']
231 def __init__(self, num): 685 def __init__(self, num):
232 idchar = 'abcdefghijklmnopqrstuvwxyz' 686 idchar = 'abcdefghijklmnopqrstuvwxyz'
233 self.testnumber = num 687 self.testnumber = num
@@ -257,6 +711,9 @@ class Data:
257 'row': 0, 'color': '#FFFFCC', 'order': 9} 711 'row': 0, 'color': '#FFFFCC', 'order': 9}
258 } 712 }
259 self.phases = self.sortedPhases() 713 self.phases = self.sortedPhases()
714 self.devicegroups = []
715 for phase in self.phases:
716 self.devicegroups.append([phase])
260 def getStart(self): 717 def getStart(self):
261 return self.dmesg[self.phases[0]]['start'] 718 return self.dmesg[self.phases[0]]['start']
262 def setStart(self, time): 719 def setStart(self, time):
@@ -273,51 +730,61 @@ class Data:
273 for dev in list: 730 for dev in list:
274 d = list[dev] 731 d = list[dev]
275 if(d['pid'] == pid and time >= d['start'] and 732 if(d['pid'] == pid and time >= d['start'] and
276 time <= d['end']): 733 time < d['end']):
277 return False 734 return False
278 return True 735 return True
279 def addIntraDevTraceEvent(self, action, name, pid, time): 736 def targetDevice(self, phaselist, start, end, pid=-1):
280 if(action == 'mutex_lock_try'): 737 tgtdev = ''
281 color = 'red' 738 for phase in phaselist:
282 elif(action == 'mutex_lock_pass'):
283 color = 'green'
284 elif(action == 'mutex_unlock'):
285 color = 'blue'
286 else:
287 # create separate colors based on the name
288 v1 = len(name)*10 % 256
289 v2 = string.count(name, 'e')*100 % 256
290 v3 = ord(name[0])*20 % 256
291 color = '#%06X' % ((v1*0x10000) + (v2*0x100) + v3)
292 for phase in self.phases:
293 list = self.dmesg[phase]['list']
294 for dev in list:
295 d = list[dev]
296 if(d['pid'] == pid and time >= d['start'] and
297 time <= d['end']):
298 e = TraceEvent(action, name, color, time)
299 if('traceevents' not in d):
300 d['traceevents'] = []
301 d['traceevents'].append(e)
302 return d
303 break
304 return 0
305 def capIntraDevTraceEvent(self, action, name, pid, time):
306 for phase in self.phases:
307 list = self.dmesg[phase]['list'] 739 list = self.dmesg[phase]['list']
308 for dev in list: 740 for devname in list:
309 d = list[dev] 741 dev = list[devname]
310 if(d['pid'] == pid and time >= d['start'] and 742 if(pid >= 0 and dev['pid'] != pid):
311 time <= d['end']): 743 continue
312 if('traceevents' not in d): 744 devS = dev['start']
313 return 745 devE = dev['end']
314 for e in d['traceevents']: 746 if(start < devS or start >= devE or end <= devS or end > devE):
315 if(e.action == action and 747 continue
316 e.name == name and not e.ready): 748 tgtdev = dev
317 e.length = time - e.time 749 break
318 e.ready = True 750 return tgtdev
319 break 751 def addDeviceFunctionCall(self, displayname, kprobename, proc, pid, start, end, cdata, rdata):
320 return 752 machstart = self.dmesg['suspend_machine']['start']
753 machend = self.dmesg['resume_machine']['end']
754 tgtdev = self.targetDevice(self.phases, start, end, pid)
755 if not tgtdev and start >= machstart and end < machend:
756 # device calls in machine phases should be serial
757 tgtdev = self.targetDevice(['suspend_machine', 'resume_machine'], start, end)
758 if not tgtdev:
759 if 'scsi_eh' in proc:
760 self.newActionGlobal(proc, start, end, pid)
761 self.addDeviceFunctionCall(displayname, kprobename, proc, pid, start, end, cdata, rdata)
762 else:
763 vprint('IGNORE: %s[%s](%d) [%f - %f] | %s | %s | %s' % (displayname, kprobename,
764 pid, start, end, cdata, rdata, proc))
765 return False
766 # detail block fits within tgtdev
767 if('src' not in tgtdev):
768 tgtdev['src'] = []
769 title = cdata+' '+rdata
770 mstr = '\(.*\) *(?P<args>.*) *\((?P<caller>.*)\+.* arg1=(?P<ret>.*)'
771 m = re.match(mstr, title)
772 if m:
773 c = m.group('caller')
774 a = m.group('args').strip()
775 r = m.group('ret')
776 if len(r) > 6:
777 r = ''
778 else:
779 r = 'ret=%s ' % r
780 l = '%0.3fms' % ((end - start) * 1000)
781 if kprobename in self.dev_ubiquitous:
782 title = '%s(%s) <- %s, %s(%s)' % (displayname, a, c, r, l)
783 else:
784 title = '%s(%s) %s(%s)' % (displayname, a, r, l)
785 e = TraceEvent(title, kprobename, start, end - start)
786 tgtdev['src'].append(e)
787 return True
321 def trimTimeVal(self, t, t0, dT, left): 788 def trimTimeVal(self, t, t0, dT, left):
322 if left: 789 if left:
323 if(t > t0): 790 if(t > t0):
@@ -353,11 +820,11 @@ class Data:
353 cg.end = self.trimTimeVal(cg.end, t0, dT, left) 820 cg.end = self.trimTimeVal(cg.end, t0, dT, left)
354 for line in cg.list: 821 for line in cg.list:
355 line.time = self.trimTimeVal(line.time, t0, dT, left) 822 line.time = self.trimTimeVal(line.time, t0, dT, left)
356 if('traceevents' in d): 823 if('src' in d):
357 for e in d['traceevents']: 824 for e in d['src']:
358 e.time = self.trimTimeVal(e.time, t0, dT, left) 825 e.time = self.trimTimeVal(e.time, t0, dT, left)
359 def normalizeTime(self, tZero): 826 def normalizeTime(self, tZero):
360 # first trim out any standby or freeze clock time 827 # trim out any standby or freeze clock time
361 if(self.tSuspended != self.tResumed): 828 if(self.tSuspended != self.tResumed):
362 if(self.tResumed > tZero): 829 if(self.tResumed > tZero):
363 self.trimTime(self.tSuspended, \ 830 self.trimTime(self.tSuspended, \
@@ -365,29 +832,6 @@ class Data:
365 else: 832 else:
366 self.trimTime(self.tSuspended, \ 833 self.trimTime(self.tSuspended, \
367 self.tResumed-self.tSuspended, False) 834 self.tResumed-self.tSuspended, False)
368 # shift the timeline so that tZero is the new 0
369 self.tSuspended -= tZero
370 self.tResumed -= tZero
371 self.start -= tZero
372 self.end -= tZero
373 for phase in self.phases:
374 p = self.dmesg[phase]
375 p['start'] -= tZero
376 p['end'] -= tZero
377 list = p['list']
378 for name in list:
379 d = list[name]
380 d['start'] -= tZero
381 d['end'] -= tZero
382 if('ftrace' in d):
383 cg = d['ftrace']
384 cg.start -= tZero
385 cg.end -= tZero
386 for line in cg.list:
387 line.time -= tZero
388 if('traceevents' in d):
389 for e in d['traceevents']:
390 e.time -= tZero
391 def newPhaseWithSingleAction(self, phasename, devname, start, end, color): 835 def newPhaseWithSingleAction(self, phasename, devname, start, end, color):
392 for phase in self.phases: 836 for phase in self.phases:
393 self.dmesg[phase]['order'] += 1 837 self.dmesg[phase]['order'] += 1
@@ -417,6 +861,7 @@ class Data:
417 {'list': list, 'start': start, 'end': end, 861 {'list': list, 'start': start, 'end': end,
418 'row': 0, 'color': color, 'order': order} 862 'row': 0, 'color': color, 'order': order}
419 self.phases = self.sortedPhases() 863 self.phases = self.sortedPhases()
864 self.devicegroups.append([phasename])
420 def setPhase(self, phase, ktime, isbegin): 865 def setPhase(self, phase, ktime, isbegin):
421 if(isbegin): 866 if(isbegin):
422 self.dmesg[phase]['start'] = ktime 867 self.dmesg[phase]['start'] = ktime
@@ -442,7 +887,10 @@ class Data:
442 for devname in phaselist: 887 for devname in phaselist:
443 dev = phaselist[devname] 888 dev = phaselist[devname]
444 if(dev['end'] < 0): 889 if(dev['end'] < 0):
445 dev['end'] = end 890 for p in self.phases:
891 if self.dmesg[p]['end'] > dev['start']:
892 dev['end'] = self.dmesg[p]['end']
893 break
446 vprint('%s (%s): callback didnt return' % (devname, phase)) 894 vprint('%s (%s): callback didnt return' % (devname, phase))
447 def deviceFilter(self, devicefilter): 895 def deviceFilter(self, devicefilter):
448 # remove all by the relatives of the filter devnames 896 # remove all by the relatives of the filter devnames
@@ -472,22 +920,58 @@ class Data:
472 # if any calls never returned, clip them at system resume end 920 # if any calls never returned, clip them at system resume end
473 for phase in self.phases: 921 for phase in self.phases:
474 self.fixupInitcalls(phase, self.getEnd()) 922 self.fixupInitcalls(phase, self.getEnd())
475 def newActionGlobal(self, name, start, end): 923 def isInsideTimeline(self, start, end):
924 if(self.start <= start and self.end > start):
925 return True
926 return False
927 def phaseOverlap(self, phases):
928 rmgroups = []
929 newgroup = []
930 for group in self.devicegroups:
931 for phase in phases:
932 if phase not in group:
933 continue
934 for p in group:
935 if p not in newgroup:
936 newgroup.append(p)
937 if group not in rmgroups:
938 rmgroups.append(group)
939 for group in rmgroups:
940 self.devicegroups.remove(group)
941 self.devicegroups.append(newgroup)
942 def newActionGlobal(self, name, start, end, pid=-1, color=''):
943 # if event starts before timeline start, expand timeline
944 if(start < self.start):
945 self.setStart(start)
946 # if event ends after timeline end, expand the timeline
947 if(end > self.end):
948 self.setEnd(end)
476 # which phase is this device callback or action "in" 949 # which phase is this device callback or action "in"
477 targetphase = "none" 950 targetphase = "none"
951 htmlclass = ''
478 overlap = 0.0 952 overlap = 0.0
953 phases = []
479 for phase in self.phases: 954 for phase in self.phases:
480 pstart = self.dmesg[phase]['start'] 955 pstart = self.dmesg[phase]['start']
481 pend = self.dmesg[phase]['end'] 956 pend = self.dmesg[phase]['end']
482 o = max(0, min(end, pend) - max(start, pstart)) 957 o = max(0, min(end, pend) - max(start, pstart))
483 if(o > overlap): 958 if o > 0:
959 phases.append(phase)
960 if o > overlap:
961 if overlap > 0 and phase == 'post_resume':
962 continue
484 targetphase = phase 963 targetphase = phase
485 overlap = o 964 overlap = o
965 if pid == -2:
966 htmlclass = ' bg'
967 if len(phases) > 1:
968 htmlclass = ' bg'
969 self.phaseOverlap(phases)
486 if targetphase in self.phases: 970 if targetphase in self.phases:
487 self.newAction(targetphase, name, -1, '', start, end, '') 971 newname = self.newAction(targetphase, name, pid, '', start, end, '', htmlclass, color)
488 return True 972 return (targetphase, newname)
489 return False 973 return False
490 def newAction(self, phase, name, pid, parent, start, end, drv): 974 def newAction(self, phase, name, pid, parent, start, end, drv, htmlclass='', color=''):
491 # new device callback for a specific phase 975 # new device callback for a specific phase
492 self.html_device_id += 1 976 self.html_device_id += 1
493 devid = '%s%d' % (self.idstr, self.html_device_id) 977 devid = '%s%d' % (self.idstr, self.html_device_id)
@@ -495,8 +979,19 @@ class Data:
495 length = -1.0 979 length = -1.0
496 if(start >= 0 and end >= 0): 980 if(start >= 0 and end >= 0):
497 length = end - start 981 length = end - start
982 if pid == -2:
983 i = 2
984 origname = name
985 while(name in list):
986 name = '%s[%d]' % (origname, i)
987 i += 1
498 list[name] = {'start': start, 'end': end, 'pid': pid, 'par': parent, 988 list[name] = {'start': start, 'end': end, 'pid': pid, 'par': parent,
499 'length': length, 'row': 0, 'id': devid, 'drv': drv } 989 'length': length, 'row': 0, 'id': devid, 'drv': drv }
990 if htmlclass:
991 list[name]['htmlclass'] = htmlclass
992 if color:
993 list[name]['color'] = color
994 return name
500 def deviceIDs(self, devlist, phase): 995 def deviceIDs(self, devlist, phase):
501 idlist = [] 996 idlist = []
502 list = self.dmesg[phase]['list'] 997 list = self.dmesg[phase]['list']
@@ -536,10 +1031,21 @@ class Data:
536 vprint(' %16s: %f - %f (%d devices)' % (phase, \ 1031 vprint(' %16s: %f - %f (%d devices)' % (phase, \
537 self.dmesg[phase]['start'], self.dmesg[phase]['end'], dc)) 1032 self.dmesg[phase]['start'], self.dmesg[phase]['end'], dc))
538 vprint(' test end: %f' % self.end) 1033 vprint(' test end: %f' % self.end)
1034 def deviceChildrenAllPhases(self, devname):
1035 devlist = []
1036 for phase in self.phases:
1037 list = self.deviceChildren(devname, phase)
1038 for dev in list:
1039 if dev not in devlist:
1040 devlist.append(dev)
1041 return devlist
539 def masterTopology(self, name, list, depth): 1042 def masterTopology(self, name, list, depth):
540 node = DeviceNode(name, depth) 1043 node = DeviceNode(name, depth)
541 for cname in list: 1044 for cname in list:
542 clist = self.deviceChildren(cname, 'resume') 1045 # avoid recursions
1046 if name == cname:
1047 continue
1048 clist = self.deviceChildrenAllPhases(cname)
543 cnode = self.masterTopology(cname, clist, depth+1) 1049 cnode = self.masterTopology(cname, clist, depth+1)
544 node.children.append(cnode) 1050 node.children.append(cnode)
545 return node 1051 return node
@@ -580,7 +1086,8 @@ class Data:
580 list = self.dmesg[phase]['list'] 1086 list = self.dmesg[phase]['list']
581 for dev in list: 1087 for dev in list:
582 pdev = list[dev]['par'] 1088 pdev = list[dev]['par']
583 if(re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)): 1089 pid = list[dev]['pid']
1090 if(pid < 0 or re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)):
584 continue 1091 continue
585 if pdev and pdev not in real and pdev not in rootlist: 1092 if pdev and pdev not in real and pdev not in rootlist:
586 rootlist.append(pdev) 1093 rootlist.append(pdev)
@@ -589,22 +1096,33 @@ class Data:
589 rootlist = self.rootDeviceList() 1096 rootlist = self.rootDeviceList()
590 master = self.masterTopology('', rootlist, 0) 1097 master = self.masterTopology('', rootlist, 0)
591 return self.printTopology(master) 1098 return self.printTopology(master)
1099 def selectTimelineDevices(self, widfmt, tTotal, mindevlen):
1100 # only select devices that will actually show up in html
1101 self.tdevlist = dict()
1102 for phase in self.dmesg:
1103 devlist = []
1104 list = self.dmesg[phase]['list']
1105 for dev in list:
1106 length = (list[dev]['end'] - list[dev]['start']) * 1000
1107 width = widfmt % (((list[dev]['end']-list[dev]['start'])*100)/tTotal)
1108 if width != '0.000000' and length >= mindevlen:
1109 devlist.append(dev)
1110 self.tdevlist[phase] = devlist
592 1111
593# Class: TraceEvent 1112# Class: TraceEvent
594# Description: 1113# Description:
595# A container for trace event data found in the ftrace file 1114# A container for trace event data found in the ftrace file
596class TraceEvent: 1115class TraceEvent:
597 ready = False 1116 text = ''
598 name = ''
599 time = 0.0 1117 time = 0.0
600 color = '#FFFFFF'
601 length = 0.0 1118 length = 0.0
602 action = '' 1119 title = ''
603 def __init__(self, a, n, c, t): 1120 row = 0
604 self.action = a 1121 def __init__(self, a, n, t, l):
605 self.name = n 1122 self.title = a
606 self.color = c 1123 self.text = n
607 self.time = t 1124 self.time = t
1125 self.length = l
608 1126
609# Class: FTraceLine 1127# Class: FTraceLine
610# Description: 1128# Description:
@@ -623,11 +1141,14 @@ class FTraceLine:
623 fcall = False 1141 fcall = False
624 freturn = False 1142 freturn = False
625 fevent = False 1143 fevent = False
1144 fkprobe = False
626 depth = 0 1145 depth = 0
627 name = '' 1146 name = ''
628 type = '' 1147 type = ''
629 def __init__(self, t, m, d): 1148 def __init__(self, t, m='', d=''):
630 self.time = float(t) 1149 self.time = float(t)
1150 if not m and not d:
1151 return
631 # is this a trace event 1152 # is this a trace event
632 if(d == 'traceevent' or re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m)): 1153 if(d == 'traceevent' or re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m)):
633 if(d == 'traceevent'): 1154 if(d == 'traceevent'):
@@ -644,6 +1165,18 @@ class FTraceLine:
644 self.type = emm.group('call') 1165 self.type = emm.group('call')
645 else: 1166 else:
646 self.name = msg 1167 self.name = msg
1168 km = re.match('^(?P<n>.*)_cal$', self.type)
1169 if km:
1170 self.fcall = True
1171 self.fkprobe = True
1172 self.type = km.group('n')
1173 return
1174 km = re.match('^(?P<n>.*)_ret$', self.type)
1175 if km:
1176 self.freturn = True
1177 self.fkprobe = True
1178 self.type = km.group('n')
1179 return
647 self.fevent = True 1180 self.fevent = True
648 return 1181 return
649 # convert the duration to seconds 1182 # convert the duration to seconds
@@ -662,7 +1195,7 @@ class FTraceLine:
662 # includes comment with function name 1195 # includes comment with function name
663 match = re.match('^} *\/\* *(?P<n>.*) *\*\/$', m) 1196 match = re.match('^} *\/\* *(?P<n>.*) *\*\/$', m)
664 if(match): 1197 if(match):
665 self.name = match.group('n') 1198 self.name = match.group('n').strip()
666 # function call 1199 # function call
667 else: 1200 else:
668 self.fcall = True 1201 self.fcall = True
@@ -670,19 +1203,19 @@ class FTraceLine:
670 if(m[-1] == '{'): 1203 if(m[-1] == '{'):
671 match = re.match('^(?P<n>.*) *\(.*', m) 1204 match = re.match('^(?P<n>.*) *\(.*', m)
672 if(match): 1205 if(match):
673 self.name = match.group('n') 1206 self.name = match.group('n').strip()
674 # function call with no children (leaf) 1207 # function call with no children (leaf)
675 elif(m[-1] == ';'): 1208 elif(m[-1] == ';'):
676 self.freturn = True 1209 self.freturn = True
677 match = re.match('^(?P<n>.*) *\(.*', m) 1210 match = re.match('^(?P<n>.*) *\(.*', m)
678 if(match): 1211 if(match):
679 self.name = match.group('n') 1212 self.name = match.group('n').strip()
680 # something else (possibly a trace marker) 1213 # something else (possibly a trace marker)
681 else: 1214 else:
682 self.name = m 1215 self.name = m
683 def getDepth(self, str): 1216 def getDepth(self, str):
684 return len(str)/2 1217 return len(str)/2
685 def debugPrint(self, dev): 1218 def debugPrint(self, dev=''):
686 if(self.freturn and self.fcall): 1219 if(self.freturn and self.fcall):
687 print('%s -- %f (%02d): %s(); (%.3f us)' % (dev, self.time, \ 1220 print('%s -- %f (%02d): %s(); (%.3f us)' % (dev, self.time, \
688 self.depth, self.name, self.length*1000000)) 1221 self.depth, self.name, self.length*1000000))
@@ -692,6 +1225,33 @@ class FTraceLine:
692 else: 1225 else:
693 print('%s -- %f (%02d): %s() { (%.3f us)' % (dev, self.time, \ 1226 print('%s -- %f (%02d): %s() { (%.3f us)' % (dev, self.time, \
694 self.depth, self.name, self.length*1000000)) 1227 self.depth, self.name, self.length*1000000))
1228 def startMarker(self):
1229 global sysvals
1230 # Is this the starting line of a suspend?
1231 if not self.fevent:
1232 return False
1233 if sysvals.usetracemarkers:
1234 if(self.name == 'SUSPEND START'):
1235 return True
1236 return False
1237 else:
1238 if(self.type == 'suspend_resume' and
1239 re.match('suspend_enter\[.*\] begin', self.name)):
1240 return True
1241 return False
1242 def endMarker(self):
1243 # Is this the ending line of a resume?
1244 if not self.fevent:
1245 return False
1246 if sysvals.usetracemarkers:
1247 if(self.name == 'RESUME COMPLETE'):
1248 return True
1249 return False
1250 else:
1251 if(self.type == 'suspend_resume' and
1252 re.match('thaw_processes\[.*\] end', self.name)):
1253 return True
1254 return False
695 1255
696# Class: FTraceCallGraph 1256# Class: FTraceCallGraph
697# Description: 1257# Description:
@@ -705,54 +1265,124 @@ class FTraceCallGraph:
705 list = [] 1265 list = []
706 invalid = False 1266 invalid = False
707 depth = 0 1267 depth = 0
708 def __init__(self): 1268 pid = 0
1269 def __init__(self, pid):
709 self.start = -1.0 1270 self.start = -1.0
710 self.end = -1.0 1271 self.end = -1.0
711 self.list = [] 1272 self.list = []
712 self.depth = 0 1273 self.depth = 0
713 def setDepth(self, line): 1274 self.pid = pid
1275 def addLine(self, line, debug=False):
1276 # if this is already invalid, just leave
1277 if(self.invalid):
1278 return False
1279 # invalidate on too much data or bad depth
1280 if(len(self.list) >= 1000000 or self.depth < 0):
1281 self.invalidate(line)
1282 return False
1283 # compare current depth with this lines pre-call depth
1284 prelinedep = line.depth
1285 if(line.freturn and not line.fcall):
1286 prelinedep += 1
1287 last = 0
1288 lasttime = line.time
1289 virtualfname = 'execution_misalignment'
1290 if len(self.list) > 0:
1291 last = self.list[-1]
1292 lasttime = last.time
1293 # handle low misalignments by inserting returns
1294 if prelinedep < self.depth:
1295 if debug and last:
1296 print '-------- task %d --------' % self.pid
1297 last.debugPrint()
1298 idx = 0
1299 # add return calls to get the depth down
1300 while prelinedep < self.depth:
1301 if debug:
1302 print 'MISALIGN LOW (add returns): C%d - eC%d' % (self.depth, prelinedep)
1303 self.depth -= 1
1304 if idx == 0 and last and last.fcall and not last.freturn:
1305 # special case, turn last call into a leaf
1306 last.depth = self.depth
1307 last.freturn = True
1308 last.length = line.time - last.time
1309 if debug:
1310 last.debugPrint()
1311 else:
1312 vline = FTraceLine(lasttime)
1313 vline.depth = self.depth
1314 vline.name = virtualfname
1315 vline.freturn = True
1316 self.list.append(vline)
1317 if debug:
1318 vline.debugPrint()
1319 idx += 1
1320 if debug:
1321 line.debugPrint()
1322 print ''
1323 # handle high misalignments by inserting calls
1324 elif prelinedep > self.depth:
1325 if debug and last:
1326 print '-------- task %d --------' % self.pid
1327 last.debugPrint()
1328 idx = 0
1329 # add calls to get the depth up
1330 while prelinedep > self.depth:
1331 if debug:
1332 print 'MISALIGN HIGH (add calls): C%d - eC%d' % (self.depth, prelinedep)
1333 if idx == 0 and line.freturn and not line.fcall:
1334 # special case, turn this return into a leaf
1335 line.fcall = True
1336 prelinedep -= 1
1337 else:
1338 vline = FTraceLine(lasttime)
1339 vline.depth = self.depth
1340 vline.name = virtualfname
1341 vline.fcall = True
1342 if debug:
1343 vline.debugPrint()
1344 self.list.append(vline)
1345 self.depth += 1
1346 if not last:
1347 self.start = vline.time
1348 idx += 1
1349 if debug:
1350 line.debugPrint()
1351 print ''
1352 # process the call and set the new depth
714 if(line.fcall and not line.freturn): 1353 if(line.fcall and not line.freturn):
715 line.depth = self.depth
716 self.depth += 1 1354 self.depth += 1
717 elif(line.freturn and not line.fcall): 1355 elif(line.freturn and not line.fcall):
718 self.depth -= 1 1356 self.depth -= 1
719 line.depth = self.depth 1357 if len(self.list) < 1:
720 else: 1358 self.start = line.time
721 line.depth = self.depth 1359 self.list.append(line)
722 def addLine(self, line, match):
723 if(not self.invalid):
724 self.setDepth(line)
725 if(line.depth == 0 and line.freturn): 1360 if(line.depth == 0 and line.freturn):
726 if(self.start < 0): 1361 if(self.start < 0):
727 self.start = line.time 1362 self.start = line.time
728 self.end = line.time 1363 self.end = line.time
729 self.list.append(line) 1364 if line.fcall:
1365 self.end += line.length
1366 if self.list[0].name == virtualfname:
1367 self.invalid = True
730 return True 1368 return True
731 if(self.invalid):
732 return False
733 if(len(self.list) >= 1000000 or self.depth < 0):
734 if(len(self.list) > 0):
735 first = self.list[0]
736 self.list = []
737 self.list.append(first)
738 self.invalid = True
739 if(not match):
740 return False
741 id = 'task %s cpu %s' % (match.group('pid'), match.group('cpu'))
742 window = '(%f - %f)' % (self.start, line.time)
743 if(self.depth < 0):
744 print('Too much data for '+id+\
745 ' (buffer overflow), ignoring this callback')
746 else:
747 print('Too much data for '+id+\
748 ' '+window+', ignoring this callback')
749 return False
750 self.list.append(line)
751 if(self.start < 0):
752 self.start = line.time
753 return False 1369 return False
1370 def invalidate(self, line):
1371 if(len(self.list) > 0):
1372 first = self.list[0]
1373 self.list = []
1374 self.list.append(first)
1375 self.invalid = True
1376 id = 'task %s' % (self.pid)
1377 window = '(%f - %f)' % (self.start, line.time)
1378 if(self.depth < 0):
1379 vprint('Too much data for '+id+\
1380 ' (buffer overflow), ignoring this callback')
1381 else:
1382 vprint('Too much data for '+id+\
1383 ' '+window+', ignoring this callback')
754 def slice(self, t0, tN): 1384 def slice(self, t0, tN):
755 minicg = FTraceCallGraph() 1385 minicg = FTraceCallGraph(0)
756 count = -1 1386 count = -1
757 firstdepth = 0 1387 firstdepth = 0
758 for l in self.list: 1388 for l in self.list:
@@ -764,13 +1394,26 @@ class FTraceCallGraph:
764 firstdepth = l.depth 1394 firstdepth = l.depth
765 count = 0 1395 count = 0
766 l.depth -= firstdepth 1396 l.depth -= firstdepth
767 minicg.addLine(l, 0) 1397 minicg.addLine(l)
768 if((count == 0 and l.freturn and l.fcall) or 1398 if((count == 0 and l.freturn and l.fcall) or
769 (count > 0 and l.depth <= 0)): 1399 (count > 0 and l.depth <= 0)):
770 break 1400 break
771 count += 1 1401 count += 1
772 return minicg 1402 return minicg
773 def sanityCheck(self): 1403 def repair(self, enddepth):
1404 # bring the depth back to 0 with additional returns
1405 fixed = False
1406 last = self.list[-1]
1407 for i in reversed(range(enddepth)):
1408 t = FTraceLine(last.time)
1409 t.depth = i
1410 t.freturn = True
1411 fixed = self.addLine(t)
1412 if fixed:
1413 self.end = last.time
1414 return True
1415 return False
1416 def postProcess(self, debug=False):
774 stack = dict() 1417 stack = dict()
775 cnt = 0 1418 cnt = 0
776 for l in self.list: 1419 for l in self.list:
@@ -779,98 +1422,317 @@ class FTraceCallGraph:
779 cnt += 1 1422 cnt += 1
780 elif(l.freturn and not l.fcall): 1423 elif(l.freturn and not l.fcall):
781 if(l.depth not in stack): 1424 if(l.depth not in stack):
1425 if debug:
1426 print 'Post Process Error: Depth missing'
1427 l.debugPrint()
782 return False 1428 return False
1429 # transfer total time from return line to call line
783 stack[l.depth].length = l.length 1430 stack[l.depth].length = l.length
784 stack[l.depth] = 0 1431 stack.pop(l.depth)
785 l.length = 0 1432 l.length = 0
786 cnt -= 1 1433 cnt -= 1
787 if(cnt == 0): 1434 if(cnt == 0):
1435 # trace caught the whole call tree
788 return True 1436 return True
789 return False 1437 elif(cnt < 0):
790 def debugPrint(self, filename): 1438 if debug:
791 if(filename == 'stdout'): 1439 print 'Post Process Error: Depth is less than 0'
792 print('[%f - %f]') % (self.start, self.end) 1440 return False
793 for l in self.list: 1441 # trace ended before call tree finished
794 if(l.freturn and l.fcall): 1442 return self.repair(cnt)
795 print('%f (%02d): %s(); (%.3f us)' % (l.time, \ 1443 def deviceMatch(self, pid, data):
796 l.depth, l.name, l.length*1000000)) 1444 found = False
797 elif(l.freturn): 1445 # add the callgraph data to the device hierarchy
798 print('%f (%02d): %s} (%.3f us)' % (l.time, \ 1446 borderphase = {
799 l.depth, l.name, l.length*1000000)) 1447 'dpm_prepare': 'suspend_prepare',
800 else: 1448 'dpm_complete': 'resume_complete'
801 print('%f (%02d): %s() { (%.3f us)' % (l.time, \ 1449 }
802 l.depth, l.name, l.length*1000000)) 1450 if(self.list[0].name in borderphase):
803 print(' ') 1451 p = borderphase[self.list[0].name]
804 else: 1452 list = data.dmesg[p]['list']
805 fp = open(filename, 'w') 1453 for devname in list:
806 print(filename) 1454 dev = list[devname]
807 for l in self.list: 1455 if(pid == dev['pid'] and
808 if(l.freturn and l.fcall): 1456 self.start <= dev['start'] and
809 fp.write('%f (%02d): %s(); (%.3f us)\n' % (l.time, \ 1457 self.end >= dev['end']):
810 l.depth, l.name, l.length*1000000)) 1458 dev['ftrace'] = self.slice(dev['start'], dev['end'])
811 elif(l.freturn): 1459 found = True
812 fp.write('%f (%02d): %s} (%.3f us)\n' % (l.time, \ 1460 return found
813 l.depth, l.name, l.length*1000000)) 1461 for p in data.phases:
814 else: 1462 if(data.dmesg[p]['start'] <= self.start and
815 fp.write('%f (%02d): %s() { (%.3f us)\n' % (l.time, \ 1463 self.start <= data.dmesg[p]['end']):
816 l.depth, l.name, l.length*1000000)) 1464 list = data.dmesg[p]['list']
817 fp.close() 1465 for devname in list:
1466 dev = list[devname]
1467 if(pid == dev['pid'] and
1468 self.start <= dev['start'] and
1469 self.end >= dev['end']):
1470 dev['ftrace'] = self
1471 found = True
1472 break
1473 break
1474 return found
1475 def newActionFromFunction(self, data):
1476 name = self.list[0].name
1477 if name in ['dpm_run_callback', 'dpm_prepare', 'dpm_complete']:
1478 return
1479 fs = self.start
1480 fe = self.end
1481 if fs < data.start or fe > data.end:
1482 return
1483 phase = ''
1484 for p in data.phases:
1485 if(data.dmesg[p]['start'] <= self.start and
1486 self.start < data.dmesg[p]['end']):
1487 phase = p
1488 break
1489 if not phase:
1490 return
1491 out = data.newActionGlobal(name, fs, fe, -2)
1492 if out:
1493 phase, myname = out
1494 data.dmesg[phase]['list'][myname]['ftrace'] = self
1495 def debugPrint(self):
1496 print('[%f - %f] %s (%d)') % (self.start, self.end, self.list[0].name, self.pid)
1497 for l in self.list:
1498 if(l.freturn and l.fcall):
1499 print('%f (%02d): %s(); (%.3f us)' % (l.time, \
1500 l.depth, l.name, l.length*1000000))
1501 elif(l.freturn):
1502 print('%f (%02d): %s} (%.3f us)' % (l.time, \
1503 l.depth, l.name, l.length*1000000))
1504 else:
1505 print('%f (%02d): %s() { (%.3f us)' % (l.time, \
1506 l.depth, l.name, l.length*1000000))
1507 print(' ')
818 1508
819# Class: Timeline 1509# Class: Timeline
820# Description: 1510# Description:
821# A container for a suspend/resume html timeline. In older versions 1511# A container for a device timeline which calculates
822# of the script there were multiple timelines, but in the latest 1512# all the html properties to display it correctly
823# there is only one.
824class Timeline: 1513class Timeline:
825 html = {} 1514 html = {}
826 scaleH = 0.0 # height of the row as a percent of the timeline height 1515 height = 0 # total timeline height
827 rowH = 0.0 # height of each row in percent of the timeline height 1516 scaleH = 20 # timescale (top) row height
828 row_height_pixels = 30 1517 rowH = 30 # device row height
829 maxrows = 0 1518 bodyH = 0 # body height
830 height = 0 1519 rows = 0 # total timeline rows
831 def __init__(self): 1520 phases = []
1521 rowmaxlines = dict()
1522 rowcount = dict()
1523 rowheight = dict()
1524 def __init__(self, rowheight):
1525 self.rowH = rowheight
832 self.html = { 1526 self.html = {
1527 'header': '',
833 'timeline': '', 1528 'timeline': '',
834 'legend': '', 1529 'legend': '',
835 'scale': ''
836 } 1530 }
837 def setRows(self, rows): 1531 # Function: getDeviceRows
838 self.maxrows = int(rows) 1532 # Description:
839 self.scaleH = 100.0/float(self.maxrows) 1533 # determine how may rows the device funcs will take
840 self.height = self.maxrows*self.row_height_pixels 1534 # Arguments:
841 r = float(self.maxrows - 1) 1535 # rawlist: the list of devices/actions for a single phase
842 if(r < 1.0): 1536 # Output:
843 r = 1.0 1537 # The total number of rows needed to display this phase of the timeline
844 self.rowH = (100.0 - self.scaleH)/r 1538 def getDeviceRows(self, rawlist):
1539 # clear all rows and set them to undefined
1540 lendict = dict()
1541 for item in rawlist:
1542 item.row = -1
1543 lendict[item] = item.length
1544 list = []
1545 for i in sorted(lendict, key=lendict.get, reverse=True):
1546 list.append(i)
1547 remaining = len(list)
1548 rowdata = dict()
1549 row = 1
1550 # try to pack each row with as many ranges as possible
1551 while(remaining > 0):
1552 if(row not in rowdata):
1553 rowdata[row] = []
1554 for i in list:
1555 if(i.row >= 0):
1556 continue
1557 s = i.time
1558 e = i.time + i.length
1559 valid = True
1560 for ritem in rowdata[row]:
1561 rs = ritem.time
1562 re = ritem.time + ritem.length
1563 if(not (((s <= rs) and (e <= rs)) or
1564 ((s >= re) and (e >= re)))):
1565 valid = False
1566 break
1567 if(valid):
1568 rowdata[row].append(i)
1569 i.row = row
1570 remaining -= 1
1571 row += 1
1572 return row
1573 # Function: getPhaseRows
1574 # Description:
1575 # Organize the timeline entries into the smallest
1576 # number of rows possible, with no entry overlapping
1577 # Arguments:
1578 # list: the list of devices/actions for a single phase
1579 # devlist: string list of device names to use
1580 # Output:
1581 # The total number of rows needed to display this phase of the timeline
1582 def getPhaseRows(self, dmesg, devlist):
1583 # clear all rows and set them to undefined
1584 remaining = len(devlist)
1585 rowdata = dict()
1586 row = 0
1587 lendict = dict()
1588 myphases = []
1589 for item in devlist:
1590 if item[0] not in self.phases:
1591 self.phases.append(item[0])
1592 if item[0] not in myphases:
1593 myphases.append(item[0])
1594 self.rowmaxlines[item[0]] = dict()
1595 self.rowheight[item[0]] = dict()
1596 dev = dmesg[item[0]]['list'][item[1]]
1597 dev['row'] = -1
1598 lendict[item] = float(dev['end']) - float(dev['start'])
1599 if 'src' in dev:
1600 dev['devrows'] = self.getDeviceRows(dev['src'])
1601 lenlist = []
1602 for i in sorted(lendict, key=lendict.get, reverse=True):
1603 lenlist.append(i)
1604 orderedlist = []
1605 for item in lenlist:
1606 dev = dmesg[item[0]]['list'][item[1]]
1607 if dev['pid'] == -2:
1608 orderedlist.append(item)
1609 for item in lenlist:
1610 if item not in orderedlist:
1611 orderedlist.append(item)
1612 # try to pack each row with as many ranges as possible
1613 while(remaining > 0):
1614 rowheight = 1
1615 if(row not in rowdata):
1616 rowdata[row] = []
1617 for item in orderedlist:
1618 dev = dmesg[item[0]]['list'][item[1]]
1619 if(dev['row'] < 0):
1620 s = dev['start']
1621 e = dev['end']
1622 valid = True
1623 for ritem in rowdata[row]:
1624 rs = ritem['start']
1625 re = ritem['end']
1626 if(not (((s <= rs) and (e <= rs)) or
1627 ((s >= re) and (e >= re)))):
1628 valid = False
1629 break
1630 if(valid):
1631 rowdata[row].append(dev)
1632 dev['row'] = row
1633 remaining -= 1
1634 if 'devrows' in dev and dev['devrows'] > rowheight:
1635 rowheight = dev['devrows']
1636 for phase in myphases:
1637 self.rowmaxlines[phase][row] = rowheight
1638 self.rowheight[phase][row] = rowheight * self.rowH
1639 row += 1
1640 if(row > self.rows):
1641 self.rows = int(row)
1642 for phase in myphases:
1643 self.rowcount[phase] = row
1644 return row
1645 def phaseRowHeight(self, phase, row):
1646 return self.rowheight[phase][row]
1647 def phaseRowTop(self, phase, row):
1648 top = 0
1649 for i in sorted(self.rowheight[phase]):
1650 if i >= row:
1651 break
1652 top += self.rowheight[phase][i]
1653 return top
1654 # Function: calcTotalRows
1655 # Description:
1656 # Calculate the heights and offsets for the header and rows
1657 def calcTotalRows(self):
1658 maxrows = 0
1659 standardphases = []
1660 for phase in self.phases:
1661 total = 0
1662 for i in sorted(self.rowmaxlines[phase]):
1663 total += self.rowmaxlines[phase][i]
1664 if total > maxrows:
1665 maxrows = total
1666 if total == self.rowcount[phase]:
1667 standardphases.append(phase)
1668 self.height = self.scaleH + (maxrows*self.rowH)
1669 self.bodyH = self.height - self.scaleH
1670 for phase in standardphases:
1671 for i in sorted(self.rowheight[phase]):
1672 self.rowheight[phase][i] = self.bodyH/self.rowcount[phase]
1673 # Function: createTimeScale
1674 # Description:
1675 # Create the timescale for a timeline block
1676 # Arguments:
1677 # m0: start time (mode begin)
1678 # mMax: end time (mode end)
1679 # tTotal: total timeline time
1680 # mode: suspend or resume
1681 # Output:
1682 # The html code needed to display the time scale
1683 def createTimeScale(self, m0, mMax, tTotal, mode):
1684 timescale = '<div class="t" style="right:{0}%">{1}</div>\n'
1685 rline = '<div class="t" style="left:0;border-left:1px solid black;border-right:0;">Resume</div>\n'
1686 output = '<div class="timescale">\n'
1687 # set scale for timeline
1688 mTotal = mMax - m0
1689 tS = 0.1
1690 if(tTotal <= 0):
1691 return output+'</div>\n'
1692 if(tTotal > 4):
1693 tS = 1
1694 divTotal = int(mTotal/tS) + 1
1695 divEdge = (mTotal - tS*(divTotal-1))*100/mTotal
1696 for i in range(divTotal):
1697 htmlline = ''
1698 if(mode == 'resume'):
1699 pos = '%0.3f' % (100 - ((float(i)*tS*100)/mTotal))
1700 val = '%0.fms' % (float(i)*tS*1000)
1701 htmlline = timescale.format(pos, val)
1702 if(i == 0):
1703 htmlline = rline
1704 else:
1705 pos = '%0.3f' % (100 - ((float(i)*tS*100)/mTotal) - divEdge)
1706 val = '%0.fms' % (float(i-divTotal+1)*tS*1000)
1707 if(i == divTotal - 1):
1708 val = 'Suspend'
1709 htmlline = timescale.format(pos, val)
1710 output += htmlline
1711 output += '</div>\n'
1712 return output
845 1713
846# Class: TestRun 1714# Class: TestProps
847# Description: 1715# Description:
848# A container for a suspend/resume test run. This is necessary as 1716# A list of values describing the properties of these test runs
849# there could be more than one, and they need to be separate. 1717class TestProps:
850class TestRun: 1718 stamp = ''
1719 tracertype = ''
1720 S0i3 = False
1721 fwdata = []
851 ftrace_line_fmt_fg = \ 1722 ftrace_line_fmt_fg = \
852 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\ 1723 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\
853 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\ 1724 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\
854 '[ +!]*(?P<dur>[0-9\.]*) .*\| (?P<msg>.*)' 1725 '[ +!#\*@$]*(?P<dur>[0-9\.]*) .*\| (?P<msg>.*)'
855 ftrace_line_fmt_nop = \ 1726 ftrace_line_fmt_nop = \
856 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\[(?P<cpu>[0-9]*)\] *'+\ 1727 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\[(?P<cpu>[0-9]*)\] *'+\
857 '(?P<flags>.{4}) *(?P<time>[0-9\.]*): *'+\ 1728 '(?P<flags>.{4}) *(?P<time>[0-9\.]*): *'+\
858 '(?P<msg>.*)' 1729 '(?P<msg>.*)'
859 ftrace_line_fmt = ftrace_line_fmt_nop 1730 ftrace_line_fmt = ftrace_line_fmt_nop
860 cgformat = False 1731 cgformat = False
861 ftemp = dict()
862 ttemp = dict()
863 inthepipe = False
864 tracertype = ''
865 data = 0 1732 data = 0
866 def __init__(self, dataobj): 1733 ktemp = dict()
867 self.data = dataobj 1734 def __init__(self):
868 self.ftemp = dict() 1735 self.ktemp = dict()
869 self.ttemp = dict()
870 def isReady(self):
871 if(tracertype == '' or not data):
872 return False
873 return True
874 def setTracerType(self, tracer): 1736 def setTracerType(self, tracer):
875 self.tracertype = tracer 1737 self.tracertype = tracer
876 if(tracer == 'function_graph'): 1738 if(tracer == 'function_graph'):
@@ -881,6 +1743,19 @@ class TestRun:
881 else: 1743 else:
882 doError('Invalid tracer format: [%s]' % tracer, False) 1744 doError('Invalid tracer format: [%s]' % tracer, False)
883 1745
1746# Class: TestRun
1747# Description:
1748# A container for a suspend/resume test run. This is necessary as
1749# there could be more than one, and they need to be separate.
1750class TestRun:
1751 ftemp = dict()
1752 ttemp = dict()
1753 data = 0
1754 def __init__(self, dataobj):
1755 self.data = dataobj
1756 self.ftemp = dict()
1757 self.ttemp = dict()
1758
884# ----------------- FUNCTIONS -------------------- 1759# ----------------- FUNCTIONS --------------------
885 1760
886# Function: vprint 1761# Function: vprint
@@ -893,104 +1768,16 @@ def vprint(msg):
893 if(sysvals.verbose): 1768 if(sysvals.verbose):
894 print(msg) 1769 print(msg)
895 1770
896# Function: initFtrace
897# Description:
898# Configure ftrace to use trace events and/or a callgraph
899def initFtrace():
900 global sysvals
901
902 tp = sysvals.tpath
903 cf = 'dpm_run_callback'
904 if(sysvals.usetraceeventsonly):
905 cf = '-e dpm_prepare -e dpm_complete -e dpm_run_callback'
906 if(sysvals.usecallgraph or sysvals.usetraceevents):
907 print('INITIALIZING FTRACE...')
908 # turn trace off
909 os.system('echo 0 > '+tp+'tracing_on')
910 # set the trace clock to global
911 os.system('echo global > '+tp+'trace_clock')
912 # set trace buffer to a huge value
913 os.system('echo nop > '+tp+'current_tracer')
914 os.system('echo 100000 > '+tp+'buffer_size_kb')
915 # initialize the callgraph trace, unless this is an x2 run
916 if(sysvals.usecallgraph and sysvals.execcount == 1):
917 # set trace type
918 os.system('echo function_graph > '+tp+'current_tracer')
919 os.system('echo "" > '+tp+'set_ftrace_filter')
920 # set trace format options
921 os.system('echo funcgraph-abstime > '+tp+'trace_options')
922 os.system('echo funcgraph-proc > '+tp+'trace_options')
923 # focus only on device suspend and resume
924 os.system('cat '+tp+'available_filter_functions | grep '+\
925 cf+' > '+tp+'set_graph_function')
926 if(sysvals.usetraceevents):
927 # turn trace events on
928 events = iter(sysvals.traceevents)
929 for e in events:
930 os.system('echo 1 > '+sysvals.epath+e+'/enable')
931 # clear the trace buffer
932 os.system('echo "" > '+tp+'trace')
933
934# Function: initFtraceAndroid
935# Description:
936# Configure ftrace to capture trace events
937def initFtraceAndroid():
938 global sysvals
939
940 tp = sysvals.tpath
941 if(sysvals.usetraceevents):
942 print('INITIALIZING FTRACE...')
943 # turn trace off
944 os.system(sysvals.adb+" shell 'echo 0 > "+tp+"tracing_on'")
945 # set the trace clock to global
946 os.system(sysvals.adb+" shell 'echo global > "+tp+"trace_clock'")
947 # set trace buffer to a huge value
948 os.system(sysvals.adb+" shell 'echo nop > "+tp+"current_tracer'")
949 os.system(sysvals.adb+" shell 'echo 10000 > "+tp+"buffer_size_kb'")
950 # turn trace events on
951 events = iter(sysvals.traceevents)
952 for e in events:
953 os.system(sysvals.adb+" shell 'echo 1 > "+\
954 sysvals.epath+e+"/enable'")
955 # clear the trace buffer
956 os.system(sysvals.adb+" shell 'echo \"\" > "+tp+"trace'")
957
958# Function: verifyFtrace
959# Description:
960# Check that ftrace is working on the system
961# Output:
962# True or False
963def verifyFtrace():
964 global sysvals
965 # files needed for any trace data
966 files = ['buffer_size_kb', 'current_tracer', 'trace', 'trace_clock',
967 'trace_marker', 'trace_options', 'tracing_on']
968 # files needed for callgraph trace data
969 tp = sysvals.tpath
970 if(sysvals.usecallgraph):
971 files += [
972 'available_filter_functions',
973 'set_ftrace_filter',
974 'set_graph_function'
975 ]
976 for f in files:
977 if(sysvals.android):
978 out = os.popen(sysvals.adb+' shell ls '+tp+f).read().strip()
979 if(out != tp+f):
980 return False
981 else:
982 if(os.path.exists(tp+f) == False):
983 return False
984 return True
985
986# Function: parseStamp 1771# Function: parseStamp
987# Description: 1772# Description:
988# Pull in the stamp comment line from the data file(s), 1773# Pull in the stamp comment line from the data file(s),
989# create the stamp, and add it to the global sysvals object 1774# create the stamp, and add it to the global sysvals object
990# Arguments: 1775# Arguments:
991# m: the valid re.match output for the stamp line 1776# m: the valid re.match output for the stamp line
992def parseStamp(m, data): 1777def parseStamp(line, data):
993 global sysvals 1778 global sysvals
1779
1780 m = re.match(sysvals.stampfmt, line)
994 data.stamp = {'time': '', 'host': '', 'mode': ''} 1781 data.stamp = {'time': '', 'host': '', 'mode': ''}
995 dt = datetime(int(m.group('y'))+2000, int(m.group('m')), 1782 dt = datetime(int(m.group('y'))+2000, int(m.group('m')),
996 int(m.group('d')), int(m.group('H')), int(m.group('M')), 1783 int(m.group('d')), int(m.group('H')), int(m.group('M')),
@@ -999,6 +1786,7 @@ def parseStamp(m, data):
999 data.stamp['host'] = m.group('host') 1786 data.stamp['host'] = m.group('host')
1000 data.stamp['mode'] = m.group('mode') 1787 data.stamp['mode'] = m.group('mode')
1001 data.stamp['kernel'] = m.group('kernel') 1788 data.stamp['kernel'] = m.group('kernel')
1789 sysvals.hostname = data.stamp['host']
1002 sysvals.suspendmode = data.stamp['mode'] 1790 sysvals.suspendmode = data.stamp['mode']
1003 if not sysvals.stamp: 1791 if not sysvals.stamp:
1004 sysvals.stamp = data.stamp 1792 sysvals.stamp = data.stamp
@@ -1031,14 +1819,35 @@ def diffStamp(stamp1, stamp2):
1031def doesTraceLogHaveTraceEvents(): 1819def doesTraceLogHaveTraceEvents():
1032 global sysvals 1820 global sysvals
1033 1821
1822 # check for kprobes
1823 sysvals.usekprobes = False
1824 out = os.system('grep -q "_cal: (" '+sysvals.ftracefile)
1825 if(out == 0):
1826 sysvals.usekprobes = True
1827 # check for callgraph data on trace event blocks
1828 out = os.system('grep -q "_cpu_down()" '+sysvals.ftracefile)
1829 if(out == 0):
1830 sysvals.usekprobes = True
1831 out = os.popen('head -1 '+sysvals.ftracefile).read().replace('\n', '')
1832 m = re.match(sysvals.stampfmt, out)
1833 if m and m.group('mode') == 'command':
1834 sysvals.usetraceeventsonly = True
1835 sysvals.usetraceevents = True
1836 return
1837 # figure out what level of trace events are supported
1034 sysvals.usetraceeventsonly = True 1838 sysvals.usetraceeventsonly = True
1035 sysvals.usetraceevents = False 1839 sysvals.usetraceevents = False
1036 for e in sysvals.traceevents: 1840 for e in sysvals.traceevents:
1037 out = os.popen('cat '+sysvals.ftracefile+' | grep "'+e+': "').read() 1841 out = os.system('grep -q "'+e+': " '+sysvals.ftracefile)
1038 if(not out): 1842 if(out != 0):
1039 sysvals.usetraceeventsonly = False 1843 sysvals.usetraceeventsonly = False
1040 if(e == 'suspend_resume' and out): 1844 if(e == 'suspend_resume' and out == 0):
1041 sysvals.usetraceevents = True 1845 sysvals.usetraceevents = True
1846 # determine is this log is properly formatted
1847 for e in ['SUSPEND START', 'RESUME COMPLETE']:
1848 out = os.system('grep -q "'+e+'" '+sysvals.ftracefile)
1849 if(out != 0):
1850 sysvals.usetracemarkers = False
1042 1851
1043# Function: appendIncompleteTraceLog 1852# Function: appendIncompleteTraceLog
1044# Description: 1853# Description:
@@ -1055,44 +1864,42 @@ def appendIncompleteTraceLog(testruns):
1055 1864
1056 # create TestRun vessels for ftrace parsing 1865 # create TestRun vessels for ftrace parsing
1057 testcnt = len(testruns) 1866 testcnt = len(testruns)
1058 testidx = -1 1867 testidx = 0
1059 testrun = [] 1868 testrun = []
1060 for data in testruns: 1869 for data in testruns:
1061 testrun.append(TestRun(data)) 1870 testrun.append(TestRun(data))
1062 1871
1063 # extract the callgraph and traceevent data 1872 # extract the callgraph and traceevent data
1064 vprint('Analyzing the ftrace data...') 1873 vprint('Analyzing the ftrace data...')
1874 tp = TestProps()
1065 tf = open(sysvals.ftracefile, 'r') 1875 tf = open(sysvals.ftracefile, 'r')
1876 data = 0
1066 for line in tf: 1877 for line in tf:
1067 # remove any latent carriage returns 1878 # remove any latent carriage returns
1068 line = line.replace('\r\n', '') 1879 line = line.replace('\r\n', '')
1069 # grab the time stamp first (signifies the start of the test run) 1880 # grab the time stamp
1070 m = re.match(sysvals.stampfmt, line) 1881 m = re.match(sysvals.stampfmt, line)
1071 if(m): 1882 if(m):
1072 testidx += 1 1883 tp.stamp = line
1073 parseStamp(m, testrun[testidx].data)
1074 continue
1075 # pull out any firmware data
1076 if(re.match(sysvals.firmwarefmt, line)):
1077 continue
1078 # if we havent found a test time stamp yet keep spinning til we do
1079 if(testidx < 0):
1080 continue 1884 continue
1081 # determine the trace data type (required for further parsing) 1885 # determine the trace data type (required for further parsing)
1082 m = re.match(sysvals.tracertypefmt, line) 1886 m = re.match(sysvals.tracertypefmt, line)
1083 if(m): 1887 if(m):
1084 tracer = m.group('t') 1888 tp.setTracerType(m.group('t'))
1085 testrun[testidx].setTracerType(tracer) 1889 continue
1890 # device properties line
1891 if(re.match(sysvals.devpropfmt, line)):
1892 devProps(line)
1086 continue 1893 continue
1087 # parse only valid lines, if this isnt one move on 1894 # parse only valid lines, if this is not one move on
1088 m = re.match(testrun[testidx].ftrace_line_fmt, line) 1895 m = re.match(tp.ftrace_line_fmt, line)
1089 if(not m): 1896 if(not m):
1090 continue 1897 continue
1091 # gather the basic message data from the line 1898 # gather the basic message data from the line
1092 m_time = m.group('time') 1899 m_time = m.group('time')
1093 m_pid = m.group('pid') 1900 m_pid = m.group('pid')
1094 m_msg = m.group('msg') 1901 m_msg = m.group('msg')
1095 if(testrun[testidx].cgformat): 1902 if(tp.cgformat):
1096 m_param3 = m.group('dur') 1903 m_param3 = m.group('dur')
1097 else: 1904 else:
1098 m_param3 = 'traceevent' 1905 m_param3 = 'traceevent'
@@ -1104,119 +1911,114 @@ def appendIncompleteTraceLog(testruns):
1104 # the line should be a call, return, or event 1911 # the line should be a call, return, or event
1105 if(not t.fcall and not t.freturn and not t.fevent): 1912 if(not t.fcall and not t.freturn and not t.fevent):
1106 continue 1913 continue
1107 # only parse the ftrace data during suspend/resume 1914 # look for the suspend start marker
1108 data = testrun[testidx].data 1915 if(t.startMarker()):
1109 if(not testrun[testidx].inthepipe): 1916 data = testrun[testidx].data
1110 # look for the suspend start marker 1917 parseStamp(tp.stamp, data)
1111 if(t.fevent): 1918 data.setStart(t.time)
1112 if(t.name == 'SUSPEND START'): 1919 continue
1113 testrun[testidx].inthepipe = True 1920 if(not data):
1114 data.setStart(t.time) 1921 continue
1922 # find the end of resume
1923 if(t.endMarker()):
1924 data.setEnd(t.time)
1925 testidx += 1
1926 if(testidx >= testcnt):
1927 break
1928 continue
1929 # trace event processing
1930 if(t.fevent):
1931 # general trace events have two types, begin and end
1932 if(re.match('(?P<name>.*) begin$', t.name)):
1933 isbegin = True
1934 elif(re.match('(?P<name>.*) end$', t.name)):
1935 isbegin = False
1936 else:
1115 continue 1937 continue
1116 else: 1938 m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name)
1117 # trace event processing 1939 if(m):
1118 if(t.fevent): 1940 val = m.group('val')
1119 if(t.name == 'RESUME COMPLETE'): 1941 if val == '0':
1120 testrun[testidx].inthepipe = False 1942 name = m.group('name')
1121 data.setEnd(t.time)
1122 if(testidx == testcnt - 1):
1123 break
1124 continue
1125 # general trace events have two types, begin and end
1126 if(re.match('(?P<name>.*) begin$', t.name)):
1127 isbegin = True
1128 elif(re.match('(?P<name>.*) end$', t.name)):
1129 isbegin = False
1130 else: 1943 else:
1131 continue 1944 name = m.group('name')+'['+val+']'
1132 m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name) 1945 else:
1133 if(m): 1946 m = re.match('(?P<name>.*) .*', t.name)
1134 val = m.group('val') 1947 name = m.group('name')
1135 if val == '0': 1948 # special processing for trace events
1136 name = m.group('name') 1949 if re.match('dpm_prepare\[.*', name):
1137 else: 1950 continue
1138 name = m.group('name')+'['+val+']' 1951 elif re.match('machine_suspend.*', name):
1952 continue
1953 elif re.match('suspend_enter\[.*', name):
1954 if(not isbegin):
1955 data.dmesg['suspend_prepare']['end'] = t.time
1956 continue
1957 elif re.match('dpm_suspend\[.*', name):
1958 if(not isbegin):
1959 data.dmesg['suspend']['end'] = t.time
1960 continue
1961 elif re.match('dpm_suspend_late\[.*', name):
1962 if(isbegin):
1963 data.dmesg['suspend_late']['start'] = t.time
1139 else: 1964 else:
1140 m = re.match('(?P<name>.*) .*', t.name) 1965 data.dmesg['suspend_late']['end'] = t.time
1141 name = m.group('name') 1966 continue
1142 # special processing for trace events 1967 elif re.match('dpm_suspend_noirq\[.*', name):
1143 if re.match('dpm_prepare\[.*', name): 1968 if(isbegin):
1144 continue 1969 data.dmesg['suspend_noirq']['start'] = t.time
1145 elif re.match('machine_suspend.*', name):
1146 continue
1147 elif re.match('suspend_enter\[.*', name):
1148 if(not isbegin):
1149 data.dmesg['suspend_prepare']['end'] = t.time
1150 continue
1151 elif re.match('dpm_suspend\[.*', name):
1152 if(not isbegin):
1153 data.dmesg['suspend']['end'] = t.time
1154 continue
1155 elif re.match('dpm_suspend_late\[.*', name):
1156 if(isbegin):
1157 data.dmesg['suspend_late']['start'] = t.time
1158 else:
1159 data.dmesg['suspend_late']['end'] = t.time
1160 continue
1161 elif re.match('dpm_suspend_noirq\[.*', name):
1162 if(isbegin):
1163 data.dmesg['suspend_noirq']['start'] = t.time
1164 else:
1165 data.dmesg['suspend_noirq']['end'] = t.time
1166 continue
1167 elif re.match('dpm_resume_noirq\[.*', name):
1168 if(isbegin):
1169 data.dmesg['resume_machine']['end'] = t.time
1170 data.dmesg['resume_noirq']['start'] = t.time
1171 else:
1172 data.dmesg['resume_noirq']['end'] = t.time
1173 continue
1174 elif re.match('dpm_resume_early\[.*', name):
1175 if(isbegin):
1176 data.dmesg['resume_early']['start'] = t.time
1177 else:
1178 data.dmesg['resume_early']['end'] = t.time
1179 continue
1180 elif re.match('dpm_resume\[.*', name):
1181 if(isbegin):
1182 data.dmesg['resume']['start'] = t.time
1183 else:
1184 data.dmesg['resume']['end'] = t.time
1185 continue
1186 elif re.match('dpm_complete\[.*', name):
1187 if(isbegin):
1188 data.dmesg['resume_complete']['start'] = t.time
1189 else:
1190 data.dmesg['resume_complete']['end'] = t.time
1191 continue
1192 # is this trace event outside of the devices calls
1193 if(data.isTraceEventOutsideDeviceCalls(pid, t.time)):
1194 # global events (outside device calls) are simply graphed
1195 if(isbegin):
1196 # store each trace event in ttemp
1197 if(name not in testrun[testidx].ttemp):
1198 testrun[testidx].ttemp[name] = []
1199 testrun[testidx].ttemp[name].append(\
1200 {'begin': t.time, 'end': t.time})
1201 else:
1202 # finish off matching trace event in ttemp
1203 if(name in testrun[testidx].ttemp):
1204 testrun[testidx].ttemp[name][-1]['end'] = t.time
1205 else: 1970 else:
1206 if(isbegin): 1971 data.dmesg['suspend_noirq']['end'] = t.time
1207 data.addIntraDevTraceEvent('', name, pid, t.time) 1972 continue
1208 else: 1973 elif re.match('dpm_resume_noirq\[.*', name):
1209 data.capIntraDevTraceEvent('', name, pid, t.time) 1974 if(isbegin):
1210 # call/return processing 1975 data.dmesg['resume_machine']['end'] = t.time
1211 elif sysvals.usecallgraph: 1976 data.dmesg['resume_noirq']['start'] = t.time
1212 # create a callgraph object for the data 1977 else:
1213 if(pid not in testrun[testidx].ftemp): 1978 data.dmesg['resume_noirq']['end'] = t.time
1214 testrun[testidx].ftemp[pid] = [] 1979 continue
1215 testrun[testidx].ftemp[pid].append(FTraceCallGraph()) 1980 elif re.match('dpm_resume_early\[.*', name):
1216 # when the call is finished, see which device matches it 1981 if(isbegin):
1217 cg = testrun[testidx].ftemp[pid][-1] 1982 data.dmesg['resume_early']['start'] = t.time
1218 if(cg.addLine(t, m)): 1983 else:
1219 testrun[testidx].ftemp[pid].append(FTraceCallGraph()) 1984 data.dmesg['resume_early']['end'] = t.time
1985 continue
1986 elif re.match('dpm_resume\[.*', name):
1987 if(isbegin):
1988 data.dmesg['resume']['start'] = t.time
1989 else:
1990 data.dmesg['resume']['end'] = t.time
1991 continue
1992 elif re.match('dpm_complete\[.*', name):
1993 if(isbegin):
1994 data.dmesg['resume_complete']['start'] = t.time
1995 else:
1996 data.dmesg['resume_complete']['end'] = t.time
1997 continue
1998 # skip trace events inside devices calls
1999 if(not data.isTraceEventOutsideDeviceCalls(pid, t.time)):
2000 continue
2001 # global events (outside device calls) are simply graphed
2002 if(isbegin):
2003 # store each trace event in ttemp
2004 if(name not in testrun[testidx].ttemp):
2005 testrun[testidx].ttemp[name] = []
2006 testrun[testidx].ttemp[name].append(\
2007 {'begin': t.time, 'end': t.time})
2008 else:
2009 # finish off matching trace event in ttemp
2010 if(name in testrun[testidx].ttemp):
2011 testrun[testidx].ttemp[name][-1]['end'] = t.time
2012 # call/return processing
2013 elif sysvals.usecallgraph:
2014 # create a callgraph object for the data
2015 if(pid not in testrun[testidx].ftemp):
2016 testrun[testidx].ftemp[pid] = []
2017 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid))
2018 # when the call is finished, see which device matches it
2019 cg = testrun[testidx].ftemp[pid][-1]
2020 if(cg.addLine(t)):
2021 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid))
1220 tf.close() 2022 tf.close()
1221 2023
1222 for test in testrun: 2024 for test in testrun:
@@ -1224,20 +2026,14 @@ def appendIncompleteTraceLog(testruns):
1224 if(sysvals.usetraceevents): 2026 if(sysvals.usetraceevents):
1225 for name in test.ttemp: 2027 for name in test.ttemp:
1226 for event in test.ttemp[name]: 2028 for event in test.ttemp[name]:
1227 begin = event['begin'] 2029 test.data.newActionGlobal(name, event['begin'], event['end'])
1228 end = event['end']
1229 # if event starts before timeline start, expand timeline
1230 if(begin < test.data.start):
1231 test.data.setStart(begin)
1232 # if event ends after timeline end, expand the timeline
1233 if(end > test.data.end):
1234 test.data.setEnd(end)
1235 test.data.newActionGlobal(name, begin, end)
1236 2030
1237 # add the callgraph data to the device hierarchy 2031 # add the callgraph data to the device hierarchy
1238 for pid in test.ftemp: 2032 for pid in test.ftemp:
1239 for cg in test.ftemp[pid]: 2033 for cg in test.ftemp[pid]:
1240 if(not cg.sanityCheck()): 2034 if len(cg.list) < 1 or cg.invalid:
2035 continue
2036 if(not cg.postProcess()):
1241 id = 'task %s cpu %s' % (pid, m.group('cpu')) 2037 id = 'task %s cpu %s' % (pid, m.group('cpu'))
1242 vprint('Sanity check failed for '+\ 2038 vprint('Sanity check failed for '+\
1243 id+', ignoring this callback') 2039 id+', ignoring this callback')
@@ -1259,14 +2055,6 @@ def appendIncompleteTraceLog(testruns):
1259 if(sysvals.verbose): 2055 if(sysvals.verbose):
1260 test.data.printDetails() 2056 test.data.printDetails()
1261 2057
1262
1263 # add the time in between the tests as a new phase so we can see it
1264 if(len(testruns) > 1):
1265 t1e = testruns[0].getEnd()
1266 t2s = testruns[-1].getStart()
1267 testruns[-1].newPhaseWithSingleAction('user mode', \
1268 'user mode', t1e, t2s, '#FF9966')
1269
1270# Function: parseTraceLog 2058# Function: parseTraceLog
1271# Description: 2059# Description:
1272# Analyze an ftrace log output file generated from this app during 2060# Analyze an ftrace log output file generated from this app during
@@ -1280,9 +2068,16 @@ def parseTraceLog():
1280 2068
1281 vprint('Analyzing the ftrace data...') 2069 vprint('Analyzing the ftrace data...')
1282 if(os.path.exists(sysvals.ftracefile) == False): 2070 if(os.path.exists(sysvals.ftracefile) == False):
1283 doError('%s doesnt exist' % sysvals.ftracefile, False) 2071 doError('%s does not exist' % sysvals.ftracefile, False)
2072
2073 sysvals.setupAllKprobes()
2074 tracewatch = ['suspend_enter']
2075 if sysvals.usekprobes:
2076 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend',
2077 'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON', 'CPU_OFF']
1284 2078
1285 # extract the callgraph and traceevent data 2079 # extract the callgraph and traceevent data
2080 tp = TestProps()
1286 testruns = [] 2081 testruns = []
1287 testdata = [] 2082 testdata = []
1288 testrun = 0 2083 testrun = 0
@@ -1295,27 +2090,17 @@ def parseTraceLog():
1295 # stamp line: each stamp means a new test run 2090 # stamp line: each stamp means a new test run
1296 m = re.match(sysvals.stampfmt, line) 2091 m = re.match(sysvals.stampfmt, line)
1297 if(m): 2092 if(m):
1298 data = Data(len(testdata)) 2093 tp.stamp = line
1299 testdata.append(data)
1300 testrun = TestRun(data)
1301 testruns.append(testrun)
1302 parseStamp(m, data)
1303 continue
1304 if(not data):
1305 continue 2094 continue
1306 # firmware line: pull out any firmware data 2095 # firmware line: pull out any firmware data
1307 m = re.match(sysvals.firmwarefmt, line) 2096 m = re.match(sysvals.firmwarefmt, line)
1308 if(m): 2097 if(m):
1309 data.fwSuspend = int(m.group('s')) 2098 tp.fwdata.append((int(m.group('s')), int(m.group('r'))))
1310 data.fwResume = int(m.group('r'))
1311 if(data.fwSuspend > 0 or data.fwResume > 0):
1312 data.fwValid = True
1313 continue 2099 continue
1314 # tracer type line: determine the trace data type 2100 # tracer type line: determine the trace data type
1315 m = re.match(sysvals.tracertypefmt, line) 2101 m = re.match(sysvals.tracertypefmt, line)
1316 if(m): 2102 if(m):
1317 tracer = m.group('t') 2103 tp.setTracerType(m.group('t'))
1318 testrun.setTracerType(tracer)
1319 continue 2104 continue
1320 # post resume time line: did this test run include post-resume data 2105 # post resume time line: did this test run include post-resume data
1321 m = re.match(sysvals.postresumefmt, line) 2106 m = re.match(sysvals.postresumefmt, line)
@@ -1324,15 +2109,20 @@ def parseTraceLog():
1324 if(t > 0): 2109 if(t > 0):
1325 sysvals.postresumetime = t 2110 sysvals.postresumetime = t
1326 continue 2111 continue
2112 # device properties line
2113 if(re.match(sysvals.devpropfmt, line)):
2114 devProps(line)
2115 continue
1327 # ftrace line: parse only valid lines 2116 # ftrace line: parse only valid lines
1328 m = re.match(testrun.ftrace_line_fmt, line) 2117 m = re.match(tp.ftrace_line_fmt, line)
1329 if(not m): 2118 if(not m):
1330 continue 2119 continue
1331 # gather the basic message data from the line 2120 # gather the basic message data from the line
1332 m_time = m.group('time') 2121 m_time = m.group('time')
2122 m_proc = m.group('proc')
1333 m_pid = m.group('pid') 2123 m_pid = m.group('pid')
1334 m_msg = m.group('msg') 2124 m_msg = m.group('msg')
1335 if(testrun.cgformat): 2125 if(tp.cgformat):
1336 m_param3 = m.group('dur') 2126 m_param3 = m.group('dur')
1337 else: 2127 else:
1338 m_param3 = 'traceevent' 2128 m_param3 = 'traceevent'
@@ -1344,24 +2134,38 @@ def parseTraceLog():
1344 # the line should be a call, return, or event 2134 # the line should be a call, return, or event
1345 if(not t.fcall and not t.freturn and not t.fevent): 2135 if(not t.fcall and not t.freturn and not t.fevent):
1346 continue 2136 continue
1347 # only parse the ftrace data during suspend/resume 2137 # find the start of suspend
1348 if(not testrun.inthepipe): 2138 if(t.startMarker()):
1349 # look for the suspend start marker 2139 phase = 'suspend_prepare'
1350 if(t.fevent): 2140 data = Data(len(testdata))
1351 if(t.name == 'SUSPEND START'): 2141 testdata.append(data)
1352 testrun.inthepipe = True 2142 testrun = TestRun(data)
1353 data.setStart(t.time) 2143 testruns.append(testrun)
2144 parseStamp(tp.stamp, data)
2145 if len(tp.fwdata) > data.testnumber:
2146 data.fwSuspend, data.fwResume = tp.fwdata[data.testnumber]
2147 if(data.fwSuspend > 0 or data.fwResume > 0):
2148 data.fwValid = True
2149 data.setStart(t.time)
2150 continue
2151 if(not data):
2152 continue
2153 # find the end of resume
2154 if(t.endMarker()):
2155 if(sysvals.usetracemarkers and sysvals.postresumetime > 0):
2156 phase = 'post_resume'
2157 data.newPhase(phase, t.time, t.time, '#F0F0F0', -1)
2158 data.setEnd(t.time)
2159 if(not sysvals.usetracemarkers):
2160 # no trace markers? then quit and be sure to finish recording
2161 # the event we used to trigger resume end
2162 if(len(testrun.ttemp['thaw_processes']) > 0):
2163 # if an entry exists, assume this is its end
2164 testrun.ttemp['thaw_processes'][-1]['end'] = t.time
2165 break
1354 continue 2166 continue
1355 # trace event processing 2167 # trace event processing
1356 if(t.fevent): 2168 if(t.fevent):
1357 if(t.name == 'RESUME COMPLETE'):
1358 if(sysvals.postresumetime > 0):
1359 phase = 'post_resume'
1360 data.newPhase(phase, t.time, t.time, '#FF9966', -1)
1361 else:
1362 testrun.inthepipe = False
1363 data.setEnd(t.time)
1364 continue
1365 if(phase == 'post_resume'): 2169 if(phase == 'post_resume'):
1366 data.setEnd(t.time) 2170 data.setEnd(t.time)
1367 if(t.type == 'suspend_resume'): 2171 if(t.type == 'suspend_resume'):
@@ -1383,8 +2187,7 @@ def parseTraceLog():
1383 m = re.match('(?P<name>.*) .*', t.name) 2187 m = re.match('(?P<name>.*) .*', t.name)
1384 name = m.group('name') 2188 name = m.group('name')
1385 # ignore these events 2189 # ignore these events
1386 if(re.match('acpi_suspend\[.*', t.name) or 2190 if(name.split('[')[0] in tracewatch):
1387 re.match('suspend_enter\[.*', name)):
1388 continue 2191 continue
1389 # -- phase changes -- 2192 # -- phase changes --
1390 # suspend_prepare start 2193 # suspend_prepare start
@@ -1418,7 +2221,7 @@ def parseTraceLog():
1418 data.dmesg[phase]['end'] = t.time 2221 data.dmesg[phase]['end'] = t.time
1419 data.tSuspended = t.time 2222 data.tSuspended = t.time
1420 else: 2223 else:
1421 if(sysvals.suspendmode in ['mem', 'disk']): 2224 if(sysvals.suspendmode in ['mem', 'disk'] and not tp.S0i3):
1422 data.dmesg['suspend_machine']['end'] = t.time 2225 data.dmesg['suspend_machine']['end'] = t.time
1423 data.tSuspended = t.time 2226 data.tSuspended = t.time
1424 phase = 'resume_machine' 2227 phase = 'resume_machine'
@@ -1426,6 +2229,15 @@ def parseTraceLog():
1426 data.tResumed = t.time 2229 data.tResumed = t.time
1427 data.tLow = data.tResumed - data.tSuspended 2230 data.tLow = data.tResumed - data.tSuspended
1428 continue 2231 continue
2232 # acpi_suspend
2233 elif(re.match('acpi_suspend\[.*', t.name)):
2234 # acpi_suspend[0] S0i3
2235 if(re.match('acpi_suspend\[0\] begin', t.name)):
2236 if(sysvals.suspendmode == 'mem'):
2237 tp.S0i3 = True
2238 data.dmesg['suspend_machine']['end'] = t.time
2239 data.tSuspended = t.time
2240 continue
1429 # resume_noirq start 2241 # resume_noirq start
1430 elif(re.match('dpm_resume_noirq\[.*', t.name)): 2242 elif(re.match('dpm_resume_noirq\[.*', t.name)):
1431 phase = 'resume_noirq' 2243 phase = 'resume_noirq'
@@ -1449,30 +2261,25 @@ def parseTraceLog():
1449 if(isbegin): 2261 if(isbegin):
1450 data.dmesg[phase]['start'] = t.time 2262 data.dmesg[phase]['start'] = t.time
1451 continue 2263 continue
1452 2264 # skip trace events inside devices calls
1453 # is this trace event outside of the devices calls 2265 if(not data.isTraceEventOutsideDeviceCalls(pid, t.time)):
1454 if(data.isTraceEventOutsideDeviceCalls(pid, t.time)): 2266 continue
1455 # global events (outside device calls) are simply graphed 2267 # global events (outside device calls) are graphed
1456 if(name not in testrun.ttemp): 2268 if(name not in testrun.ttemp):
1457 testrun.ttemp[name] = [] 2269 testrun.ttemp[name] = []
1458 if(isbegin): 2270 if(isbegin):
1459 # create a new list entry 2271 # create a new list entry
1460 testrun.ttemp[name].append(\ 2272 testrun.ttemp[name].append(\
1461 {'begin': t.time, 'end': t.time}) 2273 {'begin': t.time, 'end': t.time, 'pid': pid})
1462 else:
1463 if(len(testrun.ttemp[name]) > 0):
1464 # if an antry exists, assume this is its end
1465 testrun.ttemp[name][-1]['end'] = t.time
1466 elif(phase == 'post_resume'):
1467 # post resume events can just have ends
1468 testrun.ttemp[name].append({
1469 'begin': data.dmesg[phase]['start'],
1470 'end': t.time})
1471 else: 2274 else:
1472 if(isbegin): 2275 if(len(testrun.ttemp[name]) > 0):
1473 data.addIntraDevTraceEvent('', name, pid, t.time) 2276 # if an entry exists, assume this is its end
1474 else: 2277 testrun.ttemp[name][-1]['end'] = t.time
1475 data.capIntraDevTraceEvent('', name, pid, t.time) 2278 elif(phase == 'post_resume'):
2279 # post resume events can just have ends
2280 testrun.ttemp[name].append({
2281 'begin': data.dmesg[phase]['start'],
2282 'end': t.time})
1476 # device callback start 2283 # device callback start
1477 elif(t.type == 'device_pm_callback_start'): 2284 elif(t.type == 'device_pm_callback_start'):
1478 m = re.match('(?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*',\ 2285 m = re.match('(?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*',\
@@ -1495,75 +2302,127 @@ def parseTraceLog():
1495 dev = list[n] 2302 dev = list[n]
1496 dev['length'] = t.time - dev['start'] 2303 dev['length'] = t.time - dev['start']
1497 dev['end'] = t.time 2304 dev['end'] = t.time
2305 # kprobe event processing
2306 elif(t.fkprobe):
2307 kprobename = t.type
2308 kprobedata = t.name
2309 key = (kprobename, pid)
2310 # displayname is generated from kprobe data
2311 displayname = ''
2312 if(t.fcall):
2313 displayname = sysvals.kprobeDisplayName(kprobename, kprobedata)
2314 if not displayname:
2315 continue
2316 if(key not in tp.ktemp):
2317 tp.ktemp[key] = []
2318 tp.ktemp[key].append({
2319 'pid': pid,
2320 'begin': t.time,
2321 'end': t.time,
2322 'name': displayname,
2323 'cdata': kprobedata,
2324 'proc': m_proc,
2325 })
2326 elif(t.freturn):
2327 if(key not in tp.ktemp) or len(tp.ktemp[key]) < 1:
2328 continue
2329 e = tp.ktemp[key][-1]
2330 if e['begin'] < 0.0 or t.time - e['begin'] < 0.000001:
2331 tp.ktemp[key].pop()
2332 else:
2333 e['end'] = t.time
2334 e['rdata'] = kprobedata
1498 # callgraph processing 2335 # callgraph processing
1499 elif sysvals.usecallgraph: 2336 elif sysvals.usecallgraph:
1500 # this shouldn't happen, but JIC, ignore callgraph data post-res
1501 if(phase == 'post_resume'):
1502 continue
1503 # create a callgraph object for the data 2337 # create a callgraph object for the data
1504 if(pid not in testrun.ftemp): 2338 key = (m_proc, pid)
1505 testrun.ftemp[pid] = [] 2339 if(key not in testrun.ftemp):
1506 testrun.ftemp[pid].append(FTraceCallGraph()) 2340 testrun.ftemp[key] = []
2341 testrun.ftemp[key].append(FTraceCallGraph(pid))
1507 # when the call is finished, see which device matches it 2342 # when the call is finished, see which device matches it
1508 cg = testrun.ftemp[pid][-1] 2343 cg = testrun.ftemp[key][-1]
1509 if(cg.addLine(t, m)): 2344 if(cg.addLine(t)):
1510 testrun.ftemp[pid].append(FTraceCallGraph()) 2345 testrun.ftemp[key].append(FTraceCallGraph(pid))
1511 tf.close() 2346 tf.close()
1512 2347
2348 if sysvals.suspendmode == 'command':
2349 for test in testruns:
2350 for p in test.data.phases:
2351 if p == 'resume_complete':
2352 test.data.dmesg[p]['start'] = test.data.start
2353 test.data.dmesg[p]['end'] = test.data.end
2354 else:
2355 test.data.dmesg[p]['start'] = test.data.start
2356 test.data.dmesg[p]['end'] = test.data.start
2357 test.data.tSuspended = test.data.start
2358 test.data.tResumed = test.data.start
2359 test.data.tLow = 0
2360 test.data.fwValid = False
2361
1513 for test in testruns: 2362 for test in testruns:
1514 # add the traceevent data to the device hierarchy 2363 # add the traceevent data to the device hierarchy
1515 if(sysvals.usetraceevents): 2364 if(sysvals.usetraceevents):
2365 # add actual trace funcs
1516 for name in test.ttemp: 2366 for name in test.ttemp:
1517 for event in test.ttemp[name]: 2367 for event in test.ttemp[name]:
1518 begin = event['begin'] 2368 test.data.newActionGlobal(name, event['begin'], event['end'], event['pid'])
1519 end = event['end'] 2369 # add the kprobe based virtual tracefuncs as actual devices
1520 # if event starts before timeline start, expand timeline 2370 for key in tp.ktemp:
1521 if(begin < test.data.start): 2371 name, pid = key
1522 test.data.setStart(begin) 2372 if name not in sysvals.tracefuncs:
1523 # if event ends after timeline end, expand the timeline
1524 if(end > test.data.end):
1525 test.data.setEnd(end)
1526 test.data.newActionGlobal(name, begin, end)
1527
1528 # add the callgraph data to the device hierarchy
1529 borderphase = {
1530 'dpm_prepare': 'suspend_prepare',
1531 'dpm_complete': 'resume_complete'
1532 }
1533 for pid in test.ftemp:
1534 for cg in test.ftemp[pid]:
1535 if len(cg.list) < 2:
1536 continue 2373 continue
1537 if(not cg.sanityCheck()): 2374 for e in tp.ktemp[key]:
1538 id = 'task %s cpu %s' % (pid, m.group('cpu')) 2375 kb, ke = e['begin'], e['end']
1539 vprint('Sanity check failed for '+\ 2376 if kb == ke or not test.data.isInsideTimeline(kb, ke):
1540 id+', ignoring this callback') 2377 continue
2378 test.data.newActionGlobal(e['name'], kb, ke, pid)
2379 # add config base kprobes and dev kprobes
2380 for key in tp.ktemp:
2381 name, pid = key
2382 if name in sysvals.tracefuncs:
1541 continue 2383 continue
1542 callstart = cg.start 2384 for e in tp.ktemp[key]:
1543 callend = cg.end 2385 kb, ke = e['begin'], e['end']
1544 if(cg.list[0].name in borderphase): 2386 if kb == ke or not test.data.isInsideTimeline(kb, ke):
1545 p = borderphase[cg.list[0].name] 2387 continue
1546 list = test.data.dmesg[p]['list'] 2388 color = sysvals.kprobeColor(e['name'])
1547 for devname in list: 2389 if name not in sysvals.dev_tracefuncs:
1548 dev = list[devname] 2390 # config base kprobe
1549 if(pid == dev['pid'] and 2391 test.data.newActionGlobal(e['name'], kb, ke, -2, color)
1550 callstart <= dev['start'] and 2392 elif sysvals.usedevsrc:
1551 callend >= dev['end']): 2393 # dev kprobe
1552 dev['ftrace'] = cg.slice(dev['start'], dev['end']) 2394 data.addDeviceFunctionCall(e['name'], name, e['proc'], pid, kb,
1553 continue 2395 ke, e['cdata'], e['rdata'])
1554 if(cg.list[0].name != 'dpm_run_callback'): 2396 if sysvals.usecallgraph:
1555 continue 2397 # add the callgraph data to the device hierarchy
1556 for p in test.data.phases: 2398 sortlist = dict()
1557 if(test.data.dmesg[p]['start'] <= callstart and 2399 for key in test.ftemp:
1558 callstart <= test.data.dmesg[p]['end']): 2400 proc, pid = key
1559 list = test.data.dmesg[p]['list'] 2401 for cg in test.ftemp[key]:
1560 for devname in list: 2402 if len(cg.list) < 1 or cg.invalid:
1561 dev = list[devname] 2403 continue
1562 if(pid == dev['pid'] and 2404 if(not cg.postProcess()):
1563 callstart <= dev['start'] and 2405 id = 'task %s' % (pid)
1564 callend >= dev['end']): 2406 vprint('Sanity check failed for '+\
1565 dev['ftrace'] = cg 2407 id+', ignoring this callback')
1566 break 2408 continue
2409 # match cg data to devices
2410 if sysvals.suspendmode == 'command' or not cg.deviceMatch(pid, test.data):
2411 sortkey = '%f%f%d' % (cg.start, cg.end, pid)
2412 sortlist[sortkey] = cg
2413 # create blocks for orphan cg data
2414 for sortkey in sorted(sortlist):
2415 cg = sortlist[sortkey]
2416 name = cg.list[0].name
2417 if sysvals.isCallgraphFunc(name):
2418 vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name))
2419 cg.newActionFromFunction(test.data)
2420
2421 if sysvals.suspendmode == 'command':
2422 if(sysvals.verbose):
2423 for data in testdata:
2424 data.printDetails()
2425 return testdata
1567 2426
1568 # fill in any missing phases 2427 # fill in any missing phases
1569 for data in testdata: 2428 for data in testdata:
@@ -1587,14 +2446,52 @@ def parseTraceLog():
1587 if(sysvals.verbose): 2446 if(sysvals.verbose):
1588 data.printDetails() 2447 data.printDetails()
1589 2448
1590 # add the time in between the tests as a new phase so we can see it
1591 if(len(testdata) > 1):
1592 t1e = testdata[0].getEnd()
1593 t2s = testdata[-1].getStart()
1594 testdata[-1].newPhaseWithSingleAction('user mode', \
1595 'user mode', t1e, t2s, '#FF9966')
1596 return testdata 2449 return testdata
1597 2450
2451# Function: loadRawKernelLog
2452# Description:
2453# Load a raw kernel log that wasn't created by this tool, it might be
2454# possible to extract a valid suspend/resume log
2455def loadRawKernelLog(dmesgfile):
2456 global sysvals
2457
2458 stamp = {'time': '', 'host': '', 'mode': 'mem', 'kernel': ''}
2459 stamp['time'] = datetime.now().strftime('%B %d %Y, %I:%M:%S %p')
2460 stamp['host'] = sysvals.hostname
2461
2462 testruns = []
2463 data = 0
2464 lf = open(dmesgfile, 'r')
2465 for line in lf:
2466 line = line.replace('\r\n', '')
2467 idx = line.find('[')
2468 if idx > 1:
2469 line = line[idx:]
2470 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
2471 if(not m):
2472 continue
2473 msg = m.group("msg")
2474 m = re.match('PM: Syncing filesystems.*', msg)
2475 if(m):
2476 if(data):
2477 testruns.append(data)
2478 data = Data(len(testruns))
2479 data.stamp = stamp
2480 if(data):
2481 m = re.match('.* *(?P<k>[0-9]\.[0-9]{2}\.[0-9]-.*) .*', msg)
2482 if(m):
2483 stamp['kernel'] = m.group('k')
2484 m = re.match('PM: Preparing system for (?P<m>.*) sleep', msg)
2485 if(m):
2486 stamp['mode'] = m.group('m')
2487 data.dmesgtext.append(line)
2488 if(data):
2489 testruns.append(data)
2490 sysvals.stamp = stamp
2491 sysvals.suspendmode = stamp['mode']
2492 lf.close()
2493 return testruns
2494
1598# Function: loadKernelLog 2495# Function: loadKernelLog
1599# Description: 2496# Description:
1600# [deprecated for kernel 3.15.0 or newer] 2497# [deprecated for kernel 3.15.0 or newer]
@@ -1607,9 +2504,10 @@ def loadKernelLog():
1607 2504
1608 vprint('Analyzing the dmesg data...') 2505 vprint('Analyzing the dmesg data...')
1609 if(os.path.exists(sysvals.dmesgfile) == False): 2506 if(os.path.exists(sysvals.dmesgfile) == False):
1610 doError('%s doesnt exist' % sysvals.dmesgfile, False) 2507 doError('%s does not exist' % sysvals.dmesgfile, False)
1611 2508
1612 # there can be multiple test runs in a single file delineated by stamps 2509 # there can be multiple test runs in a single file
2510 tp = TestProps()
1613 testruns = [] 2511 testruns = []
1614 data = 0 2512 data = 0
1615 lf = open(sysvals.dmesgfile, 'r') 2513 lf = open(sysvals.dmesgfile, 'r')
@@ -1620,35 +2518,43 @@ def loadKernelLog():
1620 line = line[idx:] 2518 line = line[idx:]
1621 m = re.match(sysvals.stampfmt, line) 2519 m = re.match(sysvals.stampfmt, line)
1622 if(m): 2520 if(m):
1623 if(data): 2521 tp.stamp = line
1624 testruns.append(data)
1625 data = Data(len(testruns))
1626 parseStamp(m, data)
1627 continue
1628 if(not data):
1629 continue 2522 continue
1630 m = re.match(sysvals.firmwarefmt, line) 2523 m = re.match(sysvals.firmwarefmt, line)
1631 if(m): 2524 if(m):
1632 data.fwSuspend = int(m.group('s')) 2525 tp.fwdata.append((int(m.group('s')), int(m.group('r'))))
1633 data.fwResume = int(m.group('r'))
1634 if(data.fwSuspend > 0 or data.fwResume > 0):
1635 data.fwValid = True
1636 continue 2526 continue
1637 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 2527 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
1638 if(m): 2528 if(not m):
1639 data.dmesgtext.append(line) 2529 continue
1640 if(re.match('ACPI: resume from mwait', m.group('msg'))): 2530 msg = m.group("msg")
1641 print('NOTE: This suspend appears to be freeze rather than'+\ 2531 if(re.match('PM: Syncing filesystems.*', msg)):
1642 ' %s, it will be treated as such' % sysvals.suspendmode) 2532 if(data):
1643 sysvals.suspendmode = 'freeze' 2533 testruns.append(data)
1644 else: 2534 data = Data(len(testruns))
1645 vprint('ignoring dmesg line: %s' % line.replace('\n', '')) 2535 parseStamp(tp.stamp, data)
1646 testruns.append(data) 2536 if len(tp.fwdata) > data.testnumber:
2537 data.fwSuspend, data.fwResume = tp.fwdata[data.testnumber]
2538 if(data.fwSuspend > 0 or data.fwResume > 0):
2539 data.fwValid = True
2540 if(re.match('ACPI: resume from mwait', msg)):
2541 print('NOTE: This suspend appears to be freeze rather than'+\
2542 ' %s, it will be treated as such' % sysvals.suspendmode)
2543 sysvals.suspendmode = 'freeze'
2544 if(not data):
2545 continue
2546 data.dmesgtext.append(line)
2547 if(data):
2548 testruns.append(data)
1647 lf.close() 2549 lf.close()
1648 2550
1649 if(not data): 2551 if(len(testruns) < 1):
1650 print('ERROR: analyze_suspend header missing from dmesg log') 2552 # bad log, but see if you can extract something meaningful anyway
1651 sys.exit() 2553 testruns = loadRawKernelLog(sysvals.dmesgfile)
2554
2555 if(len(testruns) < 1):
2556 doError(' dmesg log is completely unreadable: %s' \
2557 % sysvals.dmesgfile, False)
1652 2558
1653 # fix lines with same timestamp/function with the call and return swapped 2559 # fix lines with same timestamp/function with the call and return swapped
1654 for data in testruns: 2560 for data in testruns:
@@ -1865,7 +2771,8 @@ def parseKernelLog(data):
1865 actions[a] = [] 2771 actions[a] = []
1866 actions[a].append({'begin': ktime, 'end': ktime}) 2772 actions[a].append({'begin': ktime, 'end': ktime})
1867 if(re.match(at[a]['emsg'], msg)): 2773 if(re.match(at[a]['emsg'], msg)):
1868 actions[a][-1]['end'] = ktime 2774 if(a in actions):
2775 actions[a][-1]['end'] = ktime
1869 # now look for CPU on/off events 2776 # now look for CPU on/off events
1870 if(re.match('Disabling non-boot CPUs .*', msg)): 2777 if(re.match('Disabling non-boot CPUs .*', msg)):
1871 # start of first cpu suspend 2778 # start of first cpu suspend
@@ -1912,15 +2819,7 @@ def parseKernelLog(data):
1912 # fill in any actions we've found 2819 # fill in any actions we've found
1913 for name in actions: 2820 for name in actions:
1914 for event in actions[name]: 2821 for event in actions[name]:
1915 begin = event['begin'] 2822 data.newActionGlobal(name, event['begin'], event['end'])
1916 end = event['end']
1917 # if event starts before timeline start, expand timeline
1918 if(begin < data.start):
1919 data.setStart(begin)
1920 # if event ends after timeline end, expand the timeline
1921 if(end > data.end):
1922 data.setEnd(end)
1923 data.newActionGlobal(name, begin, end)
1924 2823
1925 if(sysvals.verbose): 2824 if(sysvals.verbose):
1926 data.printDetails() 2825 data.printDetails()
@@ -1929,92 +2828,6 @@ def parseKernelLog(data):
1929 data.fixupInitcallsThatDidntReturn() 2828 data.fixupInitcallsThatDidntReturn()
1930 return True 2829 return True
1931 2830
1932# Function: setTimelineRows
1933# Description:
1934# Organize the timeline entries into the smallest
1935# number of rows possible, with no entry overlapping
1936# Arguments:
1937# list: the list of devices/actions for a single phase
1938# sortedkeys: cronologically sorted key list to use
1939# Output:
1940# The total number of rows needed to display this phase of the timeline
1941def setTimelineRows(list, sortedkeys):
1942
1943 # clear all rows and set them to undefined
1944 remaining = len(list)
1945 rowdata = dict()
1946 row = 0
1947 for item in list:
1948 list[item]['row'] = -1
1949
1950 # try to pack each row with as many ranges as possible
1951 while(remaining > 0):
1952 if(row not in rowdata):
1953 rowdata[row] = []
1954 for item in sortedkeys:
1955 if(list[item]['row'] < 0):
1956 s = list[item]['start']
1957 e = list[item]['end']
1958 valid = True
1959 for ritem in rowdata[row]:
1960 rs = ritem['start']
1961 re = ritem['end']
1962 if(not (((s <= rs) and (e <= rs)) or
1963 ((s >= re) and (e >= re)))):
1964 valid = False
1965 break
1966 if(valid):
1967 rowdata[row].append(list[item])
1968 list[item]['row'] = row
1969 remaining -= 1
1970 row += 1
1971 return row
1972
1973# Function: createTimeScale
1974# Description:
1975# Create the timescale header for the html timeline
1976# Arguments:
1977# t0: start time (suspend begin)
1978# tMax: end time (resume end)
1979# tSuspend: time when suspend occurs, i.e. the zero time
1980# Output:
1981# The html code needed to display the time scale
1982def createTimeScale(t0, tMax, tSuspended):
1983 timescale = '<div class="t" style="right:{0}%">{1}</div>\n'
1984 output = '<div id="timescale">\n'
1985
1986 # set scale for timeline
1987 tTotal = tMax - t0
1988 tS = 0.1
1989 if(tTotal <= 0):
1990 return output
1991 if(tTotal > 4):
1992 tS = 1
1993 if(tSuspended < 0):
1994 for i in range(int(tTotal/tS)+1):
1995 pos = '%0.3f' % (100 - ((float(i)*tS*100)/tTotal))
1996 if(i > 0):
1997 val = '%0.fms' % (float(i)*tS*1000)
1998 else:
1999 val = ''
2000 output += timescale.format(pos, val)
2001 else:
2002 tSuspend = tSuspended - t0
2003 divTotal = int(tTotal/tS) + 1
2004 divSuspend = int(tSuspend/tS)
2005 s0 = (tSuspend - tS*divSuspend)*100/tTotal
2006 for i in range(divTotal):
2007 pos = '%0.3f' % (100 - ((float(i)*tS*100)/tTotal) - s0)
2008 if((i == 0) and (s0 < 3)):
2009 val = ''
2010 elif(i == divSuspend):
2011 val = 'S/R'
2012 else:
2013 val = '%0.fms' % (float(i-divSuspend)*tS*1000)
2014 output += timescale.format(pos, val)
2015 output += '</div>\n'
2016 return output
2017
2018# Function: createHTMLSummarySimple 2831# Function: createHTMLSummarySimple
2019# Description: 2832# Description:
2020# Create summary html file for a series of tests 2833# Create summary html file for a series of tests
@@ -2146,6 +2959,32 @@ def createHTMLSummarySimple(testruns, htmlfile):
2146 hf.write('</body>\n</html>\n') 2959 hf.write('</body>\n</html>\n')
2147 hf.close() 2960 hf.close()
2148 2961
2962def htmlTitle():
2963 global sysvals
2964 modename = {
2965 'freeze': 'Freeze (S0)',
2966 'standby': 'Standby (S1)',
2967 'mem': 'Suspend (S3)',
2968 'disk': 'Hibernate (S4)'
2969 }
2970 kernel = sysvals.stamp['kernel']
2971 host = sysvals.hostname[0].upper()+sysvals.hostname[1:]
2972 mode = sysvals.suspendmode
2973 if sysvals.suspendmode in modename:
2974 mode = modename[sysvals.suspendmode]
2975 return host+' '+mode+' '+kernel
2976
2977def ordinal(value):
2978 suffix = 'th'
2979 if value < 10 or value > 19:
2980 if value % 10 == 1:
2981 suffix = 'st'
2982 elif value % 10 == 2:
2983 suffix = 'nd'
2984 elif value % 10 == 3:
2985 suffix = 'rd'
2986 return '%d%s' % (value, suffix)
2987
2149# Function: createHTML 2988# Function: createHTML
2150# Description: 2989# Description:
2151# Create the output html file from the resident test data 2990# Create the output html file from the resident test data
@@ -2156,6 +2995,10 @@ def createHTMLSummarySimple(testruns, htmlfile):
2156def createHTML(testruns): 2995def createHTML(testruns):
2157 global sysvals 2996 global sysvals
2158 2997
2998 if len(testruns) < 1:
2999 print('ERROR: Not enough test data to build a timeline')
3000 return
3001
2159 for data in testruns: 3002 for data in testruns:
2160 data.normalizeTime(testruns[-1].tSuspended) 3003 data.normalizeTime(testruns[-1].tSuspended)
2161 3004
@@ -2163,16 +3006,18 @@ def createHTML(testruns):
2163 if len(testruns) > 1: 3006 if len(testruns) > 1:
2164 x2changes = ['1', 'relative'] 3007 x2changes = ['1', 'relative']
2165 # html function templates 3008 # html function templates
3009 headline_version = '<div class="version"><a href="https://01.org/suspendresume">AnalyzeSuspend v%s</a></div>' % sysvals.version
2166 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n' 3010 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n'
2167 html_devlist1 = '<button id="devlist1" class="devlist" style="float:left;">Device Detail%s</button>' % x2changes[0] 3011 html_devlist1 = '<button id="devlist1" class="devlist" style="float:left;">Device Detail%s</button>' % x2changes[0]
2168 html_zoombox = '<center><button id="zoomin">ZOOM IN</button><button id="zoomout">ZOOM OUT</button><button id="zoomdef">ZOOM 1:1</button></center>\n' 3012 html_zoombox = '<center><button id="zoomin">ZOOM IN</button><button id="zoomout">ZOOM OUT</button><button id="zoomdef">ZOOM 1:1</button></center>\n'
2169 html_devlist2 = '<button id="devlist2" class="devlist" style="float:right;">Device Detail2</button>\n' 3013 html_devlist2 = '<button id="devlist2" class="devlist" style="float:right;">Device Detail2</button>\n'
2170 html_timeline = '<div id="dmesgzoombox" class="zoombox">\n<div id="{0}" class="timeline" style="height:{1}px">\n' 3014 html_timeline = '<div id="dmesgzoombox" class="zoombox">\n<div id="{0}" class="timeline" style="height:{1}px">\n'
2171 html_device = '<div id="{0}" title="{1}" class="thread" style="left:{2}%;top:{3}%;height:{4}%;width:{5}%;">{6}</div>\n' 3015 html_tblock = '<div id="block{0}" class="tblock" style="left:{1}%;width:{2}%;">\n'
2172 html_traceevent = '<div title="{0}" class="traceevent" style="left:{1}%;top:{2}%;height:{3}%;width:{4}%;border:1px solid {5};background-color:{5}">{6}</div>\n' 3016 html_device = '<div id="{0}" title="{1}" class="thread{7}" style="left:{2}%;top:{3}px;height:{4}px;width:{5}%;{8}">{6}</div>\n'
2173 html_phase = '<div class="phase" style="left:{0}%;width:{1}%;top:{2}%;height:{3}%;background-color:{4}">{5}</div>\n' 3017 html_traceevent = '<div title="{0}" class="traceevent" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;">{5}</div>\n'
3018 html_phase = '<div class="phase" style="left:{0}%;width:{1}%;top:{2}px;height:{3}px;background-color:{4}">{5}</div>\n'
2174 html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background-color:{3}"></div>\n' 3019 html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background-color:{3}"></div>\n'
2175 html_legend = '<div class="square" style="left:{0}%;background-color:{1}">&nbsp;{2}</div>\n' 3020 html_legend = '<div id="p{3}" class="square" style="left:{0}%;background-color:{1}">&nbsp;{2}</div>\n'
2176 html_timetotal = '<table class="time1">\n<tr>'\ 3021 html_timetotal = '<table class="time1">\n<tr>'\
2177 '<td class="green">{2} Suspend Time: <b>{0} ms</b></td>'\ 3022 '<td class="green">{2} Suspend Time: <b>{0} ms</b></td>'\
2178 '<td class="yellow">{2} Resume Time: <b>{1} ms</b></td>'\ 3023 '<td class="yellow">{2} Resume Time: <b>{1} ms</b></td>'\
@@ -2182,6 +3027,10 @@ def createHTML(testruns):
2182 '<td class="gray">'+sysvals.suspendmode+' time: <b>{1} ms</b></td>'\ 3027 '<td class="gray">'+sysvals.suspendmode+' time: <b>{1} ms</b></td>'\
2183 '<td class="yellow">{3} Resume Time: <b>{2} ms</b></td>'\ 3028 '<td class="yellow">{3} Resume Time: <b>{2} ms</b></td>'\
2184 '</tr>\n</table>\n' 3029 '</tr>\n</table>\n'
3030 html_timetotal3 = '<table class="time1">\n<tr>'\
3031 '<td class="green">Execution Time: <b>{0} ms</b></td>'\
3032 '<td class="yellow">Command: <b>{1}</b></td>'\
3033 '</tr>\n</table>\n'
2185 html_timegroups = '<table class="time2">\n<tr>'\ 3034 html_timegroups = '<table class="time2">\n<tr>'\
2186 '<td class="green">{4}Kernel Suspend: {0} ms</td>'\ 3035 '<td class="green">{4}Kernel Suspend: {0} ms</td>'\
2187 '<td class="purple">{4}Firmware Suspend: {1} ms</td>'\ 3036 '<td class="purple">{4}Firmware Suspend: {1} ms</td>'\
@@ -2189,12 +3038,21 @@ def createHTML(testruns):
2189 '<td class="yellow">{4}Kernel Resume: {3} ms</td>'\ 3038 '<td class="yellow">{4}Kernel Resume: {3} ms</td>'\
2190 '</tr>\n</table>\n' 3039 '</tr>\n</table>\n'
2191 3040
3041 # html format variables
3042 rowheight = 30
3043 devtextS = '14px'
3044 devtextH = '30px'
3045 hoverZ = 'z-index:10;'
3046
3047 if sysvals.usedevsrc:
3048 hoverZ = ''
3049
2192 # device timeline 3050 # device timeline
2193 vprint('Creating Device Timeline...') 3051 vprint('Creating Device Timeline...')
2194 devtl = Timeline() 3052
3053 devtl = Timeline(rowheight)
2195 3054
2196 # Generate the header for this timeline 3055 # Generate the header for this timeline
2197 textnum = ['First', 'Second']
2198 for data in testruns: 3056 for data in testruns:
2199 tTotal = data.end - data.start 3057 tTotal = data.end - data.start
2200 tEnd = data.dmesg['resume_complete']['end'] 3058 tEnd = data.dmesg['resume_complete']['end']
@@ -2203,7 +3061,17 @@ def createHTML(testruns):
2203 sys.exit() 3061 sys.exit()
2204 if(data.tLow > 0): 3062 if(data.tLow > 0):
2205 low_time = '%.0f'%(data.tLow*1000) 3063 low_time = '%.0f'%(data.tLow*1000)
2206 if data.fwValid: 3064 if sysvals.suspendmode == 'command':
3065 run_time = '%.0f'%((data.end-data.start)*1000)
3066 if sysvals.testcommand:
3067 testdesc = sysvals.testcommand
3068 else:
3069 testdesc = 'unknown'
3070 if(len(testruns) > 1):
3071 testdesc = ordinal(data.testnumber+1)+' '+testdesc
3072 thtml = html_timetotal3.format(run_time, testdesc)
3073 devtl.html['header'] += thtml
3074 elif data.fwValid:
2207 suspend_time = '%.0f'%((data.tSuspended-data.start)*1000 + \ 3075 suspend_time = '%.0f'%((data.tSuspended-data.start)*1000 + \
2208 (data.fwSuspend/1000000.0)) 3076 (data.fwSuspend/1000000.0))
2209 resume_time = '%.0f'%((tEnd-data.tSuspended)*1000 + \ 3077 resume_time = '%.0f'%((tEnd-data.tSuspended)*1000 + \
@@ -2211,7 +3079,7 @@ def createHTML(testruns):
2211 testdesc1 = 'Total' 3079 testdesc1 = 'Total'
2212 testdesc2 = '' 3080 testdesc2 = ''
2213 if(len(testruns) > 1): 3081 if(len(testruns) > 1):
2214 testdesc1 = testdesc2 = textnum[data.testnumber] 3082 testdesc1 = testdesc2 = ordinal(data.testnumber+1)
2215 testdesc2 += ' ' 3083 testdesc2 += ' '
2216 if(data.tLow == 0): 3084 if(data.tLow == 0):
2217 thtml = html_timetotal.format(suspend_time, \ 3085 thtml = html_timetotal.format(suspend_time, \
@@ -2219,28 +3087,28 @@ def createHTML(testruns):
2219 else: 3087 else:
2220 thtml = html_timetotal2.format(suspend_time, low_time, \ 3088 thtml = html_timetotal2.format(suspend_time, low_time, \
2221 resume_time, testdesc1) 3089 resume_time, testdesc1)
2222 devtl.html['timeline'] += thtml 3090 devtl.html['header'] += thtml
2223 sktime = '%.3f'%((data.dmesg['suspend_machine']['end'] - \ 3091 sktime = '%.3f'%((data.dmesg['suspend_machine']['end'] - \
2224 data.getStart())*1000) 3092 data.getStart())*1000)
2225 sftime = '%.3f'%(data.fwSuspend / 1000000.0) 3093 sftime = '%.3f'%(data.fwSuspend / 1000000.0)
2226 rftime = '%.3f'%(data.fwResume / 1000000.0) 3094 rftime = '%.3f'%(data.fwResume / 1000000.0)
2227 rktime = '%.3f'%((data.getEnd() - \ 3095 rktime = '%.3f'%((data.dmesg['resume_complete']['end'] - \
2228 data.dmesg['resume_machine']['start'])*1000) 3096 data.dmesg['resume_machine']['start'])*1000)
2229 devtl.html['timeline'] += html_timegroups.format(sktime, \ 3097 devtl.html['header'] += html_timegroups.format(sktime, \
2230 sftime, rftime, rktime, testdesc2) 3098 sftime, rftime, rktime, testdesc2)
2231 else: 3099 else:
2232 suspend_time = '%.0f'%((data.tSuspended-data.start)*1000) 3100 suspend_time = '%.0f'%((data.tSuspended-data.start)*1000)
2233 resume_time = '%.0f'%((tEnd-data.tSuspended)*1000) 3101 resume_time = '%.0f'%((tEnd-data.tSuspended)*1000)
2234 testdesc = 'Kernel' 3102 testdesc = 'Kernel'
2235 if(len(testruns) > 1): 3103 if(len(testruns) > 1):
2236 testdesc = textnum[data.testnumber]+' '+testdesc 3104 testdesc = ordinal(data.testnumber+1)+' '+testdesc
2237 if(data.tLow == 0): 3105 if(data.tLow == 0):
2238 thtml = html_timetotal.format(suspend_time, \ 3106 thtml = html_timetotal.format(suspend_time, \
2239 resume_time, testdesc) 3107 resume_time, testdesc)
2240 else: 3108 else:
2241 thtml = html_timetotal2.format(suspend_time, low_time, \ 3109 thtml = html_timetotal2.format(suspend_time, low_time, \
2242 resume_time, testdesc) 3110 resume_time, testdesc)
2243 devtl.html['timeline'] += thtml 3111 devtl.html['header'] += thtml
2244 3112
2245 # time scale for potentially multiple datasets 3113 # time scale for potentially multiple datasets
2246 t0 = testruns[0].start 3114 t0 = testruns[0].start
@@ -2249,153 +3117,241 @@ def createHTML(testruns):
2249 tTotal = tMax - t0 3117 tTotal = tMax - t0
2250 3118
2251 # determine the maximum number of rows we need to draw 3119 # determine the maximum number of rows we need to draw
2252 timelinerows = 0
2253 for data in testruns: 3120 for data in testruns:
2254 for phase in data.dmesg: 3121 data.selectTimelineDevices('%f', tTotal, sysvals.mindevlen)
2255 list = data.dmesg[phase]['list'] 3122 for group in data.devicegroups:
2256 rows = setTimelineRows(list, list) 3123 devlist = []
2257 data.dmesg[phase]['row'] = rows 3124 for phase in group:
2258 if(rows > timelinerows): 3125 for devname in data.tdevlist[phase]:
2259 timelinerows = rows 3126 devlist.append((phase,devname))
2260 3127 devtl.getPhaseRows(data.dmesg, devlist)
2261 # calculate the timeline height and create bounding box, add buttons 3128 devtl.calcTotalRows()
2262 devtl.setRows(timelinerows + 1) 3129
2263 devtl.html['timeline'] += html_devlist1 3130 # create bounding box, add buttons
2264 if len(testruns) > 1: 3131 if sysvals.suspendmode != 'command':
2265 devtl.html['timeline'] += html_devlist2 3132 devtl.html['timeline'] += html_devlist1
3133 if len(testruns) > 1:
3134 devtl.html['timeline'] += html_devlist2
2266 devtl.html['timeline'] += html_zoombox 3135 devtl.html['timeline'] += html_zoombox
2267 devtl.html['timeline'] += html_timeline.format('dmesg', devtl.height) 3136 devtl.html['timeline'] += html_timeline.format('dmesg', devtl.height)
2268 3137
2269 # draw the colored boxes for each of the phases 3138 # draw the full timeline
2270 for data in testruns: 3139 phases = {'suspend':[],'resume':[]}
2271 for b in data.dmesg: 3140 for phase in data.dmesg:
2272 phase = data.dmesg[b] 3141 if 'resume' in phase:
2273 length = phase['end']-phase['start'] 3142 phases['resume'].append(phase)
2274 left = '%.3f' % (((phase['start']-t0)*100.0)/tTotal) 3143 else:
2275 width = '%.3f' % ((length*100.0)/tTotal) 3144 phases['suspend'].append(phase)
2276 devtl.html['timeline'] += html_phase.format(left, width, \
2277 '%.3f'%devtl.scaleH, '%.3f'%(100-devtl.scaleH), \
2278 data.dmesg[b]['color'], '')
2279 3145
2280 # draw the time scale, try to make the number of labels readable 3146 # draw each test run chronologically
2281 devtl.html['scale'] = createTimeScale(t0, tMax, tSuspended)
2282 devtl.html['timeline'] += devtl.html['scale']
2283 for data in testruns: 3147 for data in testruns:
2284 for b in data.dmesg: 3148 # if nore than one test, draw a block to represent user mode
2285 phaselist = data.dmesg[b]['list'] 3149 if(data.testnumber > 0):
2286 for d in phaselist: 3150 m0 = testruns[data.testnumber-1].end
2287 name = d 3151 mMax = testruns[data.testnumber].start
2288 drv = '' 3152 mTotal = mMax - m0
2289 dev = phaselist[d] 3153 name = 'usermode%d' % data.testnumber
2290 if(d in sysvals.altdevname): 3154 top = '%d' % devtl.scaleH
2291 name = sysvals.altdevname[d] 3155 left = '%f' % (((m0-t0)*100.0)/tTotal)
2292 if('drv' in dev and dev['drv']): 3156 width = '%f' % ((mTotal*100.0)/tTotal)
2293 drv = ' {%s}' % dev['drv'] 3157 title = 'user mode (%0.3f ms) ' % (mTotal*1000)
2294 height = (100.0 - devtl.scaleH)/data.dmesg[b]['row'] 3158 devtl.html['timeline'] += html_device.format(name, \
2295 top = '%.3f' % ((dev['row']*height) + devtl.scaleH) 3159 title, left, top, '%d'%devtl.bodyH, width, '', '', '')
2296 left = '%.3f' % (((dev['start']-t0)*100)/tTotal) 3160 # now draw the actual timeline blocks
2297 width = '%.3f' % (((dev['end']-dev['start'])*100)/tTotal) 3161 for dir in phases:
2298 length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000) 3162 # draw suspend and resume blocks separately
2299 color = 'rgba(204,204,204,0.5)' 3163 bname = '%s%d' % (dir[0], data.testnumber)
2300 devtl.html['timeline'] += html_device.format(dev['id'], \ 3164 if dir == 'suspend':
2301 d+drv+length+b, left, top, '%.3f'%height, width, name+drv) 3165 m0 = testruns[data.testnumber].start
2302 3166 mMax = testruns[data.testnumber].tSuspended
2303 # draw any trace events found 3167 mTotal = mMax - m0
2304 for data in testruns: 3168 left = '%f' % (((m0-t0)*100.0)/tTotal)
2305 for b in data.dmesg: 3169 else:
2306 phaselist = data.dmesg[b]['list'] 3170 m0 = testruns[data.testnumber].tSuspended
2307 for name in phaselist: 3171 mMax = testruns[data.testnumber].end
2308 dev = phaselist[name] 3172 mTotal = mMax - m0
2309 if('traceevents' in dev): 3173 left = '%f' % ((((m0-t0)*100.0)+sysvals.srgap/2)/tTotal)
2310 vprint('Debug trace events found for device %s' % name) 3174 # if a timeline block is 0 length, skip altogether
2311 vprint('%20s %20s %10s %8s' % ('action', \ 3175 if mTotal == 0:
3176 continue
3177 width = '%f' % (((mTotal*100.0)-sysvals.srgap/2)/tTotal)
3178 devtl.html['timeline'] += html_tblock.format(bname, left, width)
3179 for b in sorted(phases[dir]):
3180 # draw the phase color background
3181 phase = data.dmesg[b]
3182 length = phase['end']-phase['start']
3183 left = '%f' % (((phase['start']-m0)*100.0)/mTotal)
3184 width = '%f' % ((length*100.0)/mTotal)
3185 devtl.html['timeline'] += html_phase.format(left, width, \
3186 '%.3f'%devtl.scaleH, '%.3f'%devtl.bodyH, \
3187 data.dmesg[b]['color'], '')
3188 # draw the devices for this phase
3189 phaselist = data.dmesg[b]['list']
3190 for d in data.tdevlist[b]:
3191 name = d
3192 drv = ''
3193 dev = phaselist[d]
3194 xtraclass = ''
3195 xtrainfo = ''
3196 xtrastyle = ''
3197 if 'htmlclass' in dev:
3198 xtraclass = dev['htmlclass']
3199 xtrainfo = dev['htmlclass']
3200 if 'color' in dev:
3201 xtrastyle = 'background-color:%s;' % dev['color']
3202 if(d in sysvals.devprops):
3203 name = sysvals.devprops[d].altName(d)
3204 xtraclass = sysvals.devprops[d].xtraClass()
3205 xtrainfo = sysvals.devprops[d].xtraInfo()
3206 if('drv' in dev and dev['drv']):
3207 drv = ' {%s}' % dev['drv']
3208 rowheight = devtl.phaseRowHeight(b, dev['row'])
3209 rowtop = devtl.phaseRowTop(b, dev['row'])
3210 top = '%.3f' % (rowtop + devtl.scaleH)
3211 left = '%f' % (((dev['start']-m0)*100)/mTotal)
3212 width = '%f' % (((dev['end']-dev['start'])*100)/mTotal)
3213 length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000)
3214 if sysvals.suspendmode == 'command':
3215 title = name+drv+xtrainfo+length+'cmdexec'
3216 else:
3217 title = name+drv+xtrainfo+length+b
3218 devtl.html['timeline'] += html_device.format(dev['id'], \
3219 title, left, top, '%.3f'%rowheight, width, \
3220 d+drv, xtraclass, xtrastyle)
3221 if('src' not in dev):
3222 continue
3223 # draw any trace events for this device
3224 vprint('Debug trace events found for device %s' % d)
3225 vprint('%20s %20s %10s %8s' % ('title', \
2312 'name', 'time(ms)', 'length(ms)')) 3226 'name', 'time(ms)', 'length(ms)'))
2313 for e in dev['traceevents']: 3227 for e in dev['src']:
2314 vprint('%20s %20s %10.3f %8.3f' % (e.action, \ 3228 vprint('%20s %20s %10.3f %8.3f' % (e.title, \
2315 e.name, e.time*1000, e.length*1000)) 3229 e.text, e.time*1000, e.length*1000))
2316 height = (100.0 - devtl.scaleH)/data.dmesg[b]['row'] 3230 height = devtl.rowH
2317 top = '%.3f' % ((dev['row']*height) + devtl.scaleH) 3231 top = '%.3f' % (rowtop + devtl.scaleH + (e.row*devtl.rowH))
2318 left = '%.3f' % (((e.time-t0)*100)/tTotal) 3232 left = '%f' % (((e.time-m0)*100)/mTotal)
2319 width = '%.3f' % (e.length*100/tTotal) 3233 width = '%f' % (e.length*100/mTotal)
2320 color = 'rgba(204,204,204,0.5)' 3234 color = 'rgba(204,204,204,0.5)'
2321 devtl.html['timeline'] += \ 3235 devtl.html['timeline'] += \
2322 html_traceevent.format(e.action+' '+e.name, \ 3236 html_traceevent.format(e.title, \
2323 left, top, '%.3f'%height, \ 3237 left, top, '%.3f'%height, \
2324 width, e.color, '') 3238 width, e.text)
3239 # draw the time scale, try to make the number of labels readable
3240 devtl.html['timeline'] += devtl.createTimeScale(m0, mMax, tTotal, dir)
3241 devtl.html['timeline'] += '</div>\n'
2325 3242
2326 # timeline is finished 3243 # timeline is finished
2327 devtl.html['timeline'] += '</div>\n</div>\n' 3244 devtl.html['timeline'] += '</div>\n</div>\n'
2328 3245
2329 # draw a legend which describes the phases by color 3246 # draw a legend which describes the phases by color
2330 data = testruns[-1] 3247 if sysvals.suspendmode != 'command':
2331 devtl.html['legend'] = '<div class="legend">\n' 3248 data = testruns[-1]
2332 pdelta = 100.0/len(data.phases) 3249 devtl.html['legend'] = '<div class="legend">\n'
2333 pmargin = pdelta / 4.0 3250 pdelta = 100.0/len(data.phases)
2334 for phase in data.phases: 3251 pmargin = pdelta / 4.0
2335 order = '%.2f' % ((data.dmesg[phase]['order'] * pdelta) + pmargin) 3252 for phase in data.phases:
2336 name = string.replace(phase, '_', ' &nbsp;') 3253 tmp = phase.split('_')
2337 devtl.html['legend'] += html_legend.format(order, \ 3254 id = tmp[0][0]
2338 data.dmesg[phase]['color'], name) 3255 if(len(tmp) > 1):
2339 devtl.html['legend'] += '</div>\n' 3256 id += tmp[1][0]
3257 order = '%.2f' % ((data.dmesg[phase]['order'] * pdelta) + pmargin)
3258 name = string.replace(phase, '_', ' &nbsp;')
3259 devtl.html['legend'] += html_legend.format(order, \
3260 data.dmesg[phase]['color'], name, id)
3261 devtl.html['legend'] += '</div>\n'
2340 3262
2341 hf = open(sysvals.htmlfile, 'w') 3263 hf = open(sysvals.htmlfile, 'w')
2342 thread_height = 0 3264
3265 if not sysvals.cgexp:
3266 cgchk = 'checked'
3267 cgnchk = 'not(:checked)'
3268 else:
3269 cgchk = 'not(:checked)'
3270 cgnchk = 'checked'
2343 3271
2344 # write the html header first (html head, css code, up to body start) 3272 # write the html header first (html head, css code, up to body start)
2345 html_header = '<!DOCTYPE html>\n<html>\n<head>\n\ 3273 html_header = '<!DOCTYPE html>\n<html>\n<head>\n\
2346 <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\ 3274 <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\
2347 <title>AnalyzeSuspend</title>\n\ 3275 <title>'+htmlTitle()+'</title>\n\
2348 <style type=\'text/css\'>\n\ 3276 <style type=\'text/css\'>\n\
2349 body {overflow-y: scroll;}\n\ 3277 body {overflow-y:scroll;}\n\
2350 .stamp {width: 100%;text-align:center;background-color:gray;line-height:30px;color:white;font: 25px Arial;}\n\ 3278 .stamp {width:100%;text-align:center;background-color:gray;line-height:30px;color:white;font:25px Arial;}\n\
2351 .callgraph {margin-top: 30px;box-shadow: 5px 5px 20px black;}\n\ 3279 .callgraph {margin-top:30px;box-shadow:5px 5px 20px black;}\n\
2352 .callgraph article * {padding-left: 28px;}\n\ 3280 .callgraph article * {padding-left:28px;}\n\
2353 h1 {color:black;font: bold 30px Times;}\n\ 3281 h1 {color:black;font:bold 30px Times;}\n\
2354 t0 {color:black;font: bold 30px Times;}\n\ 3282 t0 {color:black;font:bold 30px Times;}\n\
2355 t1 {color:black;font: 30px Times;}\n\ 3283 t1 {color:black;font:30px Times;}\n\
2356 t2 {color:black;font: 25px Times;}\n\ 3284 t2 {color:black;font:25px Times;}\n\
2357 t3 {color:black;font: 20px Times;white-space:nowrap;}\n\ 3285 t3 {color:black;font:20px Times;white-space:nowrap;}\n\
2358 t4 {color:black;font: bold 30px Times;line-height:60px;white-space:nowrap;}\n\ 3286 t4 {color:black;font:bold 30px Times;line-height:60px;white-space:nowrap;}\n\
3287 cS {color:blue;font:bold 11px Times;}\n\
3288 cR {color:red;font:bold 11px Times;}\n\
2359 table {width:100%;}\n\ 3289 table {width:100%;}\n\
2360 .gray {background-color:rgba(80,80,80,0.1);}\n\ 3290 .gray {background-color:rgba(80,80,80,0.1);}\n\
2361 .green {background-color:rgba(204,255,204,0.4);}\n\ 3291 .green {background-color:rgba(204,255,204,0.4);}\n\
2362 .purple {background-color:rgba(128,0,128,0.2);}\n\ 3292 .purple {background-color:rgba(128,0,128,0.2);}\n\
2363 .yellow {background-color:rgba(255,255,204,0.4);}\n\ 3293 .yellow {background-color:rgba(255,255,204,0.4);}\n\
2364 .time1 {font: 22px Arial;border:1px solid;}\n\ 3294 .time1 {font:22px Arial;border:1px solid;}\n\
2365 .time2 {font: 15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\ 3295 .time2 {font:15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\
2366 td {text-align: center;}\n\ 3296 td {text-align:center;}\n\
2367 r {color:#500000;font:15px Tahoma;}\n\ 3297 r {color:#500000;font:15px Tahoma;}\n\
2368 n {color:#505050;font:15px Tahoma;}\n\ 3298 n {color:#505050;font:15px Tahoma;}\n\
2369 .tdhl {color: red;}\n\ 3299 .tdhl {color:red;}\n\
2370 .hide {display: none;}\n\ 3300 .hide {display:none;}\n\
2371 .pf {display: none;}\n\ 3301 .pf {display:none;}\n\
2372 .pf:checked + label {background: url(\'data:image/svg+xml;utf,<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" version="1.1"><circle cx="9" cy="9" r="8" stroke="black" stroke-width="1" fill="white"/><rect x="4" y="8" width="10" height="2" style="fill:black;stroke-width:0"/><rect x="8" y="4" width="2" height="10" style="fill:black;stroke-width:0"/></svg>\') no-repeat left center;}\n\ 3302 .pf:'+cgchk+' + label {background:url(\'data:image/svg+xml;utf,<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" version="1.1"><circle cx="9" cy="9" r="8" stroke="black" stroke-width="1" fill="white"/><rect x="4" y="8" width="10" height="2" style="fill:black;stroke-width:0"/><rect x="8" y="4" width="2" height="10" style="fill:black;stroke-width:0"/></svg>\') no-repeat left center;}\n\
2373 .pf:not(:checked) ~ label {background: url(\'data:image/svg+xml;utf,<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" version="1.1"><circle cx="9" cy="9" r="8" stroke="black" stroke-width="1" fill="white"/><rect x="4" y="8" width="10" height="2" style="fill:black;stroke-width:0"/></svg>\') no-repeat left center;}\n\ 3303 .pf:'+cgnchk+' ~ label {background:url(\'data:image/svg+xml;utf,<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" version="1.1"><circle cx="9" cy="9" r="8" stroke="black" stroke-width="1" fill="white"/><rect x="4" y="8" width="10" height="2" style="fill:black;stroke-width:0"/></svg>\') no-repeat left center;}\n\
2374 .pf:checked ~ *:not(:nth-child(2)) {display: none;}\n\ 3304 .pf:'+cgchk+' ~ *:not(:nth-child(2)) {display:none;}\n\
2375 .zoombox {position: relative; width: 100%; overflow-x: scroll;}\n\ 3305 .zoombox {position:relative;width:100%;overflow-x:scroll;}\n\
2376 .timeline {position: relative; font-size: 14px;cursor: pointer;width: 100%; overflow: hidden; background-color:#dddddd;}\n\ 3306 .timeline {position:relative;font-size:14px;cursor:pointer;width:100%; overflow:hidden;background:linear-gradient(#cccccc, white);}\n\
2377 .thread {position: absolute; height: '+'%.3f'%thread_height+'%; overflow: hidden; line-height: 30px; border:1px solid;text-align:center;white-space:nowrap;background-color:rgba(204,204,204,0.5);}\n\ 3307 .thread {position:absolute;height:0%;overflow:hidden;line-height:'+devtextH+';font-size:'+devtextS+';border:1px solid;text-align:center;white-space:nowrap;background-color:rgba(204,204,204,0.5);}\n\
2378 .thread:hover {background-color:white;border:1px solid red;z-index:10;}\n\ 3308 .thread.sync {background-color:'+sysvals.synccolor+';}\n\
2379 .hover {background-color:white;border:1px solid red;z-index:10;}\n\ 3309 .thread.bg {background-color:'+sysvals.kprobecolor+';}\n\
2380 .traceevent {position: absolute;opacity: 0.3;height: '+'%.3f'%thread_height+'%;width:0;overflow:hidden;line-height:30px;text-align:center;white-space:nowrap;}\n\ 3310 .thread:hover {background-color:white;border:1px solid red;'+hoverZ+'}\n\
2381 .phase {position: absolute;overflow: hidden;border:0px;text-align:center;}\n\ 3311 .hover {background-color:white;border:1px solid red;'+hoverZ+'}\n\
3312 .hover.sync {background-color:white;}\n\
3313 .hover.bg {background-color:white;}\n\
3314 .traceevent {position:absolute;font-size:10px;overflow:hidden;color:black;text-align:center;white-space:nowrap;border-radius:5px;border:1px solid black;background:linear-gradient(to bottom right,rgba(204,204,204,1),rgba(150,150,150,1));}\n\
3315 .traceevent:hover {background:white;}\n\
3316 .phase {position:absolute;overflow:hidden;border:0px;text-align:center;}\n\
2382 .phaselet {position:absolute;overflow:hidden;border:0px;text-align:center;height:100px;font-size:24px;}\n\ 3317 .phaselet {position:absolute;overflow:hidden;border:0px;text-align:center;height:100px;font-size:24px;}\n\
2383 .t {position:absolute;top:0%;height:100%;border-right:1px solid black;}\n\ 3318 .t {z-index:2;position:absolute;pointer-events:none;top:0%;height:100%;border-right:1px solid black;}\n\
2384 .legend {position: relative; width: 100%; height: 40px; text-align: center;margin-bottom:20px}\n\ 3319 .legend {position:relative; width:100%; height:40px; text-align:center;margin-bottom:20px}\n\
2385 .legend .square {position:absolute;top:10px; width: 0px;height: 20px;border:1px solid;padding-left:20px;}\n\ 3320 .legend .square {position:absolute;cursor:pointer;top:10px; width:0px;height:20px;border:1px solid;padding-left:20px;}\n\
2386 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\ 3321 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\
3322 .logbtn {position:relative;float:right;height:25px;width:50px;margin-top:3px;margin-bottom:0;font-size:10px;text-align:center;}\n\
2387 .devlist {position:'+x2changes[1]+';width:190px;}\n\ 3323 .devlist {position:'+x2changes[1]+';width:190px;}\n\
2388 #devicedetail {height:100px;box-shadow: 5px 5px 20px black;}\n\ 3324 a:link {color:white;text-decoration:none;}\n\
3325 a:visited {color:white;}\n\
3326 a:hover {color:white;}\n\
3327 a:active {color:white;}\n\
3328 .version {position:relative;float:left;color:white;font-size:10px;line-height:30px;margin-left:10px;}\n\
3329 #devicedetail {height:100px;box-shadow:5px 5px 20px black;}\n\
3330 .tblock {position:absolute;height:100%;}\n\
3331 .bg {z-index:1;}\n\
2389 </style>\n</head>\n<body>\n' 3332 </style>\n</head>\n<body>\n'
2390 hf.write(html_header) 3333
3334 # no header or css if its embedded
3335 if(sysvals.embedded):
3336 hf.write('pass True tSus %.3f tRes %.3f tLow %.3f fwvalid %s tSus %.3f tRes %.3f\n' %
3337 (data.tSuspended-data.start, data.end-data.tSuspended, data.tLow, data.fwValid, \
3338 data.fwSuspend/1000000, data.fwResume/1000000))
3339 else:
3340 hf.write(html_header)
2391 3341
2392 # write the test title and general info header 3342 # write the test title and general info header
2393 if(sysvals.stamp['time'] != ""): 3343 if(sysvals.stamp['time'] != ""):
3344 hf.write(headline_version)
3345 if sysvals.addlogs and sysvals.dmesgfile:
3346 hf.write('<button id="showdmesg" class="logbtn">dmesg</button>')
3347 if sysvals.addlogs and sysvals.ftracefile:
3348 hf.write('<button id="showftrace" class="logbtn">ftrace</button>')
2394 hf.write(headline_stamp.format(sysvals.stamp['host'], 3349 hf.write(headline_stamp.format(sysvals.stamp['host'],
2395 sysvals.stamp['kernel'], sysvals.stamp['mode'], \ 3350 sysvals.stamp['kernel'], sysvals.stamp['mode'], \
2396 sysvals.stamp['time'])) 3351 sysvals.stamp['time']))
2397 3352
2398 # write the device timeline 3353 # write the device timeline
3354 hf.write(devtl.html['header'])
2399 hf.write(devtl.html['timeline']) 3355 hf.write(devtl.html['timeline'])
2400 hf.write(devtl.html['legend']) 3356 hf.write(devtl.html['legend'])
2401 hf.write('<div id="devicedetailtitle"></div>\n') 3357 hf.write('<div id="devicedetailtitle"></div>\n')
@@ -2410,12 +3366,15 @@ def createHTML(testruns):
2410 width = '%.3f' % ((length*100.0)/tTotal) 3366 width = '%.3f' % ((length*100.0)/tTotal)
2411 hf.write(html_phaselet.format(b, left, width, \ 3367 hf.write(html_phaselet.format(b, left, width, \
2412 data.dmesg[b]['color'])) 3368 data.dmesg[b]['color']))
3369 if sysvals.suspendmode == 'command':
3370 hf.write(html_phaselet.format('cmdexec', '0', '0', \
3371 data.dmesg['resume_complete']['color']))
2413 hf.write('</div>\n') 3372 hf.write('</div>\n')
2414 hf.write('</div>\n') 3373 hf.write('</div>\n')
2415 3374
2416 # write the ftrace data (callgraph) 3375 # write the ftrace data (callgraph)
2417 data = testruns[-1] 3376 data = testruns[-1]
2418 if(sysvals.usecallgraph): 3377 if(sysvals.usecallgraph and not sysvals.embedded):
2419 hf.write('<section id="callgraphs" class="callgraph">\n') 3378 hf.write('<section id="callgraphs" class="callgraph">\n')
2420 # write out the ftrace data converted to html 3379 # write out the ftrace data converted to html
2421 html_func_top = '<article id="{0}" class="atop" style="background-color:{1}">\n<input type="checkbox" class="pf" id="f{2}" checked/><label for="f{2}">{3} {4}</label>\n' 3380 html_func_top = '<article id="{0}" class="atop" style="background-color:{1}">\n<input type="checkbox" class="pf" id="f{2}" checked/><label for="f{2}">{3} {4}</label>\n'
@@ -2428,22 +3387,29 @@ def createHTML(testruns):
2428 for devname in data.sortedDevices(p): 3387 for devname in data.sortedDevices(p):
2429 if('ftrace' not in list[devname]): 3388 if('ftrace' not in list[devname]):
2430 continue 3389 continue
2431 name = devname
2432 if(devname in sysvals.altdevname):
2433 name = sysvals.altdevname[devname]
2434 devid = list[devname]['id'] 3390 devid = list[devname]['id']
2435 cg = list[devname]['ftrace'] 3391 cg = list[devname]['ftrace']
2436 flen = '<r>(%.3f ms @ %.3f to %.3f)</r>' % \ 3392 clen = (cg.end - cg.start) * 1000
2437 ((cg.end - cg.start)*1000, cg.start*1000, cg.end*1000) 3393 if clen < sysvals.mincglen:
3394 continue
3395 fmt = '<r>(%.3f ms @ '+sysvals.timeformat+' to '+sysvals.timeformat+')</r>'
3396 flen = fmt % (clen, cg.start, cg.end)
3397 name = devname
3398 if(devname in sysvals.devprops):
3399 name = sysvals.devprops[devname].altName(devname)
3400 if sysvals.suspendmode == 'command':
3401 ftitle = name
3402 else:
3403 ftitle = name+' '+p
2438 hf.write(html_func_top.format(devid, data.dmesg[p]['color'], \ 3404 hf.write(html_func_top.format(devid, data.dmesg[p]['color'], \
2439 num, name+' '+p, flen)) 3405 num, ftitle, flen))
2440 num += 1 3406 num += 1
2441 for line in cg.list: 3407 for line in cg.list:
2442 if(line.length < 0.000000001): 3408 if(line.length < 0.000000001):
2443 flen = '' 3409 flen = ''
2444 else: 3410 else:
2445 flen = '<n>(%.3f ms @ %.3f)</n>' % (line.length*1000, \ 3411 fmt = '<n>(%.3f ms @ '+sysvals.timeformat+')</n>'
2446 line.time*1000) 3412 flen = fmt % (line.length*1000, line.time)
2447 if(line.freturn and line.fcall): 3413 if(line.freturn and line.fcall):
2448 hf.write(html_func_leaf.format(line.name, flen)) 3414 hf.write(html_func_leaf.format(line.name, flen))
2449 elif(line.freturn): 3415 elif(line.freturn):
@@ -2453,9 +3419,40 @@ def createHTML(testruns):
2453 num += 1 3419 num += 1
2454 hf.write(html_func_end) 3420 hf.write(html_func_end)
2455 hf.write('\n\n </section>\n') 3421 hf.write('\n\n </section>\n')
2456 # write the footer and close 3422
2457 addScriptCode(hf, testruns) 3423 # add the dmesg log as a hidden div
2458 hf.write('</body>\n</html>\n') 3424 if sysvals.addlogs and sysvals.dmesgfile:
3425 hf.write('<div id="dmesglog" style="display:none;">\n')
3426 lf = open(sysvals.dmesgfile, 'r')
3427 for line in lf:
3428 hf.write(line)
3429 lf.close()
3430 hf.write('</div>\n')
3431 # add the ftrace log as a hidden div
3432 if sysvals.addlogs and sysvals.ftracefile:
3433 hf.write('<div id="ftracelog" style="display:none;">\n')
3434 lf = open(sysvals.ftracefile, 'r')
3435 for line in lf:
3436 hf.write(line)
3437 lf.close()
3438 hf.write('</div>\n')
3439
3440 if(not sysvals.embedded):
3441 # write the footer and close
3442 addScriptCode(hf, testruns)
3443 hf.write('</body>\n</html>\n')
3444 else:
3445 # embedded out will be loaded in a page, skip the js
3446 t0 = (testruns[0].start - testruns[-1].tSuspended) * 1000
3447 tMax = (testruns[-1].end - testruns[-1].tSuspended) * 1000
3448 # add js code in a div entry for later evaluation
3449 detail = 'var bounds = [%f,%f];\n' % (t0, tMax)
3450 detail += 'var devtable = [\n'
3451 for data in testruns:
3452 topo = data.deviceTopology()
3453 detail += '\t"%s",\n' % (topo)
3454 detail += '];\n'
3455 hf.write('<div id=customcode style=display:none>\n'+detail+'</div>\n')
2459 hf.close() 3456 hf.close()
2460 return True 3457 return True
2461 3458
@@ -2466,8 +3463,8 @@ def createHTML(testruns):
2466# hf: the open html file pointer 3463# hf: the open html file pointer
2467# testruns: array of Data objects from parseKernelLog or parseTraceLog 3464# testruns: array of Data objects from parseKernelLog or parseTraceLog
2468def addScriptCode(hf, testruns): 3465def addScriptCode(hf, testruns):
2469 t0 = (testruns[0].start - testruns[-1].tSuspended) * 1000 3466 t0 = testruns[0].start * 1000
2470 tMax = (testruns[-1].end - testruns[-1].tSuspended) * 1000 3467 tMax = testruns[-1].end * 1000
2471 # create an array in javascript memory with the device details 3468 # create an array in javascript memory with the device details
2472 detail = ' var devtable = [];\n' 3469 detail = ' var devtable = [];\n'
2473 for data in testruns: 3470 for data in testruns:
@@ -2477,8 +3474,43 @@ def addScriptCode(hf, testruns):
2477 # add the code which will manipulate the data in the browser 3474 # add the code which will manipulate the data in the browser
2478 script_code = \ 3475 script_code = \
2479 '<script type="text/javascript">\n'+detail+\ 3476 '<script type="text/javascript">\n'+detail+\
3477 ' var resolution = -1;\n'\
3478 ' function redrawTimescale(t0, tMax, tS) {\n'\
3479 ' var rline = \'<div class="t" style="left:0;border-left:1px solid black;border-right:0;"><cR><-R</cR></div>\';\n'\
3480 ' var tTotal = tMax - t0;\n'\
3481 ' var list = document.getElementsByClassName("tblock");\n'\
3482 ' for (var i = 0; i < list.length; i++) {\n'\
3483 ' var timescale = list[i].getElementsByClassName("timescale")[0];\n'\
3484 ' var m0 = t0 + (tTotal*parseFloat(list[i].style.left)/100);\n'\
3485 ' var mTotal = tTotal*parseFloat(list[i].style.width)/100;\n'\
3486 ' var mMax = m0 + mTotal;\n'\
3487 ' var html = "";\n'\
3488 ' var divTotal = Math.floor(mTotal/tS) + 1;\n'\
3489 ' if(divTotal > 1000) continue;\n'\
3490 ' var divEdge = (mTotal - tS*(divTotal-1))*100/mTotal;\n'\
3491 ' var pos = 0.0, val = 0.0;\n'\
3492 ' for (var j = 0; j < divTotal; j++) {\n'\
3493 ' var htmlline = "";\n'\
3494 ' if(list[i].id[5] == "r") {\n'\
3495 ' pos = 100 - (((j)*tS*100)/mTotal);\n'\
3496 ' val = (j)*tS;\n'\
3497 ' htmlline = \'<div class="t" style="right:\'+pos+\'%">\'+val+\'ms</div>\';\n'\
3498 ' if(j == 0)\n'\
3499 ' htmlline = rline;\n'\
3500 ' } else {\n'\
3501 ' pos = 100 - (((j)*tS*100)/mTotal) - divEdge;\n'\
3502 ' val = (j-divTotal+1)*tS;\n'\
3503 ' if(j == divTotal - 1)\n'\
3504 ' htmlline = \'<div class="t" style="right:\'+pos+\'%"><cS>S-></cS></div>\';\n'\
3505 ' else\n'\
3506 ' htmlline = \'<div class="t" style="right:\'+pos+\'%">\'+val+\'ms</div>\';\n'\
3507 ' }\n'\
3508 ' html += htmlline;\n'\
3509 ' }\n'\
3510 ' timescale.innerHTML = html;\n'\
3511 ' }\n'\
3512 ' }\n'\
2480 ' function zoomTimeline() {\n'\ 3513 ' function zoomTimeline() {\n'\
2481 ' var timescale = document.getElementById("timescale");\n'\
2482 ' var dmesg = document.getElementById("dmesg");\n'\ 3514 ' var dmesg = document.getElementById("dmesg");\n'\
2483 ' var zoombox = document.getElementById("dmesgzoombox");\n'\ 3515 ' var zoombox = document.getElementById("dmesgzoombox");\n'\
2484 ' var val = parseFloat(dmesg.style.width);\n'\ 3516 ' var val = parseFloat(dmesg.style.width);\n'\
@@ -2486,7 +3518,7 @@ def addScriptCode(hf, testruns):
2486 ' var sh = window.outerWidth / 2;\n'\ 3518 ' var sh = window.outerWidth / 2;\n'\
2487 ' if(this.id == "zoomin") {\n'\ 3519 ' if(this.id == "zoomin") {\n'\
2488 ' newval = val * 1.2;\n'\ 3520 ' newval = val * 1.2;\n'\
2489 ' if(newval > 40000) newval = 40000;\n'\ 3521 ' if(newval > 910034) newval = 910034;\n'\
2490 ' dmesg.style.width = newval+"%";\n'\ 3522 ' dmesg.style.width = newval+"%";\n'\
2491 ' zoombox.scrollLeft = ((zoombox.scrollLeft + sh) * newval / val) - sh;\n'\ 3523 ' zoombox.scrollLeft = ((zoombox.scrollLeft + sh) * newval / val) - sh;\n'\
2492 ' } else if (this.id == "zoomout") {\n'\ 3524 ' } else if (this.id == "zoomout") {\n'\
@@ -2498,19 +3530,17 @@ def addScriptCode(hf, testruns):
2498 ' zoombox.scrollLeft = 0;\n'\ 3530 ' zoombox.scrollLeft = 0;\n'\
2499 ' dmesg.style.width = "100%";\n'\ 3531 ' dmesg.style.width = "100%";\n'\
2500 ' }\n'\ 3532 ' }\n'\
2501 ' var html = "";\n'\ 3533 ' var tS = [10000, 5000, 2000, 1000, 500, 200, 100, 50, 20, 10, 5, 2, 1];\n'\
2502 ' var t0 = bounds[0];\n'\ 3534 ' var t0 = bounds[0];\n'\
2503 ' var tMax = bounds[1];\n'\ 3535 ' var tMax = bounds[1];\n'\
2504 ' var tTotal = tMax - t0;\n'\ 3536 ' var tTotal = tMax - t0;\n'\
2505 ' var wTotal = tTotal * 100.0 / newval;\n'\ 3537 ' var wTotal = tTotal * 100.0 / newval;\n'\
2506 ' for(var tS = 1000; (wTotal / tS) < 3; tS /= 10);\n'\ 3538 ' var idx = 7*window.innerWidth/1100;\n'\
2507 ' if(tS < 1) tS = 1;\n'\ 3539 ' for(var i = 0; (i < tS.length)&&((wTotal / tS[i]) < idx); i++);\n'\
2508 ' for(var s = ((t0 / tS)|0) * tS; s < tMax; s += tS) {\n'\ 3540 ' if(i >= tS.length) i = tS.length - 1;\n'\
2509 ' var pos = (tMax - s) * 100.0 / tTotal;\n'\ 3541 ' if(tS[i] == resolution) return;\n'\
2510 ' var name = (s == 0)?"S/R":(s+"ms");\n'\ 3542 ' resolution = tS[i];\n'\
2511 ' html += "<div class=\\"t\\" style=\\"right:"+pos+"%\\">"+name+"</div>";\n'\ 3543 ' redrawTimescale(t0, tMax, tS[i]);\n'\
2512 ' }\n'\
2513 ' timescale.innerHTML = html;\n'\
2514 ' }\n'\ 3544 ' }\n'\
2515 ' function deviceHover() {\n'\ 3545 ' function deviceHover() {\n'\
2516 ' var name = this.title.slice(0, this.title.indexOf(" ("));\n'\ 3546 ' var name = this.title.slice(0, this.title.indexOf(" ("));\n'\
@@ -2523,12 +3553,13 @@ def addScriptCode(hf, testruns):
2523 ' cpu = parseInt(name.slice(8));\n'\ 3553 ' cpu = parseInt(name.slice(8));\n'\
2524 ' for (var i = 0; i < dev.length; i++) {\n'\ 3554 ' for (var i = 0; i < dev.length; i++) {\n'\
2525 ' dname = dev[i].title.slice(0, dev[i].title.indexOf(" ("));\n'\ 3555 ' dname = dev[i].title.slice(0, dev[i].title.indexOf(" ("));\n'\
3556 ' var cname = dev[i].className.slice(dev[i].className.indexOf("thread"));\n'\
2526 ' if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\ 3557 ' if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\
2527 ' (name == dname))\n'\ 3558 ' (name == dname))\n'\
2528 ' {\n'\ 3559 ' {\n'\
2529 ' dev[i].className = "thread hover";\n'\ 3560 ' dev[i].className = "hover "+cname;\n'\
2530 ' } else {\n'\ 3561 ' } else {\n'\
2531 ' dev[i].className = "thread";\n'\ 3562 ' dev[i].className = cname;\n'\
2532 ' }\n'\ 3563 ' }\n'\
2533 ' }\n'\ 3564 ' }\n'\
2534 ' }\n'\ 3565 ' }\n'\
@@ -2536,7 +3567,7 @@ def addScriptCode(hf, testruns):
2536 ' var dmesg = document.getElementById("dmesg");\n'\ 3567 ' var dmesg = document.getElementById("dmesg");\n'\
2537 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 3568 ' var dev = dmesg.getElementsByClassName("thread");\n'\
2538 ' for (var i = 0; i < dev.length; i++) {\n'\ 3569 ' for (var i = 0; i < dev.length; i++) {\n'\
2539 ' dev[i].className = "thread";\n'\ 3570 ' dev[i].className = dev[i].className.slice(dev[i].className.indexOf("thread"));\n'\
2540 ' }\n'\ 3571 ' }\n'\
2541 ' }\n'\ 3572 ' }\n'\
2542 ' function deviceTitle(title, total, cpu) {\n'\ 3573 ' function deviceTitle(title, total, cpu) {\n'\
@@ -2547,7 +3578,7 @@ def addScriptCode(hf, testruns):
2547 ' total[2] = (total[2]+total[4])/2;\n'\ 3578 ' total[2] = (total[2]+total[4])/2;\n'\
2548 ' }\n'\ 3579 ' }\n'\
2549 ' var devtitle = document.getElementById("devicedetailtitle");\n'\ 3580 ' var devtitle = document.getElementById("devicedetailtitle");\n'\
2550 ' var name = title.slice(0, title.indexOf(" "));\n'\ 3581 ' var name = title.slice(0, title.indexOf(" ("));\n'\
2551 ' if(cpu >= 0) name = "CPU"+cpu;\n'\ 3582 ' if(cpu >= 0) name = "CPU"+cpu;\n'\
2552 ' var driver = "";\n'\ 3583 ' var driver = "";\n'\
2553 ' var tS = "<t2>(</t2>";\n'\ 3584 ' var tS = "<t2>(</t2>";\n'\
@@ -2579,6 +3610,8 @@ def addScriptCode(hf, testruns):
2579 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 3610 ' var dev = dmesg.getElementsByClassName("thread");\n'\
2580 ' var idlist = [];\n'\ 3611 ' var idlist = [];\n'\
2581 ' var pdata = [[]];\n'\ 3612 ' var pdata = [[]];\n'\
3613 ' if(document.getElementById("devicedetail1"))\n'\
3614 ' pdata = [[], []];\n'\
2582 ' var pd = pdata[0];\n'\ 3615 ' var pd = pdata[0];\n'\
2583 ' var total = [0.0, 0.0, 0.0];\n'\ 3616 ' var total = [0.0, 0.0, 0.0];\n'\
2584 ' for (var i = 0; i < dev.length; i++) {\n'\ 3617 ' for (var i = 0; i < dev.length; i++) {\n'\
@@ -2634,6 +3667,7 @@ def addScriptCode(hf, testruns):
2634 ' var cglist = document.getElementById("callgraphs");\n'\ 3667 ' var cglist = document.getElementById("callgraphs");\n'\
2635 ' if(!cglist) return;\n'\ 3668 ' if(!cglist) return;\n'\
2636 ' var cg = cglist.getElementsByClassName("atop");\n'\ 3669 ' var cg = cglist.getElementsByClassName("atop");\n'\
3670 ' if(cg.length < 10) return;\n'\
2637 ' for (var i = 0; i < cg.length; i++) {\n'\ 3671 ' for (var i = 0; i < cg.length; i++) {\n'\
2638 ' if(idlist.indexOf(cg[i].id) >= 0) {\n'\ 3672 ' if(idlist.indexOf(cg[i].id) >= 0) {\n'\
2639 ' cg[i].style.display = "block";\n'\ 3673 ' cg[i].style.display = "block";\n'\
@@ -2658,15 +3692,32 @@ def addScriptCode(hf, testruns):
2658 ' dt = devtable[1];\n'\ 3692 ' dt = devtable[1];\n'\
2659 ' win.document.write(html+dt);\n'\ 3693 ' win.document.write(html+dt);\n'\
2660 ' }\n'\ 3694 ' }\n'\
3695 ' function logWindow(e) {\n'\
3696 ' var name = e.target.id.slice(4);\n'\
3697 ' var win = window.open();\n'\
3698 ' var log = document.getElementById(name+"log");\n'\
3699 ' var title = "<title>"+document.title.split(" ")[0]+" "+name+" log</title>";\n'\
3700 ' win.document.write(title+"<pre>"+log.innerHTML+"</pre>");\n'\
3701 ' win.document.close();\n'\
3702 ' }\n'\
3703 ' function onClickPhase(e) {\n'\
3704 ' }\n'\
3705 ' window.addEventListener("resize", function () {zoomTimeline();});\n'\
2661 ' window.addEventListener("load", function () {\n'\ 3706 ' window.addEventListener("load", function () {\n'\
2662 ' var dmesg = document.getElementById("dmesg");\n'\ 3707 ' var dmesg = document.getElementById("dmesg");\n'\
2663 ' dmesg.style.width = "100%"\n'\ 3708 ' dmesg.style.width = "100%"\n'\
2664 ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\ 3709 ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\
2665 ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\ 3710 ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\
2666 ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\ 3711 ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\
2667 ' var devlist = document.getElementsByClassName("devlist");\n'\ 3712 ' var list = document.getElementsByClassName("square");\n'\
2668 ' for (var i = 0; i < devlist.length; i++)\n'\ 3713 ' for (var i = 0; i < list.length; i++)\n'\
2669 ' devlist[i].onclick = devListWindow;\n'\ 3714 ' list[i].onclick = onClickPhase;\n'\
3715 ' var list = document.getElementsByClassName("logbtn");\n'\
3716 ' for (var i = 0; i < list.length; i++)\n'\
3717 ' list[i].onclick = logWindow;\n'\
3718 ' list = document.getElementsByClassName("devlist");\n'\
3719 ' for (var i = 0; i < list.length; i++)\n'\
3720 ' list[i].onclick = devListWindow;\n'\
2670 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 3721 ' var dev = dmesg.getElementsByClassName("thread");\n'\
2671 ' for (var i = 0; i < dev.length; i++) {\n'\ 3722 ' for (var i = 0; i < dev.length; i++) {\n'\
2672 ' dev[i].onclick = deviceDetail;\n'\ 3723 ' dev[i].onclick = deviceDetail;\n'\
@@ -2685,141 +3736,87 @@ def addScriptCode(hf, testruns):
2685def executeSuspend(): 3736def executeSuspend():
2686 global sysvals 3737 global sysvals
2687 3738
2688 detectUSB(False)
2689 t0 = time.time()*1000 3739 t0 = time.time()*1000
2690 tp = sysvals.tpath 3740 tp = sysvals.tpath
3741 fwdata = []
3742 # mark the start point in the kernel ring buffer just as we start
3743 sysvals.initdmesg()
3744 # start ftrace
3745 if(sysvals.usecallgraph or sysvals.usetraceevents):
3746 print('START TRACING')
3747 sysvals.fsetVal('1', 'tracing_on')
2691 # execute however many s/r runs requested 3748 # execute however many s/r runs requested
2692 for count in range(1,sysvals.execcount+1): 3749 for count in range(1,sysvals.execcount+1):
2693 # clear the kernel ring buffer just as we start
2694 os.system('dmesg -C')
2695 # enable callgraph ftrace only for the second run
2696 if(sysvals.usecallgraph and count == 2):
2697 # set trace type
2698 os.system('echo function_graph > '+tp+'current_tracer')
2699 os.system('echo "" > '+tp+'set_ftrace_filter')
2700 # set trace format options
2701 os.system('echo funcgraph-abstime > '+tp+'trace_options')
2702 os.system('echo funcgraph-proc > '+tp+'trace_options')
2703 # focus only on device suspend and resume
2704 os.system('cat '+tp+'available_filter_functions | '+\
2705 'grep dpm_run_callback > '+tp+'set_graph_function')
2706 # if this is test2 and there's a delay, start here 3750 # if this is test2 and there's a delay, start here
2707 if(count > 1 and sysvals.x2delay > 0): 3751 if(count > 1 and sysvals.x2delay > 0):
2708 tN = time.time()*1000 3752 tN = time.time()*1000
2709 while (tN - t0) < sysvals.x2delay: 3753 while (tN - t0) < sysvals.x2delay:
2710 tN = time.time()*1000 3754 tN = time.time()*1000
2711 time.sleep(0.001) 3755 time.sleep(0.001)
2712 # start ftrace
2713 if(sysvals.usecallgraph or sysvals.usetraceevents):
2714 print('START TRACING')
2715 os.system('echo 1 > '+tp+'tracing_on')
2716 # initiate suspend 3756 # initiate suspend
2717 if(sysvals.usecallgraph or sysvals.usetraceevents): 3757 if(sysvals.usecallgraph or sysvals.usetraceevents):
2718 os.system('echo SUSPEND START > '+tp+'trace_marker') 3758 sysvals.fsetVal('SUSPEND START', 'trace_marker')
2719 if(sysvals.rtcwake): 3759 if sysvals.suspendmode == 'command':
2720 print('SUSPEND START') 3760 print('COMMAND START')
2721 print('will autoresume in %d seconds' % sysvals.rtcwaketime) 3761 if(sysvals.rtcwake):
2722 sysvals.rtcWakeAlarm() 3762 print('will issue an rtcwake in %d seconds' % sysvals.rtcwaketime)
3763 sysvals.rtcWakeAlarmOn()
3764 os.system(sysvals.testcommand)
2723 else: 3765 else:
2724 print('SUSPEND START (press a key to resume)') 3766 if(sysvals.rtcwake):
2725 pf = open(sysvals.powerfile, 'w') 3767 print('SUSPEND START')
2726 pf.write(sysvals.suspendmode) 3768 print('will autoresume in %d seconds' % sysvals.rtcwaketime)
2727 # execution will pause here 3769 sysvals.rtcWakeAlarmOn()
2728 pf.close() 3770 else:
3771 print('SUSPEND START (press a key to resume)')
3772 pf = open(sysvals.powerfile, 'w')
3773 pf.write(sysvals.suspendmode)
3774 # execution will pause here
3775 try:
3776 pf.close()
3777 except:
3778 pass
2729 t0 = time.time()*1000 3779 t0 = time.time()*1000
3780 if(sysvals.rtcwake):
3781 sysvals.rtcWakeAlarmOff()
2730 # return from suspend 3782 # return from suspend
2731 print('RESUME COMPLETE') 3783 print('RESUME COMPLETE')
2732 if(sysvals.usecallgraph or sysvals.usetraceevents): 3784 if(sysvals.usecallgraph or sysvals.usetraceevents):
2733 os.system('echo RESUME COMPLETE > '+tp+'trace_marker') 3785 sysvals.fsetVal('RESUME COMPLETE', 'trace_marker')
2734 # see if there's firmware timing data to be had 3786 if(sysvals.suspendmode == 'mem'):
2735 t = sysvals.postresumetime 3787 fwdata.append(getFPDT(False))
2736 if(t > 0): 3788 # look for post resume events after the last test run
2737 print('Waiting %d seconds for POST-RESUME trace events...' % t) 3789 t = sysvals.postresumetime
2738 time.sleep(t) 3790 if(t > 0):
2739 # stop ftrace 3791 print('Waiting %d seconds for POST-RESUME trace events...' % t)
2740 if(sysvals.usecallgraph or sysvals.usetraceevents): 3792 time.sleep(t)
2741 os.system('echo 0 > '+tp+'tracing_on') 3793 # stop ftrace
2742 print('CAPTURING TRACE') 3794 if(sysvals.usecallgraph or sysvals.usetraceevents):
2743 writeDatafileHeader(sysvals.ftracefile) 3795 sysvals.fsetVal('0', 'tracing_on')
2744 os.system('cat '+tp+'trace >> '+sysvals.ftracefile) 3796 print('CAPTURING TRACE')
2745 os.system('echo "" > '+tp+'trace') 3797 writeDatafileHeader(sysvals.ftracefile, fwdata)
2746 # grab a copy of the dmesg output 3798 os.system('cat '+tp+'trace >> '+sysvals.ftracefile)
2747 print('CAPTURING DMESG') 3799 sysvals.fsetVal('', 'trace')
2748 writeDatafileHeader(sysvals.dmesgfile) 3800 devProps()
2749 os.system('dmesg -c >> '+sysvals.dmesgfile) 3801 # grab a copy of the dmesg output
2750 3802 print('CAPTURING DMESG')
2751def writeDatafileHeader(filename): 3803 writeDatafileHeader(sysvals.dmesgfile, fwdata)
3804 sysvals.getdmesg()
3805
3806def writeDatafileHeader(filename, fwdata):
2752 global sysvals 3807 global sysvals
2753 3808
2754 fw = getFPDT(False)
2755 prt = sysvals.postresumetime 3809 prt = sysvals.postresumetime
2756 fp = open(filename, 'a') 3810 fp = open(filename, 'a')
2757 fp.write(sysvals.teststamp+'\n') 3811 fp.write(sysvals.teststamp+'\n')
2758 if(fw): 3812 if(sysvals.suspendmode == 'mem'):
2759 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1])) 3813 for fw in fwdata:
3814 if(fw):
3815 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1]))
2760 if(prt > 0): 3816 if(prt > 0):
2761 fp.write('# post resume time %u\n' % prt) 3817 fp.write('# post resume time %u\n' % prt)
2762 fp.close() 3818 fp.close()
2763 3819
2764# Function: executeAndroidSuspend
2765# Description:
2766# Execute system suspend through the sysfs interface
2767# on a remote android device, then transfer the output
2768# dmesg and ftrace files to the local output directory.
2769def executeAndroidSuspend():
2770 global sysvals
2771
2772 # check to see if the display is currently off
2773 tp = sysvals.tpath
2774 out = os.popen(sysvals.adb+\
2775 ' shell dumpsys power | grep mScreenOn').read().strip()
2776 # if so we need to turn it on so we can issue a new suspend
2777 if(out.endswith('false')):
2778 print('Waking the device up for the test...')
2779 # send the KEYPAD_POWER keyevent to wake it up
2780 os.system(sysvals.adb+' shell input keyevent 26')
2781 # wait a few seconds so the user can see the device wake up
2782 time.sleep(3)
2783 # execute however many s/r runs requested
2784 for count in range(1,sysvals.execcount+1):
2785 # clear the kernel ring buffer just as we start
2786 os.system(sysvals.adb+' shell dmesg -c > /dev/null 2>&1')
2787 # start ftrace
2788 if(sysvals.usetraceevents):
2789 print('START TRACING')
2790 os.system(sysvals.adb+" shell 'echo 1 > "+tp+"tracing_on'")
2791 # initiate suspend
2792 for count in range(1,sysvals.execcount+1):
2793 if(sysvals.usetraceevents):
2794 os.system(sysvals.adb+\
2795 " shell 'echo SUSPEND START > "+tp+"trace_marker'")
2796 print('SUSPEND START (press a key on the device to resume)')
2797 os.system(sysvals.adb+" shell 'echo "+sysvals.suspendmode+\
2798 " > "+sysvals.powerfile+"'")
2799 # execution will pause here, then adb will exit
2800 while(True):
2801 check = os.popen(sysvals.adb+\
2802 ' shell pwd 2>/dev/null').read().strip()
2803 if(len(check) > 0):
2804 break
2805 time.sleep(1)
2806 if(sysvals.usetraceevents):
2807 os.system(sysvals.adb+" shell 'echo RESUME COMPLETE > "+tp+\
2808 "trace_marker'")
2809 # return from suspend
2810 print('RESUME COMPLETE')
2811 # stop ftrace
2812 if(sysvals.usetraceevents):
2813 os.system(sysvals.adb+" shell 'echo 0 > "+tp+"tracing_on'")
2814 print('CAPTURING TRACE')
2815 os.system('echo "'+sysvals.teststamp+'" > '+sysvals.ftracefile)
2816 os.system(sysvals.adb+' shell cat '+tp+\
2817 'trace >> '+sysvals.ftracefile)
2818 # grab a copy of the dmesg output
2819 print('CAPTURING DMESG')
2820 os.system('echo "'+sysvals.teststamp+'" > '+sysvals.dmesgfile)
2821 os.system(sysvals.adb+' shell dmesg >> '+sysvals.dmesgfile)
2822
2823# Function: setUSBDevicesAuto 3820# Function: setUSBDevicesAuto
2824# Description: 3821# Description:
2825# Set the autosuspend control parameter of all USB devices to auto 3822# Set the autosuspend control parameter of all USB devices to auto
@@ -2829,7 +3826,7 @@ def executeAndroidSuspend():
2829def setUSBDevicesAuto(): 3826def setUSBDevicesAuto():
2830 global sysvals 3827 global sysvals
2831 3828
2832 rootCheck() 3829 rootCheck(True)
2833 for dirname, dirnames, filenames in os.walk('/sys/devices'): 3830 for dirname, dirnames, filenames in os.walk('/sys/devices'):
2834 if(re.match('.*/usb[0-9]*.*', dirname) and 3831 if(re.match('.*/usb[0-9]*.*', dirname) and
2835 'idVendor' in filenames and 'idProduct' in filenames): 3832 'idVendor' in filenames and 'idProduct' in filenames):
@@ -2874,9 +3871,7 @@ def ms2nice(val):
2874# Description: 3871# Description:
2875# Detect all the USB hosts and devices currently connected and add 3872# Detect all the USB hosts and devices currently connected and add
2876# a list of USB device names to sysvals for better timeline readability 3873# a list of USB device names to sysvals for better timeline readability
2877# Arguments: 3874def detectUSB():
2878# output: True to output the info to stdout, False otherwise
2879def detectUSB(output):
2880 global sysvals 3875 global sysvals
2881 3876
2882 field = {'idVendor':'', 'idProduct':'', 'product':'', 'speed':''} 3877 field = {'idVendor':'', 'idProduct':'', 'product':'', 'speed':''}
@@ -2887,18 +3882,18 @@ def detectUSB(output):
2887 'runtime_suspended_time':'', 3882 'runtime_suspended_time':'',
2888 'active_duration':'', 3883 'active_duration':'',
2889 'connected_duration':''} 3884 'connected_duration':''}
2890 if(output): 3885
2891 print('LEGEND') 3886 print('LEGEND')
2892 print('---------------------------------------------------------------------------------------------') 3887 print('---------------------------------------------------------------------------------------------')
2893 print(' A = async/sync PM queue Y/N D = autosuspend delay (seconds)') 3888 print(' A = async/sync PM queue Y/N D = autosuspend delay (seconds)')
2894 print(' S = autosuspend Y/N rACTIVE = runtime active (min/sec)') 3889 print(' S = autosuspend Y/N rACTIVE = runtime active (min/sec)')
2895 print(' P = persist across suspend Y/N rSUSPEN = runtime suspend (min/sec)') 3890 print(' P = persist across suspend Y/N rSUSPEN = runtime suspend (min/sec)')
2896 print(' E = runtime suspend enabled/forbidden Y/N ACTIVE = active duration (min/sec)') 3891 print(' E = runtime suspend enabled/forbidden Y/N ACTIVE = active duration (min/sec)')
2897 print(' R = runtime status active/suspended Y/N CONNECT = connected duration (min/sec)') 3892 print(' R = runtime status active/suspended Y/N CONNECT = connected duration (min/sec)')
2898 print(' U = runtime usage count') 3893 print(' U = runtime usage count')
2899 print('---------------------------------------------------------------------------------------------') 3894 print('---------------------------------------------------------------------------------------------')
2900 print(' NAME ID DESCRIPTION SPEED A S P E R U D rACTIVE rSUSPEN ACTIVE CONNECT') 3895 print(' NAME ID DESCRIPTION SPEED A S P E R U D rACTIVE rSUSPEN ACTIVE CONNECT')
2901 print('---------------------------------------------------------------------------------------------') 3896 print('---------------------------------------------------------------------------------------------')
2902 3897
2903 for dirname, dirnames, filenames in os.walk('/sys/devices'): 3898 for dirname, dirnames, filenames in os.walk('/sys/devices'):
2904 if(re.match('.*/usb[0-9]*.*', dirname) and 3899 if(re.match('.*/usb[0-9]*.*', dirname) and
@@ -2907,35 +3902,149 @@ def detectUSB(output):
2907 field[i] = os.popen('cat %s/%s 2>/dev/null' % \ 3902 field[i] = os.popen('cat %s/%s 2>/dev/null' % \
2908 (dirname, i)).read().replace('\n', '') 3903 (dirname, i)).read().replace('\n', '')
2909 name = dirname.split('/')[-1] 3904 name = dirname.split('/')[-1]
2910 if(len(field['product']) > 0): 3905 for i in power:
2911 sysvals.altdevname[name] = \ 3906 power[i] = os.popen('cat %s/power/%s 2>/dev/null' % \
2912 '%s [%s]' % (field['product'], name) 3907 (dirname, i)).read().replace('\n', '')
3908 if(re.match('usb[0-9]*', name)):
3909 first = '%-8s' % name
2913 else: 3910 else:
2914 sysvals.altdevname[name] = \ 3911 first = '%8s' % name
2915 '%s:%s [%s]' % (field['idVendor'], \ 3912 print('%s [%s:%s] %-20s %-4s %1s %1s %1s %1s %1s %1s %1s %s %s %s %s' % \
2916 field['idProduct'], name) 3913 (first, field['idVendor'], field['idProduct'], \
2917 if(output): 3914 field['product'][0:20], field['speed'], \
2918 for i in power: 3915 yesno(power['async']), \
2919 power[i] = os.popen('cat %s/power/%s 2>/dev/null' % \ 3916 yesno(power['control']), \
2920 (dirname, i)).read().replace('\n', '') 3917 yesno(power['persist']), \
2921 if(re.match('usb[0-9]*', name)): 3918 yesno(power['runtime_enabled']), \
2922 first = '%-8s' % name 3919 yesno(power['runtime_status']), \
2923 else: 3920 power['runtime_usage'], \
2924 first = '%8s' % name 3921 power['autosuspend'], \
2925 print('%s [%s:%s] %-20s %-4s %1s %1s %1s %1s %1s %1s %1s %s %s %s %s' % \ 3922 ms2nice(power['runtime_active_time']), \
2926 (first, field['idVendor'], field['idProduct'], \ 3923 ms2nice(power['runtime_suspended_time']), \
2927 field['product'][0:20], field['speed'], \ 3924 ms2nice(power['active_duration']), \
2928 yesno(power['async']), \ 3925 ms2nice(power['connected_duration'])))
2929 yesno(power['control']), \ 3926
2930 yesno(power['persist']), \ 3927# Function: devProps
2931 yesno(power['runtime_enabled']), \ 3928# Description:
2932 yesno(power['runtime_status']), \ 3929# Retrieve a list of properties for all devices in the trace log
2933 power['runtime_usage'], \ 3930def devProps(data=0):
2934 power['autosuspend'], \ 3931 global sysvals
2935 ms2nice(power['runtime_active_time']), \ 3932 props = dict()
2936 ms2nice(power['runtime_suspended_time']), \ 3933
2937 ms2nice(power['active_duration']), \ 3934 if data:
2938 ms2nice(power['connected_duration']))) 3935 idx = data.index(': ') + 2
3936 if idx >= len(data):
3937 return
3938 devlist = data[idx:].split(';')
3939 for dev in devlist:
3940 f = dev.split(',')
3941 if len(f) < 3:
3942 continue
3943 dev = f[0]
3944 props[dev] = DevProps()
3945 props[dev].altname = f[1]
3946 if int(f[2]):
3947 props[dev].async = True
3948 else:
3949 props[dev].async = False
3950 sysvals.devprops = props
3951 if sysvals.suspendmode == 'command' and 'testcommandstring' in props:
3952 sysvals.testcommand = props['testcommandstring'].altname
3953 return
3954
3955 if(os.path.exists(sysvals.ftracefile) == False):
3956 doError('%s does not exist' % sysvals.ftracefile, False)
3957
3958 # first get the list of devices we need properties for
3959 msghead = 'Additional data added by AnalyzeSuspend'
3960 alreadystamped = False
3961 tp = TestProps()
3962 tf = open(sysvals.ftracefile, 'r')
3963 for line in tf:
3964 if msghead in line:
3965 alreadystamped = True
3966 continue
3967 # determine the trace data type (required for further parsing)
3968 m = re.match(sysvals.tracertypefmt, line)
3969 if(m):
3970 tp.setTracerType(m.group('t'))
3971 continue
3972 # parse only valid lines, if this is not one move on
3973 m = re.match(tp.ftrace_line_fmt, line)
3974 if(not m or 'device_pm_callback_start' not in line):
3975 continue
3976 m = re.match('.*: (?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*', m.group('msg'));
3977 if(not m):
3978 continue
3979 drv, dev, par = m.group('drv'), m.group('d'), m.group('p')
3980 if dev not in props:
3981 props[dev] = DevProps()
3982 tf.close()
3983
3984 if not alreadystamped and sysvals.suspendmode == 'command':
3985 out = '#\n# '+msghead+'\n# Device Properties: '
3986 out += 'testcommandstring,%s,0;' % (sysvals.testcommand)
3987 with open(sysvals.ftracefile, 'a') as fp:
3988 fp.write(out+'\n')
3989 sysvals.devprops = props
3990 return
3991
3992 # now get the syspath for each of our target devices
3993 for dirname, dirnames, filenames in os.walk('/sys/devices'):
3994 if(re.match('.*/power', dirname) and 'async' in filenames):
3995 dev = dirname.split('/')[-2]
3996 if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)):
3997 props[dev].syspath = dirname[:-6]
3998
3999 # now fill in the properties for our target devices
4000 for dev in props:
4001 dirname = props[dev].syspath
4002 if not dirname or not os.path.exists(dirname):
4003 continue
4004 with open(dirname+'/power/async') as fp:
4005 text = fp.read()
4006 props[dev].async = False
4007 if 'enabled' in text:
4008 props[dev].async = True
4009 fields = os.listdir(dirname)
4010 if 'product' in fields:
4011 with open(dirname+'/product') as fp:
4012 props[dev].altname = fp.read()
4013 elif 'name' in fields:
4014 with open(dirname+'/name') as fp:
4015 props[dev].altname = fp.read()
4016 elif 'model' in fields:
4017 with open(dirname+'/model') as fp:
4018 props[dev].altname = fp.read()
4019 elif 'description' in fields:
4020 with open(dirname+'/description') as fp:
4021 props[dev].altname = fp.read()
4022 elif 'id' in fields:
4023 with open(dirname+'/id') as fp:
4024 props[dev].altname = fp.read()
4025 elif 'idVendor' in fields and 'idProduct' in fields:
4026 idv, idp = '', ''
4027 with open(dirname+'/idVendor') as fp:
4028 idv = fp.read().strip()
4029 with open(dirname+'/idProduct') as fp:
4030 idp = fp.read().strip()
4031 props[dev].altname = '%s:%s' % (idv, idp)
4032
4033 if props[dev].altname:
4034 out = props[dev].altname.strip().replace('\n', ' ')
4035 out = out.replace(',', ' ')
4036 out = out.replace(';', ' ')
4037 props[dev].altname = out
4038
4039 # and now write the data to the ftrace file
4040 if not alreadystamped:
4041 out = '#\n# '+msghead+'\n# Device Properties: '
4042 for dev in sorted(props):
4043 out += props[dev].out(dev)
4044 with open(sysvals.ftracefile, 'a') as fp:
4045 fp.write(out+'\n')
4046
4047 sysvals.devprops = props
2939 4048
2940# Function: getModes 4049# Function: getModes
2941# Description: 4050# Description:
@@ -2945,15 +4054,10 @@ def detectUSB(output):
2945def getModes(): 4054def getModes():
2946 global sysvals 4055 global sysvals
2947 modes = '' 4056 modes = ''
2948 if(not sysvals.android): 4057 if(os.path.exists(sysvals.powerfile)):
2949 if(os.path.exists(sysvals.powerfile)): 4058 fp = open(sysvals.powerfile, 'r')
2950 fp = open(sysvals.powerfile, 'r') 4059 modes = string.split(fp.read())
2951 modes = string.split(fp.read()) 4060 fp.close()
2952 fp.close()
2953 else:
2954 line = os.popen(sysvals.adb+' shell cat '+\
2955 sysvals.powerfile).read().strip()
2956 modes = string.split(line)
2957 return modes 4061 return modes
2958 4062
2959# Function: getFPDT 4063# Function: getFPDT
@@ -2971,22 +4075,22 @@ def getFPDT(output):
2971 prectype[0] = 'Basic S3 Resume Performance Record' 4075 prectype[0] = 'Basic S3 Resume Performance Record'
2972 prectype[1] = 'Basic S3 Suspend Performance Record' 4076 prectype[1] = 'Basic S3 Suspend Performance Record'
2973 4077
2974 rootCheck() 4078 rootCheck(True)
2975 if(not os.path.exists(sysvals.fpdtpath)): 4079 if(not os.path.exists(sysvals.fpdtpath)):
2976 if(output): 4080 if(output):
2977 doError('file doesnt exist: %s' % sysvals.fpdtpath, False) 4081 doError('file does not exist: %s' % sysvals.fpdtpath, False)
2978 return False 4082 return False
2979 if(not os.access(sysvals.fpdtpath, os.R_OK)): 4083 if(not os.access(sysvals.fpdtpath, os.R_OK)):
2980 if(output): 4084 if(output):
2981 doError('file isnt readable: %s' % sysvals.fpdtpath, False) 4085 doError('file is not readable: %s' % sysvals.fpdtpath, False)
2982 return False 4086 return False
2983 if(not os.path.exists(sysvals.mempath)): 4087 if(not os.path.exists(sysvals.mempath)):
2984 if(output): 4088 if(output):
2985 doError('file doesnt exist: %s' % sysvals.mempath, False) 4089 doError('file does not exist: %s' % sysvals.mempath, False)
2986 return False 4090 return False
2987 if(not os.access(sysvals.mempath, os.R_OK)): 4091 if(not os.access(sysvals.mempath, os.R_OK)):
2988 if(output): 4092 if(output):
2989 doError('file isnt readable: %s' % sysvals.mempath, False) 4093 doError('file is not readable: %s' % sysvals.mempath, False)
2990 return False 4094 return False
2991 4095
2992 fp = open(sysvals.fpdtpath, 'rb') 4096 fp = open(sysvals.fpdtpath, 'rb')
@@ -3027,15 +4131,19 @@ def getFPDT(output):
3027 while(i < len(records)): 4131 while(i < len(records)):
3028 header = struct.unpack('HBB', records[i:i+4]) 4132 header = struct.unpack('HBB', records[i:i+4])
3029 if(header[0] not in rectype): 4133 if(header[0] not in rectype):
4134 i += header[1]
3030 continue 4135 continue
3031 if(header[1] != 16): 4136 if(header[1] != 16):
4137 i += header[1]
3032 continue 4138 continue
3033 addr = struct.unpack('Q', records[i+8:i+16])[0] 4139 addr = struct.unpack('Q', records[i+8:i+16])[0]
3034 try: 4140 try:
3035 fp.seek(addr) 4141 fp.seek(addr)
3036 first = fp.read(8) 4142 first = fp.read(8)
3037 except: 4143 except:
3038 doError('Bad address 0x%x in %s' % (addr, sysvals.mempath), False) 4144 if(output):
4145 print('Bad address 0x%x in %s' % (addr, sysvals.mempath))
4146 return [0, 0]
3039 rechead = struct.unpack('4sI', first) 4147 rechead = struct.unpack('4sI', first)
3040 recdata = fp.read(rechead[1]-8) 4148 recdata = fp.read(rechead[1]-8)
3041 if(rechead[0] == 'FBPT'): 4149 if(rechead[0] == 'FBPT'):
@@ -3090,89 +4198,60 @@ def getFPDT(output):
3090# print the results to the terminal 4198# print the results to the terminal
3091# Output: 4199# Output:
3092# True if the test will work, False if not 4200# True if the test will work, False if not
3093def statusCheck(): 4201def statusCheck(probecheck=False):
3094 global sysvals 4202 global sysvals
3095 status = True 4203 status = True
3096 4204
3097 if(sysvals.android): 4205 print('Checking this system (%s)...' % platform.node())
3098 print('Checking the android system ...')
3099 else:
3100 print('Checking this system (%s)...' % platform.node())
3101
3102 # check if adb is connected to a device
3103 if(sysvals.android):
3104 res = 'NO'
3105 out = os.popen(sysvals.adb+' get-state').read().strip()
3106 if(out == 'device'):
3107 res = 'YES'
3108 print(' is android device connected: %s' % res)
3109 if(res != 'YES'):
3110 print(' Please connect the device before using this tool')
3111 return False
3112 4206
3113 # check we have root access 4207 # check we have root access
3114 res = 'NO (No features of this tool will work!)' 4208 res = sysvals.colorText('NO (No features of this tool will work!)')
3115 if(sysvals.android): 4209 if(rootCheck(False)):
3116 out = os.popen(sysvals.adb+' shell id').read().strip() 4210 res = 'YES'
3117 if('root' in out):
3118 res = 'YES'
3119 else:
3120 if(os.environ['USER'] == 'root'):
3121 res = 'YES'
3122 print(' have root access: %s' % res) 4211 print(' have root access: %s' % res)
3123 if(res != 'YES'): 4212 if(res != 'YES'):
3124 if(sysvals.android): 4213 print(' Try running this script with sudo')
3125 print(' Try running "adb root" to restart the daemon as root')
3126 else:
3127 print(' Try running this script with sudo')
3128 return False 4214 return False
3129 4215
3130 # check sysfs is mounted 4216 # check sysfs is mounted
3131 res = 'NO (No features of this tool will work!)' 4217 res = sysvals.colorText('NO (No features of this tool will work!)')
3132 if(sysvals.android): 4218 if(os.path.exists(sysvals.powerfile)):
3133 out = os.popen(sysvals.adb+' shell ls '+\ 4219 res = 'YES'
3134 sysvals.powerfile).read().strip()
3135 if(out == sysvals.powerfile):
3136 res = 'YES'
3137 else:
3138 if(os.path.exists(sysvals.powerfile)):
3139 res = 'YES'
3140 print(' is sysfs mounted: %s' % res) 4220 print(' is sysfs mounted: %s' % res)
3141 if(res != 'YES'): 4221 if(res != 'YES'):
3142 return False 4222 return False
3143 4223
3144 # check target mode is a valid mode 4224 # check target mode is a valid mode
3145 res = 'NO' 4225 if sysvals.suspendmode != 'command':
3146 modes = getModes() 4226 res = sysvals.colorText('NO')
3147 if(sysvals.suspendmode in modes): 4227 modes = getModes()
3148 res = 'YES' 4228 if(sysvals.suspendmode in modes):
3149 else: 4229 res = 'YES'
3150 status = False 4230 else:
3151 print(' is "%s" a valid power mode: %s' % (sysvals.suspendmode, res)) 4231 status = False
3152 if(res == 'NO'): 4232 print(' is "%s" a valid power mode: %s' % (sysvals.suspendmode, res))
3153 print(' valid power modes are: %s' % modes) 4233 if(res == 'NO'):
3154 print(' please choose one with -m') 4234 print(' valid power modes are: %s' % modes)
3155 4235 print(' please choose one with -m')
3156 # check if the tool can unlock the device
3157 if(sysvals.android):
3158 res = 'YES'
3159 out1 = os.popen(sysvals.adb+\
3160 ' shell dumpsys power | grep mScreenOn').read().strip()
3161 out2 = os.popen(sysvals.adb+\
3162 ' shell input').read().strip()
3163 if(not out1.startswith('mScreenOn') or not out2.startswith('usage')):
3164 res = 'NO (wake the android device up before running the test)'
3165 print(' can I unlock the screen: %s' % res)
3166 4236
3167 # check if ftrace is available 4237 # check if ftrace is available
3168 res = 'NO' 4238 res = sysvals.colorText('NO')
3169 ftgood = verifyFtrace() 4239 ftgood = sysvals.verifyFtrace()
3170 if(ftgood): 4240 if(ftgood):
3171 res = 'YES' 4241 res = 'YES'
3172 elif(sysvals.usecallgraph): 4242 elif(sysvals.usecallgraph):
3173 status = False 4243 status = False
3174 print(' is ftrace supported: %s' % res) 4244 print(' is ftrace supported: %s' % res)
3175 4245
4246 # check if kprobes are available
4247 res = sysvals.colorText('NO')
4248 sysvals.usekprobes = sysvals.verifyKprobes()
4249 if(sysvals.usekprobes):
4250 res = 'YES'
4251 else:
4252 sysvals.usedevsrc = False
4253 print(' are kprobes supported: %s' % res)
4254
3176 # what data source are we using 4255 # what data source are we using
3177 res = 'DMESG' 4256 res = 'DMESG'
3178 if(ftgood): 4257 if(ftgood):
@@ -3180,14 +4259,8 @@ def statusCheck():
3180 sysvals.usetraceevents = False 4259 sysvals.usetraceevents = False
3181 for e in sysvals.traceevents: 4260 for e in sysvals.traceevents:
3182 check = False 4261 check = False
3183 if(sysvals.android): 4262 if(os.path.exists(sysvals.epath+e)):
3184 out = os.popen(sysvals.adb+' shell ls -d '+\ 4263 check = True
3185 sysvals.epath+e).read().strip()
3186 if(out == sysvals.epath+e):
3187 check = True
3188 else:
3189 if(os.path.exists(sysvals.epath+e)):
3190 check = True
3191 if(not check): 4264 if(not check):
3192 sysvals.usetraceeventsonly = False 4265 sysvals.usetraceeventsonly = False
3193 if(e == 'suspend_resume' and check): 4266 if(e == 'suspend_resume' and check):
@@ -3199,13 +4272,48 @@ def statusCheck():
3199 print(' timeline data source: %s' % res) 4272 print(' timeline data source: %s' % res)
3200 4273
3201 # check if rtcwake 4274 # check if rtcwake
3202 res = 'NO' 4275 res = sysvals.colorText('NO')
3203 if(sysvals.rtcpath != ''): 4276 if(sysvals.rtcpath != ''):
3204 res = 'YES' 4277 res = 'YES'
3205 elif(sysvals.rtcwake): 4278 elif(sysvals.rtcwake):
3206 status = False 4279 status = False
3207 print(' is rtcwake supported: %s' % res) 4280 print(' is rtcwake supported: %s' % res)
3208 4281
4282 if not probecheck:
4283 return status
4284
4285 if (sysvals.usecallgraph and len(sysvals.debugfuncs) > 0) or len(sysvals.kprobes) > 0:
4286 sysvals.initFtrace(True)
4287
4288 # verify callgraph debugfuncs
4289 if sysvals.usecallgraph and len(sysvals.debugfuncs) > 0:
4290 print(' verifying these ftrace callgraph functions work:')
4291 sysvals.setFtraceFilterFunctions(sysvals.debugfuncs)
4292 fp = open(sysvals.tpath+'set_graph_function', 'r')
4293 flist = fp.read().split('\n')
4294 fp.close()
4295 for func in sysvals.debugfuncs:
4296 res = sysvals.colorText('NO')
4297 if func in flist:
4298 res = 'YES'
4299 else:
4300 for i in flist:
4301 if ' [' in i and func == i.split(' ')[0]:
4302 res = 'YES'
4303 break
4304 print(' %s: %s' % (func, res))
4305
4306 # verify kprobes
4307 if len(sysvals.kprobes) > 0:
4308 print(' verifying these kprobes work:')
4309 for name in sorted(sysvals.kprobes):
4310 if name in sysvals.tracefuncs:
4311 continue
4312 res = sysvals.colorText('NO')
4313 if sysvals.testKprobe(sysvals.kprobes[name]):
4314 res = 'YES'
4315 print(' %s: %s' % (name, res))
4316
3209 return status 4317 return status
3210 4318
3211# Function: doError 4319# Function: doError
@@ -3226,7 +4334,7 @@ def doError(msg, help):
3226# Arguments: 4334# Arguments:
3227# msg: the warning message to print 4335# msg: the warning message to print
3228# file: If not empty, a filename to request be sent to the owner for debug 4336# file: If not empty, a filename to request be sent to the owner for debug
3229def doWarning(msg, file): 4337def doWarning(msg, file=''):
3230 print('/* %s */') % msg 4338 print('/* %s */') % msg
3231 if(file): 4339 if(file):
3232 print('/* For a fix, please send this'+\ 4340 print('/* For a fix, please send this'+\
@@ -3235,18 +4343,25 @@ def doWarning(msg, file):
3235# Function: rootCheck 4343# Function: rootCheck
3236# Description: 4344# Description:
3237# quick check to see if we have root access 4345# quick check to see if we have root access
3238def rootCheck(): 4346def rootCheck(fatal):
3239 if(os.environ['USER'] != 'root'): 4347 global sysvals
3240 doError('This script must be run as root', False) 4348 if(os.access(sysvals.powerfile, os.W_OK)):
4349 return True
4350 if fatal:
4351 doError('This command must be run as root', False)
4352 return False
3241 4353
3242# Function: getArgInt 4354# Function: getArgInt
3243# Description: 4355# Description:
3244# pull out an integer argument from the command line with checks 4356# pull out an integer argument from the command line with checks
3245def getArgInt(name, args, min, max): 4357def getArgInt(name, args, min, max, main=True):
3246 try: 4358 if main:
3247 arg = args.next() 4359 try:
3248 except: 4360 arg = args.next()
3249 doError(name+': no argument supplied', True) 4361 except:
4362 doError(name+': no argument supplied', True)
4363 else:
4364 arg = args
3250 try: 4365 try:
3251 val = int(arg) 4366 val = int(arg)
3252 except: 4367 except:
@@ -3255,6 +4370,25 @@ def getArgInt(name, args, min, max):
3255 doError(name+': value should be between %d and %d' % (min, max), True) 4370 doError(name+': value should be between %d and %d' % (min, max), True)
3256 return val 4371 return val
3257 4372
4373# Function: getArgFloat
4374# Description:
4375# pull out a float argument from the command line with checks
4376def getArgFloat(name, args, min, max, main=True):
4377 if main:
4378 try:
4379 arg = args.next()
4380 except:
4381 doError(name+': no argument supplied', True)
4382 else:
4383 arg = args
4384 try:
4385 val = float(arg)
4386 except:
4387 doError(name+': non-numerical value given', True)
4388 if(val < min or val > max):
4389 doError(name+': value should be between %f and %f' % (min, max), True)
4390 return val
4391
3258# Function: rerunTest 4392# Function: rerunTest
3259# Description: 4393# Description:
3260# generate an output from an existing set of ftrace/dmesg logs 4394# generate an output from an existing set of ftrace/dmesg logs
@@ -3282,15 +4416,12 @@ def rerunTest():
3282# Function: runTest 4416# Function: runTest
3283# Description: 4417# Description:
3284# execute a suspend/resume, gather the logs, and generate the output 4418# execute a suspend/resume, gather the logs, and generate the output
3285def runTest(subdir): 4419def runTest(subdir, testpath=''):
3286 global sysvals 4420 global sysvals
3287 4421
3288 # prepare for the test 4422 # prepare for the test
3289 if(not sysvals.android): 4423 sysvals.initFtrace()
3290 initFtrace() 4424 sysvals.initTestOutput(subdir, testpath)
3291 else:
3292 initFtraceAndroid()
3293 sysvals.initTestOutput(subdir)
3294 4425
3295 vprint('Output files:\n %s' % sysvals.dmesgfile) 4426 vprint('Output files:\n %s' % sysvals.dmesgfile)
3296 if(sysvals.usecallgraph or 4427 if(sysvals.usecallgraph or
@@ -3300,10 +4431,8 @@ def runTest(subdir):
3300 vprint(' %s' % sysvals.htmlfile) 4431 vprint(' %s' % sysvals.htmlfile)
3301 4432
3302 # execute the test 4433 # execute the test
3303 if(not sysvals.android): 4434 executeSuspend()
3304 executeSuspend() 4435 sysvals.cleanupFtrace()
3305 else:
3306 executeAndroidSuspend()
3307 4436
3308 # analyze the data and create the html output 4437 # analyze the data and create the html output
3309 print('PROCESSING DATA') 4438 print('PROCESSING DATA')
@@ -3367,6 +4496,153 @@ def runSummary(subdir, output):
3367 4496
3368 createHTMLSummarySimple(testruns, subdir+'/summary.html') 4497 createHTMLSummarySimple(testruns, subdir+'/summary.html')
3369 4498
4499# Function: checkArgBool
4500# Description:
4501# check if a boolean string value is true or false
4502def checkArgBool(value):
4503 yes = ['1', 'true', 'yes', 'on']
4504 if value.lower() in yes:
4505 return True
4506 return False
4507
4508# Function: configFromFile
4509# Description:
4510# Configure the script via the info in a config file
4511def configFromFile(file):
4512 global sysvals
4513 Config = ConfigParser.ConfigParser()
4514
4515 ignorekprobes = False
4516 Config.read(file)
4517 sections = Config.sections()
4518 if 'Settings' in sections:
4519 for opt in Config.options('Settings'):
4520 value = Config.get('Settings', opt).lower()
4521 if(opt.lower() == 'verbose'):
4522 sysvals.verbose = checkArgBool(value)
4523 elif(opt.lower() == 'addlogs'):
4524 sysvals.addlogs = checkArgBool(value)
4525 elif(opt.lower() == 'dev'):
4526 sysvals.usedevsrc = checkArgBool(value)
4527 elif(opt.lower() == 'ignorekprobes'):
4528 ignorekprobes = checkArgBool(value)
4529 elif(opt.lower() == 'x2'):
4530 if checkArgBool(value):
4531 sysvals.execcount = 2
4532 elif(opt.lower() == 'callgraph'):
4533 sysvals.usecallgraph = checkArgBool(value)
4534 elif(opt.lower() == 'callgraphfunc'):
4535 sysvals.debugfuncs = []
4536 if value:
4537 value = value.split(',')
4538 for i in value:
4539 sysvals.debugfuncs.append(i.strip())
4540 elif(opt.lower() == 'expandcg'):
4541 sysvals.cgexp = checkArgBool(value)
4542 elif(opt.lower() == 'srgap'):
4543 if checkArgBool(value):
4544 sysvals.srgap = 5
4545 elif(opt.lower() == 'mode'):
4546 sysvals.suspendmode = value
4547 elif(opt.lower() == 'command'):
4548 sysvals.testcommand = value
4549 elif(opt.lower() == 'x2delay'):
4550 sysvals.x2delay = getArgInt('-x2delay', value, 0, 60000, False)
4551 elif(opt.lower() == 'postres'):
4552 sysvals.postresumetime = getArgInt('-postres', value, 0, 3600, False)
4553 elif(opt.lower() == 'rtcwake'):
4554 sysvals.rtcwake = True
4555 sysvals.rtcwaketime = getArgInt('-rtcwake', value, 0, 3600, False)
4556 elif(opt.lower() == 'timeprec'):
4557 sysvals.setPrecision(getArgInt('-timeprec', value, 0, 6, False))
4558 elif(opt.lower() == 'mindev'):
4559 sysvals.mindevlen = getArgFloat('-mindev', value, 0.0, 10000.0, False)
4560 elif(opt.lower() == 'mincg'):
4561 sysvals.mincglen = getArgFloat('-mincg', value, 0.0, 10000.0, False)
4562 elif(opt.lower() == 'kprobecolor'):
4563 try:
4564 val = int(value, 16)
4565 sysvals.kprobecolor = '#'+value
4566 except:
4567 sysvals.kprobecolor = value
4568 elif(opt.lower() == 'synccolor'):
4569 try:
4570 val = int(value, 16)
4571 sysvals.synccolor = '#'+value
4572 except:
4573 sysvals.synccolor = value
4574 elif(opt.lower() == 'output-dir'):
4575 args = dict()
4576 n = datetime.now()
4577 args['date'] = n.strftime('%y%m%d')
4578 args['time'] = n.strftime('%H%M%S')
4579 args['hostname'] = sysvals.hostname
4580 sysvals.outdir = value.format(**args)
4581
4582 if sysvals.suspendmode == 'command' and not sysvals.testcommand:
4583 doError('No command supplied for mode "command"', False)
4584 if sysvals.usedevsrc and sysvals.usecallgraph:
4585 doError('dev and callgraph cannot both be true', False)
4586 if sysvals.usecallgraph and sysvals.execcount > 1:
4587 doError('-x2 is not compatible with -f', False)
4588
4589 if ignorekprobes:
4590 return
4591
4592 kprobes = dict()
4593 archkprobe = 'Kprobe_'+platform.machine()
4594 if archkprobe in sections:
4595 for name in Config.options(archkprobe):
4596 kprobes[name] = Config.get(archkprobe, name)
4597 if 'Kprobe' in sections:
4598 for name in Config.options('Kprobe'):
4599 kprobes[name] = Config.get('Kprobe', name)
4600
4601 for name in kprobes:
4602 function = name
4603 format = name
4604 color = ''
4605 args = dict()
4606 data = kprobes[name].split()
4607 i = 0
4608 for val in data:
4609 # bracketted strings are special formatting, read them separately
4610 if val[0] == '[' and val[-1] == ']':
4611 for prop in val[1:-1].split(','):
4612 p = prop.split('=')
4613 if p[0] == 'color':
4614 try:
4615 color = int(p[1], 16)
4616 color = '#'+p[1]
4617 except:
4618 color = p[1]
4619 continue
4620 # first real arg should be the format string
4621 if i == 0:
4622 format = val
4623 # all other args are actual function args
4624 else:
4625 d = val.split('=')
4626 args[d[0]] = d[1]
4627 i += 1
4628 if not function or not format:
4629 doError('Invalid kprobe: %s' % name, False)
4630 for arg in re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', format):
4631 if arg not in args:
4632 doError('Kprobe "%s" is missing argument "%s"' % (name, arg), False)
4633 if name in sysvals.kprobes:
4634 doError('Duplicate kprobe found "%s"' % (name), False)
4635 vprint('Adding KPROBE: %s %s %s %s' % (name, function, format, args))
4636 sysvals.kprobes[name] = {
4637 'name': name,
4638 'func': function,
4639 'format': format,
4640 'args': args,
4641 'mask': re.sub('{(?P<n>[a-z,A-Z,0-9]*)}', '.*', format)
4642 }
4643 if color:
4644 sysvals.kprobes[name]['color'] = color
4645
3370# Function: printHelp 4646# Function: printHelp
3371# Description: 4647# Description:
3372# print out the help text 4648# print out the help text
@@ -3375,7 +4651,7 @@ def printHelp():
3375 modes = getModes() 4651 modes = getModes()
3376 4652
3377 print('') 4653 print('')
3378 print('AnalyzeSuspend v%.1f' % sysvals.version) 4654 print('AnalyzeSuspend v%s' % sysvals.version)
3379 print('Usage: sudo analyze_suspend.py <options>') 4655 print('Usage: sudo analyze_suspend.py <options>')
3380 print('') 4656 print('')
3381 print('Description:') 4657 print('Description:')
@@ -3396,27 +4672,38 @@ def printHelp():
3396 print(' [general]') 4672 print(' [general]')
3397 print(' -h Print this help text') 4673 print(' -h Print this help text')
3398 print(' -v Print the current tool version') 4674 print(' -v Print the current tool version')
4675 print(' -config file Pull arguments and config options from a file')
3399 print(' -verbose Print extra information during execution and analysis') 4676 print(' -verbose Print extra information during execution and analysis')
3400 print(' -status Test to see if the system is enabled to run this tool') 4677 print(' -status Test to see if the system is enabled to run this tool')
3401 print(' -modes List available suspend modes') 4678 print(' -modes List available suspend modes')
3402 print(' -m mode Mode to initiate for suspend %s (default: %s)') % (modes, sysvals.suspendmode) 4679 print(' -m mode Mode to initiate for suspend %s (default: %s)') % (modes, sysvals.suspendmode)
3403 print(' -rtcwake t Use rtcwake to autoresume after <t> seconds (default: disabled)') 4680 print(' -o subdir Override the output subdirectory')
3404 print(' [advanced]') 4681 print(' [advanced]')
4682 print(' -rtcwake t Use rtcwake to autoresume after <t> seconds (default: disabled)')
4683 print(' -addlogs Add the dmesg and ftrace logs to the html output')
4684 print(' -multi n d Execute <n> consecutive tests at <d> seconds intervals. The outputs will')
4685 print(' be created in a new subdirectory with a summary page.')
4686 print(' -srgap Add a visible gap in the timeline between sus/res (default: disabled)')
4687 print(' -cmd {s} Instead of suspend/resume, run a command, e.g. "sync -d"')
4688 print(' -mindev ms Discard all device blocks shorter than ms milliseconds (e.g. 0.001 for us)')
4689 print(' -mincg ms Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)')
4690 print(' -timeprec N Number of significant digits in timestamps (0:S, [3:ms], 6:us)')
4691 print(' [debug]')
3405 print(' -f Use ftrace to create device callgraphs (default: disabled)') 4692 print(' -f Use ftrace to create device callgraphs (default: disabled)')
3406 print(' -filter "d1 d2 ..." Filter out all but this list of dev names') 4693 print(' -expandcg pre-expand the callgraph data in the html output (default: disabled)')
4694 print(' -flist Print the list of functions currently being captured in ftrace')
4695 print(' -flistall Print all functions capable of being captured in ftrace')
4696 print(' -fadd file Add functions to be graphed in the timeline from a list in a text file')
4697 print(' -filter "d1 d2 ..." Filter out all but this list of device names')
4698 print(' -dev Display common low level functions in the timeline')
4699 print(' [post-resume task analysis]')
3407 print(' -x2 Run two suspend/resumes back to back (default: disabled)') 4700 print(' -x2 Run two suspend/resumes back to back (default: disabled)')
3408 print(' -x2delay t Minimum millisecond delay <t> between the two test runs (default: 0 ms)') 4701 print(' -x2delay t Minimum millisecond delay <t> between the two test runs (default: 0 ms)')
3409 print(' -postres t Time after resume completion to wait for post-resume events (default: 0 S)') 4702 print(' -postres t Time after resume completion to wait for post-resume events (default: 0 S)')
3410 print(' -multi n d Execute <n> consecutive tests at <d> seconds intervals. The outputs will')
3411 print(' be created in a new subdirectory with a summary page.')
3412 print(' [utilities]') 4703 print(' [utilities]')
3413 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table') 4704 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table')
3414 print(' -usbtopo Print out the current USB topology with power info') 4705 print(' -usbtopo Print out the current USB topology with power info')
3415 print(' -usbauto Enable autosuspend for all connected USB devices') 4706 print(' -usbauto Enable autosuspend for all connected USB devices')
3416 print(' [android testing]')
3417 print(' -adb binary Use the given adb binary to run the test on an android device.')
3418 print(' The device should already be connected and with root access.')
3419 print(' Commands will be executed on the device using "adb shell"')
3420 print(' [re-analyze data from previous runs]') 4707 print(' [re-analyze data from previous runs]')
3421 print(' -ftrace ftracefile Create HTML output using ftrace input') 4708 print(' -ftrace ftracefile Create HTML output using ftrace input')
3422 print(' -dmesg dmesgfile Create HTML output using dmesg (not needed for kernel >= 3.15)') 4709 print(' -dmesg dmesgfile Create HTML output using dmesg (not needed for kernel >= 3.15)')
@@ -3430,6 +4717,7 @@ if __name__ == '__main__':
3430 cmd = '' 4717 cmd = ''
3431 cmdarg = '' 4718 cmdarg = ''
3432 multitest = {'run': False, 'count': 0, 'delay': 0} 4719 multitest = {'run': False, 'count': 0, 'delay': 0}
4720 simplecmds = ['-modes', '-fpdt', '-flist', '-flistall', '-usbtopo', '-usbauto', '-status']
3433 # loop through the command line arguments 4721 # loop through the command line arguments
3434 args = iter(sys.argv[1:]) 4722 args = iter(sys.argv[1:])
3435 for arg in args: 4723 for arg in args:
@@ -3438,58 +4726,85 @@ if __name__ == '__main__':
3438 val = args.next() 4726 val = args.next()
3439 except: 4727 except:
3440 doError('No mode supplied', True) 4728 doError('No mode supplied', True)
4729 if val == 'command' and not sysvals.testcommand:
4730 doError('No command supplied for mode "command"', True)
3441 sysvals.suspendmode = val 4731 sysvals.suspendmode = val
3442 elif(arg == '-adb'): 4732 elif(arg in simplecmds):
3443 try: 4733 cmd = arg[1:]
3444 val = args.next() 4734 elif(arg == '-h'):
3445 except: 4735 printHelp()
3446 doError('No adb binary supplied', True) 4736 sys.exit()
3447 if(not os.path.exists(val)): 4737 elif(arg == '-v'):
3448 doError('file doesnt exist: %s' % val, False) 4738 print("Version %s" % sysvals.version)
3449 if(not os.access(val, os.X_OK)): 4739 sys.exit()
3450 doError('file isnt executable: %s' % val, False)
3451 try:
3452 check = os.popen(val+' version').read().strip()
3453 except:
3454 doError('adb version failed to execute', False)
3455 if(not re.match('Android Debug Bridge .*', check)):
3456 doError('adb version failed to execute', False)
3457 sysvals.adb = val
3458 sysvals.android = True
3459 elif(arg == '-x2'): 4740 elif(arg == '-x2'):
3460 if(sysvals.postresumetime > 0):
3461 doError('-x2 is not compatible with -postres', False)
3462 sysvals.execcount = 2 4741 sysvals.execcount = 2
4742 if(sysvals.usecallgraph):
4743 doError('-x2 is not compatible with -f', False)
3463 elif(arg == '-x2delay'): 4744 elif(arg == '-x2delay'):
3464 sysvals.x2delay = getArgInt('-x2delay', args, 0, 60000) 4745 sysvals.x2delay = getArgInt('-x2delay', args, 0, 60000)
3465 elif(arg == '-postres'): 4746 elif(arg == '-postres'):
3466 if(sysvals.execcount != 1):
3467 doError('-x2 is not compatible with -postres', False)
3468 sysvals.postresumetime = getArgInt('-postres', args, 0, 3600) 4747 sysvals.postresumetime = getArgInt('-postres', args, 0, 3600)
3469 elif(arg == '-f'): 4748 elif(arg == '-f'):
3470 sysvals.usecallgraph = True 4749 sysvals.usecallgraph = True
3471 elif(arg == '-modes'): 4750 if(sysvals.execcount > 1):
3472 cmd = 'modes' 4751 doError('-x2 is not compatible with -f', False)
3473 elif(arg == '-fpdt'): 4752 if(sysvals.usedevsrc):
3474 cmd = 'fpdt' 4753 doError('-dev is not compatible with -f', False)
3475 elif(arg == '-usbtopo'): 4754 elif(arg == '-addlogs'):
3476 cmd = 'usbtopo' 4755 sysvals.addlogs = True
3477 elif(arg == '-usbauto'):
3478 cmd = 'usbauto'
3479 elif(arg == '-status'):
3480 cmd = 'status'
3481 elif(arg == '-verbose'): 4756 elif(arg == '-verbose'):
3482 sysvals.verbose = True 4757 sysvals.verbose = True
3483 elif(arg == '-v'): 4758 elif(arg == '-dev'):
3484 print("Version %.1f" % sysvals.version) 4759 sysvals.usedevsrc = True
3485 sys.exit() 4760 if(sysvals.usecallgraph):
4761 doError('-dev is not compatible with -f', False)
3486 elif(arg == '-rtcwake'): 4762 elif(arg == '-rtcwake'):
3487 sysvals.rtcwake = True 4763 sysvals.rtcwake = True
3488 sysvals.rtcwaketime = getArgInt('-rtcwake', args, 0, 3600) 4764 sysvals.rtcwaketime = getArgInt('-rtcwake', args, 0, 3600)
4765 elif(arg == '-timeprec'):
4766 sysvals.setPrecision(getArgInt('-timeprec', args, 0, 6))
4767 elif(arg == '-mindev'):
4768 sysvals.mindevlen = getArgFloat('-mindev', args, 0.0, 10000.0)
4769 elif(arg == '-mincg'):
4770 sysvals.mincglen = getArgFloat('-mincg', args, 0.0, 10000.0)
4771 elif(arg == '-cmd'):
4772 try:
4773 val = args.next()
4774 except:
4775 doError('No command string supplied', True)
4776 sysvals.testcommand = val
4777 sysvals.suspendmode = 'command'
4778 elif(arg == '-expandcg'):
4779 sysvals.cgexp = True
4780 elif(arg == '-srgap'):
4781 sysvals.srgap = 5
3489 elif(arg == '-multi'): 4782 elif(arg == '-multi'):
3490 multitest['run'] = True 4783 multitest['run'] = True
3491 multitest['count'] = getArgInt('-multi n (exec count)', args, 2, 1000000) 4784 multitest['count'] = getArgInt('-multi n (exec count)', args, 2, 1000000)
3492 multitest['delay'] = getArgInt('-multi d (delay between tests)', args, 0, 3600) 4785 multitest['delay'] = getArgInt('-multi d (delay between tests)', args, 0, 3600)
4786 elif(arg == '-o'):
4787 try:
4788 val = args.next()
4789 except:
4790 doError('No subdirectory name supplied', True)
4791 sysvals.outdir = val
4792 elif(arg == '-config'):
4793 try:
4794 val = args.next()
4795 except:
4796 doError('No text file supplied', True)
4797 if(os.path.exists(val) == False):
4798 doError('%s does not exist' % val, False)
4799 configFromFile(val)
4800 elif(arg == '-fadd'):
4801 try:
4802 val = args.next()
4803 except:
4804 doError('No text file supplied', True)
4805 if(os.path.exists(val) == False):
4806 doError('%s does not exist' % val, False)
4807 sysvals.addFtraceFilterFunctions(val)
3493 elif(arg == '-dmesg'): 4808 elif(arg == '-dmesg'):
3494 try: 4809 try:
3495 val = args.next() 4810 val = args.next()
@@ -3498,17 +4813,16 @@ if __name__ == '__main__':
3498 sysvals.notestrun = True 4813 sysvals.notestrun = True
3499 sysvals.dmesgfile = val 4814 sysvals.dmesgfile = val
3500 if(os.path.exists(sysvals.dmesgfile) == False): 4815 if(os.path.exists(sysvals.dmesgfile) == False):
3501 doError('%s doesnt exist' % sysvals.dmesgfile, False) 4816 doError('%s does not exist' % sysvals.dmesgfile, False)
3502 elif(arg == '-ftrace'): 4817 elif(arg == '-ftrace'):
3503 try: 4818 try:
3504 val = args.next() 4819 val = args.next()
3505 except: 4820 except:
3506 doError('No ftrace file supplied', True) 4821 doError('No ftrace file supplied', True)
3507 sysvals.notestrun = True 4822 sysvals.notestrun = True
3508 sysvals.usecallgraph = True
3509 sysvals.ftracefile = val 4823 sysvals.ftracefile = val
3510 if(os.path.exists(sysvals.ftracefile) == False): 4824 if(os.path.exists(sysvals.ftracefile) == False):
3511 doError('%s doesnt exist' % sysvals.ftracefile, False) 4825 doError('%s does not exist' % sysvals.ftracefile, False)
3512 elif(arg == '-summary'): 4826 elif(arg == '-summary'):
3513 try: 4827 try:
3514 val = args.next() 4828 val = args.next()
@@ -3518,35 +4832,35 @@ if __name__ == '__main__':
3518 cmdarg = val 4832 cmdarg = val
3519 sysvals.notestrun = True 4833 sysvals.notestrun = True
3520 if(os.path.isdir(val) == False): 4834 if(os.path.isdir(val) == False):
3521 doError('%s isnt accesible' % val, False) 4835 doError('%s is not accesible' % val, False)
3522 elif(arg == '-filter'): 4836 elif(arg == '-filter'):
3523 try: 4837 try:
3524 val = args.next() 4838 val = args.next()
3525 except: 4839 except:
3526 doError('No devnames supplied', True) 4840 doError('No devnames supplied', True)
3527 sysvals.setDeviceFilter(val) 4841 sysvals.setDeviceFilter(val)
3528 elif(arg == '-h'):
3529 printHelp()
3530 sys.exit()
3531 else: 4842 else:
3532 doError('Invalid argument: '+arg, True) 4843 doError('Invalid argument: '+arg, True)
3533 4844
4845 # callgraph size cannot exceed device size
4846 if sysvals.mincglen < sysvals.mindevlen:
4847 sysvals.mincglen = sysvals.mindevlen
4848
3534 # just run a utility command and exit 4849 # just run a utility command and exit
3535 if(cmd != ''): 4850 if(cmd != ''):
3536 if(cmd == 'status'): 4851 if(cmd == 'status'):
3537 statusCheck() 4852 statusCheck(True)
3538 elif(cmd == 'fpdt'): 4853 elif(cmd == 'fpdt'):
3539 if(sysvals.android):
3540 doError('cannot read FPDT on android device', False)
3541 getFPDT(True) 4854 getFPDT(True)
3542 elif(cmd == 'usbtopo'): 4855 elif(cmd == 'usbtopo'):
3543 if(sysvals.android): 4856 detectUSB()
3544 doError('cannot read USB topology '+\
3545 'on an android device', False)
3546 detectUSB(True)
3547 elif(cmd == 'modes'): 4857 elif(cmd == 'modes'):
3548 modes = getModes() 4858 modes = getModes()
3549 print modes 4859 print modes
4860 elif(cmd == 'flist'):
4861 sysvals.getFtraceFilterFunctions(True)
4862 elif(cmd == 'flistall'):
4863 sysvals.getFtraceFilterFunctions(False)
3550 elif(cmd == 'usbauto'): 4864 elif(cmd == 'usbauto'):
3551 setUSBDevicesAuto() 4865 setUSBDevicesAuto()
3552 elif(cmd == 'summary'): 4866 elif(cmd == 'summary'):
@@ -3554,15 +4868,6 @@ if __name__ == '__main__':
3554 runSummary(cmdarg, True) 4868 runSummary(cmdarg, True)
3555 sys.exit() 4869 sys.exit()
3556 4870
3557 # run test on android device
3558 if(sysvals.android):
3559 if(sysvals.usecallgraph):
3560 doError('ftrace (-f) is not yet supported '+\
3561 'in the android kernel', False)
3562 if(sysvals.notestrun):
3563 doError('cannot analyze test files on the '+\
3564 'android device', False)
3565
3566 # if instructed, re-analyze existing data files 4871 # if instructed, re-analyze existing data files
3567 if(sysvals.notestrun): 4872 if(sysvals.notestrun):
3568 rerunTest() 4873 rerunTest()
@@ -3574,18 +4879,20 @@ if __name__ == '__main__':
3574 sys.exit() 4879 sys.exit()
3575 4880
3576 if multitest['run']: 4881 if multitest['run']:
3577 # run multiple tests in a separte subdirectory 4882 # run multiple tests in a separate subdirectory
3578 s = 'x%d' % multitest['count'] 4883 s = 'x%d' % multitest['count']
3579 subdir = datetime.now().strftime('suspend-'+s+'-%m%d%y-%H%M%S') 4884 if not sysvals.outdir:
3580 os.mkdir(subdir) 4885 sysvals.outdir = datetime.now().strftime('suspend-'+s+'-%m%d%y-%H%M%S')
4886 if not os.path.isdir(sysvals.outdir):
4887 os.mkdir(sysvals.outdir)
3581 for i in range(multitest['count']): 4888 for i in range(multitest['count']):
3582 if(i != 0): 4889 if(i != 0):
3583 print('Waiting %d seconds...' % (multitest['delay'])) 4890 print('Waiting %d seconds...' % (multitest['delay']))
3584 time.sleep(multitest['delay']) 4891 time.sleep(multitest['delay'])
3585 print('TEST (%d/%d) START' % (i+1, multitest['count'])) 4892 print('TEST (%d/%d) START' % (i+1, multitest['count']))
3586 runTest(subdir) 4893 runTest(sysvals.outdir)
3587 print('TEST (%d/%d) COMPLETE' % (i+1, multitest['count'])) 4894 print('TEST (%d/%d) COMPLETE' % (i+1, multitest['count']))
3588 runSummary(subdir, False) 4895 runSummary(sysvals.outdir, False)
3589 else: 4896 else:
3590 # run the test in the current directory 4897 # run the test in the current directory
3591 runTest(".") 4898 runTest('.', sysvals.outdir)
diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile
index e367b1a85d70..8561e7ddca59 100644
--- a/tools/power/x86/turbostat/Makefile
+++ b/tools/power/x86/turbostat/Makefile
@@ -1,7 +1,7 @@
1CC = $(CROSS_COMPILE)gcc 1CC = $(CROSS_COMPILE)gcc
2BUILD_OUTPUT := $(CURDIR) 2BUILD_OUTPUT := $(CURDIR)
3PREFIX := /usr 3PREFIX ?= /usr
4DESTDIR := 4DESTDIR ?=
5 5
6ifeq ("$(origin O)", "command line") 6ifeq ("$(origin O)", "command line")
7 BUILD_OUTPUT := $(O) 7 BUILD_OUTPUT := $(O)
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index 89a55d5e32f3..492e84fbebfa 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -123,7 +123,7 @@ cpu0: MSR_NHM_PLATFORM_INFO: 0x80838f3012300
12335 * 100 = 3500 MHz TSC frequency 12335 * 100 = 3500 MHz TSC frequency
124cpu0: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled) 124cpu0: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled)
125cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x1e000400 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, UNlocked: pkg-cstate-limit=0: pc0) 125cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x1e000400 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, UNlocked: pkg-cstate-limit=0: pc0)
126cpu0: MSR_NHM_TURBO_RATIO_LIMIT: 0x25262727 126cpu0: MSR_TURBO_RATIO_LIMIT: 0x25262727
12737 * 100 = 3700 MHz max turbo 4 active cores 12737 * 100 = 3700 MHz max turbo 4 active cores
12838 * 100 = 3800 MHz max turbo 3 active cores 12838 * 100 = 3800 MHz max turbo 3 active cores
12939 * 100 = 3900 MHz max turbo 2 active cores 12939 * 100 = 3900 MHz max turbo 2 active cores
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index acbf7ff2ee6e..3e199b508a96 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -1480,7 +1480,7 @@ dump_knl_turbo_ratio_limits(void)
1480 unsigned int cores[buckets_no]; 1480 unsigned int cores[buckets_no];
1481 unsigned int ratio[buckets_no]; 1481 unsigned int ratio[buckets_no];
1482 1482
1483 get_msr(base_cpu, MSR_NHM_TURBO_RATIO_LIMIT, &msr); 1483 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
1484 1484
1485 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", 1485 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n",
1486 base_cpu, msr); 1486 base_cpu, msr);