pm-graph v5.10

sleepgraph:
- add -wifitrace argument for tracing all the way to wifi reconnect
- include more data in ftrace to mark the end of kernel resume
- add async_synchronize_full to the list of funcs to chart
- add thermal zone info to the log data
- include a check for s0ix support (s2idle is the default mem_sleep)
- if s2idle does not support s0ix, remove the SYS%LPI turbostat var
- fix -dev crash when kprobe caller is just an address (not a symbol)
- fix the cpuexec data in -proc to display in resume

sleepgraph.8:
- add -wifitrace documentation

README:
- change links from 01.org to developer.intel.com

Signed-off-by: Todd Brandt <todd.e.brandt@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Todd Brandt 2022-10-20 02:23:10 -07:00 committed by Rafael J. Wysocki
parent 247f34f7b8
commit 9bfb09774e
3 changed files with 118 additions and 122 deletions

View File

@ -6,22 +6,22 @@
|_| |___/ |_| |_| |___/ |_|
pm-graph: suspend/resume/boot timing analysis tools pm-graph: suspend/resume/boot timing analysis tools
Version: 5.9 Version: 5.10
Author: Todd Brandt <todd.e.brandt@intel.com> Author: Todd Brandt <todd.e.brandt@intel.com>
Home Page: https://01.org/pm-graph Home Page: https://www.intel.com/content/www/us/en/developer/topic-technology/open/pm-graph/overview.html
Report bugs/issues at bugzilla.kernel.org Tools/pm-graph Report bugs/issues at bugzilla.kernel.org Tools/pm-graph
- https://bugzilla.kernel.org/buglist.cgi?component=pm-graph&product=Tools - https://bugzilla.kernel.org/buglist.cgi?component=pm-graph&product=Tools
Full documentation available online & in man pages Full documentation available online & in man pages
- Getting Started: - Getting Started:
https://01.org/pm-graph/documentation/getting-started https://www.intel.com/content/www/us/en/developer/articles/technical/usage.html
- Config File Format: - Feature Summary:
https://01.org/pm-graph/documentation/3-config-file-format https://www.intel.com/content/www/us/en/developer/topic-technology/open/pm-graph/features.html
- upstream version in git: - upstream version in git:
https://github.com/intel/pm-graph/ git clone https://github.com/intel/pm-graph/
Table of Contents Table of Contents
- Overview - Overview

View File

@ -78,6 +78,9 @@ This helps maintain the consistency of test data for better comparison.
If a wifi connection is available, check that it reconnects after resume. Include If a wifi connection is available, check that it reconnects after resume. Include
the reconnect time in the total resume time calculation and treat wifi timeouts the reconnect time in the total resume time calculation and treat wifi timeouts
as resume failures. as resume failures.
.TP
\fB-wifitrace\fR
Trace through the wifi reconnect time and include it in the timeline.
.SS "advanced" .SS "advanced"
.TP .TP

View File

