aboutsummaryrefslogtreecommitdiff
path: root/tools/power
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-12-15 16:30:31 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2020-12-15 16:30:31 -0800
commitb4ec805464a4a0299216a003278351d0b4806450 (patch)
tree1a864de7b10116bbf6cf16c9095a19921d7ed7eb /tools/power
parentb109bc72295363fb746bc42bdd777f7a8abb177b (diff)
parentb3fac817830306328d5195e7f4fb332277f3b146 (diff)
Merge tag 'pm-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael Wysocki: "These update cpufreq (core and drivers), cpuidle (polling state implementation and the PSCI driver), the OPP (operating performance points) framework, devfreq (core and drivers), the power capping RAPL (Running Average Power Limit) driver, the Energy Model support, the generic power domains (genpd) framework, the ACPI device power management, the core system-wide suspend code and power management utilities. Specifics: - Use local_clock() instead of jiffies in the cpufreq statistics to improve accuracy (Viresh Kumar). - Fix up OPP usage in the cpufreq-dt and qcom-cpufreq-nvmem cpufreq drivers (Viresh Kumar). - Clean up the cpufreq core, the intel_pstate driver and the schedutil cpufreq governor (Rafael Wysocki). - Fix up error code paths in the sti-cpufreq and mediatek cpufreq drivers (Yangtao Li, Qinglang Miao). - Fix cpufreq_online() to return error codes instead of success (0) in all cases when it fails (Wang ShaoBo). - Add mt8167 support to the mediatek cpufreq driver and blacklist mt8516 in the cpufreq-dt-platdev driver (Fabien Parent). - Modify the tegra194 cpufreq driver to always return values from the frequency table as the current frequency and clean up that driver (Sumit Gupta, Jon Hunter). - Modify the arm_scmi cpufreq driver to allow it to discover the power scale present in the performance protocol and provide this information to the Energy Model (Lukasz Luba). - Add missing MODULE_DEVICE_TABLE to several cpufreq drivers (Pali Rohár). - Clean up the CPPC cpufreq driver (Ionela Voinescu). - Fix NVMEM_IMX_OCOTP dependency in the imx cpufreq driver (Arnd Bergmann). - Rework the poling interval selection for the polling state in cpuidle (Mel Gorman). - Enable suspend-to-idle for PSCI OSI mode in the PSCI cpuidle driver (Ulf Hansson). - Modify the OPP framework to support empty (node-less) OPP tables in DT for passing dependency information (Nicola Mazzucato). - Fix potential lockdep issue in the OPP core and clean up the OPP core (Viresh Kumar). - Modify dev_pm_opp_put_regulators() to accept a NULL argument and update its users accordingly (Viresh Kumar). - Add frequency changes tracepoint to devfreq (Matthias Kaehlcke). - Add support for governor feature flags to devfreq, make devfreq sysfs file permissions depend on the governor and clean up the devfreq core (Chanwoo Choi). - Clean up the tegra20 devfreq driver and deprecate it to allow another driver based on EMC_STAT to be used instead of it (Dmitry Osipenko). - Add interconnect support to the tegra30 devfreq driver, allow it to take the interconnect and OPP information from DT and clean it up (Dmitry Osipenko). - Add interconnect support to the exynos-bus devfreq driver along with interconnect properties documentation (Sylwester Nawrocki). - Add suport for AMD Fam17h and Fam19h processors to the RAPL power capping driver (Victor Ding, Kim Phillips). - Fix handling of overly long constraint names in the powercap framework (Lukasz Luba). - Fix the wakeup configuration handling for bridges in the ACPI device power management core (Rafael Wysocki). - Add support for using an abstract scale for power units in the Energy Model (EM) and document it (Lukasz Luba). - Add em_cpu_energy() micro-optimization to the EM (Pavankumar Kondeti). - Modify the generic power domains (genpd) framwework to support suspend-to-idle (Ulf Hansson). - Fix creation of debugfs nodes in genpd (Thierry Strudel). - Clean up genpd (Lina Iyer). - Clean up the core system-wide suspend code and make it print driver flags for devices with debug enabled (Alex Shi, Patrice Chotard, Chen Yu). - Modify the ACPI system reboot code to make it prepare for system power off to avoid confusing the platform firmware (Kai-Heng Feng). - Update the pm-graph (multiple changes, mostly usability-related) and cpupower (online and offline CPU information support) PM utilities (Todd Brandt, Brahadambal Srinivasan)" * tag 'pm-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (86 commits) cpufreq: Fix cpufreq_online() return value on errors cpufreq: Fix up several kerneldoc comments cpufreq: stats: Use local_clock() instead of jiffies cpufreq: schedutil: Simplify sugov_update_next_freq() cpufreq: intel_pstate: Simplify intel_cpufreq_update_pstate() PM: domains: create debugfs nodes when adding power domains opp: of: Allow empty opp-table with opp-shared dt-bindings: opp: Allow empty OPP tables media: venus: dev_pm_opp_put_*() accepts NULL argument drm/panfrost: dev_pm_opp_put_*() accepts NULL argument drm/lima: dev_pm_opp_put_*() accepts NULL argument PM / devfreq: exynos: dev_pm_opp_put_*() accepts NULL argument cpufreq: qcom-cpufreq-nvmem: dev_pm_opp_put_*() accepts NULL argument cpufreq: dt: dev_pm_opp_put_regulators() accepts NULL argument opp: Allow dev_pm_opp_put_*() APIs to accept NULL opp_table opp: Don't create an OPP table from dev_pm_opp_get_opp_table() cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP table opp: Reduce the size of critical section in _opp_kref_release() PM / EM: Micro optimization in em_cpu_energy cpufreq: arm_scmi: Discover the power scale in performance protocol ...
Diffstat (limited to 'tools/power')
-rw-r--r--tools/power/cpupower/utils/cpufreq-set.c3
-rw-r--r--tools/power/cpupower/utils/cpuidle-set.c4
-rw-r--r--tools/power/cpupower/utils/cpupower.c8
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h12
-rw-r--r--tools/power/cpupower/utils/helpers/misc.c64
-rw-r--r--tools/power/pm-graph/README4
-rwxr-xr-xtools/power/pm-graph/sleepgraph.py387
7 files changed, 316 insertions, 166 deletions
diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c
index 7b2164e07057..c5e60a39cfa6 100644
--- a/tools/power/cpupower/utils/cpufreq-set.c
+++ b/tools/power/cpupower/utils/cpufreq-set.c
@@ -315,6 +315,7 @@ int cmd_freq_set(int argc, char **argv)
}
}
+ get_cpustate();
/* loop over CPUs */
for (cpu = bitmask_first(cpus_chosen);
@@ -332,5 +333,7 @@ int cmd_freq_set(int argc, char **argv)
}
}
+ print_offline_cpus();
+
return 0;
}
diff --git a/tools/power/cpupower/utils/cpuidle-set.c b/tools/power/cpupower/utils/cpuidle-set.c
index 569f268f4c7f..46158928f9ad 100644
--- a/tools/power/cpupower/utils/cpuidle-set.c
+++ b/tools/power/cpupower/utils/cpuidle-set.c
@@ -95,6 +95,8 @@ int cmd_idle_set(int argc, char **argv)
exit(EXIT_FAILURE);
}
+ get_cpustate();
+
/* Default is: set all CPUs */
if (bitmask_isallclear(cpus_chosen))
bitmask_setall(cpus_chosen);
@@ -181,5 +183,7 @@ int cmd_idle_set(int argc, char **argv)
break;
}
}
+
+ print_offline_cpus();
return EXIT_SUCCESS;
}
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c
index 8e3d08042825..8ac3304a9957 100644
--- a/tools/power/cpupower/utils/cpupower.c
+++ b/tools/power/cpupower/utils/cpupower.c
@@ -34,6 +34,8 @@ int run_as_root;
int base_cpu;
/* Affected cpus chosen by -c/--cpu param */
struct bitmask *cpus_chosen;
+struct bitmask *online_cpus;
+struct bitmask *offline_cpus;
#ifdef DEBUG
int be_verbose;
@@ -178,6 +180,8 @@ int main(int argc, const char *argv[])
char pathname[32];
cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
+ online_cpus = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
+ offline_cpus = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
argc--;
argv += 1;
@@ -230,6 +234,10 @@ int main(int argc, const char *argv[])
ret = p->main(argc, argv);
if (cpus_chosen)
bitmask_free(cpus_chosen);
+ if (online_cpus)
+ bitmask_free(online_cpus);
+ if (offline_cpus)
+ bitmask_free(offline_cpus);
return ret;
}
print_help();
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index 37dac161f3fe..0642e60a6ce1 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -94,6 +94,8 @@ struct cpupower_cpu_info {
*/
extern int get_cpu_info(struct cpupower_cpu_info *cpu_info);
extern struct cpupower_cpu_info cpupower_cpu_info;
+
+
/* cpuid and cpuinfo helpers **************************/
/* X86 ONLY ****************************************/
@@ -171,4 +173,14 @@ static inline unsigned int cpuid_ecx(unsigned int op) { return 0; };
static inline unsigned int cpuid_edx(unsigned int op) { return 0; };
#endif /* defined(__i386__) || defined(__x86_64__) */
+/*
+ * CPU State related functions
+ */
+extern struct bitmask *online_cpus;
+extern struct bitmask *offline_cpus;
+
+void get_cpustate(void);
+void print_online_cpus(void);
+void print_offline_cpus(void);
+
#endif /* __CPUPOWERUTILS_HELPERS__ */
diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
index e8f8f643a627..650b9a9a6584 100644
--- a/tools/power/cpupower/utils/helpers/misc.c
+++ b/tools/power/cpupower/utils/helpers/misc.c
@@ -4,11 +4,11 @@
#include <errno.h>
#include <stdlib.h>
-#if defined(__i386__) || defined(__x86_64__)
-
#include "helpers/helpers.h"
#include "helpers/sysfs.h"
+#if defined(__i386__) || defined(__x86_64__)
+
#include "cpupower_intern.h"
#define MSR_AMD_HWCR 0xc0010015
@@ -89,3 +89,63 @@ int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val)
}
#endif /* #if defined(__i386__) || defined(__x86_64__) */
+
+/* get_cpustate
+ *
+ * Gather the information of all online CPUs into bitmask struct
+ */
+void get_cpustate(void)
+{
+ unsigned int cpu = 0;
+
+ bitmask_clearall(online_cpus);
+ bitmask_clearall(offline_cpus);
+
+ for (cpu = bitmask_first(cpus_chosen);
+ cpu <= bitmask_last(cpus_chosen); cpu++) {
+
+ if (cpupower_is_cpu_online(cpu) == 1)
+ bitmask_setbit(online_cpus, cpu);
+ else
+ bitmask_setbit(offline_cpus, cpu);
+
+ continue;
+ }
+}
+
+/* print_online_cpus
+ *
+ * Print the CPU numbers of all CPUs that are online currently
+ */
+void print_online_cpus(void)
+{
+ int str_len = 0;
+ char *online_cpus_str = NULL;
+
+ str_len = online_cpus->size * 5;
+ online_cpus_str = (void *)malloc(sizeof(char) * str_len);
+
+ if (!bitmask_isallclear(online_cpus)) {
+ bitmask_displaylist(online_cpus_str, str_len, online_cpus);
+ printf(_("Following CPUs are online:\n%s\n"), online_cpus_str);
+ }
+}
+
+/* print_offline_cpus
+ *
+ * Print the CPU numbers of all CPUs that are offline currently
+ */
+void print_offline_cpus(void)
+{
+ int str_len = 0;
+ char *offline_cpus_str = NULL;
+
+ str_len = offline_cpus->size * 5;
+ offline_cpus_str = (void *)malloc(sizeof(char) * str_len);
+
+ if (!bitmask_isallclear(offline_cpus)) {
+ bitmask_displaylist(offline_cpus_str, str_len, offline_cpus);
+ printf(_("Following CPUs are offline:\n%s\n"), offline_cpus_str);
+ printf(_("cpupower set operation was not performed on them\n"));
+ }
+}
diff --git a/tools/power/pm-graph/README b/tools/power/pm-graph/README
index 89d0a7dab4bc..da468bd510ca 100644
--- a/tools/power/pm-graph/README
+++ b/tools/power/pm-graph/README
@@ -6,7 +6,7 @@
|_| |___/ |_|
pm-graph: suspend/resume/boot timing analysis tools
- Version: 5.7
+ Version: 5.8
Author: Todd Brandt <todd.e.brandt@intel.com>
Home Page: https://01.org/pm-graph
@@ -61,7 +61,7 @@
- runs with python2 or python3, choice is made by /usr/bin/python link
- python
- python-configparser (for python2 sleepgraph)
- - python-requests (for googlesheet.py)
+ - python-requests (for stresstester.py)
- linux-tools-common (for turbostat usage in sleepgraph)
Ubuntu:
diff --git a/tools/power/pm-graph/sleepgraph.py b/tools/power/pm-graph/sleepgraph.py
index 1bc36a1db14f..81f4b8abbdf7 100755
--- a/tools/power/pm-graph/sleepgraph.py
+++ b/tools/power/pm-graph/sleepgraph.py
@@ -81,7 +81,7 @@ def ascii(text):
# store system values and test parameters
class SystemValues:
title = 'SleepGraph'
- version = '5.7'
+ version = '5.8'
ansi = False
rs = 0
display = ''
@@ -92,8 +92,9 @@ class SystemValues:
testlog = True
dmesglog = True
ftracelog = False
+ acpidebug = True
tstat = True
- mindevlen = 0.0
+ mindevlen = 0.0001
mincglen = 0.0
cgphase = ''
cgtest = -1
@@ -115,6 +116,7 @@ class SystemValues:
fpdtpath = '/sys/firmware/acpi/tables/FPDT'
epath = '/sys/kernel/debug/tracing/events/power/'
pmdpath = '/sys/power/pm_debug_messages'
+ acpipath='/sys/module/acpi/parameters/debug_level'
traceevents = [
'suspend_resume',
'wakeup_source_activate',
@@ -162,16 +164,16 @@ class SystemValues:
devdump = False
mixedphaseheight = True
devprops = dict()
+ cfgdef = dict()
platinfo = []
predelay = 0
postdelay = 0
- pmdebug = ''
tmstart = 'SUSPEND START %Y%m%d-%H:%M:%S.%f'
tmend = 'RESUME COMPLETE %Y%m%d-%H:%M:%S.%f'
tracefuncs = {
'sys_sync': {},
'ksys_sync': {},
- 'pm_notifier_call_chain_robust': {},
+ '__pm_notifier_call_chain': {},
'pm_prepare_console': {},
'pm_notifier_call_chain': {},
'freeze_processes': {},
@@ -490,9 +492,9 @@ class SystemValues:
call('echo 0 > %s/wakealarm' % self.rtcpath, shell=True)
def initdmesg(self):
# get the latest time stamp from the dmesg log
- fp = Popen('dmesg', stdout=PIPE).stdout
+ lines = Popen('dmesg', stdout=PIPE).stdout.readlines()
ktime = '0'
- for line in fp:
+ for line in reversed(lines):
line = ascii(line).replace('\r\n', '')
idx = line.find('[')
if idx > 1:
@@ -500,7 +502,7 @@ class SystemValues:
m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
if(m):
ktime = m.group('ktime')
- fp.close()
+ break
self.dmesgstart = float(ktime)
def getdmesg(self, testdata):
op = self.writeDatafileHeader(self.dmesgfile, testdata)
@@ -715,8 +717,6 @@ class SystemValues:
self.fsetVal('0', 'events/kprobes/enable')
self.fsetVal('', 'kprobe_events')
self.fsetVal('1024', 'buffer_size_kb')
- if self.pmdebug:
- self.setVal(self.pmdebug, self.pmdpath)
def setupAllKprobes(self):
for name in self.tracefuncs:
self.defaultKprobe(name, self.tracefuncs[name])
@@ -740,11 +740,7 @@ class SystemValues:
# turn trace off
self.fsetVal('0', 'tracing_on')
self.cleanupFtrace()
- # pm debug messages
- pv = self.getVal(self.pmdpath)
- if pv != '1':
- self.setVal('1', self.pmdpath)
- self.pmdebug = pv
+ self.testVal(self.pmdpath, 'basic', '1')
# set the trace clock to global
self.fsetVal('global', 'trace_clock')
self.fsetVal('nop', 'current_tracer')
@@ -900,6 +896,14 @@ class SystemValues:
if isgz:
return gzip.open(filename, mode+'t')
return open(filename, mode)
+ def putlog(self, filename, text):
+ with self.openlog(filename, 'a') as fp:
+ fp.write(text)
+ fp.close()
+ def dlog(self, text):
+ self.putlog(self.dmesgfile, '# %s\n' % text)
+ def flog(self, text):
+ self.putlog(self.ftracefile, text)
def b64unzip(self, data):
try:
out = codecs.decode(base64.b64decode(data), 'zlib').decode()
@@ -992,9 +996,7 @@ class SystemValues:
# add a line for each of these commands with their outputs
for name, cmdline, info in cmdafter:
footer += '# platform-%s: %s | %s\n' % (name, cmdline, self.b64zip(info))
-
- with self.openlog(self.ftracefile, 'a') as fp:
- fp.write(footer)
+ self.flog(footer)
return True
def commonPrefix(self, list):
if len(list) < 2:
@@ -1034,6 +1036,7 @@ class SystemValues:
cmdline, cmdpath = ' '.join(cargs[2:]), self.getExec(cargs[2])
if not cmdpath or (begin and not delta):
continue
+ self.dlog('[%s]' % cmdline)
try:
fp = Popen([cmdpath]+cargs[3:], stdout=PIPE, stderr=PIPE).stdout
info = ascii(fp.read()).strip()
@@ -1060,6 +1063,29 @@ class SystemValues:
else:
out.append((name, cmdline, '\tnothing' if not info else info))
return out
+ def testVal(self, file, fmt='basic', value=''):
+ if file == 'restoreall':
+ for f in self.cfgdef:
+ if os.path.exists(f):
+ fp = open(f, 'w')
+ fp.write(self.cfgdef[f])
+ fp.close()
+ self.cfgdef = dict()
+ elif value and os.path.exists(file):
+ fp = open(file, 'r+')
+ if fmt == 'radio':
+ m = re.match('.*\[(?P<v>.*)\].*', fp.read())
+ if m:
+ self.cfgdef[file] = m.group('v')
+ elif fmt == 'acpi':
+ line = fp.read().strip().split('\n')[-1]
+ m = re.match('.* (?P<v>[0-9A-Fx]*) .*', line)
+ if m:
+ self.cfgdef[file] = m.group('v')
+ else:
+ self.cfgdef[file] = fp.read().strip()
+ fp.write(value)
+ fp.close()
def haveTurbostat(self):
if not self.tstat:
return False
@@ -1201,6 +1227,57 @@ class SystemValues:
self.multitest[sz] *= 1440
elif unit == 'h':
self.multitest[sz] *= 60
+ def displayControl(self, cmd):
+ xset, ret = 'timeout 10 xset -d :0.0 {0}', 0
+ if self.sudouser:
+ xset = 'sudo -u %s %s' % (self.sudouser, xset)
+ if cmd == 'init':
+ ret = call(xset.format('dpms 0 0 0'), shell=True)
+ if not ret:
+ ret = call(xset.format('s off'), shell=True)
+ elif cmd == 'reset':
+ ret = call(xset.format('s reset'), shell=True)
+ elif cmd in ['on', 'off', 'standby', 'suspend']:
+ b4 = self.displayControl('stat')
+ ret = call(xset.format('dpms force %s' % cmd), shell=True)
+ if not ret:
+ curr = self.displayControl('stat')
+ self.vprint('Display Switched: %s -> %s' % (b4, curr))
+ if curr != cmd:
+ self.vprint('WARNING: Display failed to change to %s' % cmd)
+ if ret:
+ self.vprint('WARNING: Display failed to change to %s with xset' % cmd)
+ return ret
+ elif cmd == 'stat':
+ fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout
+ ret = 'unknown'
+ for line in fp:
+ m = re.match('[\s]*Monitor is (?P<m>.*)', ascii(line))
+ if(m and len(m.group('m')) >= 2):
+ out = m.group('m').lower()
+ ret = out[3:] if out[0:2] == 'in' else out
+ break
+ fp.close()
+ return ret
+ def setRuntimeSuspend(self, before=True):
+ if before:
+ # runtime suspend disable or enable
+ if self.rs > 0:
+ self.rstgt, self.rsval, self.rsdir = 'on', 'auto', 'enabled'
+ else:
+ self.rstgt, self.rsval, self.rsdir = 'auto', 'on', 'disabled'
+ pprint('CONFIGURING RUNTIME SUSPEND...')
+ self.rslist = deviceInfo(self.rstgt)
+ for i in self.rslist:
+ self.setVal(self.rsval, i)
+ pprint('runtime suspend %s on all devices (%d changed)' % (self.rsdir, len(self.rslist)))
+ pprint('waiting 5 seconds...')
+ time.sleep(5)
+ else:
+ # runtime suspend re-enable or re-disable
+ for i in self.rslist:
+ self.setVal(self.rstgt, i)
+ pprint('runtime suspend settings restored on %d devices' % len(self.rslist))
sysvals = SystemValues()
switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0']
@@ -1640,15 +1717,20 @@ class Data:
if 'resume_machine' in phase and 'suspend_machine' in lp:
tS, tR = self.dmesg[lp]['end'], self.dmesg[phase]['start']
tL = tR - tS
- if tL > 0:
- left = True if tR > tZero else False
- self.trimTime(tS, tL, left)
- if 'trying' in self.dmesg[lp] and self.dmesg[lp]['trying'] >= 0.001:
- tTry = round(self.dmesg[lp]['trying'] * 1000)
- text = '%.0f (-%.0f waking)' % (tL * 1000, tTry)
+ if tL <= 0:
+ continue
+ left = True if tR > tZero else False
+ self.trimTime(tS, tL, left)
+ if 'waking' in self.dmesg[lp]:
+ tCnt = self.dmesg[lp]['waking'][0]
+ if self.dmesg[lp]['waking'][1] >= 0.001:
+ tTry = '-%.0f' % (round(self.dmesg[lp]['waking'][1] * 1000))
else:
- text = '%.0f' % (tL * 1000)
- self.tLow.append(text)
+ tTry = '-%.3f' % (self.dmesg[lp]['waking'][1] * 1000)
+ text = '%.0f (%s ms waking %d times)' % (tL * 1000, tTry, tCnt)
+ else:
+ text = '%.0f' % (tL * 1000)
+ self.tLow.append(text)
lp = phase
def getMemTime(self):
if not self.hwstart or not self.hwend:
@@ -1921,7 +2003,7 @@ class Data:
for dev in list:
length = (list[dev]['end'] - list[dev]['start']) * 1000
width = widfmt % (((list[dev]['end']-list[dev]['start'])*100)/tTotal)
- if width != '0.000000' and length >= mindevlen:
+ if length >= mindevlen:
devlist.append(dev)
self.tdevlist[phase] = devlist
def addHorizontalDivider(self, devname, devend):
@@ -3316,9 +3398,10 @@ def parseTraceLog(live=False):
# trim out s2idle loops, track time trying to freeze
llp = data.lastPhase(2)
if llp.startswith('suspend_machine'):
- if 'trying' not in data.dmesg[llp]:
- data.dmesg[llp]['trying'] = 0
- data.dmesg[llp]['trying'] += \
+ if 'waking' not in data.dmesg[llp]:
+ data.dmesg[llp]['waking'] = [0, 0.0]
+ data.dmesg[llp]['waking'][0] += 1
+ data.dmesg[llp]['waking'][1] += \
t.time - data.dmesg[lp]['start']
data.currphase = ''
del data.dmesg[lp]
@@ -4555,7 +4638,7 @@ def createHTML(testruns, testfail):
# draw the devices for this phase
phaselist = data.dmesg[b]['list']
for d in sorted(data.tdevlist[b]):
- dname = d if '[' not in d else d.split('[')[0]
+ dname = d if ('[' not in d or 'CPU' in d) else d.split('[')[0]
name, dev = dname, phaselist[d]
drv = xtraclass = xtrainfo = xtrastyle = ''
if 'htmlclass' in dev:
@@ -5194,156 +5277,146 @@ def addScriptCode(hf, testruns):
'</script>\n'
hf.write(script_code);
-def setRuntimeSuspend(before=True):
- global sysvals
- sv = sysvals
- if sv.rs == 0:
- return
- if before:
- # runtime suspend disable or enable
- if sv.rs > 0:
- sv.rstgt, sv.rsval, sv.rsdir = 'on', 'auto', 'enabled'
- else:
- sv.rstgt, sv.rsval, sv.rsdir = 'auto', 'on', 'disabled'
- pprint('CONFIGURING RUNTIME SUSPEND...')
- sv.rslist = deviceInfo(sv.rstgt)
- for i in sv.rslist:
- sv.setVal(sv.rsval, i)
- pprint('runtime suspend %s on all devices (%d changed)' % (sv.rsdir, len(sv.rslist)))
- pprint('waiting 5 seconds...')
- time.sleep(5)
- else:
- # runtime suspend re-enable or re-disable
- for i in sv.rslist:
- sv.setVal(sv.rstgt, i)
- pprint('runtime suspend settings restored on %d devices' % len(sv.rslist))
-
# Function: executeSuspend
# Description:
# Execute system suspend through the sysfs interface, then copy the output
# dmesg and ftrace files to the test output directory.
def executeSuspend(quiet=False):
- pm = ProcessMonitor()
- tp = sysvals.tpath
- if sysvals.wifi:
- wifi = sysvals.checkWifi()
+ sv, tp, pm = sysvals, sysvals.tpath, ProcessMonitor()
+ if sv.wifi:
+ wifi = sv.checkWifi()
+ sv.dlog('wifi check, connected device is "%s"' % wifi)
testdata = []
# run these commands to prepare the system for suspend
- if sysvals.display:
+ if sv.display:
if not quiet:
- pprint('SET DISPLAY TO %s' % sysvals.display.upper())
- displayControl(sysvals.display)
+ pprint('SET DISPLAY TO %s' % sv.display.upper())
+ ret = sv.displayControl(sv.display)
+ sv.dlog('xset display %s, ret = %d' % (sv.display, ret))
time.sleep(1)
- if sysvals.sync:
+ if sv.sync:
if not quiet:
pprint('SYNCING FILESYSTEMS')
+ sv.dlog('syncing filesystems')
call('sync', shell=True)
- # mark the start point in the kernel ring buffer just as we start
- sysvals.initdmesg()
+ sv.dlog('read dmesg')
+ sv.initdmesg()
# start ftrace
- if(sysvals.usecallgraph or sysvals.usetraceevents):
+ if(sv.usecallgraph or sv.usetraceevents):
if not quiet:
pprint('START TRACING')
- sysvals.fsetVal('1', 'tracing_on')
- if sysvals.useprocmon:
+ sv.dlog('start ftrace tracing')
+ sv.fsetVal('1', 'tracing_on')
+ if sv.useprocmon:
+ sv.dlog('start the process monitor')
pm.start()
- sysvals.cmdinfo(True)
+ sv.dlog('run the cmdinfo list before')
+ sv.cmdinfo(True)
# execute however many s/r runs requested
- for count in range(1,sysvals.execcount+1):
+ for count in range(1,sv.execcount+1):
# x2delay in between test runs
- if(count > 1 and sysvals.x2delay > 0):
- sysvals.fsetVal('WAIT %d' % sysvals.x2delay, 'trace_marker')
- time.sleep(sysvals.x2delay/1000.0)
- sysvals.fsetVal('WAIT END', 'trace_marker')
+ if(count > 1 and sv.x2delay > 0):
+ sv.fsetVal('WAIT %d' % sv.x2delay, 'trace_marker')
+ time.sleep(sv.x2delay/1000.0)
+ sv.fsetVal('WAIT END', 'trace_marker')
# start message
- if sysvals.testcommand != '':
+ if sv.testcommand != '':
pprint('COMMAND START')
else:
- if(sysvals.rtcwake):
+ if(sv.rtcwake):
pprint('SUSPEND START')
else:
pprint('SUSPEND START (press a key to resume)')
# set rtcwake
- if(sysvals.rtcwake):
+ if(sv.rtcwake):
if not quiet:
- pprint('will issue an rtcwake in %d seconds' % sysvals.rtcwaketime)
- sysvals.rtcWakeAlarmOn()
+ pprint('will issue an rtcwake in %d seconds' % sv.rtcwaketime)
+ sv.dlog('enable RTC wake alarm')
+ sv.rtcWakeAlarmOn()
# start of suspend trace marker
- if(sysvals.usecallgraph or sysvals.usetraceevents):
- sysvals.fsetVal(datetime.now().strftime(sysvals.tmstart), 'trace_marker')
+ if(sv.usecallgraph or sv.usetraceevents):
+ sv.fsetVal(datetime.now().strftime(sv.tmstart), 'trace_marker')
# predelay delay
- if(count == 1 and sysvals.predelay > 0):
- sysvals.fsetVal('WAIT %d' % sysvals.predelay, 'trace_marker')
- time.sleep(sysvals.predelay/1000.0)
- sysvals.fsetVal('WAIT END', 'trace_marker')
+ if(count == 1 and sv.predelay > 0):
+ sv.fsetVal('WAIT %d' % sv.predelay, 'trace_marker')
+ time.sleep(sv.predelay/1000.0)
+ sv.fsetVal('WAIT END', 'trace_marker')
# initiate suspend or command
+ sv.dlog('system executing a suspend')
tdata = {'error': ''}
- if sysvals.testcommand != '':
- res = call(sysvals.testcommand+' 2>&1', shell=True);
+ if sv.testcommand != '':
+ res = call(sv.testcommand+' 2>&1', shell=True);
if res != 0:
tdata['error'] = 'cmd returned %d' % res
else:
- mode = sysvals.suspendmode
- if sysvals.memmode and os.path.exists(sysvals.mempowerfile):
+ mode = sv.suspendmode
+ if sv.memmode and os.path.exists(sv.mempowerfile):
mode = 'mem'
- pf = open(sysvals.mempowerfile, 'w')
- pf.write(sysvals.memmode)
- pf.close()
- if sysvals.diskmode and os.path.exists(sysvals.diskpowerfile):
+ sv.testVal(sv.mempowerfile, 'radio', sv.memmode)
+ if sv.diskmode and os.path.exists(sv.diskpowerfile):
mode = 'disk'
- pf = open(sysvals.diskpowerfile, 'w')
- pf.write(sysvals.diskmode)
- pf.close()
- if mode == 'freeze' and sysvals.haveTurbostat():
+ sv.testVal(sv.diskpowerfile, 'radio', sv.diskmode)
+ if sv.acpidebug:
+ sv.testVal(sv.acpipath, 'acpi', '0xe')
+ if mode == 'freeze' and sv.haveTurbostat():
# execution will pause here
- turbo = sysvals.turbostat()
+ turbo = sv.turbostat()
if turbo:
tdata['turbo'] = turbo
else:
- pf = open(sysvals.powerfile, 'w')
+ pf = open(sv.powerfile, 'w')
pf.write(mode)
# execution will pause here
try:
pf.close()
except Exception as e:
tdata['error'] = str(e)
- if(sysvals.rtcwake):
- sysvals.rtcWakeAlarmOff()
+ sv.dlog('system returned from resume')
+ # reset everything
+ sv.testVal('restoreall')
+ if(sv.rtcwake):
+ sv.dlog('disable RTC wake alarm')
+ sv.rtcWakeAlarmOff()
# postdelay delay
- if(count == sysvals.execcount and sysvals.postdelay > 0):
- sysvals.fsetVal('WAIT %d' % sysvals.postdelay, 'trace_marker')
- time.sleep(sysvals.postdelay/1000.0)
- sysvals.fsetVal('WAIT END', 'trace_marker')
+ if(count == sv.execcount and sv.postdelay > 0):
+ sv.fsetVal('WAIT %d' % sv.postdelay, 'trace_marker')
+ time.sleep(sv.postdelay/1000.0)
+ sv.fsetVal('WAIT END', 'trace_marker')
# return from suspend
pprint('RESUME COMPLETE')
- if(sysvals.usecallgraph or sysvals.usetraceevents):
- sysvals.fsetVal(datetime.now().strftime(sysvals.tmend), 'trace_marker')
- if sysvals.wifi and wifi:
- tdata['wifi'] = sysvals.pollWifi(wifi)
- if(sysvals.suspendmode == 'mem' or sysvals.suspendmode == 'command'):
+ if(sv.usecallgraph or sv.usetraceevents):
+ sv.fsetVal(datetime.now().strftime(sv.tmend), 'trace_marker')
+ if sv.wifi and wifi:
+ tdata['wifi'] = sv.pollWifi(wifi)
+ sv.dlog('wifi check, %s' % tdata['wifi'])
+ if(sv.suspendmode == 'mem' or sv.suspendmode == 'command'):
+ sv.dlog('read the ACPI FPDT')
tdata['fw'] = getFPDT(False)
testdata.append(tdata)
- cmdafter = sysvals.cmdinfo(False)
+ sv.dlog('run the cmdinfo list after')
+ cmdafter = sv.cmdinfo(False)
# stop ftrace
- if(sysvals.usecallgraph or sysvals.usetraceevents):
- if sysvals.useprocmon:
+ if(sv.usecallgraph or sv.usetraceevents):
+ if sv.useprocmon:
+ sv.dlog('stop the process monitor')
pm.stop()
- sysvals.fsetVal('0', 'tracing_on')
+ sv.fsetVal('0', 'tracing_on')
# grab a copy of the dmesg output
if not quiet:
pprint('CAPTURING DMESG')
- sysvals.getdmesg(testdata)
+ sysvals.dlog('EXECUTION TRACE END')
+ sv.getdmesg(testdata)
# grab a copy of the ftrace output
- if(sysvals.usecallgraph or sysvals.usetraceevents):
+ if(sv.usecallgraph or sv.usetraceevents):
if not quiet:
pprint('CAPTURING TRACE')
- op = sysvals.writeDatafileHeader(sysvals.ftracefile, testdata)
+ op = sv.writeDatafileHeader(sv.ftracefile, testdata)
fp = open(tp+'trace', 'r')
for line in fp:
op.write(line)
op.close()
- sysvals.fsetVal('', 'trace')
- sysvals.platforminfo(cmdafter)
+ sv.fsetVal('', 'trace')
+ sv.platforminfo(cmdafter)
def readFile(file):
if os.path.islink(file):
@@ -5586,39 +5659,6 @@ def dmidecode(mempath, fatal=False):
count += 1
return out
-def displayControl(cmd):
- xset, ret = 'timeout 10 xset -d :0.0 {0}', 0
- if sysvals.sudouser:
- xset = 'sudo -u %s %s' % (sysvals.sudouser, xset)
- if cmd == 'init':
- ret = call(xset.format('dpms 0 0 0'), shell=True)
- if not ret:
- ret = call(xset.format('s off'), shell=True)
- elif cmd == 'reset':
- ret = call(xset.format('s reset'), shell=True)
- elif cmd in ['on', 'off', 'standby', 'suspend']:
- b4 = displayControl('stat')
- ret = call(xset.format('dpms force %s' % cmd), shell=True)
- if not ret:
- curr = displayControl('stat')
- sysvals.vprint('Display Switched: %s -> %s' % (b4, curr))
- if curr != cmd:
- sysvals.vprint('WARNING: Display failed to change to %s' % cmd)
- if ret:
- sysvals.vprint('WARNING: Display failed to change to %s with xset' % cmd)
- return ret
- elif cmd == 'stat':
- fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout
- ret = 'unknown'
- for line in fp:
- m = re.match('[\s]*Monitor is (?P<m>.*)', ascii(line))
- if(m and len(m.group('m')) >= 2):
- out = m.group('m').lower()
- ret = out[3:] if out[0:2] == 'in' else out
- break
- fp.close()
- return ret
-
# Function: getFPDT
# Description:
# Read the acpi bios tables and pull out FPDT, the firmware data
@@ -6001,8 +6041,19 @@ def rerunTest(htmlfile=''):
# execute a suspend/resume, gather the logs, and generate the output
def runTest(n=0, quiet=False):
# prepare for the test
- sysvals.initFtrace(quiet)
sysvals.initTestOutput('suspend')
+ op = sysvals.writeDatafileHeader(sysvals.dmesgfile, [])
+ op.write('# EXECUTION TRACE START\n')
+ op.close()
+ if n <= 1:
+ if sysvals.rs != 0:
+ sysvals.dlog('%sabling runtime suspend' % ('en' if sysvals.rs > 0 else 'dis'))
+ sysvals.setRuntimeSuspend(True)
+ if sysvals.display:
+ ret = sysvals.displayControl('init')
+ sysvals.dlog('xset display init, ret = %d' % ret)
+ sysvals.dlog('initialize ftrace')
+ sysvals.initFtrace(quiet)
# execute the test
executeSuspend(quiet)
@@ -6098,8 +6149,16 @@ def data_from_html(file, outpath, issues, fulldetail=False):
if wifi:
extra['wifi'] = wifi
low = find_in_html(html, 'freeze time: <b>', ' ms</b>')
- if low and 'waking' in low:
- issue = 'FREEZEWAKE'
+ for lowstr in ['waking', '+']:
+ if not low:
+ break
+ if lowstr not in low:
+ continue
+ if lowstr == '+':
+ issue = 'S2LOOPx%d' % len(low.split('+'))
+ else:
+ m = re.match('.*waking *(?P<n>[0-9]*) *times.*', low)
+ issue = 'S2WAKEx%s' % m.group('n') if m else 'S2WAKExNaN'
match = [i for i in issues if i['match'] == issue]
if len(match) > 0:
match[0]['count'] += 1
@@ -6605,6 +6664,11 @@ if __name__ == '__main__':
val = next(args)
except:
doError('-info requires one string argument', True)
+ elif(arg == '-desc'):
+ try:
+ val = next(args)
+ except:
+ doError('-desc requires one string argument', True)
elif(arg == '-rs'):
try:
val = next(args)
@@ -6814,9 +6878,9 @@ if __name__ == '__main__':
runSummary(sysvals.outdir, True, genhtml)
elif(cmd in ['xon', 'xoff', 'xstandby', 'xsuspend', 'xinit', 'xreset']):
sysvals.verbose = True
- ret = displayControl(cmd[1:])
+ ret = sysvals.displayControl(cmd[1:])
elif(cmd == 'xstat'):
- pprint('Display Status: %s' % displayControl('stat').upper())
+ pprint('Display Status: %s' % sysvals.displayControl('stat').upper())
elif(cmd == 'wificheck'):
dev = sysvals.checkWifi()
if dev:
@@ -6854,12 +6918,8 @@ if __name__ == '__main__':
if mode.startswith('disk-'):
sysvals.diskmode = mode.split('-', 1)[-1]
sysvals.suspendmode = 'disk'
-
sysvals.systemInfo(dmidecode(sysvals.mempath))
- setRuntimeSuspend(True)
- if sysvals.display:
- displayControl('init')
failcnt, ret = 0, 0
if sysvals.multitest['run']:
# run multiple tests in a separate subdirectory
@@ -6900,7 +6960,10 @@ if __name__ == '__main__':
sysvals.testdir = sysvals.outdir
# run the test in the current directory
ret = runTest()
+
+ # reset to default values after testing
if sysvals.display:
- displayControl('reset')
- setRuntimeSuspend(False)
+ sysvals.displayControl('reset')
+ if sysvals.rs != 0:
+ sysvals.setRuntimeSuspend(False)
sys.exit(ret)