aboutsummaryrefslogtreecommitdiffstats
path: root/tools/power
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-09-07 17:39:55 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-09-07 17:39:55 -0400
commite3e2ffdc0c13db8631a7248a3f356bb006ff5068 (patch)
tree2a4a8bee128c69490836cf907dbecb368afae9a9 /tools/power
parenta41f7f0ae7b340adaaaaad162fd363859e346c75 (diff)
parent4216148337211be7ad2bfe38a0dffc3ce479c283 (diff)
Merge back earlier power management tools updates for v5.4.
Diffstat (limited to 'tools/power')
-rw-r--r--tools/power/pm-graph/README6
-rwxr-xr-xtools/power/pm-graph/bootgraph.py59
-rw-r--r--tools/power/pm-graph/sleepgraph.88
-rwxr-xr-xtools/power/pm-graph/sleepgraph.py618
4 files changed, 391 insertions, 300 deletions
diff --git a/tools/power/pm-graph/README b/tools/power/pm-graph/README
index 58a5591e3951..96259f6e5715 100644
--- a/tools/power/pm-graph/README
+++ b/tools/power/pm-graph/README
@@ -1,7 +1,7 @@
1 p m - g r a p h 1 p m - g r a p h
2 2
3 pm-graph: suspend/resume/boot timing analysis tools 3 pm-graph: suspend/resume/boot timing analysis tools
4 Version: 5.4 4 Version: 5.5
5 Author: Todd Brandt <todd.e.brandt@intel.com> 5 Author: Todd Brandt <todd.e.brandt@intel.com>
6 Home Page: https://01.org/pm-graph 6 Home Page: https://01.org/pm-graph
7 7
@@ -18,6 +18,10 @@
18 - upstream version in git: 18 - upstream version in git:
19 https://github.com/intel/pm-graph/ 19 https://github.com/intel/pm-graph/
20 20
21 Requirements:
22 - runs with python2 or python3, choice is made by /usr/bin/python link
23 - python2 now requires python-configparser be installed
24
21 Table of Contents 25 Table of Contents
22 - Overview 26 - Overview
23 - Setup 27 - Setup
diff --git a/tools/power/pm-graph/bootgraph.py b/tools/power/pm-graph/bootgraph.py
index 666bcbda648d..d3b99a1e92d6 100755
--- a/tools/power/pm-graph/bootgraph.py
+++ b/tools/power/pm-graph/bootgraph.py
@@ -1,9 +1,18 @@
1#!/usr/bin/python2 1#!/usr/bin/python
2# SPDX-License-Identifier: GPL-2.0-only 2# SPDX-License-Identifier: GPL-2.0-only
3# 3#
4# Tool for analyzing boot timing 4# Tool for analyzing boot timing
5# Copyright (c) 2013, Intel Corporation. 5# Copyright (c) 2013, Intel Corporation.
6# 6#
7# This program is free software; you can redistribute it and/or modify it
8# under the terms and conditions of the GNU General Public License,
9# version 2, as published by the Free Software Foundation.
10#
11# This program is distributed in the hope it will be useful, but WITHOUT
12# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14# more details.
15#
7# Authors: 16# Authors:
8# Todd Brandt <todd.e.brandt@linux.intel.com> 17# Todd Brandt <todd.e.brandt@linux.intel.com>
9# 18#
@@ -81,7 +90,7 @@ class SystemValues(aslib.SystemValues):
81 cmdline = 'initcall_debug log_buf_len=32M' 90 cmdline = 'initcall_debug log_buf_len=32M'
82 if self.useftrace: 91 if self.useftrace:
83 if self.cpucount > 0: 92 if self.cpucount > 0:
84 bs = min(self.memtotal / 2, 2*1024*1024) / self.cpucount 93 bs = min(self.memtotal // 2, 2*1024*1024) // self.cpucount
85 else: 94 else:
86 bs = 131072 95 bs = 131072
87 cmdline += ' trace_buf_size=%dK trace_clock=global '\ 96 cmdline += ' trace_buf_size=%dK trace_clock=global '\
@@ -137,13 +146,13 @@ class SystemValues(aslib.SystemValues):
137 if arg in ['-h', '-v', '-cronjob', '-reboot', '-verbose']: 146 if arg in ['-h', '-v', '-cronjob', '-reboot', '-verbose']:
138 continue 147 continue
139 elif arg in ['-o', '-dmesg', '-ftrace', '-func']: 148 elif arg in ['-o', '-dmesg', '-ftrace', '-func']:
140 args.next() 149 next(args)
141 continue 150 continue
142 elif arg == '-result': 151 elif arg == '-result':
143 cmdline += ' %s "%s"' % (arg, os.path.abspath(args.next())) 152 cmdline += ' %s "%s"' % (arg, os.path.abspath(next(args)))
144 continue 153 continue
145 elif arg == '-cgskip': 154 elif arg == '-cgskip':
146 file = self.configFile(args.next()) 155 file = self.configFile(next(args))
147 cmdline += ' %s "%s"' % (arg, os.path.abspath(file)) 156 cmdline += ' %s "%s"' % (arg, os.path.abspath(file))
148 continue 157 continue
149 cmdline += ' '+arg 158 cmdline += ' '+arg
@@ -292,11 +301,11 @@ def parseKernelLog():
292 tp = aslib.TestProps() 301 tp = aslib.TestProps()
293 devtemp = dict() 302 devtemp = dict()
294 if(sysvals.dmesgfile): 303 if(sysvals.dmesgfile):
295 lf = open(sysvals.dmesgfile, 'r') 304 lf = open(sysvals.dmesgfile, 'rb')
296 else: 305 else:
297 lf = Popen('dmesg', stdout=PIPE).stdout 306 lf = Popen('dmesg', stdout=PIPE).stdout
298 for line in lf: 307 for line in lf:
299 line = line.replace('\r\n', '') 308 line = aslib.ascii(line).replace('\r\n', '')
300 # grab the stamp and sysinfo 309 # grab the stamp and sysinfo
301 if re.match(tp.stampfmt, line): 310 if re.match(tp.stampfmt, line):
302 tp.stamp = line 311 tp.stamp = line
@@ -649,7 +658,7 @@ def createBootGraph(data):
649 statinfo += '\t"%s": [\n\t\t"%s",\n' % (n, devstats[n]['info']) 658 statinfo += '\t"%s": [\n\t\t"%s",\n' % (n, devstats[n]['info'])
650 if 'fstat' in devstats[n]: 659 if 'fstat' in devstats[n]:
651 funcs = devstats[n]['fstat'] 660 funcs = devstats[n]['fstat']
652 for f in sorted(funcs, key=funcs.get, reverse=True): 661 for f in sorted(funcs, key=lambda k:(funcs[k], k), reverse=True):
653 if funcs[f][0] < 0.01 and len(funcs) > 10: 662 if funcs[f][0] < 0.01 and len(funcs) > 10:
654 break 663 break
655 statinfo += '\t\t"%f|%s|%d",\n' % (funcs[f][0], f, funcs[f][1]) 664 statinfo += '\t\t"%f|%s|%d",\n' % (funcs[f][0], f, funcs[f][1])
@@ -729,7 +738,7 @@ def updateCron(restore=False):
729 op.write('@reboot python %s\n' % sysvals.cronjobCmdString()) 738 op.write('@reboot python %s\n' % sysvals.cronjobCmdString())
730 op.close() 739 op.close()
731 res = call([cmd, cronfile]) 740 res = call([cmd, cronfile])
732 except Exception, e: 741 except Exception as e:
733 pprint('Exception: %s' % str(e)) 742 pprint('Exception: %s' % str(e))
734 shutil.move(backfile, cronfile) 743 shutil.move(backfile, cronfile)
735 res = -1 744 res = -1
@@ -745,7 +754,7 @@ def updateGrub(restore=False):
745 try: 754 try:
746 call(sysvals.blexec, stderr=PIPE, stdout=PIPE, 755 call(sysvals.blexec, stderr=PIPE, stdout=PIPE,
747 env={'PATH': '.:/sbin:/usr/sbin:/usr/bin:/sbin:/bin'}) 756 env={'PATH': '.:/sbin:/usr/sbin:/usr/bin:/sbin:/bin'})
748 except Exception, e: 757 except Exception as e:
749 pprint('Exception: %s\n' % str(e)) 758 pprint('Exception: %s\n' % str(e))
750 return 759 return
751 # extract the option and create a grub config without it 760 # extract the option and create a grub config without it
@@ -792,7 +801,7 @@ def updateGrub(restore=False):
792 op.close() 801 op.close()
793 res = call(sysvals.blexec) 802 res = call(sysvals.blexec)
794 os.remove(grubfile) 803 os.remove(grubfile)
795 except Exception, e: 804 except Exception as e:
796 pprint('Exception: %s' % str(e)) 805 pprint('Exception: %s' % str(e))
797 res = -1 806 res = -1
798 # cleanup 807 # cleanup
@@ -866,6 +875,7 @@ def printHelp():
866 'Other commands:\n'\ 875 'Other commands:\n'\
867 ' -flistall Print all functions capable of being captured in ftrace\n'\ 876 ' -flistall Print all functions capable of being captured in ftrace\n'\
868 ' -sysinfo Print out system info extracted from BIOS\n'\ 877 ' -sysinfo Print out system info extracted from BIOS\n'\
878 ' -which exec Print an executable path, should function even without PATH\n'\
869 ' [redo]\n'\ 879 ' [redo]\n'\
870 ' -dmesg file Create HTML output using dmesg input (used with -ftrace)\n'\ 880 ' -dmesg file Create HTML output using dmesg input (used with -ftrace)\n'\
871 ' -ftrace file Create HTML output using ftrace input (used with -dmesg)\n'\ 881 ' -ftrace file Create HTML output using ftrace input (used with -dmesg)\n'\
@@ -907,13 +917,13 @@ if __name__ == '__main__':
907 sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0) 917 sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0)
908 elif(arg == '-cgfilter'): 918 elif(arg == '-cgfilter'):
909 try: 919 try:
910 val = args.next() 920 val = next(args)
911 except: 921 except:
912 doError('No callgraph functions supplied', True) 922 doError('No callgraph functions supplied', True)
913 sysvals.setCallgraphFilter(val) 923 sysvals.setCallgraphFilter(val)
914 elif(arg == '-cgskip'): 924 elif(arg == '-cgskip'):
915 try: 925 try:
916 val = args.next() 926 val = next(args)
917 except: 927 except:
918 doError('No file supplied', True) 928 doError('No file supplied', True)
919 if val.lower() in switchoff: 929 if val.lower() in switchoff:
@@ -924,7 +934,7 @@ if __name__ == '__main__':
924 doError('%s does not exist' % cgskip) 934 doError('%s does not exist' % cgskip)
925 elif(arg == '-bl'): 935 elif(arg == '-bl'):
926 try: 936 try:
927 val = args.next() 937 val = next(args)
928 except: 938 except:
929 doError('No boot loader name supplied', True) 939 doError('No boot loader name supplied', True)
930 if val.lower() not in ['grub']: 940 if val.lower() not in ['grub']:
@@ -937,7 +947,7 @@ if __name__ == '__main__':
937 sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000) 947 sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000)
938 elif(arg == '-func'): 948 elif(arg == '-func'):
939 try: 949 try:
940 val = args.next() 950 val = next(args)
941 except: 951 except:
942 doError('No filter functions supplied', True) 952 doError('No filter functions supplied', True)
943 sysvals.useftrace = True 953 sysvals.useftrace = True
@@ -946,7 +956,7 @@ if __name__ == '__main__':
946 sysvals.setGraphFilter(val) 956 sysvals.setGraphFilter(val)
947 elif(arg == '-ftrace'): 957 elif(arg == '-ftrace'):
948 try: 958 try:
949 val = args.next() 959 val = next(args)
950 except: 960 except:
951 doError('No ftrace file supplied', True) 961 doError('No ftrace file supplied', True)
952 if(os.path.exists(val) == False): 962 if(os.path.exists(val) == False):
@@ -959,7 +969,7 @@ if __name__ == '__main__':
959 sysvals.cgexp = True 969 sysvals.cgexp = True
960 elif(arg == '-dmesg'): 970 elif(arg == '-dmesg'):
961 try: 971 try:
962 val = args.next() 972 val = next(args)
963 except: 973 except:
964 doError('No dmesg file supplied', True) 974 doError('No dmesg file supplied', True)
965 if(os.path.exists(val) == False): 975 if(os.path.exists(val) == False):
@@ -968,13 +978,13 @@ if __name__ == '__main__':
968 sysvals.dmesgfile = val 978 sysvals.dmesgfile = val
969 elif(arg == '-o'): 979 elif(arg == '-o'):
970 try: 980 try:
971 val = args.next() 981 val = next(args)
972 except: 982 except:
973 doError('No subdirectory name supplied', True) 983 doError('No subdirectory name supplied', True)
974 sysvals.testdir = sysvals.setOutputFolder(val) 984 sysvals.testdir = sysvals.setOutputFolder(val)
975 elif(arg == '-result'): 985 elif(arg == '-result'):
976 try: 986 try:
977 val = args.next() 987 val = next(args)
978 except: 988 except:
979 doError('No result file supplied', True) 989 doError('No result file supplied', True)
980 sysvals.result = val 990 sysvals.result = val
@@ -986,6 +996,17 @@ if __name__ == '__main__':
986 # remaining options are only for cron job use 996 # remaining options are only for cron job use
987 elif(arg == '-cronjob'): 997 elif(arg == '-cronjob'):
988 sysvals.iscronjob = True 998 sysvals.iscronjob = True
999 elif(arg == '-which'):
1000 try:
1001 val = next(args)
1002 except:
1003 doError('No executable supplied', True)
1004 out = sysvals.getExec(val)
1005 if not out:
1006 print('%s not found' % val)
1007 sys.exit(1)
1008 print(out)
1009 sys.exit(0)
989 else: 1010 else:
990 doError('Invalid argument: '+arg, True) 1011 doError('Invalid argument: '+arg, True)
991 1012
diff --git a/tools/power/pm-graph/sleepgraph.8 b/tools/power/pm-graph/sleepgraph.8
index 9648be644d5f..43aee64316df 100644
--- a/tools/power/pm-graph/sleepgraph.8
+++ b/tools/power/pm-graph/sleepgraph.8
@@ -53,10 +53,10 @@ disable rtcwake and require a user keypress to resume.
53Add the dmesg and ftrace logs to the html output. They will be viewable by 53Add the dmesg and ftrace logs to the html output. They will be viewable by
54clicking buttons in the timeline. 54clicking buttons in the timeline.
55.TP 55.TP
56\fB-turbostat\fR 56\fB-noturbostat\fR
57Use turbostat to execute the command in freeze mode (default: disabled). This 57By default, if turbostat is found and the requested mode is freeze, sleepgraph
58will provide turbostat output in the log which will tell you which actual 58will execute the suspend via turbostat and collect data in the timeline log.
59power modes were entered. 59This option disables the use of turbostat.
60.TP 60.TP
61\fB-result \fIfile\fR 61\fB-result \fIfile\fR
62Export a results table to a text file for parsing. 62Export a results table to a text file for parsing.
diff --git a/tools/power/pm-graph/sleepgraph.py b/tools/power/pm-graph/sleepgraph.py
index 4f46a7a1feb6..f7d1c1f62f86 100755
--- a/tools/power/pm-graph/sleepgraph.py
+++ b/tools/power/pm-graph/sleepgraph.py
@@ -1,9 +1,18 @@
1#!/usr/bin/python2 1#!/usr/bin/python
2# SPDX-License-Identifier: GPL-2.0-only 2# SPDX-License-Identifier: GPL-2.0-only
3# 3#
4# Tool for analyzing suspend/resume timing 4# Tool for analyzing suspend/resume timing
5# Copyright (c) 2013, Intel Corporation. 5# Copyright (c) 2013, Intel Corporation.
6# 6#
7# This program is free software; you can redistribute it and/or modify it
8# under the terms and conditions of the GNU General Public License,
9# version 2, as published by the Free Software Foundation.
10#
11# This program is distributed in the hope it will be useful, but WITHOUT
12# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14# more details.
15#
7# Authors: 16# Authors:
8# Todd Brandt <todd.e.brandt@linux.intel.com> 17# Todd Brandt <todd.e.brandt@linux.intel.com>
9# 18#
@@ -48,9 +57,10 @@ import string
48import re 57import re
49import platform 58import platform
50import signal 59import signal
60import codecs
51from datetime import datetime 61from datetime import datetime
52import struct 62import struct
53import ConfigParser 63import configparser
54import gzip 64import gzip
55from threading import Thread 65from threading import Thread
56from subprocess import call, Popen, PIPE 66from subprocess import call, Popen, PIPE
@@ -60,6 +70,9 @@ def pprint(msg):
60 print(msg) 70 print(msg)
61 sys.stdout.flush() 71 sys.stdout.flush()
62 72
73def ascii(text):
74 return text.decode('ascii', 'ignore')
75
63# ----------------- CLASSES -------------------- 76# ----------------- CLASSES --------------------
64 77
65# Class: SystemValues 78# Class: SystemValues
@@ -68,7 +81,7 @@ def pprint(msg):
68# store system values and test parameters 81# store system values and test parameters
69class SystemValues: 82class SystemValues:
70 title = 'SleepGraph' 83 title = 'SleepGraph'
71 version = '5.4' 84 version = '5.5'
72 ansi = False 85 ansi = False
73 rs = 0 86 rs = 0
74 display = '' 87 display = ''
@@ -78,7 +91,7 @@ class SystemValues:
78 testlog = True 91 testlog = True
79 dmesglog = True 92 dmesglog = True
80 ftracelog = False 93 ftracelog = False
81 tstat = False 94 tstat = True
82 mindevlen = 0.0 95 mindevlen = 0.0
83 mincglen = 0.0 96 mincglen = 0.0
84 cgphase = '' 97 cgphase = ''
@@ -147,6 +160,7 @@ class SystemValues:
147 devdump = False 160 devdump = False
148 mixedphaseheight = True 161 mixedphaseheight = True
149 devprops = dict() 162 devprops = dict()
163 platinfo = []
150 predelay = 0 164 predelay = 0
151 postdelay = 0 165 postdelay = 0
152 pmdebug = '' 166 pmdebug = ''
@@ -323,13 +337,20 @@ class SystemValues:
323 sys.exit(1) 337 sys.exit(1)
324 return False 338 return False
325 def getExec(self, cmd): 339 def getExec(self, cmd):
326 dirlist = ['/sbin', '/bin', '/usr/sbin', '/usr/bin', 340 try:
327 '/usr/local/sbin', '/usr/local/bin'] 341 fp = Popen(['which', cmd], stdout=PIPE, stderr=PIPE).stdout
328 for path in dirlist: 342 out = ascii(fp.read()).strip()
343 fp.close()
344 except:
345 out = ''
346 if out:
347 return out
348 for path in ['/sbin', '/bin', '/usr/sbin', '/usr/bin',
349 '/usr/local/sbin', '/usr/local/bin']:
329 cmdfull = os.path.join(path, cmd) 350 cmdfull = os.path.join(path, cmd)
330 if os.path.exists(cmdfull): 351 if os.path.exists(cmdfull):
331 return cmdfull 352 return cmdfull
332 return '' 353 return out
333 def setPrecision(self, num): 354 def setPrecision(self, num):
334 if num < 0 or num > 6: 355 if num < 0 or num > 6:
335 return 356 return
@@ -455,7 +476,7 @@ class SystemValues:
455 fp = Popen('dmesg', stdout=PIPE).stdout 476 fp = Popen('dmesg', stdout=PIPE).stdout
456 ktime = '0' 477 ktime = '0'
457 for line in fp: 478 for line in fp:
458 line = line.replace('\r\n', '') 479 line = ascii(line).replace('\r\n', '')
459 idx = line.find('[') 480 idx = line.find('[')
460 if idx > 1: 481 if idx > 1:
461 line = line[idx:] 482 line = line[idx:]
@@ -469,7 +490,7 @@ class SystemValues:
469 # store all new dmesg lines since initdmesg was called 490 # store all new dmesg lines since initdmesg was called
470 fp = Popen('dmesg', stdout=PIPE).stdout 491 fp = Popen('dmesg', stdout=PIPE).stdout
471 for line in fp: 492 for line in fp:
472 line = line.replace('\r\n', '') 493 line = ascii(line).replace('\r\n', '')
473 idx = line.find('[') 494 idx = line.find('[')
474 if idx > 1: 495 if idx > 1:
475 line = line[idx:] 496 line = line[idx:]
@@ -501,7 +522,7 @@ class SystemValues:
501 call('cat '+self.tpath+'available_filter_functions', shell=True) 522 call('cat '+self.tpath+'available_filter_functions', shell=True)
502 return 523 return
503 master = self.listFromFile(self.tpath+'available_filter_functions') 524 master = self.listFromFile(self.tpath+'available_filter_functions')
504 for i in self.tracefuncs: 525 for i in sorted(self.tracefuncs):
505 if 'func' in self.tracefuncs[i]: 526 if 'func' in self.tracefuncs[i]:
506 i = self.tracefuncs[i]['func'] 527 i = self.tracefuncs[i]['func']
507 if i in master: 528 if i in master:
@@ -628,7 +649,7 @@ class SystemValues:
628 self.fsetVal(kprobeevents, 'kprobe_events') 649 self.fsetVal(kprobeevents, 'kprobe_events')
629 if output: 650 if output:
630 check = self.fgetVal('kprobe_events') 651 check = self.fgetVal('kprobe_events')
631 linesack = (len(check.split('\n')) - 1) / 2 652 linesack = (len(check.split('\n')) - 1) // 2
632 pprint(' kprobe functions enabled: %d/%d' % (linesack, linesout)) 653 pprint(' kprobe functions enabled: %d/%d' % (linesack, linesout))
633 self.fsetVal('1', 'events/kprobes/enable') 654 self.fsetVal('1', 'events/kprobes/enable')
634 def testKprobe(self, kname, kprobe): 655 def testKprobe(self, kname, kprobe):
@@ -646,19 +667,19 @@ class SystemValues:
646 if linesack < linesout: 667 if linesack < linesout:
647 return False 668 return False
648 return True 669 return True
649 def setVal(self, val, file, mode='w'): 670 def setVal(self, val, file):
650 if not os.path.exists(file): 671 if not os.path.exists(file):
651 return False 672 return False
652 try: 673 try:
653 fp = open(file, mode, 0) 674 fp = open(file, 'wb', 0)
654 fp.write(val) 675 fp.write(val.encode())
655 fp.flush() 676 fp.flush()
656 fp.close() 677 fp.close()
657 except: 678 except:
658 return False 679 return False
659 return True 680 return True
660 def fsetVal(self, val, path, mode='w'): 681 def fsetVal(self, val, path):
661 return self.setVal(val, self.tpath+path, mode) 682 return self.setVal(val, self.tpath+path)
662 def getVal(self, file): 683 def getVal(self, file):
663 res = '' 684 res = ''
664 if not os.path.exists(file): 685 if not os.path.exists(file):
@@ -719,7 +740,7 @@ class SystemValues:
719 tgtsize = min(self.memfree, bmax) 740 tgtsize = min(self.memfree, bmax)
720 else: 741 else:
721 tgtsize = 65536 742 tgtsize = 65536
722 while not self.fsetVal('%d' % (tgtsize / cpus), 'buffer_size_kb'): 743 while not self.fsetVal('%d' % (tgtsize // cpus), 'buffer_size_kb'):
723 # if the size failed to set, lower it and keep trying 744 # if the size failed to set, lower it and keep trying
724 tgtsize -= 65536 745 tgtsize -= 65536
725 if tgtsize < 65536: 746 if tgtsize < 65536:
@@ -863,14 +884,23 @@ class SystemValues:
863 isgz = self.gzip 884 isgz = self.gzip
864 if mode == 'r': 885 if mode == 'r':
865 try: 886 try:
866 with gzip.open(filename, mode+'b') as fp: 887 with gzip.open(filename, mode+'t') as fp:
867 test = fp.read(64) 888 test = fp.read(64)
868 isgz = True 889 isgz = True
869 except: 890 except:
870 isgz = False 891 isgz = False
871 if isgz: 892 if isgz:
872 return gzip.open(filename, mode+'b') 893 return gzip.open(filename, mode+'t')
873 return open(filename, mode) 894 return open(filename, mode)
895 def b64unzip(self, data):
896 try:
897 out = codecs.decode(base64.b64decode(data), 'zlib').decode()
898 except:
899 out = data
900 return out
901 def b64zip(self, data):
902 out = base64.b64encode(codecs.encode(data.encode(), 'zlib')).decode()
903 return out
874 def mcelog(self, clear=False): 904 def mcelog(self, clear=False):
875 cmd = self.getExec('mcelog') 905 cmd = self.getExec('mcelog')
876 if not cmd: 906 if not cmd:
@@ -878,12 +908,124 @@ class SystemValues:
878 if clear: 908 if clear:
879 call(cmd+' > /dev/null 2>&1', shell=True) 909 call(cmd+' > /dev/null 2>&1', shell=True)
880 return '' 910 return ''
881 fp = Popen([cmd], stdout=PIPE, stderr=PIPE).stdout 911 try:
882 out = fp.read().strip() 912 fp = Popen([cmd], stdout=PIPE, stderr=PIPE).stdout
883 fp.close() 913 out = ascii(fp.read()).strip()
914 fp.close()
915 except:
916 return ''
884 if not out: 917 if not out:
885 return '' 918 return ''
886 return base64.b64encode(out.encode('zlib')) 919 return self.b64zip(out)
920 def platforminfo(self):
921 # add platform info on to a completed ftrace file
922 if not os.path.exists(self.ftracefile):
923 return False
924 footer = '#\n'
925
926 # add test command string line if need be
927 if self.suspendmode == 'command' and self.testcommand:
928 footer += '# platform-testcmd: %s\n' % (self.testcommand)
929
930 # get a list of target devices from the ftrace file
931 props = dict()
932 tp = TestProps()
933 tf = self.openlog(self.ftracefile, 'r')
934 for line in tf:
935 # determine the trace data type (required for further parsing)
936 m = re.match(tp.tracertypefmt, line)
937 if(m):
938 tp.setTracerType(m.group('t'))
939 continue
940 # parse only valid lines, if this is not one move on
941 m = re.match(tp.ftrace_line_fmt, line)
942 if(not m or 'device_pm_callback_start' not in line):
943 continue
944 m = re.match('.*: (?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*', m.group('msg'));
945 if(not m):
946 continue
947 dev = m.group('d')
948 if dev not in props:
949 props[dev] = DevProps()
950 tf.close()
951
952 # now get the syspath for each target device
953 for dirname, dirnames, filenames in os.walk('/sys/devices'):
954 if(re.match('.*/power', dirname) and 'async' in filenames):
955 dev = dirname.split('/')[-2]
956 if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)):
957 props[dev].syspath = dirname[:-6]
958
959 # now fill in the properties for our target devices
960 for dev in sorted(props):
961 dirname = props[dev].syspath
962 if not dirname or not os.path.exists(dirname):
963 continue
964 with open(dirname+'/power/async') as fp:
965 text = fp.read()
966 props[dev].isasync = False
967 if 'enabled' in text:
968 props[dev].isasync = True
969 fields = os.listdir(dirname)
970 if 'product' in fields:
971 with open(dirname+'/product', 'rb') as fp:
972 props[dev].altname = ascii(fp.read())
973 elif 'name' in fields:
974 with open(dirname+'/name', 'rb') as fp:
975 props[dev].altname = ascii(fp.read())
976 elif 'model' in fields:
977 with open(dirname+'/model', 'rb') as fp:
978 props[dev].altname = ascii(fp.read())
979 elif 'description' in fields:
980 with open(dirname+'/description', 'rb') as fp:
981 props[dev].altname = ascii(fp.read())
982 elif 'id' in fields:
983 with open(dirname+'/id', 'rb') as fp:
984 props[dev].altname = ascii(fp.read())
985 elif 'idVendor' in fields and 'idProduct' in fields:
986 idv, idp = '', ''
987 with open(dirname+'/idVendor', 'rb') as fp:
988 idv = ascii(fp.read()).strip()
989 with open(dirname+'/idProduct', 'rb') as fp:
990 idp = ascii(fp.read()).strip()
991 props[dev].altname = '%s:%s' % (idv, idp)
992 if props[dev].altname:
993 out = props[dev].altname.strip().replace('\n', ' ')\
994 .replace(',', ' ').replace(';', ' ')
995 props[dev].altname = out
996
997 # add a devinfo line to the bottom of ftrace
998 out = ''
999 for dev in sorted(props):
1000 out += props[dev].out(dev)
1001 footer += '# platform-devinfo: %s\n' % self.b64zip(out)
1002
1003 # add a line for each of these commands with their outputs
1004 cmds = [
1005 ['pcidevices', 'lspci', '-tv'],
1006 ['interrupts', 'cat', '/proc/interrupts'],
1007 ['gpecounts', 'sh', '-c', 'grep -v invalid /sys/firmware/acpi/interrupts/gpe*'],
1008 ]
1009 for cargs in cmds:
1010 name = cargs[0]
1011 cmdline = ' '.join(cargs[1:])
1012 cmdpath = self.getExec(cargs[1])
1013 if not cmdpath:
1014 continue
1015 cmd = [cmdpath] + cargs[2:]
1016 try:
1017 fp = Popen(cmd, stdout=PIPE, stderr=PIPE).stdout
1018 info = ascii(fp.read()).strip()
1019 fp.close()
1020 except:
1021 continue
1022 if not info:
1023 continue
1024 footer += '# platform-%s: %s | %s\n' % (name, cmdline, self.b64zip(info))
1025
1026 with self.openlog(self.ftracefile, 'a') as fp:
1027 fp.write(footer)
1028 return True
887 def haveTurbostat(self): 1029 def haveTurbostat(self):
888 if not self.tstat: 1030 if not self.tstat:
889 return False 1031 return False
@@ -891,31 +1033,40 @@ class SystemValues:
891 if not cmd: 1033 if not cmd:
892 return False 1034 return False
893 fp = Popen([cmd, '-v'], stdout=PIPE, stderr=PIPE).stderr 1035 fp = Popen([cmd, '-v'], stdout=PIPE, stderr=PIPE).stderr
894 out = fp.read().strip() 1036 out = ascii(fp.read()).strip()
895 fp.close() 1037 fp.close()
896 return re.match('turbostat version [0-9\.]* .*', out) 1038 if re.match('turbostat version [0-9\.]* .*', out):
1039 sysvals.vprint(out)
1040 return True
1041 return False
897 def turbostat(self): 1042 def turbostat(self):
898 cmd = self.getExec('turbostat') 1043 cmd = self.getExec('turbostat')
899 if not cmd: 1044 rawout = keyline = valline = ''
900 return 'missing turbostat executable'
901 text = []
902 fullcmd = '%s -q -S echo freeze > %s' % (cmd, self.powerfile) 1045 fullcmd = '%s -q -S echo freeze > %s' % (cmd, self.powerfile)
903 fp = Popen(['sh', '-c', fullcmd], stdout=PIPE, stderr=PIPE).stderr 1046 fp = Popen(['sh', '-c', fullcmd], stdout=PIPE, stderr=PIPE).stderr
904 for line in fp: 1047 for line in fp:
905 if re.match('[0-9.]* sec', line): 1048 line = ascii(line)
1049 rawout += line
1050 if keyline and valline:
906 continue 1051 continue
907 text.append(line.split()) 1052 if re.match('(?i)Avg_MHz.*', line):
1053 keyline = line.strip().split()
1054 elif keyline:
1055 valline = line.strip().split()
908 fp.close() 1056 fp.close()
909 if len(text) < 2: 1057 if not keyline or not valline or len(keyline) != len(valline):
910 return 'turbostat output format error' 1058 errmsg = 'unrecognized turbostat output:\n'+rawout.strip()
1059 sysvals.vprint(errmsg)
1060 if not sysvals.verbose:
1061 pprint(errmsg)
1062 return ''
1063 if sysvals.verbose:
1064 pprint(rawout.strip())
911 out = [] 1065 out = []
912 for key in text[0]: 1066 for key in keyline:
913 values = [] 1067 idx = keyline.index(key)
914 idx = text[0].index(key) 1068 val = valline[idx]
915 for line in text[1:]: 1069 out.append('%s=%s' % (key, val))
916 if len(line) > idx:
917 values.append(line[idx])
918 out.append('%s=%s' % (key, ','.join(values)))
919 return '|'.join(out) 1070 return '|'.join(out)
920 def checkWifi(self): 1071 def checkWifi(self):
921 out = dict() 1072 out = dict()
@@ -924,7 +1075,7 @@ class SystemValues:
924 return out 1075 return out
925 fp = Popen(iwcmd, stdout=PIPE, stderr=PIPE).stdout 1076 fp = Popen(iwcmd, stdout=PIPE, stderr=PIPE).stdout
926 for line in fp: 1077 for line in fp:
927 m = re.match('(?P<dev>\S*) .* ESSID:(?P<ess>\S*)', line) 1078 m = re.match('(?P<dev>\S*) .* ESSID:(?P<ess>\S*)', ascii(line))
928 if not m: 1079 if not m:
929 continue 1080 continue
930 out['device'] = m.group('dev') 1081 out['device'] = m.group('dev')
@@ -935,7 +1086,7 @@ class SystemValues:
935 if 'device' in out: 1086 if 'device' in out:
936 fp = Popen([ifcmd, out['device']], stdout=PIPE, stderr=PIPE).stdout 1087 fp = Popen([ifcmd, out['device']], stdout=PIPE, stderr=PIPE).stdout
937 for line in fp: 1088 for line in fp:
938 m = re.match('.* inet (?P<ip>[0-9\.]*)', line) 1089 m = re.match('.* inet (?P<ip>[0-9\.]*)', ascii(line))
939 if m: 1090 if m:
940 out['ip'] = m.group('ip') 1091 out['ip'] = m.group('ip')
941 break 1092 break
@@ -990,13 +1141,13 @@ class DevProps:
990 def __init__(self): 1141 def __init__(self):
991 self.syspath = '' 1142 self.syspath = ''
992 self.altname = '' 1143 self.altname = ''
993 self.async = True 1144 self.isasync = True
994 self.xtraclass = '' 1145 self.xtraclass = ''
995 self.xtrainfo = '' 1146 self.xtrainfo = ''
996 def out(self, dev): 1147 def out(self, dev):
997 return '%s,%s,%d;' % (dev, self.altname, self.async) 1148 return '%s,%s,%d;' % (dev, self.altname, self.isasync)
998 def debug(self, dev): 1149 def debug(self, dev):
999 pprint('%s:\n\taltname = %s\n\t async = %s' % (dev, self.altname, self.async)) 1150 pprint('%s:\n\taltname = %s\n\t async = %s' % (dev, self.altname, self.isasync))
1000 def altName(self, dev): 1151 def altName(self, dev):
1001 if not self.altname or self.altname == dev: 1152 if not self.altname or self.altname == dev:
1002 return dev 1153 return dev
@@ -1004,13 +1155,13 @@ class DevProps:
1004 def xtraClass(self): 1155 def xtraClass(self):
1005 if self.xtraclass: 1156 if self.xtraclass:
1006 return ' '+self.xtraclass 1157 return ' '+self.xtraclass
1007 if not self.async: 1158 if not self.isasync:
1008 return ' sync' 1159 return ' sync'
1009 return '' 1160 return ''
1010 def xtraInfo(self): 1161 def xtraInfo(self):
1011 if self.xtraclass: 1162 if self.xtraclass:
1012 return ' '+self.xtraclass 1163 return ' '+self.xtraclass
1013 if self.async: 1164 if self.isasync:
1014 return ' async_device' 1165 return ' async_device'
1015 return ' sync_device' 1166 return ' sync_device'
1016 1167
@@ -1108,7 +1259,7 @@ class Data:
1108 return sorted(self.dmesg, key=lambda k:self.dmesg[k]['order']) 1259 return sorted(self.dmesg, key=lambda k:self.dmesg[k]['order'])
1109 def initDevicegroups(self): 1260 def initDevicegroups(self):
1110 # called when phases are all finished being added 1261 # called when phases are all finished being added
1111 for phase in self.dmesg.keys(): 1262 for phase in sorted(self.dmesg.keys()):
1112 if '*' in phase: 1263 if '*' in phase:
1113 p = phase.split('*') 1264 p = phase.split('*')
1114 pnew = '%s%d' % (p[0], len(p)) 1265 pnew = '%s%d' % (p[0], len(p))
@@ -1430,16 +1581,7 @@ class Data:
1430 return phase 1581 return phase
1431 def sortedDevices(self, phase): 1582 def sortedDevices(self, phase):
1432 list = self.dmesg[phase]['list'] 1583 list = self.dmesg[phase]['list']
1433 slist = [] 1584 return sorted(list, key=lambda k:list[k]['start'])
1434 tmp = dict()
1435 for devname in list:
1436 dev = list[devname]
1437 if dev['length'] == 0:
1438 continue
1439 tmp[dev['start']] = devname
1440 for t in sorted(tmp):
1441 slist.append(tmp[t])
1442 return slist
1443 def fixupInitcalls(self, phase): 1585 def fixupInitcalls(self, phase):
1444 # if any calls never returned, clip them at system resume end 1586 # if any calls never returned, clip them at system resume end
1445 phaselist = self.dmesg[phase]['list'] 1587 phaselist = self.dmesg[phase]['list']
@@ -1576,7 +1718,7 @@ class Data:
1576 maxname = '%d' % self.maxDeviceNameSize(phase) 1718 maxname = '%d' % self.maxDeviceNameSize(phase)
1577 fmt = '%3d) %'+maxname+'s - %f - %f' 1719 fmt = '%3d) %'+maxname+'s - %f - %f'
1578 c = 1 1720 c = 1
1579 for name in devlist: 1721 for name in sorted(devlist):
1580 s = devlist[name]['start'] 1722 s = devlist[name]['start']
1581 e = devlist[name]['end'] 1723 e = devlist[name]['end']
1582 sysvals.vprint(fmt % (c, name, s, e)) 1724 sysvals.vprint(fmt % (c, name, s, e))
@@ -1588,7 +1730,7 @@ class Data:
1588 devlist = [] 1730 devlist = []
1589 for phase in self.sortedPhases(): 1731 for phase in self.sortedPhases():
1590 list = self.deviceChildren(devname, phase) 1732 list = self.deviceChildren(devname, phase)
1591 for dev in list: 1733 for dev in sorted(list):
1592 if dev not in devlist: 1734 if dev not in devlist:
1593 devlist.append(dev) 1735 devlist.append(dev)
1594 return devlist 1736 return devlist
@@ -1628,16 +1770,16 @@ class Data:
1628 def rootDeviceList(self): 1770 def rootDeviceList(self):
1629 # list of devices graphed 1771 # list of devices graphed
1630 real = [] 1772 real = []
1631 for phase in self.dmesg: 1773 for phase in self.sortedPhases():
1632 list = self.dmesg[phase]['list'] 1774 list = self.dmesg[phase]['list']
1633 for dev in list: 1775 for dev in sorted(list):
1634 if list[dev]['pid'] >= 0 and dev not in real: 1776 if list[dev]['pid'] >= 0 and dev not in real:
1635 real.append(dev) 1777 real.append(dev)
1636 # list of top-most root devices 1778 # list of top-most root devices
1637 rootlist = [] 1779 rootlist = []
1638 for phase in self.dmesg: 1780 for phase in self.sortedPhases():
1639 list = self.dmesg[phase]['list'] 1781 list = self.dmesg[phase]['list']
1640 for dev in list: 1782 for dev in sorted(list):
1641 pdev = list[dev]['par'] 1783 pdev = list[dev]['par']
1642 pid = list[dev]['pid'] 1784 pid = list[dev]['pid']
1643 if(pid < 0 or re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)): 1785 if(pid < 0 or re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)):
@@ -1718,9 +1860,9 @@ class Data:
1718 def createProcessUsageEvents(self): 1860 def createProcessUsageEvents(self):
1719 # get an array of process names 1861 # get an array of process names
1720 proclist = [] 1862 proclist = []
1721 for t in self.pstl: 1863 for t in sorted(self.pstl):
1722 pslist = self.pstl[t] 1864 pslist = self.pstl[t]
1723 for ps in pslist: 1865 for ps in sorted(pslist):
1724 if ps not in proclist: 1866 if ps not in proclist:
1725 proclist.append(ps) 1867 proclist.append(ps)
1726 # get a list of data points for suspend and resume 1868 # get a list of data points for suspend and resume
@@ -1765,7 +1907,7 @@ class Data:
1765 def debugPrint(self): 1907 def debugPrint(self):
1766 for p in self.sortedPhases(): 1908 for p in self.sortedPhases():
1767 list = self.dmesg[p]['list'] 1909 list = self.dmesg[p]['list']
1768 for devname in list: 1910 for devname in sorted(list):
1769 dev = list[devname] 1911 dev = list[devname]
1770 if 'ftrace' in dev: 1912 if 'ftrace' in dev:
1771 dev['ftrace'].debugPrint(' [%s]' % devname) 1913 dev['ftrace'].debugPrint(' [%s]' % devname)
@@ -2466,7 +2608,7 @@ class Timeline:
2466 # if there is 1 line per row, draw them the standard way 2608 # if there is 1 line per row, draw them the standard way
2467 for t, p in standardphases: 2609 for t, p in standardphases:
2468 for i in sorted(self.rowheight[t][p]): 2610 for i in sorted(self.rowheight[t][p]):
2469 self.rowheight[t][p][i] = self.bodyH/len(self.rowlines[t][p]) 2611 self.rowheight[t][p][i] = float(self.bodyH)/len(self.rowlines[t][p])
2470 def createZoomBox(self, mode='command', testcount=1): 2612 def createZoomBox(self, mode='command', testcount=1):
2471 # Create bounding box, add buttons 2613 # Create bounding box, add buttons
2472 html_zoombox = '<center><button id="zoomin">ZOOM IN +</button><button id="zoomout">ZOOM OUT -</button><button id="zoomdef">ZOOM 1:1</button></center>\n' 2614 html_zoombox = '<center><button id="zoomin">ZOOM IN +</button><button id="zoomout">ZOOM OUT -</button><button id="zoomdef">ZOOM 1:1</button></center>\n'
@@ -2537,6 +2679,7 @@ class TestProps:
2537 cmdlinefmt = '^# command \| (?P<cmd>.*)' 2679 cmdlinefmt = '^# command \| (?P<cmd>.*)'
2538 kparamsfmt = '^# kparams \| (?P<kp>.*)' 2680 kparamsfmt = '^# kparams \| (?P<kp>.*)'
2539 devpropfmt = '# Device Properties: .*' 2681 devpropfmt = '# Device Properties: .*'
2682 pinfofmt = '# platform-(?P<val>[a-z,A-Z,0-9]*): (?P<info>.*)'
2540 tracertypefmt = '# tracer: (?P<t>.*)' 2683 tracertypefmt = '# tracer: (?P<t>.*)'
2541 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$' 2684 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$'
2542 procexecfmt = 'ps - (?P<ps>.*)$' 2685 procexecfmt = 'ps - (?P<ps>.*)$'
@@ -2571,12 +2714,6 @@ class TestProps:
2571 self.ftrace_line_fmt = self.ftrace_line_fmt_nop 2714 self.ftrace_line_fmt = self.ftrace_line_fmt_nop
2572 else: 2715 else:
2573 doError('Invalid tracer format: [%s]' % tracer) 2716 doError('Invalid tracer format: [%s]' % tracer)
2574 def decode(self, data):
2575 try:
2576 out = base64.b64decode(data).decode('zlib')
2577 except:
2578 out = data
2579 return out
2580 def stampInfo(self, line): 2717 def stampInfo(self, line):
2581 if re.match(self.stampfmt, line): 2718 if re.match(self.stampfmt, line):
2582 self.stamp = line 2719 self.stamp = line
@@ -2660,7 +2797,7 @@ class TestProps:
2660 if len(self.mcelog) > data.testnumber: 2797 if len(self.mcelog) > data.testnumber:
2661 m = re.match(self.mcelogfmt, self.mcelog[data.testnumber]) 2798 m = re.match(self.mcelogfmt, self.mcelog[data.testnumber])
2662 if m: 2799 if m:
2663 data.mcelog = self.decode(m.group('m')) 2800 data.mcelog = sv.b64unzip(m.group('m'))
2664 # turbostat data 2801 # turbostat data
2665 if len(self.turbostat) > data.testnumber: 2802 if len(self.turbostat) > data.testnumber:
2666 m = re.match(self.tstatfmt, self.turbostat[data.testnumber]) 2803 m = re.match(self.tstatfmt, self.turbostat[data.testnumber])
@@ -2681,6 +2818,46 @@ class TestProps:
2681 m = re.match(self.testerrfmt, self.testerror[data.testnumber]) 2818 m = re.match(self.testerrfmt, self.testerror[data.testnumber])
2682 if m: 2819 if m:
2683 data.enterfail = m.group('e') 2820 data.enterfail = m.group('e')
2821 def devprops(self, data):
2822 props = dict()
2823 devlist = data.split(';')
2824 for dev in devlist:
2825 f = dev.split(',')
2826 if len(f) < 3:
2827 continue
2828 dev = f[0]
2829 props[dev] = DevProps()
2830 props[dev].altname = f[1]
2831 if int(f[2]):
2832 props[dev].isasync = True
2833 else:
2834 props[dev].isasync = False
2835 return props
2836 def parseDevprops(self, line, sv):
2837 idx = line.index(': ') + 2
2838 if idx >= len(line):
2839 return
2840 props = self.devprops(line[idx:])
2841 if sv.suspendmode == 'command' and 'testcommandstring' in props:
2842 sv.testcommand = props['testcommandstring'].altname
2843 sv.devprops = props
2844 def parsePlatformInfo(self, line, sv):
2845 m = re.match(self.pinfofmt, line)
2846 if not m:
2847 return
2848 name, info = m.group('val'), m.group('info')
2849 if name == 'devinfo':
2850 sv.devprops = self.devprops(sv.b64unzip(info))
2851 return
2852 elif name == 'testcmd':
2853 sv.testcommand = info
2854 return
2855 field = info.split('|')
2856 if len(field) < 2:
2857 return
2858 cmdline = field[0].strip()
2859 output = sv.b64unzip(field[1].strip())
2860 sv.platinfo.append([name, cmdline, output])
2684 2861
2685# Class: TestRun 2862# Class: TestRun
2686# Description: 2863# Description:
@@ -2701,7 +2878,7 @@ class ProcessMonitor:
2701 process = Popen(c, shell=True, stdout=PIPE) 2878 process = Popen(c, shell=True, stdout=PIPE)
2702 running = dict() 2879 running = dict()
2703 for line in process.stdout: 2880 for line in process.stdout:
2704 data = line.split() 2881 data = ascii(line).split()
2705 pid = data[0] 2882 pid = data[0]
2706 name = re.sub('[()]', '', data[1]) 2883 name = re.sub('[()]', '', data[1])
2707 user = int(data[13]) 2884 user = int(data[13])
@@ -2805,7 +2982,11 @@ def appendIncompleteTraceLog(testruns):
2805 continue 2982 continue
2806 # device properties line 2983 # device properties line
2807 if(re.match(tp.devpropfmt, line)): 2984 if(re.match(tp.devpropfmt, line)):
2808 devProps(line) 2985 tp.parseDevprops(line, sysvals)
2986 continue
2987 # platform info line
2988 if(re.match(tp.pinfofmt, line)):
2989 tp.parsePlatformInfo(line, sysvals)
2809 continue 2990 continue
2810 # parse only valid lines, if this is not one move on 2991 # parse only valid lines, if this is not one move on
2811 m = re.match(tp.ftrace_line_fmt, line) 2992 m = re.match(tp.ftrace_line_fmt, line)
@@ -2902,7 +3083,7 @@ def parseTraceLog(live=False):
2902 sysvals.setupAllKprobes() 3083 sysvals.setupAllKprobes()
2903 ksuscalls = ['pm_prepare_console'] 3084 ksuscalls = ['pm_prepare_console']
2904 krescalls = ['pm_restore_console'] 3085 krescalls = ['pm_restore_console']
2905 tracewatch = [] 3086 tracewatch = ['irq_wakeup']
2906 if sysvals.usekprobes: 3087 if sysvals.usekprobes:
2907 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend', 3088 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend',
2908 'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON', 3089 'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON',
@@ -2928,7 +3109,11 @@ def parseTraceLog(live=False):
2928 continue 3109 continue
2929 # device properties line 3110 # device properties line
2930 if(re.match(tp.devpropfmt, line)): 3111 if(re.match(tp.devpropfmt, line)):
2931 devProps(line) 3112 tp.parseDevprops(line, sysvals)
3113 continue
3114 # platform info line
3115 if(re.match(tp.pinfofmt, line)):
3116 tp.parsePlatformInfo(line, sysvals)
2932 continue 3117 continue
2933 # ignore all other commented lines 3118 # ignore all other commented lines
2934 if line[0] == '#': 3119 if line[0] == '#':
@@ -3001,16 +3186,11 @@ def parseTraceLog(live=False):
3001 isbegin = False 3186 isbegin = False
3002 else: 3187 else:
3003 continue 3188 continue
3004 m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name) 3189 if '[' in t.name:
3005 if(m): 3190 m = re.match('(?P<name>.*)\[.*', t.name)
3006 val = m.group('val')
3007 if val == '0':
3008 name = m.group('name')
3009 else:
3010 name = m.group('name')+'['+val+']'
3011 else: 3191 else:
3012 m = re.match('(?P<name>.*) .*', t.name) 3192 m = re.match('(?P<name>.*) .*', t.name)
3013 name = m.group('name') 3193 name = m.group('name')
3014 # ignore these events 3194 # ignore these events
3015 if(name.split('[')[0] in tracewatch): 3195 if(name.split('[')[0] in tracewatch):
3016 continue 3196 continue
@@ -3045,6 +3225,8 @@ def parseTraceLog(live=False):
3045 elif(re.match('machine_suspend\[.*', t.name)): 3225 elif(re.match('machine_suspend\[.*', t.name)):
3046 if(isbegin): 3226 if(isbegin):
3047 lp = data.lastPhase() 3227 lp = data.lastPhase()
3228 if lp == 'resume_machine':
3229 data.dmesg[lp]['end'] = t.time
3048 phase = data.setPhase('suspend_machine', data.dmesg[lp]['end'], True) 3230 phase = data.setPhase('suspend_machine', data.dmesg[lp]['end'], True)
3049 data.setPhase(phase, t.time, False) 3231 data.setPhase(phase, t.time, False)
3050 if data.tSuspended == 0: 3232 if data.tSuspended == 0:
@@ -3213,11 +3395,11 @@ def parseTraceLog(live=False):
3213 # add the traceevent data to the device hierarchy 3395 # add the traceevent data to the device hierarchy
3214 if(sysvals.usetraceevents): 3396 if(sysvals.usetraceevents):
3215 # add actual trace funcs 3397 # add actual trace funcs
3216 for name in test.ttemp: 3398 for name in sorted(test.ttemp):
3217 for event in test.ttemp[name]: 3399 for event in test.ttemp[name]:
3218 data.newActionGlobal(name, event['begin'], event['end'], event['pid']) 3400 data.newActionGlobal(name, event['begin'], event['end'], event['pid'])
3219 # add the kprobe based virtual tracefuncs as actual devices 3401 # add the kprobe based virtual tracefuncs as actual devices
3220 for key in tp.ktemp: 3402 for key in sorted(tp.ktemp):
3221 name, pid = key 3403 name, pid = key
3222 if name not in sysvals.tracefuncs: 3404 if name not in sysvals.tracefuncs:
3223 continue 3405 continue
@@ -3231,7 +3413,7 @@ def parseTraceLog(live=False):
3231 data.newActionGlobal(e['name'], kb, ke, pid, color) 3413 data.newActionGlobal(e['name'], kb, ke, pid, color)
3232 # add config base kprobes and dev kprobes 3414 # add config base kprobes and dev kprobes
3233 if sysvals.usedevsrc: 3415 if sysvals.usedevsrc:
3234 for key in tp.ktemp: 3416 for key in sorted(tp.ktemp):
3235 name, pid = key 3417 name, pid = key
3236 if name in sysvals.tracefuncs or name not in sysvals.dev_tracefuncs: 3418 if name in sysvals.tracefuncs or name not in sysvals.dev_tracefuncs:
3237 continue 3419 continue
@@ -3244,7 +3426,7 @@ def parseTraceLog(live=False):
3244 if sysvals.usecallgraph: 3426 if sysvals.usecallgraph:
3245 # add the callgraph data to the device hierarchy 3427 # add the callgraph data to the device hierarchy
3246 sortlist = dict() 3428 sortlist = dict()
3247 for key in test.ftemp: 3429 for key in sorted(test.ftemp):
3248 proc, pid = key 3430 proc, pid = key
3249 for cg in test.ftemp[key]: 3431 for cg in test.ftemp[key]:
3250 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0): 3432 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0):
@@ -3582,7 +3764,7 @@ def parseKernelLog(data):
3582 # if trace events are not available, these are better than nothing 3764 # if trace events are not available, these are better than nothing
3583 if(not sysvals.usetraceevents): 3765 if(not sysvals.usetraceevents):
3584 # look for known actions 3766 # look for known actions
3585 for a in at: 3767 for a in sorted(at):
3586 if(re.match(at[a]['smsg'], msg)): 3768 if(re.match(at[a]['smsg'], msg)):
3587 if(a not in actions): 3769 if(a not in actions):
3588 actions[a] = [] 3770 actions[a] = []
@@ -3641,7 +3823,7 @@ def parseKernelLog(data):
3641 data.tResumed = data.tSuspended 3823 data.tResumed = data.tSuspended
3642 3824
3643 # fill in any actions we've found 3825 # fill in any actions we've found
3644 for name in actions: 3826 for name in sorted(actions):
3645 for event in actions[name]: 3827 for event in actions[name]:
3646 data.newActionGlobal(name, event['begin'], event['end']) 3828 data.newActionGlobal(name, event['begin'], event['end'])
3647 3829
@@ -3761,7 +3943,7 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
3761 if lastmode and lastmode != mode and num > 0: 3943 if lastmode and lastmode != mode and num > 0:
3762 for i in range(2): 3944 for i in range(2):
3763 s = sorted(tMed[i]) 3945 s = sorted(tMed[i])
3764 list[lastmode]['med'][i] = s[int(len(s)/2)] 3946 list[lastmode]['med'][i] = s[int(len(s)//2)]
3765 iMed[i] = tMed[i][list[lastmode]['med'][i]] 3947 iMed[i] = tMed[i][list[lastmode]['med'][i]]
3766 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num] 3948 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num]
3767 list[lastmode]['min'] = tMin 3949 list[lastmode]['min'] = tMin
@@ -3803,7 +3985,7 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
3803 if lastmode and num > 0: 3985 if lastmode and num > 0:
3804 for i in range(2): 3986 for i in range(2):
3805 s = sorted(tMed[i]) 3987 s = sorted(tMed[i])
3806 list[lastmode]['med'][i] = s[int(len(s)/2)] 3988 list[lastmode]['med'][i] = s[int(len(s)//2)]
3807 iMed[i] = tMed[i][list[lastmode]['med'][i]] 3989 iMed[i] = tMed[i][list[lastmode]['med'][i]]
3808 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num] 3990 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num]
3809 list[lastmode]['min'] = tMin 3991 list[lastmode]['min'] = tMin
@@ -3845,7 +4027,7 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
3845 '</tr>\n' 4027 '</tr>\n'
3846 headnone = '<tr class="head"><td>{0}</td><td>{1}</td><td colspan='+\ 4028 headnone = '<tr class="head"><td>{0}</td><td>{1}</td><td colspan='+\
3847 colspan+'></td></tr>\n' 4029 colspan+'></td></tr>\n'
3848 for mode in list: 4030 for mode in sorted(list):
3849 # header line for each suspend mode 4031 # header line for each suspend mode
3850 num = 0 4032 num = 0
3851 tAvg, tMin, tMax, tMed = list[mode]['avg'], list[mode]['min'],\ 4033 tAvg, tMin, tMax, tMed = list[mode]['avg'], list[mode]['min'],\
@@ -3944,7 +4126,8 @@ def createHTMLDeviceSummary(testruns, htmlfile, title):
3944 th.format('Average Time') + th.format('Count') +\ 4126 th.format('Average Time') + th.format('Count') +\
3945 th.format('Worst Time') + th.format('Host (worst time)') +\ 4127 th.format('Worst Time') + th.format('Host (worst time)') +\
3946 th.format('Link (worst time)') + '</tr>\n' 4128 th.format('Link (worst time)') + '</tr>\n'
3947 for name in sorted(devlist, key=lambda k:devlist[k]['worst'], reverse=True): 4129 for name in sorted(devlist, key=lambda k:(devlist[k]['worst'], \
4130 devlist[k]['total'], devlist[k]['name']), reverse=True):
3948 data = devall[type][name] 4131 data = devall[type][name]
3949 data['average'] = data['total'] / data['count'] 4132 data['average'] = data['total'] / data['count']
3950 if data['average'] < limit: 4133 if data['average'] < limit:
@@ -4085,7 +4268,7 @@ def createHTML(testruns, testfail):
4085 if(tTotal == 0): 4268 if(tTotal == 0):
4086 doError('No timeline data') 4269 doError('No timeline data')
4087 if(len(data.tLow) > 0): 4270 if(len(data.tLow) > 0):
4088 low_time = '|'.join(data.tLow) 4271 low_time = '+'.join(data.tLow)
4089 if sysvals.suspendmode == 'command': 4272 if sysvals.suspendmode == 'command':
4090 run_time = '%.0f'%((data.end-data.start)*1000) 4273 run_time = '%.0f'%((data.end-data.start)*1000)
4091 if sysvals.testcommand: 4274 if sysvals.testcommand:
@@ -4151,7 +4334,7 @@ def createHTML(testruns, testfail):
4151 for group in data.devicegroups: 4334 for group in data.devicegroups:
4152 devlist = [] 4335 devlist = []
4153 for phase in group: 4336 for phase in group:
4154 for devname in data.tdevlist[phase]: 4337 for devname in sorted(data.tdevlist[phase]):
4155 d = DevItem(data.testnumber, phase, data.dmesg[phase]['list'][devname]) 4338 d = DevItem(data.testnumber, phase, data.dmesg[phase]['list'][devname])
4156 devlist.append(d) 4339 devlist.append(d)
4157 if d.isa('kth'): 4340 if d.isa('kth'):
@@ -4230,7 +4413,7 @@ def createHTML(testruns, testfail):
4230 for b in phases[dir]: 4413 for b in phases[dir]:
4231 # draw the devices for this phase 4414 # draw the devices for this phase
4232 phaselist = data.dmesg[b]['list'] 4415 phaselist = data.dmesg[b]['list']
4233 for d in data.tdevlist[b]: 4416 for d in sorted(data.tdevlist[b]):
4234 name = d 4417 name = d
4235 drv = '' 4418 drv = ''
4236 dev = phaselist[d] 4419 dev = phaselist[d]
@@ -4971,13 +5154,9 @@ def executeSuspend():
4971 if mode == 'freeze' and sysvals.haveTurbostat(): 5154 if mode == 'freeze' and sysvals.haveTurbostat():
4972 # execution will pause here 5155 # execution will pause here
4973 turbo = sysvals.turbostat() 5156 turbo = sysvals.turbostat()
4974 if '|' in turbo: 5157 if turbo:
4975 tdata['turbo'] = turbo 5158 tdata['turbo'] = turbo
4976 else:
4977 tdata['error'] = turbo
4978 else: 5159 else:
4979 if sysvals.haveTurbostat():
4980 sysvals.vprint('WARNING: ignoring turbostat in mode "%s"' % mode)
4981 pf = open(sysvals.powerfile, 'w') 5160 pf = open(sysvals.powerfile, 'w')
4982 pf.write(mode) 5161 pf.write(mode)
4983 # execution will pause here 5162 # execution will pause here
@@ -5024,7 +5203,7 @@ def executeSuspend():
5024 op.write(line) 5203 op.write(line)
5025 op.close() 5204 op.close()
5026 sysvals.fsetVal('', 'trace') 5205 sysvals.fsetVal('', 'trace')
5027 devProps() 5206 sysvals.platforminfo()
5028 return testdata 5207 return testdata
5029 5208
5030def readFile(file): 5209def readFile(file):
@@ -5040,9 +5219,9 @@ def readFile(file):
5040# The time string, e.g. "1901m16s" 5219# The time string, e.g. "1901m16s"
5041def ms2nice(val): 5220def ms2nice(val):
5042 val = int(val) 5221 val = int(val)
5043 h = val / 3600000 5222 h = val // 3600000
5044 m = (val / 60000) % 60 5223 m = (val // 60000) % 60
5045 s = (val / 1000) % 60 5224 s = (val // 1000) % 60
5046 if h > 0: 5225 if h > 0:
5047 return '%d:%02d:%02d' % (h, m, s) 5226 return '%d:%02d:%02d' % (h, m, s)
5048 if m > 0: 5227 if m > 0:
@@ -5115,127 +5294,6 @@ def deviceInfo(output=''):
5115 print(lines[i]) 5294 print(lines[i])
5116 return res 5295 return res
5117 5296
5118# Function: devProps
5119# Description:
5120# Retrieve a list of properties for all devices in the trace log
5121def devProps(data=0):
5122 props = dict()
5123
5124 if data:
5125 idx = data.index(': ') + 2
5126 if idx >= len(data):
5127 return
5128 devlist = data[idx:].split(';')
5129 for dev in devlist:
5130 f = dev.split(',')
5131 if len(f) < 3:
5132 continue
5133 dev = f[0]
5134 props[dev] = DevProps()
5135 props[dev].altname = f[1]
5136 if int(f[2]):
5137 props[dev].async = True
5138 else:
5139 props[dev].async = False
5140 sysvals.devprops = props
5141 if sysvals.suspendmode == 'command' and 'testcommandstring' in props:
5142 sysvals.testcommand = props['testcommandstring'].altname
5143 return
5144
5145 if(os.path.exists(sysvals.ftracefile) == False):
5146 doError('%s does not exist' % sysvals.ftracefile)
5147
5148 # first get the list of devices we need properties for
5149 msghead = 'Additional data added by AnalyzeSuspend'
5150 alreadystamped = False
5151 tp = TestProps()
5152 tf = sysvals.openlog(sysvals.ftracefile, 'r')
5153 for line in tf:
5154 if msghead in line:
5155 alreadystamped = True
5156 continue
5157 # determine the trace data type (required for further parsing)
5158 m = re.match(tp.tracertypefmt, line)
5159 if(m):
5160 tp.setTracerType(m.group('t'))
5161 continue
5162 # parse only valid lines, if this is not one move on
5163 m = re.match(tp.ftrace_line_fmt, line)
5164 if(not m or 'device_pm_callback_start' not in line):
5165 continue
5166 m = re.match('.*: (?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*', m.group('msg'));
5167 if(not m):
5168 continue
5169 dev = m.group('d')
5170 if dev not in props:
5171 props[dev] = DevProps()
5172 tf.close()
5173
5174 if not alreadystamped and sysvals.suspendmode == 'command':
5175 out = '#\n# '+msghead+'\n# Device Properties: '
5176 out += 'testcommandstring,%s,0;' % (sysvals.testcommand)
5177 with sysvals.openlog(sysvals.ftracefile, 'a') as fp:
5178 fp.write(out+'\n')
5179 sysvals.devprops = props
5180 return
5181
5182 # now get the syspath for each of our target devices
5183 for dirname, dirnames, filenames in os.walk('/sys/devices'):
5184 if(re.match('.*/power', dirname) and 'async' in filenames):
5185 dev = dirname.split('/')[-2]
5186 if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)):
5187 props[dev].syspath = dirname[:-6]
5188
5189 # now fill in the properties for our target devices
5190 for dev in props:
5191 dirname = props[dev].syspath
5192 if not dirname or not os.path.exists(dirname):
5193 continue
5194 with open(dirname+'/power/async') as fp:
5195 text = fp.read()
5196 props[dev].async = False
5197 if 'enabled' in text:
5198 props[dev].async = True
5199 fields = os.listdir(dirname)
5200 if 'product' in fields:
5201 with open(dirname+'/product') as fp:
5202 props[dev].altname = fp.read()
5203 elif 'name' in fields:
5204 with open(dirname+'/name') as fp:
5205 props[dev].altname = fp.read()
5206 elif 'model' in fields:
5207 with open(dirname+'/model') as fp:
5208 props[dev].altname = fp.read()
5209 elif 'description' in fields:
5210 with open(dirname+'/description') as fp:
5211 props[dev].altname = fp.read()
5212 elif 'id' in fields:
5213 with open(dirname+'/id') as fp:
5214 props[dev].altname = fp.read()
5215 elif 'idVendor' in fields and 'idProduct' in fields:
5216 idv, idp = '', ''
5217 with open(dirname+'/idVendor') as fp:
5218 idv = fp.read().strip()
5219 with open(dirname+'/idProduct') as fp:
5220 idp = fp.read().strip()
5221 props[dev].altname = '%s:%s' % (idv, idp)
5222
5223 if props[dev].altname:
5224 out = props[dev].altname.strip().replace('\n', ' ')
5225 out = out.replace(',', ' ')
5226 out = out.replace(';', ' ')
5227 props[dev].altname = out
5228
5229 # and now write the data to the ftrace file
5230 if not alreadystamped:
5231 out = '#\n# '+msghead+'\n# Device Properties: '
5232 for dev in sorted(props):
5233 out += props[dev].out(dev)
5234 with sysvals.openlog(sysvals.ftracefile, 'a') as fp:
5235 fp.write(out+'\n')
5236
5237 sysvals.devprops = props
5238
5239# Function: getModes 5297# Function: getModes
5240# Description: 5298# Description:
5241# Determine the supported power modes on this system 5299# Determine the supported power modes on this system
@@ -5339,11 +5397,11 @@ def dmidecode(mempath, fatal=False):
5339 # search for either an SM table or DMI table 5397 # search for either an SM table or DMI table
5340 i = base = length = num = 0 5398 i = base = length = num = 0
5341 while(i < memsize): 5399 while(i < memsize):
5342 if buf[i:i+4] == '_SM_' and i < memsize - 16: 5400 if buf[i:i+4] == b'_SM_' and i < memsize - 16:
5343 length = struct.unpack('H', buf[i+22:i+24])[0] 5401 length = struct.unpack('H', buf[i+22:i+24])[0]
5344 base, num = struct.unpack('IH', buf[i+24:i+30]) 5402 base, num = struct.unpack('IH', buf[i+24:i+30])
5345 break 5403 break
5346 elif buf[i:i+5] == '_DMI_': 5404 elif buf[i:i+5] == b'_DMI_':
5347 length = struct.unpack('H', buf[i+6:i+8])[0] 5405 length = struct.unpack('H', buf[i+6:i+8])[0]
5348 base, num = struct.unpack('IH', buf[i+8:i+14]) 5406 base, num = struct.unpack('IH', buf[i+8:i+14])
5349 break 5407 break
@@ -5376,15 +5434,15 @@ def dmidecode(mempath, fatal=False):
5376 if 0 == struct.unpack('H', buf[n:n+2])[0]: 5434 if 0 == struct.unpack('H', buf[n:n+2])[0]:
5377 break 5435 break
5378 n += 1 5436 n += 1
5379 data = buf[i+size:n+2].split('\0') 5437 data = buf[i+size:n+2].split(b'\0')
5380 for name in info: 5438 for name in info:
5381 itype, idxadr = info[name] 5439 itype, idxadr = info[name]
5382 if itype == type: 5440 if itype == type:
5383 idx = struct.unpack('B', buf[i+idxadr])[0] 5441 idx = struct.unpack('B', buf[i+idxadr:i+idxadr+1])[0]
5384 if idx > 0 and idx < len(data) - 1: 5442 if idx > 0 and idx < len(data) - 1:
5385 s = data[idx-1].strip() 5443 s = data[idx-1].decode('utf-8')
5386 if s and s.lower() != 'to be filled by o.e.m.': 5444 if s.strip() and s.strip().lower() != 'to be filled by o.e.m.':
5387 out[name] = data[idx-1] 5445 out[name] = s
5388 i = n + 2 5446 i = n + 2
5389 count += 1 5447 count += 1
5390 return out 5448 return out
@@ -5409,7 +5467,7 @@ def getBattery():
5409 return (ac, charge) 5467 return (ac, charge)
5410 5468
5411def displayControl(cmd): 5469def displayControl(cmd):
5412 xset, ret = 'xset -d :0.0 {0}', 0 5470 xset, ret = 'timeout 10 xset -d :0.0 {0}', 0
5413 if sysvals.sudouser: 5471 if sysvals.sudouser:
5414 xset = 'sudo -u %s %s' % (sysvals.sudouser, xset) 5472 xset = 'sudo -u %s %s' % (sysvals.sudouser, xset)
5415 if cmd == 'init': 5473 if cmd == 'init':
@@ -5433,7 +5491,7 @@ def displayControl(cmd):
5433 fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout 5491 fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout
5434 ret = 'unknown' 5492 ret = 'unknown'
5435 for line in fp: 5493 for line in fp:
5436 m = re.match('[\s]*Monitor is (?P<m>.*)', line) 5494 m = re.match('[\s]*Monitor is (?P<m>.*)', ascii(line))
5437 if(m and len(m.group('m')) >= 2): 5495 if(m and len(m.group('m')) >= 2):
5438 out = m.group('m').lower() 5496 out = m.group('m').lower()
5439 ret = out[3:] if out[0:2] == 'in' else out 5497 ret = out[3:] if out[0:2] == 'in' else out
@@ -5495,10 +5553,11 @@ def getFPDT(output):
5495 ' OEM Revision : %u\n'\ 5553 ' OEM Revision : %u\n'\
5496 ' Creator ID : %s\n'\ 5554 ' Creator ID : %s\n'\
5497 ' Creator Revision : 0x%x\n'\ 5555 ' Creator Revision : 0x%x\n'\
5498 '' % (table[0], table[0], table[1], table[2], table[3], 5556 '' % (ascii(table[0]), ascii(table[0]), table[1], table[2],
5499 table[4], table[5], table[6], table[7], table[8])) 5557 table[3], ascii(table[4]), ascii(table[5]), table[6],
5558 ascii(table[7]), table[8]))
5500 5559
5501 if(table[0] != 'FPDT'): 5560 if(table[0] != b'FPDT'):
5502 if(output): 5561 if(output):
5503 doError('Invalid FPDT table') 5562 doError('Invalid FPDT table')
5504 return False 5563 return False
@@ -5530,8 +5589,8 @@ def getFPDT(output):
5530 return [0, 0] 5589 return [0, 0]
5531 rechead = struct.unpack('4sI', first) 5590 rechead = struct.unpack('4sI', first)
5532 recdata = fp.read(rechead[1]-8) 5591 recdata = fp.read(rechead[1]-8)
5533 if(rechead[0] == 'FBPT'): 5592 if(rechead[0] == b'FBPT'):
5534 record = struct.unpack('HBBIQQQQQ', recdata) 5593 record = struct.unpack('HBBIQQQQQ', recdata[:48])
5535 if(output): 5594 if(output):
5536 pprint('%s (%s)\n'\ 5595 pprint('%s (%s)\n'\
5537 ' Reset END : %u ns\n'\ 5596 ' Reset END : %u ns\n'\
@@ -5539,11 +5598,11 @@ def getFPDT(output):
5539 ' OS Loader StartImage Start : %u ns\n'\ 5598 ' OS Loader StartImage Start : %u ns\n'\
5540 ' ExitBootServices Entry : %u ns\n'\ 5599 ' ExitBootServices Entry : %u ns\n'\
5541 ' ExitBootServices Exit : %u ns'\ 5600 ' ExitBootServices Exit : %u ns'\
5542 '' % (rectype[header[0]], rechead[0], record[4], record[5], 5601 '' % (rectype[header[0]], ascii(rechead[0]), record[4], record[5],
5543 record[6], record[7], record[8])) 5602 record[6], record[7], record[8]))
5544 elif(rechead[0] == 'S3PT'): 5603 elif(rechead[0] == b'S3PT'):
5545 if(output): 5604 if(output):
5546 pprint('%s (%s)' % (rectype[header[0]], rechead[0])) 5605 pprint('%s (%s)' % (rectype[header[0]], ascii(rechead[0])))
5547 j = 0 5606 j = 0
5548 while(j < len(recdata)): 5607 while(j < len(recdata)):
5549 prechead = struct.unpack('HBB', recdata[j:j+4]) 5608 prechead = struct.unpack('HBB', recdata[j:j+4])
@@ -5689,7 +5748,7 @@ def doError(msg, help=False):
5689def getArgInt(name, args, min, max, main=True): 5748def getArgInt(name, args, min, max, main=True):
5690 if main: 5749 if main:
5691 try: 5750 try:
5692 arg = args.next() 5751 arg = next(args)
5693 except: 5752 except:
5694 doError(name+': no argument supplied', True) 5753 doError(name+': no argument supplied', True)
5695 else: 5754 else:
@@ -5708,7 +5767,7 @@ def getArgInt(name, args, min, max, main=True):
5708def getArgFloat(name, args, min, max, main=True): 5767def getArgFloat(name, args, min, max, main=True):
5709 if main: 5768 if main:
5710 try: 5769 try:
5711 arg = args.next() 5770 arg = next(args)
5712 except: 5771 except:
5713 doError(name+': no argument supplied', True) 5772 doError(name+': no argument supplied', True)
5714 else: 5773 else:
@@ -5737,9 +5796,12 @@ def processData(live=False):
5737 parseKernelLog(data) 5796 parseKernelLog(data)
5738 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)): 5797 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)):
5739 appendIncompleteTraceLog(testruns) 5798 appendIncompleteTraceLog(testruns)
5799 shown = ['bios', 'biosdate', 'cpu', 'host', 'kernel', 'man', 'memfr',
5800 'memsz', 'mode', 'numcpu', 'plat', 'time']
5740 sysvals.vprint('System Info:') 5801 sysvals.vprint('System Info:')
5741 for key in sorted(sysvals.stamp): 5802 for key in sorted(sysvals.stamp):
5742 sysvals.vprint(' %-8s : %s' % (key.upper(), sysvals.stamp[key])) 5803 if key in shown:
5804 sysvals.vprint(' %-8s : %s' % (key.upper(), sysvals.stamp[key]))
5743 if sysvals.kparams: 5805 if sysvals.kparams:
5744 sysvals.vprint('Kparams:\n %s' % sysvals.kparams) 5806 sysvals.vprint('Kparams:\n %s' % sysvals.kparams)
5745 sysvals.vprint('Command:\n %s' % sysvals.cmdline) 5807 sysvals.vprint('Command:\n %s' % sysvals.cmdline)
@@ -5768,6 +5830,12 @@ def processData(live=False):
5768 (w[0], w[1]) 5830 (w[0], w[1])
5769 sysvals.vprint(s) 5831 sysvals.vprint(s)
5770 data.printDetails() 5832 data.printDetails()
5833 if len(sysvals.platinfo) > 0:
5834 sysvals.vprint('\nPlatform Info:')
5835 for info in sysvals.platinfo:
5836 sysvals.vprint(info[0]+' - '+info[1])
5837 sysvals.vprint(info[2])
5838 sysvals.vprint('')
5771 if sysvals.cgdump: 5839 if sysvals.cgdump:
5772 for data in testruns: 5840 for data in testruns:
5773 data.debugPrint() 5841 data.debugPrint()
@@ -5951,7 +6019,7 @@ def data_from_html(file, outpath, issues, fulldetail=False):
5951 worst[d] = {'name':'', 'time': 0.0} 6019 worst[d] = {'name':'', 'time': 0.0}
5952 dev = devices[d] if d in devices else 0 6020 dev = devices[d] if d in devices else 0
5953 if dev and len(dev.keys()) > 0: 6021 if dev and len(dev.keys()) > 0:
5954 n = sorted(dev, key=dev.get, reverse=True)[0] 6022 n = sorted(dev, key=lambda k:(dev[k], k), reverse=True)[0]
5955 worst[d]['name'], worst[d]['time'] = n, dev[n] 6023 worst[d]['name'], worst[d]['time'] = n, dev[n]
5956 data = { 6024 data = {
5957 'mode': stmp[2], 6025 'mode': stmp[2],
@@ -5976,7 +6044,7 @@ def data_from_html(file, outpath, issues, fulldetail=False):
5976 data['funclist'] = find_in_html(html, '<div title="', '" class="traceevent"', False) 6044 data['funclist'] = find_in_html(html, '<div title="', '" class="traceevent"', False)
5977 return data 6045 return data
5978 6046
5979def genHtml(subdir): 6047def genHtml(subdir, force=False):
5980 for dirname, dirnames, filenames in os.walk(subdir): 6048 for dirname, dirnames, filenames in os.walk(subdir):
5981 sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = '' 6049 sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = ''
5982 for filename in filenames: 6050 for filename in filenames:
@@ -5986,7 +6054,7 @@ def genHtml(subdir):
5986 sysvals.ftracefile = os.path.join(dirname, filename) 6054 sysvals.ftracefile = os.path.join(dirname, filename)
5987 sysvals.setOutputFile() 6055 sysvals.setOutputFile()
5988 if sysvals.ftracefile and sysvals.htmlfile and \ 6056 if sysvals.ftracefile and sysvals.htmlfile and \
5989 not os.path.exists(sysvals.htmlfile): 6057 (force or not os.path.exists(sysvals.htmlfile)):
5990 pprint('FTRACE: %s' % sysvals.ftracefile) 6058 pprint('FTRACE: %s' % sysvals.ftracefile)
5991 if sysvals.dmesgfile: 6059 if sysvals.dmesgfile:
5992 pprint('DMESG : %s' % sysvals.dmesgfile) 6060 pprint('DMESG : %s' % sysvals.dmesgfile)
@@ -6042,7 +6110,7 @@ def checkArgBool(name, value):
6042# Description: 6110# Description:
6043# Configure the script via the info in a config file 6111# Configure the script via the info in a config file
6044def configFromFile(file): 6112def configFromFile(file):
6045 Config = ConfigParser.ConfigParser() 6113 Config = configparser.ConfigParser()
6046 6114
6047 Config.read(file) 6115 Config.read(file)
6048 sections = Config.sections() 6116 sections = Config.sections()
@@ -6270,7 +6338,7 @@ def printHelp():
6270 ' default: suspend-{date}-{time}\n'\ 6338 ' default: suspend-{date}-{time}\n'\
6271 ' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)\n'\ 6339 ' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)\n'\
6272 ' -addlogs Add the dmesg and ftrace logs to the html output\n'\ 6340 ' -addlogs Add the dmesg and ftrace logs to the html output\n'\
6273 ' -turbostat Use turbostat to execute the command in freeze mode (default: disabled)\n'\ 6341 ' -noturbostat Dont use turbostat in freeze mode (default: disabled)\n'\
6274 ' -srgap Add a visible gap in the timeline between sus/res (default: disabled)\n'\ 6342 ' -srgap Add a visible gap in the timeline between sus/res (default: disabled)\n'\
6275 ' -skiphtml Run the test and capture the trace logs, but skip the timeline (default: disabled)\n'\ 6343 ' -skiphtml Run the test and capture the trace logs, but skip the timeline (default: disabled)\n'\
6276 ' -result fn Export a results table to a text file for parsing.\n'\ 6344 ' -result fn Export a results table to a text file for parsing.\n'\
@@ -6340,7 +6408,7 @@ if __name__ == '__main__':
6340 for arg in args: 6408 for arg in args:
6341 if(arg == '-m'): 6409 if(arg == '-m'):
6342 try: 6410 try:
6343 val = args.next() 6411 val = next(args)
6344 except: 6412 except:
6345 doError('No mode supplied', True) 6413 doError('No mode supplied', True)
6346 if val == 'command' and not sysvals.testcommand: 6414 if val == 'command' and not sysvals.testcommand:
@@ -6384,10 +6452,8 @@ if __name__ == '__main__':
6384 sysvals.dmesglog = True 6452 sysvals.dmesglog = True
6385 elif(arg == '-addlogftrace'): 6453 elif(arg == '-addlogftrace'):
6386 sysvals.ftracelog = True 6454 sysvals.ftracelog = True
6387 elif(arg == '-turbostat'): 6455 elif(arg == '-noturbostat'):
6388 sysvals.tstat = True 6456 sysvals.tstat = False
6389 if not sysvals.haveTurbostat():
6390 doError('Turbostat command not found')
6391 elif(arg == '-verbose'): 6457 elif(arg == '-verbose'):
6392 sysvals.verbose = True 6458 sysvals.verbose = True
6393 elif(arg == '-proc'): 6459 elif(arg == '-proc'):
@@ -6400,7 +6466,7 @@ if __name__ == '__main__':
6400 sysvals.gzip = True 6466 sysvals.gzip = True
6401 elif(arg == '-rs'): 6467 elif(arg == '-rs'):
6402 try: 6468 try:
6403 val = args.next() 6469 val = next(args)
6404 except: 6470 except:
6405 doError('-rs requires "enable" or "disable"', True) 6471 doError('-rs requires "enable" or "disable"', True)
6406 if val.lower() in switchvalues: 6472 if val.lower() in switchvalues:
@@ -6412,7 +6478,7 @@ if __name__ == '__main__':
6412 doError('invalid option: %s, use "enable/disable" or "on/off"' % val, True) 6478 doError('invalid option: %s, use "enable/disable" or "on/off"' % val, True)
6413 elif(arg == '-display'): 6479 elif(arg == '-display'):
6414 try: 6480 try:
6415 val = args.next() 6481 val = next(args)
6416 except: 6482 except:
6417 doError('-display requires an mode value', True) 6483 doError('-display requires an mode value', True)
6418 disopt = ['on', 'off', 'standby', 'suspend'] 6484 disopt = ['on', 'off', 'standby', 'suspend']
@@ -6423,7 +6489,7 @@ if __name__ == '__main__':
6423 sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000) 6489 sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000)
6424 elif(arg == '-rtcwake'): 6490 elif(arg == '-rtcwake'):
6425 try: 6491 try:
6426 val = args.next() 6492 val = next(args)
6427 except: 6493 except:
6428 doError('No rtcwake time supplied', True) 6494 doError('No rtcwake time supplied', True)
6429 if val.lower() in switchoff: 6495 if val.lower() in switchoff:
@@ -6443,7 +6509,7 @@ if __name__ == '__main__':
6443 sysvals.cgtest = getArgInt('-cgtest', args, 0, 1) 6509 sysvals.cgtest = getArgInt('-cgtest', args, 0, 1)
6444 elif(arg == '-cgphase'): 6510 elif(arg == '-cgphase'):
6445 try: 6511 try:
6446 val = args.next() 6512 val = next(args)
6447 except: 6513 except:
6448 doError('No phase name supplied', True) 6514 doError('No phase name supplied', True)
6449 d = Data(0) 6515 d = Data(0)
@@ -6453,19 +6519,19 @@ if __name__ == '__main__':
6453 sysvals.cgphase = val 6519 sysvals.cgphase = val
6454 elif(arg == '-cgfilter'): 6520 elif(arg == '-cgfilter'):
6455 try: 6521 try:
6456 val = args.next() 6522 val = next(args)
6457 except: 6523 except:
6458 doError('No callgraph functions supplied', True) 6524 doError('No callgraph functions supplied', True)
6459 sysvals.setCallgraphFilter(val) 6525 sysvals.setCallgraphFilter(val)
6460 elif(arg == '-skipkprobe'): 6526 elif(arg == '-skipkprobe'):
6461 try: 6527 try:
6462 val = args.next() 6528 val = next(args)
6463 except: 6529 except:
6464 doError('No kprobe functions supplied', True) 6530 doError('No kprobe functions supplied', True)
6465 sysvals.skipKprobes(val) 6531 sysvals.skipKprobes(val)
6466 elif(arg == '-cgskip'): 6532 elif(arg == '-cgskip'):
6467 try: 6533 try:
6468 val = args.next() 6534 val = next(args)
6469 except: 6535 except:
6470 doError('No file supplied', True) 6536 doError('No file supplied', True)
6471 if val.lower() in switchoff: 6537 if val.lower() in switchoff:
@@ -6480,7 +6546,7 @@ if __name__ == '__main__':
6480 sysvals.callloopmaxlen = getArgFloat('-callloop-maxlen', args, 0.0, 1.0) 6546 sysvals.callloopmaxlen = getArgFloat('-callloop-maxlen', args, 0.0, 1.0)
6481 elif(arg == '-cmd'): 6547 elif(arg == '-cmd'):
6482 try: 6548 try:
6483 val = args.next() 6549 val = next(args)
6484 except: 6550 except:
6485 doError('No command string supplied', True) 6551 doError('No command string supplied', True)
6486 sysvals.testcommand = val 6552 sysvals.testcommand = val
@@ -6495,13 +6561,13 @@ if __name__ == '__main__':
6495 sysvals.multitest['delay'] = getArgInt('-multi n d (delay between tests)', args, 0, 3600) 6561 sysvals.multitest['delay'] = getArgInt('-multi n d (delay between tests)', args, 0, 3600)
6496 elif(arg == '-o'): 6562 elif(arg == '-o'):
6497 try: 6563 try:
6498 val = args.next() 6564 val = next(args)
6499 except: 6565 except:
6500 doError('No subdirectory name supplied', True) 6566 doError('No subdirectory name supplied', True)
6501 sysvals.outdir = sysvals.setOutputFolder(val) 6567 sysvals.outdir = sysvals.setOutputFolder(val)
6502 elif(arg == '-config'): 6568 elif(arg == '-config'):
6503 try: 6569 try:
6504 val = args.next() 6570 val = next(args)
6505 except: 6571 except:
6506 doError('No text file supplied', True) 6572 doError('No text file supplied', True)
6507 file = sysvals.configFile(val) 6573 file = sysvals.configFile(val)
@@ -6510,7 +6576,7 @@ if __name__ == '__main__':
6510 configFromFile(file) 6576 configFromFile(file)
6511 elif(arg == '-fadd'): 6577 elif(arg == '-fadd'):
6512 try: 6578 try:
6513 val = args.next() 6579 val = next(args)
6514 except: 6580 except:
6515 doError('No text file supplied', True) 6581 doError('No text file supplied', True)
6516 file = sysvals.configFile(val) 6582 file = sysvals.configFile(val)
@@ -6519,7 +6585,7 @@ if __name__ == '__main__':
6519 sysvals.addFtraceFilterFunctions(file) 6585 sysvals.addFtraceFilterFunctions(file)
6520 elif(arg == '-dmesg'): 6586 elif(arg == '-dmesg'):
6521 try: 6587 try:
6522 val = args.next() 6588 val = next(args)
6523 except: 6589 except:
6524 doError('No dmesg file supplied', True) 6590 doError('No dmesg file supplied', True)
6525 sysvals.notestrun = True 6591 sysvals.notestrun = True
@@ -6528,7 +6594,7 @@ if __name__ == '__main__':
6528 doError('%s does not exist' % sysvals.dmesgfile) 6594 doError('%s does not exist' % sysvals.dmesgfile)
6529 elif(arg == '-ftrace'): 6595 elif(arg == '-ftrace'):
6530 try: 6596 try:
6531 val = args.next() 6597 val = next(args)
6532 except: 6598 except:
6533 doError('No ftrace file supplied', True) 6599 doError('No ftrace file supplied', True)
6534 sysvals.notestrun = True 6600 sysvals.notestrun = True
@@ -6537,7 +6603,7 @@ if __name__ == '__main__':
6537 doError('%s does not exist' % sysvals.ftracefile) 6603 doError('%s does not exist' % sysvals.ftracefile)
6538 elif(arg == '-summary'): 6604 elif(arg == '-summary'):
6539 try: 6605 try:
6540 val = args.next() 6606 val = next(args)
6541 except: 6607 except:
6542 doError('No directory supplied', True) 6608 doError('No directory supplied', True)
6543 cmd = 'summary' 6609 cmd = 'summary'
@@ -6547,13 +6613,13 @@ if __name__ == '__main__':
6547 doError('%s is not accesible' % val) 6613 doError('%s is not accesible' % val)
6548 elif(arg == '-filter'): 6614 elif(arg == '-filter'):
6549 try: 6615 try:
6550 val = args.next() 6616 val = next(args)
6551 except: 6617 except:
6552 doError('No devnames supplied', True) 6618 doError('No devnames supplied', True)
6553 sysvals.setDeviceFilter(val) 6619 sysvals.setDeviceFilter(val)
6554 elif(arg == '-result'): 6620 elif(arg == '-result'):
6555 try: 6621 try:
6556 val = args.next() 6622 val = next(args)
6557 except: 6623 except:
6558 doError('No result file supplied', True) 6624 doError('No result file supplied', True)
6559 sysvals.result = val 6625 sysvals.result = val