@ -86,7 +86,7 @@ def ascii(text):
# store system values and test parameters # store system values and test parameters
class SystemValues: class SystemValues:
title = 'SleepGraph' title = 'SleepGraph'
version = '5.9' version = '5.10'
ansi = False ansi = False
rs = 0 rs = 0
display = '' display = ''
@ -100,6 +100,7 @@ class SystemValues:
ftracelog = False ftracelog = False
acpidebug = True acpidebug = True
tstat = True tstat = True
wifitrace = False
mindevlen = 0.0001 mindevlen = 0.0001
mincglen = 0.0 mincglen = 0.0
cgphase = '' cgphase = ''
@ -124,6 +125,7 @@ class SystemValues:
epath = '/sys/kernel/debug/tracing/events/power/' epath = '/sys/kernel/debug/tracing/events/power/'
pmdpath = '/sys/power/pm_debug_messages' pmdpath = '/sys/power/pm_debug_messages'
s0ixpath = '/sys/module/intel_pmc_core/parameters/warn_on_s0ix_failures' s0ixpath = '/sys/module/intel_pmc_core/parameters/warn_on_s0ix_failures'
s0ixres = '/sys/devices/system/cpu/cpuidle/low_power_idle_system_residency_us'
acpipath='/sys/module/acpi/parameters/debug_level' acpipath='/sys/module/acpi/parameters/debug_level'
traceevents = [ traceevents = [
'suspend_resume', 'suspend_resume',
@ -180,6 +182,7 @@ class SystemValues:
tmstart = 'SUSPEND START %Y%m%d-%H:%M:%S.%f' tmstart = 'SUSPEND START %Y%m%d-%H:%M:%S.%f'
tmend = 'RESUME COMPLETE %Y%m%d-%H:%M:%S.%f' tmend = 'RESUME COMPLETE %Y%m%d-%H:%M:%S.%f'
tracefuncs = { tracefuncs = {
'async_synchronize_full': {},
'sys_sync': {}, 'sys_sync': {},
'ksys_sync': {}, 'ksys_sync': {},
'__pm_notifier_call_chain': {}, '__pm_notifier_call_chain': {},
@ -304,6 +307,7 @@ class SystemValues:
[2, 'suspendstats', 'sh', '-c', 'grep -v invalid /sys/power/suspend_stats/*'], [2, 'suspendstats', 'sh', '-c', 'grep -v invalid /sys/power/suspend_stats/*'],
[2, 'cpuidle', 'sh', '-c', 'grep -v invalid /sys/devices/system/cpu/cpu*/cpuidle/state*/s2idle/*'], [2, 'cpuidle', 'sh', '-c', 'grep -v invalid /sys/devices/system/cpu/cpu*/cpuidle/state*/s2idle/*'],
[2, 'battery', 'sh', '-c', 'grep -v invalid /sys/class/power_supply/*/*'], [2, 'battery', 'sh', '-c', 'grep -v invalid /sys/class/power_supply/*/*'],
[2, 'thermal', 'sh', '-c', 'grep . /sys/class/thermal/thermal_zone*/temp'],
] ]
cgblacklist = [] cgblacklist = []
kprobes = dict() kprobes = dict()
@ -777,7 +781,7 @@ class SystemValues:
return return
if not quiet: if not quiet:
sysvals.printSystemInfo(False) sysvals.printSystemInfo(False)
pprint('INITIALIZING FTRACE...') pprint('INITIALIZING FTRACE')
# turn trace off # turn trace off
self.fsetVal('0', 'tracing_on') self.fsetVal('0', 'tracing_on')
self.cleanupFtrace() self.cleanupFtrace()
@ -841,7 +845,7 @@ class SystemValues:
for name in self.dev_tracefuncs: for name in self.dev_tracefuncs:
self.defaultKprobe(name, self.dev_tracefuncs[name]) self.defaultKprobe(name, self.dev_tracefuncs[name])
if not quiet: if not quiet:
pprint('INITIALIZING KPROBES...') pprint('INITIALIZING KPROBES')
self.addKprobes(self.verbose) self.addKprobes(self.verbose)
if(self.usetraceevents): if(self.usetraceevents):
# turn trace events on # turn trace events on
@ -1133,6 +1137,15 @@ class SystemValues:
self.cfgdef[file] = fp.read().strip() self.cfgdef[file] = fp.read().strip()
fp.write(value) fp.write(value)
fp.close() fp.close()
def s0ixSupport(self):
if not os.path.exists(self.s0ixres) or not os.path.exists(self.mempowerfile):
return False
fp = open(sysvals.mempowerfile, 'r')
data = fp.read().strip()
fp.close()
if '[s2idle]' in data:
return True
return False
def haveTurbostat(self): def haveTurbostat(self):
if not self.tstat: if not self.tstat:
return False return False
@ -1146,7 +1159,7 @@ class SystemValues:
self.vprint(out) self.vprint(out)
return True return True
return False return False
def turbostat(self): def turbostat(self, s0ixready):
cmd = self.getExec('turbostat') cmd = self.getExec('turbostat')
rawout = keyline = valline = '' rawout = keyline = valline = ''
fullcmd = '%s -q -S echo freeze > %s' % (cmd, self.powerfile) fullcmd = '%s -q -S echo freeze > %s' % (cmd, self.powerfile)
@ -1173,6 +1186,8 @@ class SystemValues:
for key in keyline: for key in keyline:
idx = keyline.index(key) idx = keyline.index(key)
val = valline[idx] val = valline[idx]
if key == 'SYS%LPI' and not s0ixready and re.match('^[0\.]*$', val):
continue
out.append('%s=%s' % (key, val)) out.append('%s=%s' % (key, val))
return '|'.join(out) return '|'.join(out)
def netfixon(self, net='both'): def netfixon(self, net='both'):
@ -1183,14 +1198,6 @@ class SystemValues:
out = ascii(fp.read()).strip() out = ascii(fp.read()).strip()
fp.close() fp.close()
return out return out
def wifiRepair(self):
out = self.netfixon('wifi')
if not out or 'error' in out.lower():
return ''
m = re.match('WIFI \S* ONLINE (?P<action>\S*)', out)
if not m:
return 'dead'
return m.group('action')
def wifiDetails(self, dev): def wifiDetails(self, dev):
try: try:
info = open('/sys/class/net/%s/device/uevent' % dev, 'r').read().strip() info = open('/sys/class/net/%s/device/uevent' % dev, 'r').read().strip()
@ -1220,11 +1227,6 @@ class SystemValues:
return '%s reconnected %.2f' % \ return '%s reconnected %.2f' % \
(self.wifiDetails(dev), max(0, time.time() - start)) (self.wifiDetails(dev), max(0, time.time() - start))
time.sleep(0.01) time.sleep(0.01)
if self.netfix:
res = self.wifiRepair()
if res:
timeout = max(0, time.time() - start)
return '%s %s %d' % (self.wifiDetails(dev), res, timeout)
return '%s timeout %d' % (self.wifiDetails(dev), timeout) return '%s timeout %d' % (self.wifiDetails(dev), timeout)
def errorSummary(self, errinfo, msg): def errorSummary(self, errinfo, msg):
found = False found = False
@ -1346,6 +1348,20 @@ class SystemValues:
for i in self.rslist: for i in self.rslist:
self.setVal(self.rstgt, i) self.setVal(self.rstgt, i)
pprint('runtime suspend settings restored on %d devices' % len(self.rslist)) pprint('runtime suspend settings restored on %d devices' % len(self.rslist))
def start(self, pm):
if self.useftrace:
self.dlog('start ftrace tracing')
self.fsetVal('1', 'tracing_on')
if self.useprocmon:
self.dlog('start the process monitor')
pm.start()
def stop(self, pm):
if self.useftrace:
if self.useprocmon:
self.dlog('stop the process monitor')
pm.stop()
self.dlog('stop ftrace tracing')
self.fsetVal('0', 'tracing_on')
sysvals = SystemValues() sysvals = SystemValues()
switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0'] switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0']
@ -1643,19 +1659,20 @@ class Data:
ubiquitous = False ubiquitous = False
if kprobename in dtf and 'ub' in dtf[kprobename]: if kprobename in dtf and 'ub' in dtf[kprobename]:
ubiquitous = True ubiquitous = True
title = cdata+' '+rdata mc = re.match('\(.*\) *(?P<args>.*)', cdata)
mstr = '\(.*\) *(?P<args>.*) *\((?P<caller>.*)\+.* arg1=(?P<ret>.*)' mr = re.match('\((?P<caller>\S*).* arg1=(?P<ret>.*)', rdata)
m = re.match(mstr, title) if mc and mr:
if m: c = mr.group('caller').split('+')[0]
c = m.group('caller') a = mc.group('args').strip()
a = m.group('args').strip() r = mr.group('ret')
r = m.group('ret')
if len(r) > 6: if len(r) > 6:
r = '' r = ''
else: else:
r = 'ret=%s ' % r r = 'ret=%s ' % r
if ubiquitous and c in dtf and 'ub' in dtf[c]: if ubiquitous and c in dtf and 'ub' in dtf[c]:
return False return False
else:
return False
color = sysvals.kprobeColor(kprobename) color = sysvals.kprobeColor(kprobename)
e = DevFunction(displayname, a, c, r, start, end, ubiquitous, proc, pid, color) e = DevFunction(displayname, a, c, r, start, end, ubiquitous, proc, pid, color)
tgtdev['src'].append(e) tgtdev['src'].append(e)
@ -1772,6 +1789,14 @@ class Data:
e.time = self.trimTimeVal(e.time, t0, dT, left) e.time = self.trimTimeVal(e.time, t0, dT, left)
e.end = self.trimTimeVal(e.end, t0, dT, left) e.end = self.trimTimeVal(e.end, t0, dT, left)
e.length = e.end - e.time e.length = e.end - e.time
if('cpuexec' in d):
cpuexec = dict()
for e in d['cpuexec']:
c0, cN = e
c0 = self.trimTimeVal(c0, t0, dT, left)
cN = self.trimTimeVal(cN, t0, dT, left)
cpuexec[(c0, cN)] = d['cpuexec'][e]
d['cpuexec'] = cpuexec
for dir in ['suspend', 'resume']: for dir in ['suspend', 'resume']:
list = [] list = []
for e in self.errorinfo[dir]: for e in self.errorinfo[dir]:
@ -2086,75 +2111,43 @@ class Data:
return d return d
def addProcessUsageEvent(self, name, times): def addProcessUsageEvent(self, name, times):
# get the start and end times for this process # get the start and end times for this process
maxC = 0 cpuexec = dict()
tlast = 0 tlast = start = end = -1
start = -1
end = -1
for t in sorted(times): for t in sorted(times):
if tlast == 0: if tlast < 0:
tlast = t tlast = t
continue continue
if name in self.pstl[t]: if name in self.pstl[t] and self.pstl[t][name] > 0:
if start == -1 or tlast < start: if start < 0:
start = tlast start = tlast
if end == -1 or t > end: end, key = t, (tlast, t)
end = t maxj = (t - tlast) * 1024.0
cpuexec[key] = min(1.0, float(self.pstl[t][name]) / maxj)
tlast = t tlast = t
if start == -1 or end == -1: if start < 0 or end < 0:
return 0 return
# add a new action for this process and get the object # add a new action for this process and get the object
out = self.newActionGlobal(name, start, end, -3) out = self.newActionGlobal(name, start, end, -3)
if not out: if out:
return 0 phase, devname = out
phase, devname = out dev = self.dmesg[phase]['list'][devname]
dev = self.dmesg[phase]['list'][devname] dev['cpuexec'] = cpuexec
# get the cpu exec data
tlast = 0
clast = 0
cpuexec = dict()
for t in sorted(times):
if tlast == 0 or t <= start or t > end:
tlast = t
continue
list = self.pstl[t]
c = 0
if name in list:
c = list[name]
if c > maxC:
maxC = c
if c != clast:
key = (tlast, t)
cpuexec[key] = c
tlast = t
clast = c
dev['cpuexec'] = cpuexec
return maxC
def createProcessUsageEvents(self): def createProcessUsageEvents(self):
# get an array of process names # get an array of process names and times
proclist = [] proclist = {'sus': dict(), 'res': dict()}
tdata = {'sus': [], 'res': []}
for t in sorted(self.pstl): for t in sorted(self.pstl):
pslist = self.pstl[t] dir = 'sus' if t < self.tSuspended else 'res'
for ps in sorted(pslist): for ps in sorted(self.pstl[t]):
if ps not in proclist: if ps not in proclist[dir]:
proclist.append(ps) proclist[dir][ps] = 0
# get a list of data points for suspend and resume tdata[dir].append(t)
tsus = []
tres = []
for t in sorted(self.pstl):
if t < self.tSuspended:
tsus.append(t)
else:
tres.append(t)
# process the events for suspend and resume # process the events for suspend and resume
if len(proclist) > 0: if len(proclist['sus']) > 0 or len(proclist['res']) > 0:
sysvals.vprint('Process Execution:') sysvals.vprint('Process Execution:')
for ps in proclist: for dir in ['sus', 'res']:
c = self.addProcessUsageEvent(ps, tsus) for ps in sorted(proclist[dir]):
if c > 0: self.addProcessUsageEvent(ps, tdata[dir])
sysvals.vprint('%25s (sus): %d' % (ps, c))
c = self.addProcessUsageEvent(ps, tres)
if c > 0:
sysvals.vprint('%25s (res): %d' % (ps, c))
def handleEndMarker(self, time, msg=''): def handleEndMarker(self, time, msg=''):
dm = self.dmesg dm = self.dmesg
self.setEnd(time, msg) self.setEnd(time, msg)
@ -3218,7 +3211,7 @@ class ProcessMonitor:
# markers, and/or kprobes required for primary parsing. # markers, and/or kprobes required for primary parsing.
def doesTraceLogHaveTraceEvents(): def doesTraceLogHaveTraceEvents():
kpcheck = ['_cal: (', '_ret: ('] kpcheck = ['_cal: (', '_ret: (']
techeck = ['suspend_resume', 'device_pm_callback'] techeck = ['suspend_resume', 'device_pm_callback', 'tracing_mark_write']
tmcheck = ['SUSPEND START', 'RESUME COMPLETE'] tmcheck = ['SUSPEND START', 'RESUME COMPLETE']
sysvals.usekprobes = False sysvals.usekprobes = False
fp = sysvals.openlog(sysvals.ftracefile, 'r') fp = sysvals.openlog(sysvals.ftracefile, 'r')
@ -3241,7 +3234,7 @@ def doesTraceLogHaveTraceEvents():
check.remove(i) check.remove(i)
tmcheck = check tmcheck = check
fp.close() fp.close()
sysvals.usetraceevents = True if len(techeck) < 2 else False sysvals.usetraceevents = True if len(techeck) < 3 else False
sysvals.usetracemarkers = True if len(tmcheck) == 0 else False sysvals.usetracemarkers = True if len(tmcheck) == 0 else False
# Function: appendIncompleteTraceLog # Function: appendIncompleteTraceLog
@ -3456,6 +3449,8 @@ def parseTraceLog(live=False):
continue continue
# process cpu exec line # process cpu exec line
if t.type == 'tracing_mark_write': if t.type == 'tracing_mark_write':
if t.name == 'CMD COMPLETE' and data.tKernRes == 0:
data.tKernRes = t.time
m = re.match(tp.procexecfmt, t.name) m = re.match(tp.procexecfmt, t.name)
if(m): if(m):
parts, msg = 1, m.group('ps') parts, msg = 1, m.group('ps')
@ -3674,6 +3669,9 @@ def parseTraceLog(live=False):
e = next((x for x in reversed(tp.ktemp[key]) if x['end'] < 0), 0) e = next((x for x in reversed(tp.ktemp[key]) if x['end'] < 0), 0)
if not e: if not e:
continue continue
if (t.time - e['begin']) * 1000 < sysvals.mindevlen:
tp.ktemp[key].pop()
continue
e['end'] = t.time e['end'] = t.time
e['rdata'] = kprobedata e['rdata'] = kprobedata
# end of kernel resume # end of kernel resume
@ -4213,6 +4211,8 @@ def callgraphHTML(sv, hf, num, cg, title, color, devid):
fmt = '<n>(%.3f ms @ '+sv.timeformat+')</n>' fmt = '<n>(%.3f ms @ '+sv.timeformat+')</n>'
flen = fmt % (line.length*1000, line.time) flen = fmt % (line.length*1000, line.time)
if line.isLeaf(): if line.isLeaf():
if line.length * 1000 < sv.mincglen:
continue
hf.write(html_func_leaf.format(line.name, flen)) hf.write(html_func_leaf.format(line.name, flen))
elif line.freturn: elif line.freturn:
hf.write(html_func_end) hf.write(html_func_end)
@ -4827,14 +4827,11 @@ def createHTML(testruns, testfail):
if('cpuexec' in dev): if('cpuexec' in dev):
for t in sorted(dev['cpuexec']): for t in sorted(dev['cpuexec']):
start, end = t start, end = t
j = float(dev['cpuexec'][t]) / 5
if j > 1.0:
j = 1.0
height = '%.3f' % (rowheight/3) height = '%.3f' % (rowheight/3)
top = '%.3f' % (rowtop + devtl.scaleH + 2*rowheight/3) top = '%.3f' % (rowtop + devtl.scaleH + 2*rowheight/3)
left = '%f' % (((start-m0)*100)/mTotal) left = '%f' % (((start-m0)*100)/mTotal)
width = '%f' % ((end-start)*100/mTotal) width = '%f' % ((end-start)*100/mTotal)
color = 'rgba(255, 0, 0, %f)' % j color = 'rgba(255, 0, 0, %f)' % dev['cpuexec'][t]
devtl.html += \ devtl.html += \
html_cpuexec.format(left, top, height, width, color) html_cpuexec.format(left, top, height, width, color)
if('src' not in dev): if('src' not in dev):
@ -5453,17 +5450,9 @@ def executeSuspend(quiet=False):
call('sync', shell=True) call('sync', shell=True)
sv.dlog('read dmesg') sv.dlog('read dmesg')
sv.initdmesg() sv.initdmesg()
# start ftrace sv.dlog('cmdinfo before')
if sv.useftrace:
if not quiet:
pprint('START TRACING')
sv.dlog('start ftrace tracing')
sv.fsetVal('1', 'tracing_on')
if sv.useprocmon:
sv.dlog('start the process monitor')
pm.start()
sv.dlog('run the cmdinfo list before')
sv.cmdinfo(True) sv.cmdinfo(True)
sv.start(pm)
# execute however many s/r runs requested # execute however many s/r runs requested
for count in range(1,sv.execcount+1): for count in range(1,sv.execcount+1):
# x2delay in between test runs # x2delay in between test runs
@ -5500,6 +5489,7 @@ def executeSuspend(quiet=False):
if res != 0: if res != 0:
tdata['error'] = 'cmd returned %d' % res tdata['error'] = 'cmd returned %d' % res
else: else:
s0ixready = sv.s0ixSupport()
mode = sv.suspendmode mode = sv.suspendmode
if sv.memmode and os.path.exists(sv.mempowerfile): if sv.memmode and os.path.exists(sv.mempowerfile):
mode = 'mem' mode = 'mem'
@ -5509,9 +5499,10 @@ def executeSuspend(quiet=False):
sv.testVal(sv.diskpowerfile, 'radio', sv.diskmode) sv.testVal(sv.diskpowerfile, 'radio', sv.diskmode)
if sv.acpidebug: if sv.acpidebug:
sv.testVal(sv.acpipath, 'acpi', '0xe') sv.testVal(sv.acpipath, 'acpi', '0xe')
if mode == 'freeze' and sv.haveTurbostat(): if ((mode == 'freeze') or (sv.memmode == 's2idle')) \
and sv.haveTurbostat():
# execution will pause here # execution will pause here
turbo = sv.turbostat() turbo = sv.turbostat(s0ixready)
if turbo: if turbo:
tdata['turbo'] = turbo tdata['turbo'] = turbo
else: else:
@ -5522,7 +5513,8 @@ def executeSuspend(quiet=False):
pf.close() pf.close()
except Exception as e: except Exception as e:
tdata['error'] = str(e) tdata['error'] = str(e)
sv.dlog('system returned from resume') sv.fsetVal('CMD COMPLETE', 'trace_marker')
sv.dlog('system returned')
# reset everything # reset everything
sv.testVal('restoreall') sv.testVal('restoreall')
if(sv.rtcwake): if(sv.rtcwake):
@ -5535,33 +5527,29 @@ def executeSuspend(quiet=False):
sv.fsetVal('WAIT END', 'trace_marker') sv.fsetVal('WAIT END', 'trace_marker')
# return from suspend # return from suspend
pprint('RESUME COMPLETE') pprint('RESUME COMPLETE')
sv.fsetVal(datetime.now().strftime(sv.tmend), 'trace_marker') if(count < sv.execcount):
sv.fsetVal(datetime.now().strftime(sv.tmend), 'trace_marker')
elif(not sv.wifitrace):
sv.fsetVal(datetime.now().strftime(sv.tmend), 'trace_marker')
sv.stop(pm)
if sv.wifi and wifi: if sv.wifi and wifi:
tdata['wifi'] = sv.pollWifi(wifi) tdata['wifi'] = sv.pollWifi(wifi)
sv.dlog('wifi check, %s' % tdata['wifi']) sv.dlog('wifi check, %s' % tdata['wifi'])
if sv.netfix: if(count == sv.execcount and sv.wifitrace):
netfixout = sv.netfixon('wired') sv.fsetVal(datetime.now().strftime(sv.tmend), 'trace_marker')
elif sv.netfix: sv.stop(pm)
netfixout = sv.netfixon() if sv.netfix:
if sv.netfix and netfixout: tdata['netfix'] = sv.netfixon()
tdata['netfix'] = netfixout
sv.dlog('netfix, %s' % tdata['netfix']) sv.dlog('netfix, %s' % tdata['netfix'])
if(sv.suspendmode == 'mem' or sv.suspendmode == 'command'): if(sv.suspendmode == 'mem' or sv.suspendmode == 'command'):
sv.dlog('read the ACPI FPDT') sv.dlog('read the ACPI FPDT')
tdata['fw'] = getFPDT(False) tdata['fw'] = getFPDT(False)
testdata.append(tdata) testdata.append(tdata)
sv.dlog('run the cmdinfo list after') sv.dlog('cmdinfo after')
cmdafter = sv.cmdinfo(False) cmdafter = sv.cmdinfo(False)
# stop ftrace
if sv.useftrace:
if sv.useprocmon:
sv.dlog('stop the process monitor')
pm.stop()
sv.fsetVal('0', 'tracing_on')
# grab a copy of the dmesg output # grab a copy of the dmesg output
if not quiet: if not quiet:
pprint('CAPTURING DMESG') pprint('CAPTURING DMESG')
sysvals.dlog('EXECUTION TRACE END')
sv.getdmesg(testdata) sv.getdmesg(testdata)
# grab a copy of the ftrace output # grab a copy of the ftrace output
if sv.useftrace: if sv.useftrace:
@ -6350,6 +6338,8 @@ def data_from_html(file, outpath, issues, fulldetail=False):
if not m: if not m:
continue continue
name, time, phase = m.group('n'), m.group('t'), m.group('p') name, time, phase = m.group('n'), m.group('t'), m.group('p')
if name == 'async_synchronize_full':
continue
if ' async' in name or ' sync' in name: if ' async' in name or ' sync' in name:
name = ' '.join(name.split(' ')[:-1]) name = ' '.join(name.split(' ')[:-1])
if phase.startswith('suspend'): if phase.startswith('suspend'):
@ -6701,6 +6691,7 @@ def printHelp():
' -skiphtml Run the test and capture the trace logs, but skip the timeline (default: disabled)\n'\ ' -skiphtml Run the test and capture the trace logs, but skip the timeline (default: disabled)\n'\
' -result fn Export a results table to a text file for parsing.\n'\ ' -result fn Export a results table to a text file for parsing.\n'\
' -wifi If a wifi connection is available, check that it reconnects after resume.\n'\ ' -wifi If a wifi connection is available, check that it reconnects after resume.\n'\
' -wifitrace Trace kernel execution through wifi reconnect.\n'\
' -netfix Use netfix to reset the network in the event it fails to resume.\n'\ ' -netfix Use netfix to reset the network in the event it fails to resume.\n'\
' [testprep]\n'\ ' [testprep]\n'\
' -sync Sync the filesystems before starting the test\n'\ ' -sync Sync the filesystems before starting the test\n'\
@ -6828,6 +6819,8 @@ if __name__ == '__main__':
sysvals.sync = True sysvals.sync = True
elif(arg == '-wifi'): elif(arg == '-wifi'):
sysvals.wifi = True sysvals.wifi = True
elif(arg == '-wifitrace'):
sysvals.wifitrace = True
elif(arg == '-netfix'): elif(arg == '-netfix'):
sysvals.netfix = True sysvals.netfix = True
elif(arg == '-gzip'): elif(arg == '-gzip'):