aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-06-03 04:12:30 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-06-03 04:12:30 -0400
commit9b34ffa09d227131dd764657dd38ed43b22c5611 (patch)
tree32c6cc4c352c6ae343306ceadc91273fd452c7e0
parentba8042a85e8aebc8043deee2d396459f2c39a66d (diff)
parentffbb95aa2d8248eabd594e113718b478cdc576e3 (diff)
Merge back earlier PM tools material for v4.18.
-rwxr-xr-xtools/power/pm-graph/bootgraph.py2
-rw-r--r--tools/power/pm-graph/sleepgraph.84
-rwxr-xr-xtools/power/pm-graph/sleepgraph.py399
-rwxr-xr-xtools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py54
4 files changed, 302 insertions, 157 deletions
diff --git a/tools/power/pm-graph/bootgraph.py b/tools/power/pm-graph/bootgraph.py
index abb4c38f029b..8ee626c0f6a5 100755
--- a/tools/power/pm-graph/bootgraph.py
+++ b/tools/power/pm-graph/bootgraph.py
@@ -1,4 +1,4 @@
1#!/usr/bin/python 1#!/usr/bin/python2
2# 2#
3# Tool for analyzing boot timing 3# Tool for analyzing boot timing
4# Copyright (c) 2013, Intel Corporation. 4# Copyright (c) 2013, Intel Corporation.
diff --git a/tools/power/pm-graph/sleepgraph.8 b/tools/power/pm-graph/sleepgraph.8
index 18baaf6300c9..070be2cf7f74 100644
--- a/tools/power/pm-graph/sleepgraph.8
+++ b/tools/power/pm-graph/sleepgraph.8
@@ -168,6 +168,7 @@ Create a summary page of all tests in \fIindir\fR. Creates summary.html
168in the current folder. The output page is a table of tests with 168in the current folder. The output page is a table of tests with
169suspend and resume values sorted by suspend mode, host, and kernel. 169suspend and resume values sorted by suspend mode, host, and kernel.
170Includes test averages by mode and links to the test html files. 170Includes test averages by mode and links to the test html files.
171Use -genhtml to include tests with missing html.
171.TP 172.TP
172\fB-modes\fR 173\fB-modes\fR
173List available suspend modes. 174List available suspend modes.
@@ -179,6 +180,9 @@ with any options you intend to use to see if they will work.
179\fB-fpdt\fR 180\fB-fpdt\fR
180Print out the contents of the ACPI Firmware Performance Data Table. 181Print out the contents of the ACPI Firmware Performance Data Table.
181.TP 182.TP
183\fB-battery\fR
184Print out battery status and current charge.
185.TP
182\fB-sysinfo\fR 186\fB-sysinfo\fR
183Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode. 187Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode.
184.TP 188.TP
diff --git a/tools/power/pm-graph/sleepgraph.py b/tools/power/pm-graph/sleepgraph.py
index 266409fb27ae..0c760478f7d7 100755
--- a/tools/power/pm-graph/sleepgraph.py
+++ b/tools/power/pm-graph/sleepgraph.py
@@ -1,4 +1,4 @@
1#!/usr/bin/python 1#!/usr/bin/python2
2# 2#
3# Tool for analyzing suspend/resume timing 3# Tool for analyzing suspend/resume timing
4# Copyright (c) 2013, Intel Corporation. 4# Copyright (c) 2013, Intel Corporation.
@@ -69,7 +69,7 @@ from subprocess import call, Popen, PIPE
69# store system values and test parameters 69# store system values and test parameters
70class SystemValues: 70class SystemValues:
71 title = 'SleepGraph' 71 title = 'SleepGraph'
72 version = '5.0' 72 version = '5.1'
73 ansi = False 73 ansi = False
74 rs = 0 74 rs = 0
75 display = 0 75 display = 0
@@ -240,7 +240,7 @@ class SystemValues:
240 kprobes = dict() 240 kprobes = dict()
241 timeformat = '%.3f' 241 timeformat = '%.3f'
242 cmdline = '%s %s' % \ 242 cmdline = '%s %s' % \
243 (os.path.basename(sys.argv[0]), string.join(sys.argv[1:], ' ')) 243 (os.path.basename(sys.argv[0]), ' '.join(sys.argv[1:]))
244 def __init__(self): 244 def __init__(self):
245 self.archargs = 'args_'+platform.machine() 245 self.archargs = 'args_'+platform.machine()
246 self.hostname = platform.node() 246 self.hostname = platform.node()
@@ -917,12 +917,18 @@ class Data:
917 self.devicegroups.append([phase]) 917 self.devicegroups.append([phase])
918 self.errorinfo = {'suspend':[],'resume':[]} 918 self.errorinfo = {'suspend':[],'resume':[]}
919 def extractErrorInfo(self): 919 def extractErrorInfo(self):
920 elist = {
921 'HWERROR' : '.*\[ *Hardware Error *\].*',
922 'FWBUG' : '.*\[ *Firmware Bug *\].*',
923 'BUG' : '.*BUG.*',
924 'ERROR' : '.*ERROR.*',
925 'WARNING' : '.*WARNING.*',
926 'IRQ' : '.*genirq: .*',
927 'TASKFAIL': '.*Freezing of tasks failed.*',
928 }
920 lf = sysvals.openlog(sysvals.dmesgfile, 'r') 929 lf = sysvals.openlog(sysvals.dmesgfile, 'r')
921 i = 0 930 i = 0
922 list = [] 931 list = []
923 # sl = start line, et = error time, el = error line
924 type = 'ERROR'
925 sl = et = el = -1
926 for line in lf: 932 for line in lf:
927 i += 1 933 i += 1
928 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 934 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
@@ -931,43 +937,13 @@ class Data:
931 t = float(m.group('ktime')) 937 t = float(m.group('ktime'))
932 if t < self.start or t > self.end: 938 if t < self.start or t > self.end:
933 continue 939 continue
934 if t < self.tSuspended: 940 dir = 'suspend' if t < self.tSuspended else 'resume'
935 dir = 'suspend'
936 else:
937 dir = 'resume'
938 msg = m.group('msg') 941 msg = m.group('msg')
939 if re.match('-*\[ *cut here *\]-*', msg): 942 for err in elist:
940 type = 'WARNING' 943 if re.match(elist[err], msg):
941 sl = i 944 list.append((err, dir, t, i, i))
942 elif re.match('genirq: .*', msg):
943 type = 'IRQ'
944 sl = i
945 elif re.match('BUG: .*', msg) or re.match('kernel BUG .*', msg):
946 type = 'BUG'
947 sl = i
948 elif re.match('-*\[ *end trace .*\]-*', msg) or \
949 re.match('R13: .*', msg):
950 if et >= 0 and sl >= 0:
951 list.append((type, dir, et, sl, i))
952 self.kerror = True
953 sl = et = el = -1
954 type = 'ERROR'
955 elif 'Call Trace:' in msg:
956 if el >= 0 and et >= 0:
957 list.append((type, dir, et, el, el))
958 self.kerror = True 945 self.kerror = True
959 et, el = t, i 946 break
960 if sl < 0 or type == 'BUG':
961 slval = i
962 if sl >= 0:
963 slval = sl
964 list.append((type, dir, et, slval, i))
965 self.kerror = True
966 sl = et = el = -1
967 type = 'ERROR'
968 if el >= 0 and et >= 0:
969 list.append((type, dir, et, el, el))
970 self.kerror = True
971 for e in list: 947 for e in list:
972 type, dir, t, idx1, idx2 = e 948 type, dir, t, idx1, idx2 = e
973 sysvals.vprint('kernel %s found in %s at %f' % (type, dir, t)) 949 sysvals.vprint('kernel %s found in %s at %f' % (type, dir, t))
@@ -2331,12 +2307,14 @@ class TestProps:
2331 sv.suspendmode = data.stamp['mode'] 2307 sv.suspendmode = data.stamp['mode']
2332 if sv.suspendmode == 'command' and sv.ftracefile != '': 2308 if sv.suspendmode == 'command' and sv.ftracefile != '':
2333 modes = ['on', 'freeze', 'standby', 'mem', 'disk'] 2309 modes = ['on', 'freeze', 'standby', 'mem', 'disk']
2334 out = Popen(['grep', 'machine_suspend', sv.ftracefile], 2310 fp = sysvals.openlog(sv.ftracefile, 'r')
2335 stderr=PIPE, stdout=PIPE).stdout.read() 2311 for line in fp:
2336 m = re.match('.* machine_suspend\[(?P<mode>.*)\]', out) 2312 m = re.match('.* machine_suspend\[(?P<mode>.*)\]', line)
2337 if m and m.group('mode') in ['1', '2', '3', '4']: 2313 if m and m.group('mode') in ['1', '2', '3', '4']:
2338 sv.suspendmode = modes[int(m.group('mode'))] 2314 sv.suspendmode = modes[int(m.group('mode'))]
2339 data.stamp['mode'] = sv.suspendmode 2315 data.stamp['mode'] = sv.suspendmode
2316 break
2317 fp.close()
2340 m = re.match(self.cmdlinefmt, self.cmdline) 2318 m = re.match(self.cmdlinefmt, self.cmdline)
2341 if m: 2319 if m:
2342 sv.cmdline = m.group('cmd') 2320 sv.cmdline = m.group('cmd')
@@ -2413,7 +2391,7 @@ class ProcessMonitor:
2413# markers, and/or kprobes required for primary parsing. 2391# markers, and/or kprobes required for primary parsing.
2414def doesTraceLogHaveTraceEvents(): 2392def doesTraceLogHaveTraceEvents():
2415 kpcheck = ['_cal: (', '_cpu_down()'] 2393 kpcheck = ['_cal: (', '_cpu_down()']
2416 techeck = sysvals.traceevents[:] 2394 techeck = ['suspend_resume']
2417 tmcheck = ['SUSPEND START', 'RESUME COMPLETE'] 2395 tmcheck = ['SUSPEND START', 'RESUME COMPLETE']
2418 sysvals.usekprobes = False 2396 sysvals.usekprobes = False
2419 fp = sysvals.openlog(sysvals.ftracefile, 'r') 2397 fp = sysvals.openlog(sysvals.ftracefile, 'r')
@@ -2808,7 +2786,7 @@ def parseTraceLog(live=False):
2808 # -- phase changes -- 2786 # -- phase changes --
2809 # start of kernel suspend 2787 # start of kernel suspend
2810 if(re.match('suspend_enter\[.*', t.name)): 2788 if(re.match('suspend_enter\[.*', t.name)):
2811 if(isbegin): 2789 if(isbegin and data.start == data.tKernSus):
2812 data.dmesg[phase]['start'] = t.time 2790 data.dmesg[phase]['start'] = t.time
2813 data.tKernSus = t.time 2791 data.tKernSus = t.time
2814 continue 2792 continue
@@ -3072,13 +3050,20 @@ def parseTraceLog(live=False):
3072 sysvals.vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name)) 3050 sysvals.vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name))
3073 cg.newActionFromFunction(data) 3051 cg.newActionFromFunction(data)
3074 if sysvals.suspendmode == 'command': 3052 if sysvals.suspendmode == 'command':
3075 return testdata 3053 return (testdata, '')
3076 3054
3077 # fill in any missing phases 3055 # fill in any missing phases
3056 error = []
3078 for data in testdata: 3057 for data in testdata:
3058 tn = '' if len(testdata) == 1 else ('%d' % (data.testnumber + 1))
3059 terr = ''
3079 lp = data.phases[0] 3060 lp = data.phases[0]
3080 for p in data.phases: 3061 for p in data.phases:
3081 if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0): 3062 if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0):
3063 if not terr:
3064 print 'TEST%s FAILED: %s failed in %s phase' % (tn, sysvals.suspendmode, lp)
3065 terr = '%s%s failed in %s phase' % (sysvals.suspendmode, tn, lp)
3066 error.append(terr)
3082 sysvals.vprint('WARNING: phase "%s" is missing!' % p) 3067 sysvals.vprint('WARNING: phase "%s" is missing!' % p)
3083 if(data.dmesg[p]['start'] < 0): 3068 if(data.dmesg[p]['start'] < 0):
3084 data.dmesg[p]['start'] = data.dmesg[lp]['end'] 3069 data.dmesg[p]['start'] = data.dmesg[lp]['end']
@@ -3106,7 +3091,7 @@ def parseTraceLog(live=False):
3106 for j in range(i + 1, tc): 3091 for j in range(i + 1, tc):
3107 testdata[j].mergeOverlapDevices(devlist) 3092 testdata[j].mergeOverlapDevices(devlist)
3108 testdata[0].stitchTouchingThreads(testdata[1:]) 3093 testdata[0].stitchTouchingThreads(testdata[1:])
3109 return testdata 3094 return (testdata, ', '.join(error))
3110 3095
3111# Function: loadKernelLog 3096# Function: loadKernelLog
3112# Description: 3097# Description:
@@ -3173,7 +3158,7 @@ def loadKernelLog():
3173 if data: 3158 if data:
3174 testruns.append(data) 3159 testruns.append(data)
3175 if len(testruns) < 1: 3160 if len(testruns) < 1:
3176 doError(' dmesg log has no suspend/resume data: %s' \ 3161 print('ERROR: dmesg log has no suspend/resume data: %s' \
3177 % sysvals.dmesgfile) 3162 % sysvals.dmesgfile)
3178 3163
3179 # fix lines with same timestamp/function with the call and return swapped 3164 # fix lines with same timestamp/function with the call and return swapped
@@ -3521,68 +3506,144 @@ def createHTMLSummarySimple(testruns, htmlfile, folder):
3521 .summary {border:1px solid;}\n\ 3506 .summary {border:1px solid;}\n\
3522 th {border: 1px solid black;background:#222;color:white;}\n\ 3507 th {border: 1px solid black;background:#222;color:white;}\n\
3523 td {font: 16px "Times New Roman";text-align: center;}\n\ 3508 td {font: 16px "Times New Roman";text-align: center;}\n\
3524 tr.alt td {background:#ddd;}\n\ 3509 tr.head td {border: 1px solid black;background:#aaa;}\n\
3525 tr.avg td {background:#aaa;}\n\ 3510 tr.alt {background-color:#ddd;}\n\
3511 tr.notice {color:red;}\n\
3512 .minval {background-color:#BBFFBB;}\n\
3513 .medval {background-color:#BBBBFF;}\n\
3514 .maxval {background-color:#FFBBBB;}\n\
3515 .head a {color:#000;text-decoration: none;}\n\
3526 </style>\n</head>\n<body>\n' 3516 </style>\n</head>\n<body>\n'
3527 3517
3518 # extract the test data into list
3519 list = dict()
3520 tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [[], []]
3521 iMin, iMed, iMax = [0, 0], [0, 0], [0, 0]
3522 num = 0
3523 lastmode = ''
3524 cnt = {'pass':0, 'fail':0, 'hang':0}
3525 for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])):
3526 mode = data['mode']
3527 if mode not in list:
3528 list[mode] = {'data': [], 'avg': [0,0], 'min': [0,0], 'max': [0,0], 'med': [0,0]}
3529 if lastmode and lastmode != mode and num > 0:
3530 for i in range(2):
3531 s = sorted(tMed[i])
3532 list[lastmode]['med'][i] = s[int(len(s)/2)]
3533 iMed[i] = tMed[i].index(list[lastmode]['med'][i])
3534 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num]
3535 list[lastmode]['min'] = tMin
3536 list[lastmode]['max'] = tMax
3537 list[lastmode]['idx'] = (iMin, iMed, iMax)
3538 tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [[], []]
3539 iMin, iMed, iMax = [0, 0], [0, 0], [0, 0]
3540 num = 0
3541 tVal = [float(data['suspend']), float(data['resume'])]
3542 list[mode]['data'].append([data['host'], data['kernel'],
3543 data['time'], tVal[0], tVal[1], data['url'], data['result'],
3544 data['issues']])
3545 idx = len(list[mode]['data']) - 1
3546 if data['result'] == 'pass':
3547 cnt['pass'] += 1
3548 for i in range(2):
3549 tMed[i].append(tVal[i])
3550 tAvg[i] += tVal[i]
3551 if tMin[i] == 0 or tVal[i] < tMin[i]:
3552 iMin[i] = idx
3553 tMin[i] = tVal[i]
3554 if tMax[i] == 0 or tVal[i] > tMax[i]:
3555 iMax[i] = idx
3556 tMax[i] = tVal[i]
3557 num += 1
3558 elif data['result'] == 'hang':
3559 cnt['hang'] += 1
3560 elif data['result'] == 'fail':
3561 cnt['fail'] += 1
3562 lastmode = mode
3563 if lastmode and num > 0:
3564 for i in range(2):
3565 s = sorted(tMed[i])
3566 list[lastmode]['med'][i] = s[int(len(s)/2)]
3567 iMed[i] = tMed[i].index(list[lastmode]['med'][i])
3568 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num]
3569 list[lastmode]['min'] = tMin
3570 list[lastmode]['max'] = tMax
3571 list[lastmode]['idx'] = (iMin, iMed, iMax)
3572
3528 # group test header 3573 # group test header
3529 html += '<div class="stamp">%s (%d tests)</div>\n' % (folder, len(testruns)) 3574 desc = []
3575 for ilk in sorted(cnt, reverse=True):
3576 if cnt[ilk] > 0:
3577 desc.append('%d %s' % (cnt[ilk], ilk))
3578 html += '<div class="stamp">%s (%d tests: %s)</div>\n' % (folder, len(testruns), ', '.join(desc))
3530 th = '\t<th>{0}</th>\n' 3579 th = '\t<th>{0}</th>\n'
3531 td = '\t<td>{0}</td>\n' 3580 td = '\t<td>{0}</td>\n'
3581 tdh = '\t<td{1}>{0}</td>\n'
3532 tdlink = '\t<td><a href="{0}">html</a></td>\n' 3582 tdlink = '\t<td><a href="{0}">html</a></td>\n'
3533 3583
3534 # table header 3584 # table header
3535 html += '<table class="summary">\n<tr>\n' + th.format('#') +\ 3585 html += '<table class="summary">\n<tr>\n' + th.format('#') +\
3536 th.format('Mode') + th.format('Host') + th.format('Kernel') +\ 3586 th.format('Mode') + th.format('Host') + th.format('Kernel') +\
3537 th.format('Test Time') + th.format('Suspend') + th.format('Resume') +\ 3587 th.format('Test Time') + th.format('Result') + th.format('Issues') +\
3538 th.format('Detail') + '</tr>\n' 3588 th.format('Suspend') + th.format('Resume') + th.format('Detail') + '</tr>\n'
3539 3589
3540 # test data, 1 row per test 3590 # export list into html
3541 avg = '<tr class="avg"><td></td><td></td><td></td><td></td>'+\ 3591 head = '<tr class="head"><td>{0}</td><td>{1}</td>'+\
3542 '<td>Average of {0} {1} tests</td><td>{2}</td><td>{3}</td><td></td></tr>\n' 3592 '<td colspan=8 class="sus">Suspend Avg={2} '+\
3543 sTimeAvg = rTimeAvg = 0.0 3593 '<span class=minval><a href="#s{10}min">Min={3}</a></span> '+\
3544 mode = '' 3594 '<span class=medval><a href="#s{10}med">Med={4}</a></span> '+\
3545 num = 0 3595 '<span class=maxval><a href="#s{10}max">Max={5}</a></span> '+\
3546 for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])): 3596 'Resume Avg={6} '+\
3547 if mode != data['mode']: 3597 '<span class=minval><a href="#r{10}min">Min={7}</a></span> '+\
3548 # test average line 3598 '<span class=medval><a href="#r{10}med">Med={8}</a></span> '+\
3549 if(num > 0): 3599 '<span class=maxval><a href="#r{10}max">Max={9}</a></span></td>'+\
3550 sTimeAvg /= (num - 1) 3600 '</tr>\n'
3551 rTimeAvg /= (num - 1) 3601 headnone = '<tr class="head"><td>{0}</td><td>{1}</td><td colspan=8></td></tr>\n'
3552 html += avg.format('%d' % (num - 1), mode, 3602 for mode in list:
3553 '%3.3f ms' % sTimeAvg, '%3.3f ms' % rTimeAvg) 3603 # header line for each suspend mode
3554 sTimeAvg = rTimeAvg = 0.0 3604 num = 0
3555 mode = data['mode'] 3605 tAvg, tMin, tMax, tMed = list[mode]['avg'], list[mode]['min'],\
3556 num = 1 3606 list[mode]['max'], list[mode]['med']
3557 # alternate row color 3607 count = len(list[mode]['data'])
3558 if num % 2 == 1: 3608 if 'idx' in list[mode]:
3559 html += '<tr class="alt">\n' 3609 iMin, iMed, iMax = list[mode]['idx']
3610 html += head.format('%d' % count, mode.upper(),
3611 '%.3f' % tAvg[0], '%.3f' % tMin[0], '%.3f' % tMed[0], '%.3f' % tMax[0],
3612 '%.3f' % tAvg[1], '%.3f' % tMin[1], '%.3f' % tMed[1], '%.3f' % tMax[1],
3613 mode.lower()
3614 )
3560 else: 3615 else:
3561 html += '<tr>\n' 3616 iMin = iMed = iMax = [-1, -1, -1]
3562 html += td.format("%d" % num) 3617 html += headnone.format('%d' % count, mode.upper())
3563 num += 1 3618 for d in list[mode]['data']:
3564 # basic info 3619 # row classes - alternate row color
3565 for item in ['mode', 'host', 'kernel', 'time']: 3620 rcls = ['alt'] if num % 2 == 1 else []
3566 val = "unknown" 3621 if d[6] != 'pass':
3567 if(item in data): 3622 rcls.append('notice')
3568 val = data[item] 3623 html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n'
3569 html += td.format(val) 3624 # figure out if the line has sus or res highlighted
3570 # suspend time 3625 idx = list[mode]['data'].index(d)
3571 sTime = float(data['suspend']) 3626 tHigh = ['', '']
3572 sTimeAvg += sTime 3627 for i in range(2):
3573 html += td.format('%.3f ms' % sTime) 3628 tag = 's%s' % mode if i == 0 else 'r%s' % mode
3574 # resume time 3629 if idx == iMin[i]:
3575 rTime = float(data['resume']) 3630 tHigh[i] = ' id="%smin" class=minval title="Minimum"' % tag
3576 rTimeAvg += rTime 3631 elif idx == iMax[i]:
3577 html += td.format('%.3f ms' % rTime) 3632 tHigh[i] = ' id="%smax" class=maxval title="Maximum"' % tag
3578 # link to the output html 3633 elif idx == iMed[i]:
3579 html += tdlink.format(data['url']) + '</tr>\n' 3634 tHigh[i] = ' id="%smed" class=medval title="Median"' % tag
3580 # last test average line 3635 html += td.format("%d" % (list[mode]['data'].index(d) + 1)) # row
3581 if(num > 0): 3636 html += td.format(mode) # mode
3582 sTimeAvg /= (num - 1) 3637 html += td.format(d[0]) # host
3583 rTimeAvg /= (num - 1) 3638 html += td.format(d[1]) # kernel
3584 html += avg.format('%d' % (num - 1), mode, 3639 html += td.format(d[2]) # time
3585 '%3.3f ms' % sTimeAvg, '%3.3f ms' % rTimeAvg) 3640 html += td.format(d[6]) # result
3641 html += td.format(d[7]) # issues
3642 html += tdh.format('%.3f ms' % d[3], tHigh[0]) if d[3] else td.format('') # suspend
3643 html += tdh.format('%.3f ms' % d[4], tHigh[1]) if d[4] else td.format('') # resume
3644 html += tdlink.format(d[5]) if d[5] else td.format('') # url
3645 html += '</tr>\n'
3646 num += 1
3586 3647
3587 # flush the data to file 3648 # flush the data to file
3588 hf = open(htmlfile, 'w') 3649 hf = open(htmlfile, 'w')
@@ -3607,7 +3668,7 @@ def ordinal(value):
3607# testruns: array of Data objects from parseKernelLog or parseTraceLog 3668# testruns: array of Data objects from parseKernelLog or parseTraceLog
3608# Output: 3669# Output:
3609# True if the html file was created, false if it failed 3670# True if the html file was created, false if it failed
3610def createHTML(testruns): 3671def createHTML(testruns, testfail):
3611 if len(testruns) < 1: 3672 if len(testruns) < 1:
3612 print('ERROR: Not enough test data to build a timeline') 3673 print('ERROR: Not enough test data to build a timeline')
3613 return 3674 return
@@ -3641,6 +3702,7 @@ def createHTML(testruns):
3641 '<td class="purple">{4}Firmware Resume: {2} ms</td>'\ 3702 '<td class="purple">{4}Firmware Resume: {2} ms</td>'\
3642 '<td class="yellow" title="time from firmware mode to return from kernel enter_state({5}) [kernel time only]">{4}Kernel Resume: {3} ms</td>'\ 3703 '<td class="yellow" title="time from firmware mode to return from kernel enter_state({5}) [kernel time only]">{4}Kernel Resume: {3} ms</td>'\
3643 '</tr>\n</table>\n' 3704 '</tr>\n</table>\n'
3705 html_fail = '<table class="testfail"><tr><td>{0}</td></tr></table>\n'
3644 3706
3645 # html format variables 3707 # html format variables
3646 scaleH = 20 3708 scaleH = 20
@@ -3708,6 +3770,9 @@ def createHTML(testruns):
3708 resume_time, testdesc, stitle, rtitle) 3770 resume_time, testdesc, stitle, rtitle)
3709 devtl.html += thtml 3771 devtl.html += thtml
3710 3772
3773 if testfail:
3774 devtl.html += html_fail.format(testfail)
3775
3711 # time scale for potentially multiple datasets 3776 # time scale for potentially multiple datasets
3712 t0 = testruns[0].start 3777 t0 = testruns[0].start
3713 tMax = testruns[-1].end 3778 tMax = testruns[-1].end
@@ -4006,6 +4071,7 @@ def addCSS(hf, sv, testcount=1, kerror=False, extra=''):
4006 .blue {background:rgba(169,208,245,0.4);}\n\ 4071 .blue {background:rgba(169,208,245,0.4);}\n\
4007 .time1 {font:22px Arial;border:1px solid;}\n\ 4072 .time1 {font:22px Arial;border:1px solid;}\n\
4008 .time2 {font:15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\ 4073 .time2 {font:15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\
4074 .testfail {font:bold 22px Arial;color:red;border:1px dashed;}\n\
4009 td {text-align:center;}\n\ 4075 td {text-align:center;}\n\
4010 r {color:#500000;font:15px Tahoma;}\n\ 4076 r {color:#500000;font:15px Tahoma;}\n\
4011 n {color:#505050;font:15px Tahoma;}\n\ 4077 n {color:#505050;font:15px Tahoma;}\n\
@@ -4927,6 +4993,25 @@ def dmidecode(mempath, fatal=False):
4927 count += 1 4993 count += 1
4928 return out 4994 return out
4929 4995
4996def getBattery():
4997 p = '/sys/class/power_supply'
4998 bat = dict()
4999 for d in os.listdir(p):
5000 type = sysvals.getVal(os.path.join(p, d, 'type')).strip().lower()
5001 if type != 'battery':
5002 continue
5003 for v in ['status', 'energy_now', 'capacity_now']:
5004 bat[v] = sysvals.getVal(os.path.join(p, d, v)).strip().lower()
5005 break
5006 ac = True
5007 if 'status' in bat and 'discharging' in bat['status']:
5008 ac = False
5009 charge = 0
5010 for v in ['energy_now', 'capacity_now']:
5011 if v in bat and bat[v]:
5012 charge = int(bat[v])
5013 return (ac, charge)
5014
4930# Function: getFPDT 5015# Function: getFPDT
4931# Description: 5016# Description:
4932# Read the acpi bios tables and pull out FPDT, the firmware data 5017# Read the acpi bios tables and pull out FPDT, the firmware data
@@ -5202,8 +5287,9 @@ def getArgFloat(name, args, min, max, main=True):
5202 5287
5203def processData(live=False): 5288def processData(live=False):
5204 print('PROCESSING DATA') 5289 print('PROCESSING DATA')
5290 error = ''
5205 if(sysvals.usetraceevents): 5291 if(sysvals.usetraceevents):
5206 testruns = parseTraceLog(live) 5292 testruns, error = parseTraceLog(live)
5207 if sysvals.dmesgfile: 5293 if sysvals.dmesgfile:
5208 for data in testruns: 5294 for data in testruns:
5209 data.extractErrorInfo() 5295 data.extractErrorInfo()
@@ -5220,15 +5306,18 @@ def processData(live=False):
5220 for data in testruns: 5306 for data in testruns:
5221 data.debugPrint() 5307 data.debugPrint()
5222 sys.exit() 5308 sys.exit()
5223 5309 if len(testruns) < 1:
5310 return (testruns, {'error': 'timeline generation failed'})
5224 sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile) 5311 sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile)
5225 createHTML(testruns) 5312 createHTML(testruns, error)
5226 print('DONE') 5313 print('DONE')
5227 data = testruns[0] 5314 data = testruns[0]
5228 stamp = data.stamp 5315 stamp = data.stamp
5229 stamp['suspend'], stamp['resume'] = data.getTimeValues() 5316 stamp['suspend'], stamp['resume'] = data.getTimeValues()
5230 if data.fwValid: 5317 if data.fwValid:
5231 stamp['fwsuspend'], stamp['fwresume'] = data.fwSuspend, data.fwResume 5318 stamp['fwsuspend'], stamp['fwresume'] = data.fwSuspend, data.fwResume
5319 if error:
5320 stamp['error'] = error
5232 return (testruns, stamp) 5321 return (testruns, stamp)
5233 5322
5234# Function: rerunTest 5323# Function: rerunTest
@@ -5268,58 +5357,88 @@ def runTest(n=0):
5268 sysvals.sudouser(sysvals.testdir) 5357 sysvals.sudouser(sysvals.testdir)
5269 sysvals.outputResult(stamp, n) 5358 sysvals.outputResult(stamp, n)
5270 5359
5271def find_in_html(html, strs, div=False): 5360def find_in_html(html, start, end, firstonly=True):
5272 for str in strs: 5361 n, out = 0, []
5273 l = len(str) 5362 while n < len(html):
5274 i = html.find(str) 5363 m = re.search(start, html[n:])
5275 if i >= 0: 5364 if not m:
5276 break 5365 break
5277 if i < 0: 5366 i = m.end()
5278 return '' 5367 m = re.search(end, html[n+i:])
5279 if not div: 5368 if not m:
5280 return re.search(r'[-+]?\d*\.\d+|\d+', html[i+l:i+l+50]).group() 5369 break
5281 n = html[i+l:].find('</div>') 5370 j = m.start()
5282 if n < 0: 5371 str = html[n+i:n+i+j]
5372 if end == 'ms':
5373 num = re.search(r'[-+]?\d*\.\d+|\d+', str)
5374 str = num.group() if num else 'NaN'
5375 if firstonly:
5376 return str
5377 out.append(str)
5378 n += i+j
5379 if firstonly:
5283 return '' 5380 return ''
5284 return html[i+l:i+l+n] 5381 return out
5285 5382
5286# Function: runSummary 5383# Function: runSummary
5287# Description: 5384# Description:
5288# create a summary of tests in a sub-directory 5385# create a summary of tests in a sub-directory
5289def runSummary(subdir, local=True): 5386def runSummary(subdir, local=True, genhtml=False):
5290 inpath = os.path.abspath(subdir) 5387 inpath = os.path.abspath(subdir)
5291 outpath = inpath 5388 outpath = inpath
5292 if local: 5389 if local:
5293 outpath = os.path.abspath('.') 5390 outpath = os.path.abspath('.')
5294 print('Generating a summary of folder "%s"' % inpath) 5391 print('Generating a summary of folder "%s"' % inpath)
5392 if genhtml:
5393 for dirname, dirnames, filenames in os.walk(subdir):
5394 sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = ''
5395 for filename in filenames:
5396 if(re.match('.*_dmesg.txt', filename)):
5397 sysvals.dmesgfile = os.path.join(dirname, filename)
5398 elif(re.match('.*_ftrace.txt', filename)):
5399 sysvals.ftracefile = os.path.join(dirname, filename)
5400 sysvals.setOutputFile()
5401 if sysvals.ftracefile and sysvals.htmlfile and \
5402 not os.path.exists(sysvals.htmlfile):
5403 print('FTRACE: %s' % sysvals.ftracefile)
5404 if sysvals.dmesgfile:
5405 print('DMESG : %s' % sysvals.dmesgfile)
5406 rerunTest()
5295 testruns = [] 5407 testruns = []
5296 for dirname, dirnames, filenames in os.walk(subdir): 5408 for dirname, dirnames, filenames in os.walk(subdir):
5297 for filename in filenames: 5409 for filename in filenames:
5298 if(not re.match('.*.html', filename)): 5410 if(not re.match('.*.html', filename)):
5299 continue 5411 continue
5300 file = os.path.join(dirname, filename) 5412 file = os.path.join(dirname, filename)
5301 html = open(file, 'r').read(10000) 5413 html = open(file, 'r').read()
5302 suspend = find_in_html(html, 5414 suspend = find_in_html(html, 'Kernel Suspend', 'ms')
5303 ['Kernel Suspend: ', 'Kernel Suspend Time: ']) 5415 resume = find_in_html(html, 'Kernel Resume', 'ms')
5304 resume = find_in_html(html, 5416 line = find_in_html(html, '<div class="stamp">', '</div>')
5305 ['Kernel Resume: ', 'Kernel Resume Time: '])
5306 line = find_in_html(html, ['<div class="stamp">'], True)
5307 stmp = line.split() 5417 stmp = line.split()
5308 if not suspend or not resume or len(stmp) < 4: 5418 if not suspend or not resume or len(stmp) != 8:
5309 continue 5419 continue
5420 try:
5421 dt = datetime.strptime(' '.join(stmp[3:]), '%B %d %Y, %I:%M:%S %p')
5422 except:
5423 continue
5424 tstr = dt.strftime('%Y/%m/%d %H:%M:%S')
5425 error = find_in_html(html, '<table class="testfail"><tr><td>', '</td>')
5426 result = 'fail' if error else 'pass'
5427 ilist = []
5428 e = find_in_html(html, 'class="err"[\w=":;\.%\- ]*>', '&rarr;</div>', False)
5429 for i in list(set(e)):
5430 ilist.append('%sx%d' % (i, e.count(i)) if e.count(i) > 1 else i)
5310 data = { 5431 data = {
5432 'mode': stmp[2],
5311 'host': stmp[0], 5433 'host': stmp[0],
5312 'kernel': stmp[1], 5434 'kernel': stmp[1],
5313 'mode': stmp[2], 5435 'time': tstr,
5314 'time': string.join(stmp[3:], ' '), 5436 'result': result,
5437 'issues': ','.join(ilist),
5315 'suspend': suspend, 5438 'suspend': suspend,
5316 'resume': resume, 5439 'resume': resume,
5317 'url': os.path.relpath(file, outpath), 5440 'url': os.path.relpath(file, outpath),
5318 } 5441 }
5319 if len(stmp) == 7:
5320 data['kernel'] = 'unknown'
5321 data['mode'] = stmp[1]
5322 data['time'] = string.join(stmp[2:], ' ')
5323 testruns.append(data) 5442 testruns.append(data)
5324 outfile = os.path.join(outpath, 'summary.html') 5443 outfile = os.path.join(outpath, 'summary.html')
5325 print('Summary file: %s' % outfile) 5444 print('Summary file: %s' % outfile)
@@ -5609,11 +5728,12 @@ def printHelp():
5609 print(' -modes List available suspend modes') 5728 print(' -modes List available suspend modes')
5610 print(' -status Test to see if the system is enabled to run this tool') 5729 print(' -status Test to see if the system is enabled to run this tool')
5611 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table') 5730 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table')
5731 print(' -battery Print out battery info (if available)')
5612 print(' -sysinfo Print out system info extracted from BIOS') 5732 print(' -sysinfo Print out system info extracted from BIOS')
5613 print(' -devinfo Print out the pm settings of all devices which support runtime suspend') 5733 print(' -devinfo Print out the pm settings of all devices which support runtime suspend')
5614 print(' -flist Print the list of functions currently being captured in ftrace') 5734 print(' -flist Print the list of functions currently being captured in ftrace')
5615 print(' -flistall Print all functions capable of being captured in ftrace') 5735 print(' -flistall Print all functions capable of being captured in ftrace')
5616 print(' -summary directory Create a summary of all test in this dir') 5736 print(' -summary dir Create a summary of tests in this dir [-genhtml builds missing html]')
5617 print(' [redo]') 5737 print(' [redo]')
5618 print(' -ftrace ftracefile Create HTML output using ftrace input (used with -dmesg)') 5738 print(' -ftrace ftracefile Create HTML output using ftrace input (used with -dmesg)')
5619 print(' -dmesg dmesgfile Create HTML output using dmesg (used with -ftrace)') 5739 print(' -dmesg dmesgfile Create HTML output using dmesg (used with -ftrace)')
@@ -5623,8 +5743,9 @@ def printHelp():
5623# ----------------- MAIN -------------------- 5743# ----------------- MAIN --------------------
5624# exec start (skipped if script is loaded as library) 5744# exec start (skipped if script is loaded as library)
5625if __name__ == '__main__': 5745if __name__ == '__main__':
5746 genhtml = False
5626 cmd = '' 5747 cmd = ''
5627 simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', '-devinfo', '-status'] 5748 simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', '-devinfo', '-status', '-battery']
5628 if '-f' in sys.argv: 5749 if '-f' in sys.argv:
5629 sysvals.cgskip = sysvals.configFile('cgskip.txt') 5750 sysvals.cgskip = sysvals.configFile('cgskip.txt')
5630 # loop through the command line arguments 5751 # loop through the command line arguments
@@ -5660,6 +5781,8 @@ if __name__ == '__main__':
5660 sysvals.skiphtml = True 5781 sysvals.skiphtml = True
5661 elif(arg == '-cgdump'): 5782 elif(arg == '-cgdump'):
5662 sysvals.cgdump = True 5783 sysvals.cgdump = True
5784 elif(arg == '-genhtml'):
5785 genhtml = True
5663 elif(arg == '-addlogs'): 5786 elif(arg == '-addlogs'):
5664 sysvals.dmesglog = sysvals.ftracelog = True 5787 sysvals.dmesglog = sysvals.ftracelog = True
5665 elif(arg == '-verbose'): 5788 elif(arg == '-verbose'):
@@ -5856,6 +5979,8 @@ if __name__ == '__main__':
5856 statusCheck(True) 5979 statusCheck(True)
5857 elif(cmd == 'fpdt'): 5980 elif(cmd == 'fpdt'):
5858 getFPDT(True) 5981 getFPDT(True)
5982 elif(cmd == 'battery'):
5983 print 'AC Connect: %s\nCharge: %d' % getBattery()
5859 elif(cmd == 'sysinfo'): 5984 elif(cmd == 'sysinfo'):
5860 sysvals.printSystemInfo(True) 5985 sysvals.printSystemInfo(True)
5861 elif(cmd == 'devinfo'): 5986 elif(cmd == 'devinfo'):
@@ -5867,7 +5992,7 @@ if __name__ == '__main__':
5867 elif(cmd == 'flistall'): 5992 elif(cmd == 'flistall'):
5868 sysvals.getFtraceFilterFunctions(False) 5993 sysvals.getFtraceFilterFunctions(False)
5869 elif(cmd == 'summary'): 5994 elif(cmd == 'summary'):
5870 runSummary(sysvals.outdir, True) 5995 runSummary(sysvals.outdir, True, genhtml)
5871 sys.exit() 5996 sys.exit()
5872 5997
5873 # if instructed, re-analyze existing data files 5998 # if instructed, re-analyze existing data files
@@ -5920,7 +6045,7 @@ if __name__ == '__main__':
5920 print('TEST (%d/%d) COMPLETE' % (i+1, sysvals.multitest['count'])) 6045 print('TEST (%d/%d) COMPLETE' % (i+1, sysvals.multitest['count']))
5921 sysvals.logmsg = '' 6046 sysvals.logmsg = ''
5922 if not sysvals.skiphtml: 6047 if not sysvals.skiphtml:
5923 runSummary(sysvals.outdir, False) 6048 runSummary(sysvals.outdir, False, False)
5924 sysvals.sudouser(sysvals.outdir) 6049 sysvals.sudouser(sysvals.outdir)
5925 else: 6050 else:
5926 if sysvals.outdir: 6051 if sysvals.outdir:
diff --git a/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
index 29f50d4cfea0..84e2b648e622 100755
--- a/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
+++ b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
@@ -28,6 +28,7 @@ import subprocess
28import os 28import os
29import time 29import time
30import re 30import re
31import signal
31import sys 32import sys
32import getopt 33import getopt
33import Gnuplot 34import Gnuplot
@@ -78,11 +79,12 @@ def print_help():
78 print(' Or') 79 print(' Or')
79 print(' ./intel_pstate_tracer.py [--cpu cpus] ---trace_file <trace_file> --name <test_name>') 80 print(' ./intel_pstate_tracer.py [--cpu cpus] ---trace_file <trace_file> --name <test_name>')
80 print(' To generate trace file, parse and plot, use (sudo required):') 81 print(' To generate trace file, parse and plot, use (sudo required):')
81 print(' sudo ./intel_pstate_tracer.py [-c cpus] -i <interval> -n <test_name>') 82 print(' sudo ./intel_pstate_tracer.py [-c cpus] -i <interval> -n <test_name> -m <kbytes>')
82 print(' Or') 83 print(' Or')
83 print(' sudo ./intel_pstate_tracer.py [--cpu cpus] --interval <interval> --name <test_name>') 84 print(' sudo ./intel_pstate_tracer.py [--cpu cpus] --interval <interval> --name <test_name> --memory <kbytes>')
84 print(' Optional argument:') 85 print(' Optional argument:')
85 print(' cpus: comma separated list of CPUs') 86 print(' cpus: comma separated list of CPUs')
87 print(' kbytes: Kilo bytes of memory per CPU to allocate to the trace buffer. Default: 10240')
86 print(' Output:') 88 print(' Output:')
87 print(' If not already present, creates a "results/test_name" folder in the current working directory with:') 89 print(' If not already present, creates a "results/test_name" folder in the current working directory with:')
88 print(' cpu.csv - comma seperated values file with trace contents and some additional calculations.') 90 print(' cpu.csv - comma seperated values file with trace contents and some additional calculations.')
@@ -379,7 +381,7 @@ def clear_trace_file():
379 f_handle.close() 381 f_handle.close()
380 except: 382 except:
381 print('IO error clearing trace file ') 383 print('IO error clearing trace file ')
382 quit() 384 sys.exit(2)
383 385
384def enable_trace(): 386def enable_trace():
385 """ Enable trace """ 387 """ Enable trace """
@@ -389,7 +391,7 @@ def enable_trace():
389 , 'w').write("1") 391 , 'w').write("1")
390 except: 392 except:
391 print('IO error enabling trace ') 393 print('IO error enabling trace ')
392 quit() 394 sys.exit(2)
393 395
394def disable_trace(): 396def disable_trace():
395 """ Disable trace """ 397 """ Disable trace """
@@ -399,17 +401,17 @@ def disable_trace():
399 , 'w').write("0") 401 , 'w').write("0")
400 except: 402 except:
401 print('IO error disabling trace ') 403 print('IO error disabling trace ')
402 quit() 404 sys.exit(2)
403 405
404def set_trace_buffer_size(): 406def set_trace_buffer_size():
405 """ Set trace buffer size """ 407 """ Set trace buffer size """
406 408
407 try: 409 try:
408 open('/sys/kernel/debug/tracing/buffer_size_kb' 410 with open('/sys/kernel/debug/tracing/buffer_size_kb', 'w') as fp:
409 , 'w').write("10240") 411 fp.write(memory)
410 except: 412 except:
411 print('IO error setting trace buffer size ') 413 print('IO error setting trace buffer size ')
412 quit() 414 sys.exit(2)
413 415
414def free_trace_buffer(): 416def free_trace_buffer():
415 """ Free the trace buffer memory """ 417 """ Free the trace buffer memory """
@@ -418,8 +420,8 @@ def free_trace_buffer():
418 open('/sys/kernel/debug/tracing/buffer_size_kb' 420 open('/sys/kernel/debug/tracing/buffer_size_kb'
419 , 'w').write("1") 421 , 'w').write("1")
420 except: 422 except:
421 print('IO error setting trace buffer size ') 423 print('IO error freeing trace buffer ')
422 quit() 424 sys.exit(2)
423 425
424def read_trace_data(filename): 426def read_trace_data(filename):
425 """ Read and parse trace data """ 427 """ Read and parse trace data """
@@ -431,7 +433,7 @@ def read_trace_data(filename):
431 data = open(filename, 'r').read() 433 data = open(filename, 'r').read()
432 except: 434 except:
433 print('Error opening ', filename) 435 print('Error opening ', filename)
434 quit() 436 sys.exit(2)
435 437
436 for line in data.splitlines(): 438 for line in data.splitlines():
437 search_obj = \ 439 search_obj = \
@@ -489,10 +491,22 @@ def read_trace_data(filename):
489# Now seperate the main overall csv file into per CPU csv files. 491# Now seperate the main overall csv file into per CPU csv files.
490 split_csv() 492 split_csv()
491 493
494def signal_handler(signal, frame):
495 print(' SIGINT: Forcing cleanup before exit.')
496 if interval:
497 disable_trace()
498 clear_trace_file()
499 # Free the memory
500 free_trace_buffer()
501 sys.exit(0)
502
503signal.signal(signal.SIGINT, signal_handler)
504
492interval = "" 505interval = ""
493filename = "" 506filename = ""
494cpu_list = "" 507cpu_list = ""
495testname = "" 508testname = ""
509memory = "10240"
496graph_data_present = False; 510graph_data_present = False;
497 511
498valid1 = False 512valid1 = False
@@ -501,7 +515,7 @@ valid2 = False
501cpu_mask = zeros((MAX_CPUS,), dtype=int) 515cpu_mask = zeros((MAX_CPUS,), dtype=int)
502 516
503try: 517try:
504 opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:",["help","trace_file=","interval=","cpu=","name="]) 518 opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:m:",["help","trace_file=","interval=","cpu=","name=","memory="])
505except getopt.GetoptError: 519except getopt.GetoptError:
506 print_help() 520 print_help()
507 sys.exit(2) 521 sys.exit(2)
@@ -521,6 +535,8 @@ for opt, arg in opts:
521 elif opt in ("-n", "--name"): 535 elif opt in ("-n", "--name"):
522 valid2 = True 536 valid2 = True
523 testname = arg 537 testname = arg
538 elif opt in ("-m", "--memory"):
539 memory = arg
524 540
525if not (valid1 and valid2): 541if not (valid1 and valid2):
526 print_help() 542 print_help()
@@ -569,6 +585,11 @@ current_max_cpu = 0
569 585
570read_trace_data(filename) 586read_trace_data(filename)
571 587
588clear_trace_file()
589# Free the memory
590if interval:
591 free_trace_buffer()
592
572if graph_data_present == False: 593if graph_data_present == False:
573 print('No valid data to plot') 594 print('No valid data to plot')
574 sys.exit(2) 595 sys.exit(2)
@@ -593,9 +614,4 @@ for root, dirs, files in os.walk('.'):
593 for f in files: 614 for f in files:
594 fix_ownership(f) 615 fix_ownership(f)
595 616
596clear_trace_file()
597# Free the memory
598if interval:
599 free_trace_buffer()
600
601os.chdir('../../') 617os.chdir('../../')