1 #!/usr/bin/env python3 2 # SPDX-License-Identifier: GPL-2.0-only 3 # 4 # Tool for analyzing suspend/resume timing 5 # Copyright (c) 2013, Intel Corporation. 6 # 7 # This program is free software; you can redis 8 # under the terms and conditions of the GNU Ge 9 # version 2, as published by the Free Software 10 # 11 # This program is distributed in the hope it w 12 # ANY WARRANTY; without even the implied warra 13 # FITNESS FOR A PARTICULAR PURPOSE. See the G 14 # more details. 15 # 16 # Authors: 17 # Todd Brandt <todd.e.brandt@linux.intel 18 # 19 # Links: 20 # Home Page 21 # https://01.org/pm-graph 22 # Source repo 23 # git@github.com:intel/pm-graph 24 # 25 # Description: 26 # This tool is designed to assist kerne 27 # their linux stack's suspend/resume ti 28 # with a few extra options enabled, the 29 # will capture dmesg and ftrace data un 30 # is transformed into a device timeline 31 # and detailed view of which devices an 32 # time in suspend/resume. The output is 33 # viewed in firefox or chrome. 34 # 35 # The following kernel build options ar 36 # CONFIG_DEVMEM=y 37 # CONFIG_PM_DEBUG=y 38 # CONFIG_PM_SLEEP_DEBUG=y 39 # CONFIG_FTRACE=y 40 # CONFIG_FUNCTION_TRACER=y 41 # CONFIG_FUNCTION_GRAPH_TRACER= 42 # CONFIG_KPROBES=y 43 # CONFIG_KPROBES_ON_FTRACE=y 44 # 45 # For kernel versions older than 3.15: 46 # The following additional kernel param 47 # (e.g. in file /etc/default/gr 48 # GRUB_CMDLINE_LINUX_DEFAULT=". 49 # 50 51 # ----------------- LIBRARIES ---------------- 52 53 import sys 54 import time 55 import os 56 import string 57 import re 58 import platform 59 import signal 60 import codecs 61 from datetime import datetime, timedelta 62 import struct 63 import configparser 64 import gzip 65 from threading import Thread 66 from subprocess import call, Popen, PIPE 67 import base64 68 69 debugtiming = False 70 mystarttime = time.time() 71 def pprint(msg): 72 if debugtiming: 73 print('[%09.3f] %s' % (time.ti 74 else: 75 print(msg) 76 sys.stdout.flush() 77 78 def ascii(text): 79 return text.decode('ascii', 'ignore') 80 81 # ----------------- CLASSES ------------------ 82 83 # Class: SystemValues 84 # Description: 85 # A global, single-instance container u 86 # store system values and test paramete 87 class SystemValues: 88 title = 'SleepGraph' 89 version = '5.12' 90 ansi = False 91 rs = 0 92 display = '' 93 gzip = False 94 sync = False 95 wifi = False 96 netfix = False 97 verbose = False 98 testlog = True 99 dmesglog = True 100 ftracelog = False 101 acpidebug = True 102 tstat = True 103 wifitrace = False 104 mindevlen = 0.0001 105 mincglen = 0.0 106 cgphase = '' 107 cgtest = -1 108 cgskip = '' 109 maxfail = 0 110 multitest = {'run': False, 'count': 10 111 max_graph_depth = 0 112 callloopmaxgap = 0.0001 113 callloopmaxlen = 0.005 114 bufsize = 0 115 cpucount = 0 116 memtotal = 204800 117 memfree = 204800 118 osversion = '' 119 srgap = 0 120 cgexp = False 121 testdir = '' 122 outdir = '' 123 tpath = '/sys/kernel/tracing/' 124 fpdtpath = '/sys/firmware/acpi/tables/ 125 epath = '/sys/kernel/tracing/events/po 126 pmdpath = '/sys/power/pm_debug_message 127 s0ixpath = '/sys/module/intel_pmc_core 128 s0ixres = '/sys/devices/system/cpu/cpu 129 acpipath='/sys/module/acpi/parameters/ 130 traceevents = [ 131 'suspend_resume', 132 'wakeup_source_activate', 133 'wakeup_source_deactivate', 134 'device_pm_callback_end', 135 'device_pm_callback_start' 136 ] 137 logmsg = '' 138 testcommand = '' 139 mempath = '/dev/mem' 140 powerfile = '/sys/power/state' 141 mempowerfile = '/sys/power/mem_sleep' 142 diskpowerfile = '/sys/power/disk' 143 suspendmode = 'mem' 144 memmode = '' 145 diskmode = '' 146 hostname = 'localhost' 147 prefix = 'test' 148 teststamp = '' 149 sysstamp = '' 150 dmesgstart = 0.0 151 dmesgfile = '' 152 ftracefile = '' 153 htmlfile = 'output.html' 154 result = '' 155 rtcwake = True 156 rtcwaketime = 15 157 rtcpath = '' 158 devicefilter = [] 159 cgfilter = [] 160 stamp = 0 161 execcount = 1 162 x2delay = 0 163 skiphtml = False 164 usecallgraph = False 165 ftopfunc = 'pm_suspend' 166 ftop = False 167 usetraceevents = False 168 usetracemarkers = True 169 useftrace = True 170 usekprobes = True 171 usedevsrc = False 172 useprocmon = False 173 notestrun = False 174 cgdump = False 175 devdump = False 176 mixedphaseheight = True 177 devprops = dict() 178 cfgdef = dict() 179 platinfo = [] 180 predelay = 0 181 postdelay = 0 182 tmstart = 'SUSPEND START %Y%m%d-%H:%M: 183 tmend = 'RESUME COMPLETE %Y%m%d-%H:%M: 184 tracefuncs = { 185 'async_synchronize_full': {}, 186 'sys_sync': {}, 187 'ksys_sync': {}, 188 '__pm_notifier_call_chain': {} 189 'pm_prepare_console': {}, 190 'pm_notifier_call_chain': {}, 191 'freeze_processes': {}, 192 'freeze_kernel_threads': {}, 193 'pm_restrict_gfp_mask': {}, 194 'acpi_suspend_begin': {}, 195 'acpi_hibernation_begin': {}, 196 'acpi_hibernation_enter': {}, 197 'acpi_hibernation_leave': {}, 198 'acpi_pm_freeze': {}, 199 'acpi_pm_thaw': {}, 200 'acpi_s2idle_end': {}, 201 'acpi_s2idle_sync': {}, 202 'acpi_s2idle_begin': {}, 203 'acpi_s2idle_prepare': {}, 204 'acpi_s2idle_prepare_late': {} 205 'acpi_s2idle_wake': {}, 206 'acpi_s2idle_wakeup': {}, 207 'acpi_s2idle_restore': {}, 208 'acpi_s2idle_restore_early': { 209 'hibernate_preallocate_memory' 210 'create_basic_memory_bitmaps': 211 'swsusp_write': {}, 212 'suspend_console': {}, 213 'acpi_pm_prepare': {}, 214 'syscore_suspend': {}, 215 'arch_enable_nonboot_cpus_end' 216 'syscore_resume': {}, 217 'acpi_pm_finish': {}, 218 'resume_console': {}, 219 'acpi_pm_end': {}, 220 'pm_restore_gfp_mask': {}, 221 'thaw_processes': {}, 222 'pm_restore_console': {}, 223 'CPU_OFF': { 224 'func':'_cpu_down', 225 'args_x86_64': {'cpu': 226 'format': 'CPU_OFF[{cp 227 }, 228 'CPU_ON': { 229 'func':'_cpu_up', 230 'args_x86_64': {'cpu': 231 'format': 'CPU_ON[{cpu 232 }, 233 } 234 dev_tracefuncs = { 235 # general wait/delay/sleep 236 'msleep': { 'args_x86_64': {'t 237 'schedule_timeout': { 'args_x8 238 'udelay': { 'func':'__const_ud 239 'usleep_range': { 'args_x86_64 240 'mutex_lock_slowpath': { 'func 241 'acpi_os_stall': {'ub': 1}, 242 'rt_mutex_slowlock': {'ub': 1} 243 # ACPI 244 'acpi_resume_power_resources': 245 'acpi_ps_execute_method': { 'a 246 'fullpath':'+0(+40(%di 247 }}, 248 # mei_me 249 'mei_reset': {}, 250 # filesystem 251 'ext4_sync_fs': {}, 252 # 80211 253 'ath10k_bmi_read_memory': { 'a 254 'ath10k_bmi_write_memory': { ' 255 'ath10k_bmi_fast_download': { 256 'iwlagn_mac_start': {}, 257 'iwlagn_alloc_bcast_station': 258 'iwl_trans_pcie_start_hw': {}, 259 'iwl_trans_pcie_start_fw': {}, 260 'iwl_run_init_ucode': {}, 261 'iwl_load_ucode_wait_alive': { 262 'iwl_alive_start': {}, 263 'iwlagn_mac_stop': {}, 264 'iwlagn_mac_suspend': {}, 265 'iwlagn_mac_resume': {}, 266 'iwlagn_mac_add_interface': {} 267 'iwlagn_mac_remove_interface': 268 'iwlagn_mac_change_interface': 269 'iwlagn_mac_config': {}, 270 'iwlagn_configure_filter': {}, 271 'iwlagn_mac_hw_scan': {}, 272 'iwlagn_bss_info_changed': {}, 273 'iwlagn_mac_channel_switch': { 274 'iwlagn_mac_flush': {}, 275 # ATA 276 'ata_eh_recover': { 'args_x86_ 277 # i915 278 'i915_gem_resume': {}, 279 'i915_restore_state': {}, 280 'intel_opregion_setup': {}, 281 'g4x_pre_enable_dp': {}, 282 'vlv_pre_enable_dp': {}, 283 'chv_pre_enable_dp': {}, 284 'g4x_enable_dp': {}, 285 'vlv_enable_dp': {}, 286 'intel_hpd_init': {}, 287 'intel_opregion_register': {}, 288 'intel_dp_detect': {}, 289 'intel_hdmi_detect': {}, 290 'intel_opregion_init': {}, 291 'intel_fbdev_set_suspend': {}, 292 } 293 infocmds = [ 294 [0, 'sysinfo', 'uname', '-a'], 295 [0, 'cpuinfo', 'head', '-7', ' 296 [0, 'kparams', 'cat', '/proc/c 297 [0, 'mcelog', 'mcelog'], 298 [0, 'pcidevices', 'lspci', '-t 299 [0, 'usbdevices', 'lsusb', '-t 300 [0, 'acpidevices', 'sh', '-c', 301 [0, 's0ix_require', 'cat', '/s 302 [0, 's0ix_debug', 'cat', '/sys 303 [0, 'ethtool', 'ethtool', '{et 304 [1, 's0ix_residency', 'cat', ' 305 [1, 'interrupts', 'cat', '/pro 306 [1, 'wakeups', 'cat', '/sys/ke 307 [2, 'gpecounts', 'sh', '-c', ' 308 [2, 'suspendstats', 'sh', '-c' 309 [2, 'cpuidle', 'sh', '-c', 'gr 310 [2, 'battery', 'sh', '-c', 'gr 311 [2, 'thermal', 'sh', '-c', 'gr 312 ] 313 cgblacklist = [] 314 kprobes = dict() 315 timeformat = '%.3f' 316 cmdline = '%s %s' % \ 317 (os.path.basename(sys. 318 sudouser = '' 319 def __init__(self): 320 self.archargs = 'args_'+platfo 321 self.hostname = platform.node( 322 if(self.hostname == ''): 323 self.hostname = 'local 324 rtc = "rtc0" 325 if os.path.exists('/dev/rtc'): 326 rtc = os.readlink('/de 327 rtc = '/sys/class/rtc/'+rtc 328 if os.path.exists(rtc) and os. 329 os.path.exists(rtc+'/t 330 self.rtcpath = rtc 331 if (hasattr(sys.stdout, 'isatt 332 self.ansi = True 333 self.testdir = datetime.now(). 334 if os.getuid() == 0 and 'SUDO_ 335 os.environ['SUDO_USER' 336 self.sudouser = os.env 337 def resetlog(self): 338 self.logmsg = '' 339 self.platinfo = [] 340 def vprint(self, msg): 341 self.logmsg += msg+'\n' 342 if self.verbose or msg.startsw 343 pprint(msg) 344 def signalHandler(self, signum, frame) 345 if not self.result: 346 return 347 signame = self.signames[signum 348 msg = 'Signal %s caused a tool 349 self.outputResult({'error':msg 350 sys.exit(3) 351 def signalHandlerInit(self): 352 capture = ['BUS', 'SYS', 'XCPU 353 'ILL', 'ABRT', 'FPE', 354 self.signames = dict() 355 for i in capture: 356 s = 'SIG'+i 357 try: 358 signum = getat 359 signal.signal( 360 except: 361 continue 362 self.signames[signum] 363 def rootCheck(self, fatal=True): 364 if(os.access(self.powerfile, o 365 return True 366 if fatal: 367 msg = 'This command re 368 pprint('ERROR: %s\n' % 369 self.outputResult({'er 370 sys.exit(1) 371 return False 372 def rootUser(self, fatal=False): 373 if 'USER' in os.environ and os 374 return True 375 if fatal: 376 msg = 'This command mu 377 pprint('ERROR: %s\n' % 378 self.outputResult({'er 379 sys.exit(1) 380 return False 381 def usable(self, file, ishtml=False): 382 if not os.path.exists(file) or 383 return False 384 if ishtml: 385 try: 386 fp = open(file 387 res = fp.read( 388 fp.close() 389 except: 390 return False 391 if '<html>' not in res 392 return False 393 return True 394 def getExec(self, cmd): 395 try: 396 fp = Popen(['which', c 397 out = ascii(fp.read()) 398 fp.close() 399 except: 400 out = '' 401 if out: 402 return out 403 for path in ['/sbin', '/bin', 404 '/usr/local/sbin', '/u 405 cmdfull = os.path.join 406 if os.path.exists(cmdf 407 return cmdfull 408 return out 409 def setPrecision(self, num): 410 if num < 0 or num > 6: 411 return 412 self.timeformat = '%.{0}f'.for 413 def setOutputFolder(self, value): 414 args = dict() 415 n = datetime.now() 416 args['date'] = n.strftime('%y% 417 args['time'] = n.strftime('%H% 418 args['hostname'] = args['host' 419 args['mode'] = self.suspendmod 420 return value.format(**args) 421 def setOutputFile(self): 422 if self.dmesgfile != '': 423 m = re.match(r'(?P<nam 424 if(m): 425 self.htmlfile 426 if self.ftracefile != '': 427 m = re.match(r'(?P<nam 428 if(m): 429 self.htmlfile 430 def systemInfo(self, info): 431 p = m = '' 432 if 'baseboard-manufacturer' in 433 m = info['baseboard-ma 434 elif 'system-manufacturer' in 435 m = info['system-manuf 436 if 'system-product-name' in in 437 p = info['system-produ 438 elif 'baseboard-product-name' 439 p = info['baseboard-pr 440 if m[:5].lower() == 'intel' an 441 p = info['baseboard-pr 442 c = info['processor-version'] 443 b = info['bios-version'] if 'b 444 r = info['bios-release-date'] 445 self.sysstamp = '# sysinfo | m 446 (m, p, c, b, r, self.c 447 if self.osversion: 448 self.sysstamp += ' | o 449 def printSystemInfo(self, fatal=False) 450 self.rootCheck(True) 451 out = dmidecode(self.mempath, 452 if len(out) < 1: 453 return 454 fmt = '%-24s: %s' 455 if self.osversion: 456 print(fmt % ('os-versi 457 for name in sorted(out): 458 print(fmt % (name, out 459 print(fmt % ('cpucount', ('%d' 460 print(fmt % ('memtotal', ('%d 461 print(fmt % ('memfree', ('%d k 462 def cpuInfo(self): 463 self.cpucount = 0 464 if os.path.exists('/proc/cpuin 465 with open('/proc/cpuin 466 for line in fp 467 if re. 468 469 if os.path.exists('/proc/memin 470 with open('/proc/memin 471 for line in fp 472 m = re 473 if m: 474 475 m = re 476 if m: 477 478 if os.path.exists('/etc/os-rel 479 with open('/etc/os-rel 480 for line in fp 481 if lin 482 483 def initTestOutput(self, name): 484 self.prefix = self.hostname 485 v = open('/proc/version', 'r') 486 kver = v.split()[2] 487 fmt = name+'-%m%d%y-%H%M%S' 488 testtime = datetime.now().strf 489 self.teststamp = \ 490 '# '+testtime+' '+self 491 ext = '' 492 if self.gzip: 493 ext = '.gz' 494 self.dmesgfile = \ 495 self.testdir+'/'+self. 496 self.ftracefile = \ 497 self.testdir+'/'+self. 498 self.htmlfile = \ 499 self.testdir+'/'+self. 500 if not os.path.isdir(self.test 501 os.makedirs(self.testd 502 self.sudoUserchown(self.testdi 503 def getValueList(self, value): 504 out = [] 505 for i in value.split(','): 506 if i.strip(): 507 out.append(i.s 508 return out 509 def setDeviceFilter(self, value): 510 self.devicefilter = self.getVa 511 def setCallgraphFilter(self, value): 512 self.cgfilter = self.getValueL 513 def skipKprobes(self, value): 514 for k in self.getValueList(val 515 if k in self.tracefunc 516 del self.trace 517 if k in self.dev_trace 518 del self.dev_t 519 def setCallgraphBlacklist(self, file): 520 self.cgblacklist = self.listFr 521 def rtcWakeAlarmOn(self): 522 call('echo 0 > '+self.rtcpath+ 523 nowtime = open(self.rtcpath+'/ 524 if nowtime: 525 nowtime = int(nowtime) 526 else: 527 # if hardware time fai 528 nowtime = int(datetime 529 alarm = nowtime + self.rtcwake 530 call('echo %d > %s/wakealarm' 531 def rtcWakeAlarmOff(self): 532 call('echo 0 > %s/wakealarm' % 533 def initdmesg(self): 534 # get the latest time stamp fr 535 lines = Popen('dmesg', stdout= 536 ktime = '0' 537 for line in reversed(lines): 538 line = ascii(line).rep 539 idx = line.find('[') 540 if idx > 1: 541 line = line[id 542 m = re.match(r'[ \t]*( 543 if(m): 544 ktime = m.grou 545 break 546 self.dmesgstart = float(ktime) 547 def getdmesg(self, testdata): 548 op = self.writeDatafileHeader( 549 # store all new dmesg lines si 550 fp = Popen('dmesg', stdout=PIP 551 for line in fp: 552 line = ascii(line).rep 553 idx = line.find('[') 554 if idx > 1: 555 line = line[id 556 m = re.match(r'[ \t]*( 557 if(not m): 558 continue 559 ktime = float(m.group( 560 if ktime > self.dmesgs 561 op.write(line) 562 fp.close() 563 op.close() 564 def listFromFile(self, file): 565 list = [] 566 fp = open(file) 567 for i in fp.read().split('\n') 568 i = i.strip() 569 if i and i[0] != '#': 570 list.append(i) 571 fp.close() 572 return list 573 def addFtraceFilterFunctions(self, fil 574 for i in self.listFromFile(fil 575 if len(i) < 2: 576 continue 577 self.tracefuncs[i] = d 578 def getFtraceFilterFunctions(self, cur 579 self.rootCheck(True) 580 if not current: 581 call('cat '+self.tpath 582 return 583 master = self.listFromFile(sel 584 for i in sorted(self.tracefunc 585 if 'func' in self.trac 586 i = self.trace 587 if i in master: 588 print(i) 589 else: 590 print(self.col 591 def setFtraceFilterFunctions(self, lis 592 master = self.listFromFile(sel 593 flist = '' 594 for i in list: 595 if i not in master: 596 continue 597 if ' [' in i: 598 flist += i.spl 599 else: 600 flist += i+'\n 601 fp = open(self.tpath+'set_grap 602 fp.write(flist) 603 fp.close() 604 def basicKprobe(self, name): 605 self.kprobes[name] = {'name': 606 def defaultKprobe(self, name, kdata): 607 k = kdata 608 for field in ['name', 'format' 609 if field not in k: 610 k[field] = nam 611 if self.archargs in k: 612 k['args'] = k[self.arc 613 else: 614 k['args'] = dict() 615 k['format'] = name 616 self.kprobes[name] = k 617 def kprobeColor(self, name): 618 if name not in self.kprobes or 619 return '' 620 return self.kprobes[name]['col 621 def kprobeDisplayName(self, name, data 622 if name not in self.kprobes: 623 self.basicKprobe(name) 624 data = '' 625 quote=0 626 # first remvoe any spaces insi 627 for c in dataraw: 628 if c == '"': 629 quote = (quote 630 if quote and c == ' ': 631 data += '_' 632 elif c != '"': 633 data += c 634 fmt, args = self.kprobes[name] 635 arglist = dict() 636 # now process the args 637 for arg in sorted(args): 638 arglist[arg] = '' 639 m = re.match(r'.* '+ar 640 if m: 641 arglist[arg] = 642 else: 643 m = re.match(r 644 if m: 645 arglis 646 out = fmt.format(**arglist) 647 out = out.replace(' ', '_').re 648 return out 649 def kprobeText(self, kname, kprobe): 650 name = fmt = func = kname 651 args = dict() 652 if 'name' in kprobe: 653 name = kprobe['name'] 654 if 'format' in kprobe: 655 fmt = kprobe['format'] 656 if 'func' in kprobe: 657 func = kprobe['func'] 658 if self.archargs in kprobe: 659 args = kprobe[self.arc 660 if 'args' in kprobe: 661 args = kprobe['args'] 662 if re.findall('{(?P<n>[a-z,A-Z 663 doError('Kprobe "%s" h 664 for arg in re.findall('{(?P<n> 665 if arg not in args: 666 doError('Kprob 667 val = 'p:%s_cal %s' % (name, f 668 for i in sorted(args): 669 val += ' %s=%s' % (i, 670 val += '\nr:%s_ret %s $retval\ 671 return val 672 def addKprobes(self, output=False): 673 if len(self.kprobes) < 1: 674 return 675 if output: 676 pprint(' kprobe fun 677 # first test each kprobe 678 rejects = [] 679 # sort kprobes: trace, ub-dev, 680 kpl = [[], [], [], []] 681 linesout = len(self.kprobes) 682 for name in sorted(self.kprobe 683 res = self.colorText(' 684 if not self.testKprobe 685 res = self.col 686 rejects.append 687 else: 688 if name in sel 689 kpl[0] 690 elif name in s 691 if 'ub 692 693 else: 694 695 else: 696 kpl[2] 697 if output: 698 pprint(' 699 kplist = kpl[0] + kpl[1] + kpl 700 # remove all failed ones from 701 for name in rejects: 702 self.kprobes.pop(name) 703 # set the kprobes all at once 704 self.fsetVal('', 'kprobe_event 705 kprobeevents = '' 706 for kp in kplist: 707 kprobeevents += self.k 708 self.fsetVal(kprobeevents, 'kp 709 if output: 710 check = self.fgetVal(' 711 linesack = (len(check. 712 pprint(' kprobe fun 713 self.fsetVal('1', 'events/kpro 714 def testKprobe(self, kname, kprobe): 715 self.fsetVal('0', 'events/kpro 716 kprobeevents = self.kprobeText 717 if not kprobeevents: 718 return False 719 try: 720 self.fsetVal(kprobeeve 721 check = self.fgetVal(' 722 except: 723 return False 724 linesout = len(kprobeevents.sp 725 linesack = len(check.split('\n 726 if linesack < linesout: 727 return False 728 return True 729 def setVal(self, val, file): 730 if not os.path.exists(file): 731 return False 732 try: 733 fp = open(file, 'wb', 734 fp.write(val.encode()) 735 fp.flush() 736 fp.close() 737 except: 738 return False 739 return True 740 def fsetVal(self, val, path): 741 if not self.useftrace: 742 return False 743 return self.setVal(val, self.t 744 def getVal(self, file): 745 res = '' 746 if not os.path.exists(file): 747 return res 748 try: 749 fp = open(file, 'r') 750 res = fp.read() 751 fp.close() 752 except: 753 pass 754 return res 755 def fgetVal(self, path): 756 if not self.useftrace: 757 return '' 758 return self.getVal(self.tpath+ 759 def cleanupFtrace(self): 760 if self.useftrace: 761 self.fsetVal('0', 'eve 762 self.fsetVal('', 'kpro 763 self.fsetVal('1024', ' 764 def setupAllKprobes(self): 765 for name in self.tracefuncs: 766 self.defaultKprobe(nam 767 for name in self.dev_tracefunc 768 self.defaultKprobe(nam 769 def isCallgraphFunc(self, name): 770 if len(self.tracefuncs) < 1 an 771 return True 772 for i in self.tracefuncs: 773 if 'func' in self.trac 774 f = self.trace 775 else: 776 f = i 777 if name == f: 778 return True 779 return False 780 def initFtrace(self, quiet=False): 781 if not self.useftrace: 782 return 783 if not quiet: 784 sysvals.printSystemInf 785 pprint('INITIALIZING F 786 # turn trace off 787 self.fsetVal('0', 'tracing_on' 788 self.cleanupFtrace() 789 # set the trace clock to globa 790 self.fsetVal('global', 'trace_ 791 self.fsetVal('nop', 'current_t 792 # set trace buffer to an appro 793 cpus = max(1, self.cpucount) 794 if self.bufsize > 0: 795 tgtsize = self.bufsize 796 elif self.usecallgraph or self 797 bmax = (1*1024*1024) i 798 else (3*1024*1 799 tgtsize = min(self.mem 800 else: 801 tgtsize = 65536 802 while not self.fsetVal('%d' % 803 # if the size failed t 804 tgtsize -= 65536 805 if tgtsize < 65536: 806 tgtsize = int( 807 break 808 self.vprint('Setting trace buf 809 # initialize the callgraph tra 810 if(self.usecallgraph): 811 # set trace type 812 self.fsetVal('function 813 self.fsetVal('', 'set_ 814 # temporary hack to fi 815 fp = open(self.tpath+' 816 fp.write('native_queue 817 fp.close() 818 # set trace format opt 819 self.fsetVal('print-pa 820 self.fsetVal('funcgrap 821 self.fsetVal('funcgrap 822 self.fsetVal('funcgrap 823 self.fsetVal('funcgrap 824 self.fsetVal('funcgrap 825 self.fsetVal('nofuncgr 826 self.fsetVal('context- 827 self.fsetVal('graph-ti 828 self.fsetVal('%d' % se 829 cf = ['dpm_run_callbac 830 if(self.usetraceevents 831 cf += ['dpm_pr 832 for fn in self.tracefu 833 if 'func' in s 834 cf.app 835 else: 836 cf.app 837 if self.ftop: 838 self.setFtrace 839 else: 840 self.setFtrace 841 # initialize the kprobe trace 842 elif self.usekprobes: 843 for name in self.trace 844 self.defaultKp 845 if self.usedevsrc: 846 for name in se 847 self.d 848 if not quiet: 849 pprint('INITIA 850 self.addKprobes(self.v 851 if(self.usetraceevents): 852 # turn trace events on 853 events = iter(self.tra 854 for e in events: 855 self.fsetVal(' 856 # clear the trace buffer 857 self.fsetVal('', 'trace') 858 def verifyFtrace(self): 859 # files needed for any trace d 860 files = ['buffer_size_kb', 'cu 861 'trace_marker 862 # files needed for callgraph t 863 tp = self.tpath 864 if(self.usecallgraph): 865 files += [ 866 'available_fil 867 'set_ftrace_fi 868 'set_graph_fun 869 ] 870 for f in files: 871 if(os.path.exists(tp+f 872 return False 873 return True 874 def verifyKprobes(self): 875 # files needed for kprobes to 876 files = ['kprobe_events', 'eve 877 tp = self.tpath 878 for f in files: 879 if(os.path.exists(tp+f 880 return False 881 return True 882 def colorText(self, str, color=31): 883 if not self.ansi: 884 return str 885 return '\x1B[%d;40m%s\x1B[m' % 886 def writeDatafileHeader(self, filename 887 fp = self.openlog(filename, 'w 888 fp.write('%s\n%s\n# command | 889 for test in testdata: 890 if 'fw' in test: 891 fw = test['fw' 892 if(fw): 893 fp.wri 894 if 'turbo' in test: 895 fp.write('# tu 896 if 'wifi' in test: 897 fp.write('# wi 898 if 'netfix' in test: 899 fp.write('# ne 900 if test['error'] or le 901 fp.write('# en 902 return fp 903 def sudoUserchown(self, dir): 904 if os.path.exists(dir) and sel 905 cmd = 'chown -R {0}:{0 906 call(cmd.format(self.s 907 def outputResult(self, testdata, num=0 908 if not self.result: 909 return 910 n = '' 911 if num > 0: 912 n = '%d' % num 913 fp = open(self.result, 'a') 914 if 'error' in testdata: 915 fp.write('result%s: fa 916 fp.write('error%s: %s\ 917 else: 918 fp.write('result%s: pa 919 if 'mode' in testdata: 920 fp.write('mode%s: %s\n 921 for v in ['suspend', 'resume', 922 if v in testdata: 923 fp.write('%s%s 924 for v in ['fwsuspend', 'fwresu 925 if v in testdata: 926 fp.write('%s%s 927 if 'bugurl' in testdata: 928 fp.write('url%s: %s\n' 929 fp.close() 930 self.sudoUserchown(self.result 931 def configFile(self, file): 932 dir = os.path.dirname(os.path. 933 if os.path.exists(file): 934 return file 935 elif os.path.exists(dir+'/'+fi 936 return dir+'/'+file 937 elif os.path.exists(dir+'/conf 938 return dir+'/config/'+ 939 return '' 940 def openlog(self, filename, mode): 941 isgz = self.gzip 942 if mode == 'r': 943 try: 944 with gzip.open 945 test = 946 isgz = True 947 except: 948 isgz = False 949 if isgz: 950 return gzip.open(filen 951 return open(filename, mode) 952 def putlog(self, filename, text): 953 with self.openlog(filename, 'a 954 fp.write(text) 955 fp.close() 956 def dlog(self, text): 957 if not self.dmesgfile: 958 return 959 self.putlog(self.dmesgfile, '# 960 def flog(self, text): 961 self.putlog(self.ftracefile, t 962 def b64unzip(self, data): 963 try: 964 out = codecs.decode(ba 965 except: 966 out = data 967 return out 968 def b64zip(self, data): 969 out = base64.b64encode(codecs. 970 return out 971 def platforminfo(self, cmdafter): 972 # add platform info on to a co 973 if not os.path.exists(self.ftr 974 return False 975 footer = '#\n' 976 977 # add test command string line 978 if self.suspendmode == 'comman 979 footer += '# platform- 980 981 # get a list of target devices 982 props = dict() 983 tp = TestProps() 984 tf = self.openlog(self.ftracef 985 for line in tf: 986 if tp.stampInfo(line, 987 continue 988 # parse only valid lin 989 m = re.match(tp.ftrace 990 if(not m or 'device_pm 991 continue 992 m = re.match(r'.*: (?P 993 if(not m): 994 continue 995 dev = m.group('d') 996 if dev not in props: 997 props[dev] = D 998 tf.close() 999 1000 # now get the syspath for eac 1001 for dirname, dirnames, filena 1002 if(re.match(r'.*/powe 1003 dev = dirname 1004 if dev in pro 1005 props 1006 1007 # now fill in the properties 1008 for dev in sorted(props): 1009 dirname = props[dev]. 1010 if not dirname or not 1011 continue 1012 props[dev].isasync = 1013 if os.path.exists(dir 1014 fp = open(dir 1015 if 'enabled' 1016 props 1017 fp.close() 1018 fields = os.listdir(d 1019 for file in ['product 1020 if file not i 1021 conti 1022 try: 1023 with 1024 1025 except: 1026 conti 1027 if file == 'i 1028 idv, 1029 try: 1030 1031 1032 excep 1033 1034 1035 props 1036 break 1037 if props[dev].altname 1038 out = props[d 1039 .repl 1040 props[dev].al 1041 1042 # add a devinfo line to the b 1043 out = '' 1044 for dev in sorted(props): 1045 out += props[dev].out 1046 footer += '# platform-devinfo 1047 1048 # add a line for each of thes 1049 for name, cmdline, info in cm 1050 footer += '# platform 1051 self.flog(footer) 1052 return True 1053 def commonPrefix(self, list): 1054 if len(list) < 2: 1055 return '' 1056 prefix = list[0] 1057 for s in list[1:]: 1058 while s[:len(prefix)] 1059 prefix = pref 1060 if not prefix: 1061 break 1062 if '/' in prefix and prefix[- 1063 prefix = prefix[0:pre 1064 return prefix 1065 def dictify(self, text, format): 1066 out = dict() 1067 header = True if format == 1 1068 delim = ' ' if format == 1 el 1069 for line in text.split('\n'): 1070 if header: 1071 header, out[' 1072 continue 1073 line = line.strip() 1074 if delim in line: 1075 data = line.s 1076 num = re.sear 1077 if format == 1078 out[d 1079 else: 1080 out[d 1081 return out 1082 def cmdinfovar(self, arg): 1083 if arg == 'ethdev': 1084 try: 1085 cmd = [self.g 1086 fp = Popen(cm 1087 info = ascii( 1088 fp.close() 1089 except: 1090 return 'iptoo 1091 for line in info.spli 1092 if line[0] == 1093 retur 1094 return 'nodevicefound 1095 return 'unknown' 1096 def cmdinfo(self, begin, debug=False) 1097 out = [] 1098 if begin: 1099 self.cmd1 = dict() 1100 for cargs in self.infocmds: 1101 delta, name, args = c 1102 for i in range(len(ar 1103 if args[i][0] 1104 args[ 1105 cmdline, cmdpath = ' 1106 if not cmdpath or (be 1107 continue 1108 self.dlog('[%s]' % cm 1109 try: 1110 fp = Popen([c 1111 info = ascii( 1112 fp.close() 1113 except: 1114 continue 1115 if not debug and begi 1116 self.cmd1[nam 1117 elif not debug and de 1118 before, after 1119 dinfo = ('\t% 1120 prefix = self 1121 for key in so 1122 if ke 1123 1124 1125 1126 1127 1128 1129 1130 dinfo = '\tno 1131 out.append((n 1132 else: 1133 out.append((n 1134 return out 1135 def testVal(self, file, fmt='basic', 1136 if file == 'restoreall': 1137 for f in self.cfgdef: 1138 if os.path.ex 1139 fp = 1140 fp.wr 1141 fp.cl 1142 self.cfgdef = dict() 1143 elif value and os.path.exists 1144 fp = open(file, 'r+') 1145 if fmt == 'radio': 1146 m = re.match( 1147 if m: 1148 self. 1149 elif fmt == 'acpi': 1150 line = fp.rea 1151 m = re.match( 1152 if m: 1153 self. 1154 else: 1155 self.cfgdef[f 1156 fp.write(value) 1157 fp.close() 1158 def s0ixSupport(self): 1159 if not os.path.exists(self.s0 1160 return False 1161 fp = open(sysvals.mempowerfil 1162 data = fp.read().strip() 1163 fp.close() 1164 if '[s2idle]' in data: 1165 return True 1166 return False 1167 def haveTurbostat(self): 1168 if not self.tstat: 1169 return False 1170 cmd = self.getExec('turbostat 1171 if not cmd: 1172 return False 1173 fp = Popen([cmd, '-v'], stdou 1174 out = ascii(fp.read()).strip( 1175 fp.close() 1176 if re.match(r'turbostat versi 1177 self.vprint(out) 1178 return True 1179 return False 1180 def turbostat(self, s0ixready): 1181 cmd = self.getExec('turbostat 1182 rawout = keyline = valline = 1183 fullcmd = '%s -q -S echo free 1184 fp = Popen(['sh', '-c', fullc 1185 for line in fp.stderr: 1186 line = ascii(line) 1187 rawout += line 1188 if keyline and vallin 1189 continue 1190 if re.match(r'(?i)Avg 1191 keyline = lin 1192 elif keyline: 1193 valline = lin 1194 fp.wait() 1195 if not keyline or not valline 1196 errmsg = 'unrecognize 1197 self.vprint(errmsg) 1198 if not self.verbose: 1199 pprint(errmsg 1200 return (fp.returncode 1201 if self.verbose: 1202 pprint(rawout.strip() 1203 out = [] 1204 for key in keyline: 1205 idx = keyline.index(k 1206 val = valline[idx] 1207 if key == 'SYS%LPI' a 1208 continue 1209 out.append('%s=%s' % 1210 return (fp.returncode, '|'.jo 1211 def netfixon(self, net='both'): 1212 cmd = self.getExec('netfix') 1213 if not cmd: 1214 return '' 1215 fp = Popen([cmd, '-s', net, ' 1216 out = ascii(fp.read()).strip( 1217 fp.close() 1218 return out 1219 def wifiDetails(self, dev): 1220 try: 1221 info = open('/sys/cla 1222 except: 1223 return dev 1224 vals = [dev] 1225 for prop in info.split('\n'): 1226 if prop.startswith('D 1227 vals.append(p 1228 return ':'.join(vals) 1229 def checkWifi(self, dev=''): 1230 try: 1231 w = open('/proc/net/w 1232 except: 1233 return '' 1234 for line in reversed(w.split( 1235 m = re.match(r' *(?P< 1236 if not m or (dev and 1237 continue 1238 return m.group('dev') 1239 return '' 1240 def pollWifi(self, dev, timeout=10): 1241 start = time.time() 1242 while (time.time() - start) < 1243 w = self.checkWifi(de 1244 if w: 1245 return '%s re 1246 (self 1247 time.sleep(0.01) 1248 return '%s timeout %d' % (sel 1249 def errorSummary(self, errinfo, msg): 1250 found = False 1251 for entry in errinfo: 1252 if re.match(entry['ma 1253 entry['count' 1254 if self.hostn 1255 entry 1256 elif self.htm 1257 entry 1258 found = True 1259 break 1260 if found: 1261 return 1262 arr = msg.split() 1263 for j in range(len(arr)): 1264 if re.match(r'^[0-9,\ 1265 arr[j] = r'[0 1266 else: 1267 arr[j] = arr[ 1268 .repl 1269 .repl 1270 .repl 1271 .repl 1272 mstr = ' *'.join(arr) 1273 entry = { 1274 'line': msg, 1275 'match': mstr, 1276 'count': 1, 1277 'urls': {self.hostnam 1278 } 1279 errinfo.append(entry) 1280 def multistat(self, start, idx, finis 1281 if 'time' in self.multitest: 1282 id = '%d Duration=%dm 1283 else: 1284 id = '%d/%d' % (idx+1 1285 t = time.time() 1286 if 'start' not in self.multit 1287 self.multitest['start 1288 self.multitest['total 1289 pprint('TEST (%s) STA 1290 return 1291 dt = t - self.multitest['last 1292 if not start: 1293 if idx == 0 and self. 1294 self.multites 1295 pprint('TEST (%s) COM 1296 return 1297 self.multitest['total'] += dt 1298 self.multitest['last'] = t 1299 avg = self.multitest['total'] 1300 if 'time' in self.multitest: 1301 left = finish - datet 1302 left -= timedelta(mic 1303 else: 1304 left = timedelta(seco 1305 pprint('TEST (%s) START - Avg 1306 (id, avg, str(left))) 1307 def multiinit(self, c, d): 1308 sz, unit = 'count', 'm' 1309 if c.endswith('d') or c.endsw 1310 sz, unit, c = 'time', 1311 self.multitest['run'] = True 1312 self.multitest[sz] = getArgIn 1313 self.multitest['delay'] = get 1314 if unit == 'd': 1315 self.multitest[sz] *= 1316 elif unit == 'h': 1317 self.multitest[sz] *= 1318 def displayControl(self, cmd): 1319 xset, ret = 'timeout 10 xset 1320 if self.sudouser: 1321 xset = 'sudo -u %s %s 1322 if cmd == 'init': 1323 ret = call(xset.forma 1324 if not ret: 1325 ret = call(xs 1326 elif cmd == 'reset': 1327 ret = call(xset.forma 1328 elif cmd in ['on', 'off', 'st 1329 b4 = self.displayCont 1330 ret = call(xset.forma 1331 if not ret: 1332 curr = self.d 1333 self.vprint(' 1334 if curr != cm 1335 self. 1336 if ret: 1337 self.vprint(' 1338 return ret 1339 elif cmd == 'stat': 1340 fp = Popen(xset.forma 1341 ret = 'unknown' 1342 for line in fp: 1343 m = re.match( 1344 if(m and len( 1345 out = 1346 ret = 1347 break 1348 fp.close() 1349 return ret 1350 def setRuntimeSuspend(self, before=Tr 1351 if before: 1352 # runtime suspend dis 1353 if self.rs > 0: 1354 self.rstgt, s 1355 else: 1356 self.rstgt, s 1357 pprint('CONFIGURING R 1358 self.rslist = deviceI 1359 for i in self.rslist: 1360 self.setVal(s 1361 pprint('runtime suspe 1362 pprint('waiting 5 sec 1363 time.sleep(5) 1364 else: 1365 # runtime suspend re- 1366 for i in self.rslist: 1367 self.setVal(s 1368 pprint('runtime suspe 1369 def start(self, pm): 1370 if self.useftrace: 1371 self.dlog('start ftra 1372 self.fsetVal('1', 'tr 1373 if self.useprocmon: 1374 self.dlog('st 1375 pm.start() 1376 def stop(self, pm): 1377 if self.useftrace: 1378 if self.useprocmon: 1379 self.dlog('st 1380 pm.stop() 1381 self.dlog('stop ftrac 1382 self.fsetVal('0', 'tr 1383 1384 sysvals = SystemValues() 1385 switchvalues = ['enable', 'disable', 'on', 'o 1386 switchoff = ['disable', 'off', 'false', '0'] 1387 suspendmodename = { 1388 'standby': 'standby (S1)', 1389 'freeze': 'freeze (S2idle)', 1390 'mem': 'suspend (S3)', 1391 'disk': 'hibernate (S4)' 1392 } 1393 1394 # Class: DevProps 1395 # Description: 1396 # Simple class which holds property va 1397 # for all the devices used in the time 1398 class DevProps: 1399 def __init__(self): 1400 self.syspath = '' 1401 self.altname = '' 1402 self.isasync = True 1403 self.xtraclass = '' 1404 self.xtrainfo = '' 1405 def out(self, dev): 1406 return '%s,%s,%d;' % (dev, se 1407 def debug(self, dev): 1408 pprint('%s:\n\taltname = %s\n 1409 def altName(self, dev): 1410 if not self.altname or self.a 1411 return dev 1412 return '%s [%s]' % (self.altn 1413 def xtraClass(self): 1414 if self.xtraclass: 1415 return ' '+self.xtrac 1416 if not self.isasync: 1417 return ' sync' 1418 return '' 1419 def xtraInfo(self): 1420 if self.xtraclass: 1421 return ' '+self.xtrac 1422 if self.isasync: 1423 return ' (async)' 1424 return ' (sync)' 1425 1426 # Class: DeviceNode 1427 # Description: 1428 # A container used to create a device 1429 # and a tree of child nodes. Used by D 1430 class DeviceNode: 1431 def __init__(self, nodename, nodedept 1432 self.name = nodename 1433 self.children = [] 1434 self.depth = nodedepth 1435 1436 # Class: Data 1437 # Description: 1438 # The primary container for suspend/re 1439 # each test run. The data is organized 1440 # Data.dmesg { 1441 # phases { 1442 # 10 sequential, non-ov 1443 # contents: times for p 1444 # devlist { 1445 # device callba 1446 # device { 1447 # a sin 1448 # conte 1449 # 1450 # 1451 # 1452 # } 1453 # } 1454 # } 1455 # } 1456 # 1457 class Data: 1458 phasedef = { 1459 'suspend_prepare': {'order': 1460 'suspend': {'order': 1461 'suspend_late': {'order': 1462 'suspend_noirq': {'order': 1463 'suspend_machine': {'order': 1464 'resume_machine': {'order': 1465 'resume_noirq': {'order': 1466 'resume_early': {'order': 1467 'resume': {'order': 1468 'resume_complete': {'order': 1469 } 1470 errlist = { 1471 'HWERROR' : r'.*\[ *Hardware 1472 'FWBUG' : r'.*\[ *Firmware 1473 'TASKFAIL': r'.*Freezing .*af 1474 'BUG' : r'(?i).*\bBUG\b.* 1475 'ERROR' : r'(?i).*\bERROR\b 1476 'WARNING' : r'(?i).*\bWARNING 1477 'FAULT' : r'(?i).*\bFAULT\b 1478 'FAIL' : r'(?i).*\bFAILED\ 1479 'INVALID' : r'(?i).*\bINVALID 1480 'CRASH' : r'(?i).*\bCRASHED 1481 'TIMEOUT' : r'(?i).*\bTIMEOUT 1482 'ABORT' : r'(?i).*\bABORT\b 1483 'IRQ' : r'.*\bgenirq: .*' 1484 'ACPI' : r'.*\bACPI *(?P<b 1485 'DISKFULL': r'.*\bNo space le 1486 'USBERR' : r'.*usb .*device 1487 'ATAERR' : r' *ata[0-9\.]*: 1488 'MEIERR' : r' *mei.*: .*fail 1489 'TPMERR' : r'(?i) *tpm *tpm[ 1490 } 1491 def __init__(self, num): 1492 idchar = 'abcdefghij' 1493 self.start = 0.0 # test start 1494 self.end = 0.0 # test end 1495 self.hwstart = 0 # rtc test s 1496 self.hwend = 0 # rtc test e 1497 self.tSuspended = 0.0 # low-l 1498 self.tResumed = 0.0 # low-l 1499 self.tKernSus = 0.0 # kerne 1500 self.tKernRes = 0.0 # kerne 1501 self.fwValid = False # is fi 1502 self.fwSuspend = 0 # time 1503 self.fwResume = 0 # time 1504 self.html_device_id = 0 1505 self.stamp = 0 1506 self.outfile = '' 1507 self.kerror = False 1508 self.wifi = dict() 1509 self.turbostat = 0 1510 self.enterfail = '' 1511 self.currphase = '' 1512 self.pstl = dict() # proce 1513 self.testnumber = num 1514 self.idstr = idchar[num] 1515 self.dmesgtext = [] # dmesg 1516 self.dmesg = dict() # root 1517 self.errorinfo = {'suspend':[ 1518 self.tLow = [] # time 1519 self.devpids = [] 1520 self.devicegroups = 0 1521 def sortedPhases(self): 1522 return sorted(self.dmesg, key 1523 def initDevicegroups(self): 1524 # called when phases are all 1525 for phase in sorted(self.dmes 1526 if '*' in phase: 1527 p = phase.spl 1528 pnew = '%s%d' 1529 self.dmesg[pn 1530 self.devicegroups = [] 1531 for phase in self.sortedPhase 1532 self.devicegroups.app 1533 def nextPhase(self, phase, offset): 1534 order = self.dmesg[phase]['or 1535 for p in self.dmesg: 1536 if self.dmesg[p]['ord 1537 return p 1538 return '' 1539 def lastPhase(self, depth=1): 1540 plist = self.sortedPhases() 1541 if len(plist) < depth: 1542 return '' 1543 return plist[-1*depth] 1544 def turbostatInfo(self): 1545 tp = TestProps() 1546 out = {'syslpi':'N/A','pkgpc1 1547 for line in self.dmesgtext: 1548 m = re.match(tp.tstat 1549 if not m: 1550 continue 1551 for i in m.group('t') 1552 if 'SYS%LPI' 1553 out[' 1554 elif 'pc10' i 1555 out[' 1556 break 1557 return out 1558 def extractErrorInfo(self): 1559 lf = self.dmesgtext 1560 if len(self.dmesgtext) < 1 an 1561 lf = sysvals.openlog( 1562 i = 0 1563 tp = TestProps() 1564 list = [] 1565 for line in lf: 1566 i += 1 1567 if tp.stampInfo(line, 1568 continue 1569 m = re.match(r'[ \t]* 1570 if not m: 1571 continue 1572 t = float(m.group('kt 1573 if t < self.start or 1574 continue 1575 dir = 'suspend' if t 1576 msg = m.group('msg') 1577 if re.match(r'capabil 1578 continue 1579 for err in self.errli 1580 if re.match(s 1581 list. 1582 self. 1583 break 1584 tp.msglist = [] 1585 for msg, type, dir, t, idx1, 1586 tp.msglist.append(msg 1587 self.errorinfo[dir].a 1588 if self.kerror: 1589 sysvals.dmesglog = Tr 1590 if len(self.dmesgtext) < 1 an 1591 lf.close() 1592 return tp 1593 def setStart(self, time, msg=''): 1594 self.start = time 1595 if msg: 1596 try: 1597 self.hwstart 1598 except: 1599 self.hwstart 1600 def setEnd(self, time, msg=''): 1601 self.end = time 1602 if msg: 1603 try: 1604 self.hwend = 1605 except: 1606 self.hwend = 1607 def isTraceEventOutsideDeviceCalls(se 1608 for phase in self.sortedPhase 1609 list = self.dmesg[pha 1610 for dev in list: 1611 d = list[dev] 1612 if(d['pid'] = 1613 time 1614 retur 1615 return True 1616 def sourcePhase(self, start): 1617 for phase in self.sortedPhase 1618 if 'machine' in phase 1619 continue 1620 pend = self.dmesg[pha 1621 if start <= pend: 1622 return phase 1623 return 'resume_complete' if ' 1624 def sourceDevice(self, phaselist, sta 1625 tgtdev = '' 1626 for phase in phaselist: 1627 list = self.dmesg[pha 1628 for devname in list: 1629 dev = list[de 1630 # pid must ma 1631 if dev['pid'] 1632 conti 1633 devS = dev['s 1634 devE = dev['e 1635 if type == 'd 1636 # dev 1637 if(st 1638 1639 elif type == 1640 # thr 1641 if st 1642 1643 if en 1644 1645 tgtdev = dev 1646 break 1647 return tgtdev 1648 def addDeviceFunctionCall(self, displ 1649 # try to place the call in a 1650 phases = self.sortedPhases() 1651 tgtdev = self.sourceDevice(ph 1652 # calls with device pids that 1653 # TODO: include these somehow 1654 if not tgtdev and pid in self 1655 return False 1656 # try to place the call in a 1657 if not tgtdev: 1658 tgtdev = self.sourceD 1659 # create new thread blocks, e 1660 if not tgtdev: 1661 if proc == '<...>': 1662 threadname = 1663 else: 1664 threadname = 1665 tgtphase = self.sourc 1666 if not tgtphase: 1667 return False 1668 self.newAction(tgtpha 1669 return self.addDevice 1670 # this should not happen 1671 if not tgtdev: 1672 sysvals.vprint('[%f - 1673 (start, end, 1674 return False 1675 # place the call data inside 1676 if('src' not in tgtdev): 1677 tgtdev['src'] = [] 1678 dtf = sysvals.dev_tracefuncs 1679 ubiquitous = False 1680 if kprobename in dtf and 'ub' 1681 ubiquitous = True 1682 mc = re.match(r'\(.*\) *(?P<a 1683 mr = re.match(r'\((?P<caller> 1684 if mc and mr: 1685 c = mr.group('caller' 1686 a = mc.group('args'). 1687 r = mr.group('ret') 1688 if len(r) > 6: 1689 r = '' 1690 else: 1691 r = 'ret=%s ' 1692 if ubiquitous and c i 1693 return False 1694 else: 1695 return False 1696 color = sysvals.kprobeColor(k 1697 e = DevFunction(displayname, 1698 tgtdev['src'].append(e) 1699 return True 1700 def overflowDevices(self): 1701 # get a list of devices that 1702 devlist = [] 1703 for phase in self.sortedPhase 1704 list = self.dmesg[pha 1705 for devname in list: 1706 dev = list[de 1707 if dev['end'] 1708 devli 1709 return devlist 1710 def mergeOverlapDevices(self, devlist 1711 # merge any devices that over 1712 for dev in devlist: 1713 devname = dev['name'] 1714 for phase in self.sor 1715 list = self.d 1716 if devname no 1717 conti 1718 tdev = list[d 1719 o = min(dev[' 1720 if o <= 0: 1721 conti 1722 dev['end'] = 1723 if 'src' not 1724 conti 1725 dev['src'] += 1726 del list[devn 1727 def usurpTouchingThread(self, name, d 1728 # the caller test has priorit 1729 for phase in self.sortedPhase 1730 list = self.dmesg[pha 1731 if name in list: 1732 tdev = list[n 1733 if tdev['star 1734 dev[' 1735 if 's 1736 1737 if 's 1738 1739 del l 1740 break 1741 def stitchTouchingThreads(self, testl 1742 # merge any threads between t 1743 for phase in self.sortedPhase 1744 list = self.dmesg[pha 1745 for devname in list: 1746 dev = list[de 1747 if 'htmlclass 1748 conti 1749 for data in t 1750 data. 1751 def optimizeDevSrc(self): 1752 # merge any src call loops to 1753 for phase in self.sortedPhase 1754 list = self.dmesg[pha 1755 for dev in list: 1756 if 'src' not 1757 conti 1758 src = list[de 1759 p = 0 1760 for e in sort 1761 if no 1762 1763 1764 # e i 1765 p.end 1766 p.len 1767 p.cou 1768 src.r 1769 def trimTimeVal(self, t, t0, dT, left 1770 if left: 1771 if(t > t0): 1772 if(t - dT < t 1773 retur 1774 return t - dT 1775 else: 1776 return t 1777 else: 1778 if(t < t0 + dT): 1779 if(t > t0): 1780 retur 1781 return t + dT 1782 else: 1783 return t 1784 def trimTime(self, t0, dT, left): 1785 self.tSuspended = self.trimTi 1786 self.tResumed = self.trimTime 1787 self.start = self.trimTimeVal 1788 self.tKernSus = self.trimTime 1789 self.tKernRes = self.trimTime 1790 self.end = self.trimTimeVal(s 1791 for phase in self.sortedPhase 1792 p = self.dmesg[phase] 1793 p['start'] = self.tri 1794 p['end'] = self.trimT 1795 list = p['list'] 1796 for name in list: 1797 d = list[name 1798 d['start'] = 1799 d['end'] = se 1800 d['length'] = 1801 if('ftrace' i 1802 cg = 1803 cg.st 1804 cg.en 1805 for l 1806 1807 if('src' in d 1808 for e 1809 1810 1811 1812 if('cpuexec' 1813 cpuex 1814 for e 1815 1816 1817 1818 1819 d['cp 1820 for dir in ['suspend', 'resum 1821 list = [] 1822 for e in self.errorin 1823 type, tm, idx 1824 tm = self.tri 1825 list.append(( 1826 self.errorinfo[dir] = 1827 def trimFreezeTime(self, tZero): 1828 # trim out any standby or fre 1829 lp = '' 1830 for phase in self.sortedPhase 1831 if 'resume_machine' i 1832 tS, tR = self 1833 tL = tR - tS 1834 if tL <= 0: 1835 conti 1836 left = True i 1837 self.trimTime 1838 if 'waking' i 1839 tCnt 1840 if se 1841 1842 else: 1843 1844 text 1845 else: 1846 text 1847 self.tLow.app 1848 lp = phase 1849 def getMemTime(self): 1850 if not self.hwstart or not se 1851 return 1852 stime = (self.tSuspended - se 1853 rtime = (self.end - self.tRes 1854 hws = self.hwstart + timedelt 1855 hwr = self.hwend - timedelta( 1856 self.tLow.append('%.0f'%((hwr 1857 def getTimeValues(self): 1858 s = (self.tSuspended - self.t 1859 r = (self.tKernRes - self.tRe 1860 return (max(s, 0), max(r, 0)) 1861 def setPhase(self, phase, ktime, isbe 1862 if(isbegin): 1863 # phase start over cu 1864 if self.currphase: 1865 if 'resume_ma 1866 sysva 1867 self.dmesg[se 1868 phases = self.dmesg.k 1869 color = self.phasedef 1870 count = len(phases) i 1871 # create unique name 1872 while phase in phases 1873 phase += '*' 1874 self.dmesg[phase] = { 1875 'row': 0, 'co 1876 self.dmesg[phase]['st 1877 self.currphase = phas 1878 else: 1879 # phase end without a 1880 if phase not in self. 1881 if self.currp 1882 sysva 1883 else: 1884 sysva 1885 retur 1886 phase = self.currphas 1887 self.dmesg[phase]['en 1888 self.currphase = '' 1889 return phase 1890 def sortedDevices(self, phase): 1891 list = self.dmesg[phase]['lis 1892 return sorted(list, key=lambd 1893 def fixupInitcalls(self, phase): 1894 # if any calls never returned 1895 phaselist = self.dmesg[phase] 1896 for devname in phaselist: 1897 dev = phaselist[devna 1898 if(dev['end'] < 0): 1899 for p in self 1900 if se 1901 1902 1903 sysvals.vprin 1904 def deviceFilter(self, devicefilter): 1905 for phase in self.sortedPhase 1906 list = self.dmesg[pha 1907 rmlist = [] 1908 for name in list: 1909 keep = False 1910 for filter in 1911 if fi 1912 1913 1914 if not keep: 1915 rmlis 1916 for name in rmlist: 1917 del list[name 1918 def fixupInitcallsThatDidntReturn(sel 1919 # if any calls never returned 1920 for phase in self.sortedPhase 1921 self.fixupInitcalls(p 1922 def phaseOverlap(self, phases): 1923 rmgroups = [] 1924 newgroup = [] 1925 for group in self.devicegroup 1926 for phase in phases: 1927 if phase not 1928 conti 1929 for p in grou 1930 if p 1931 1932 if group not 1933 rmgro 1934 for group in rmgroups: 1935 self.devicegroups.rem 1936 self.devicegroups.append(newg 1937 def newActionGlobal(self, name, start 1938 # which phase is this device 1939 phases = self.sortedPhases() 1940 targetphase = 'none' 1941 htmlclass = '' 1942 overlap = 0.0 1943 myphases = [] 1944 for phase in phases: 1945 pstart = self.dmesg[p 1946 pend = self.dmesg[pha 1947 # see if the action o 1948 o = max(0, min(end, p 1949 if o > 0: 1950 myphases.appe 1951 # set the target phas 1952 if o > overlap: 1953 if overlap > 1954 conti 1955 targetphase = 1956 overlap = o 1957 # if no target phase was foun 1958 if targetphase == 'none': 1959 p0start = self.dmesg[ 1960 if start <= p0start: 1961 targetphase = 1962 else: 1963 targetphase = 1964 if pid == -2: 1965 htmlclass = ' bg' 1966 elif pid == -3: 1967 htmlclass = ' ps' 1968 if len(myphases) > 1: 1969 htmlclass = ' bg' 1970 self.phaseOverlap(myp 1971 if targetphase in phases: 1972 newname = self.newAct 1973 return (targetphase, 1974 return False 1975 def newAction(self, phase, name, pid, 1976 # new device callback for a s 1977 self.html_device_id += 1 1978 devid = '%s%d' % (self.idstr, 1979 list = self.dmesg[phase]['lis 1980 length = -1.0 1981 if(start >= 0 and end >= 0): 1982 length = end - start 1983 if pid == -2 or name not in s 1984 i = 2 1985 origname = name 1986 while(name in list): 1987 name = '%s[%d 1988 i += 1 1989 list[name] = {'name': name, ' 1990 'par': parent, 'lengt 1991 if htmlclass: 1992 list[name]['htmlclass 1993 if color: 1994 list[name]['color'] = 1995 return name 1996 def findDevice(self, phase, name): 1997 list = self.dmesg[phase]['lis 1998 mydev = '' 1999 for devname in sorted(list): 2000 if name == devname or 2001 mydev = devna 2002 if mydev: 2003 return list[mydev] 2004 return False 2005 def deviceChildren(self, devname, pha 2006 devlist = [] 2007 list = self.dmesg[phase]['lis 2008 for child in list: 2009 if(list[child]['par'] 2010 devlist.appen 2011 return devlist 2012 def maxDeviceNameSize(self, phase): 2013 size = 0 2014 for name in self.dmesg[phase] 2015 if len(name) > size: 2016 size = len(na 2017 return size 2018 def printDetails(self): 2019 sysvals.vprint('Timeline Deta 2020 sysvals.vprint(' tes 2021 sysvals.vprint('kernel suspen 2022 tS = tR = False 2023 for phase in self.sortedPhase 2024 devlist = self.dmesg[ 2025 dc, ps, pe = len(devl 2026 if not tS and ps >= s 2027 sysvals.vprin 2028 tS = True 2029 if not tR and ps >= s 2030 sysvals.vprin 2031 tR = True 2032 sysvals.vprint('%20s: 2033 if sysvals.devdump: 2034 sysvals.vprin 2035 maxname = '%d 2036 fmt = '%3d) % 2037 c = 1 2038 for name in s 2039 s = d 2040 e = d 2041 sysva 2042 c += 2043 sysvals.vprin 2044 sysvals.vprint(' kernel res 2045 sysvals.vprint(' t 2046 def deviceChildrenAllPhases(self, dev 2047 devlist = [] 2048 for phase in self.sortedPhase 2049 list = self.deviceChi 2050 for dev in sorted(lis 2051 if dev not in 2052 devli 2053 return devlist 2054 def masterTopology(self, name, list, 2055 node = DeviceNode(name, depth 2056 for cname in list: 2057 # avoid recursions 2058 if name == cname: 2059 continue 2060 clist = self.deviceCh 2061 cnode = self.masterTo 2062 node.children.append( 2063 return node 2064 def printTopology(self, node): 2065 html = '' 2066 if node.name: 2067 info = '' 2068 drv = '' 2069 for phase in self.sor 2070 list = self.d 2071 if node.name 2072 s = l 2073 e = l 2074 if li 2075 2076 info 2077 html += '<li><b>'+nod 2078 if info: 2079 html += '<ul> 2080 html += '</li>' 2081 if len(node.children) > 0: 2082 html += '<ul>' 2083 for cnode in node.chi 2084 html += self. 2085 html += '</ul>' 2086 return html 2087 def rootDeviceList(self): 2088 # list of devices graphed 2089 real = [] 2090 for phase in self.sortedPhase 2091 list = self.dmesg[pha 2092 for dev in sorted(lis 2093 if list[dev][ 2094 real. 2095 # list of top-most root devic 2096 rootlist = [] 2097 for phase in self.sortedPhase 2098 list = self.dmesg[pha 2099 for dev in sorted(lis 2100 pdev = list[d 2101 pid = list[de 2102 if(pid < 0 or 2103 conti 2104 if pdev and p 2105 rootl 2106 return rootlist 2107 def deviceTopology(self): 2108 rootlist = self.rootDeviceLis 2109 master = self.masterTopology( 2110 return self.printTopology(mas 2111 def selectTimelineDevices(self, widfm 2112 # only select devices that wi 2113 self.tdevlist = dict() 2114 for phase in self.dmesg: 2115 devlist = [] 2116 list = self.dmesg[pha 2117 for dev in list: 2118 length = (lis 2119 width = widfm 2120 if length >= 2121 devli 2122 self.tdevlist[phase] 2123 def addHorizontalDivider(self, devnam 2124 phase = 'suspend_prepare' 2125 self.newAction(phase, devname 2126 self.start, devend, ' 2127 if phase not in self.tdevlist 2128 self.tdevlist[phase] 2129 self.tdevlist[phase].append(d 2130 d = DevItem(0, phase, self.dm 2131 return d 2132 def addProcessUsageEvent(self, name, 2133 # get the start and end times 2134 cpuexec = dict() 2135 tlast = start = end = -1 2136 for t in sorted(times): 2137 if tlast < 0: 2138 tlast = t 2139 continue 2140 if name in self.pstl[ 2141 if start < 0: 2142 start 2143 end, key = t, 2144 maxj = (t - t 2145 cpuexec[key] 2146 tlast = t 2147 if start < 0 or end < 0: 2148 return 2149 # add a new action for this p 2150 out = self.newActionGlobal(na 2151 if out: 2152 phase, devname = out 2153 dev = self.dmesg[phas 2154 dev['cpuexec'] = cpue 2155 def createProcessUsageEvents(self): 2156 # get an array of process nam 2157 proclist = {'sus': dict(), 'r 2158 tdata = {'sus': [], 'res': [] 2159 for t in sorted(self.pstl): 2160 dir = 'sus' if t < se 2161 for ps in sorted(self 2162 if ps not in 2163 procl 2164 tdata[dir].append(t) 2165 # process the events for susp 2166 if len(proclist['sus']) > 0 o 2167 sysvals.vprint('Proce 2168 for dir in ['sus', 'res']: 2169 for ps in sorted(proc 2170 self.addProce 2171 def handleEndMarker(self, time, msg=' 2172 dm = self.dmesg 2173 self.setEnd(time, msg) 2174 self.initDevicegroups() 2175 # give suspend_prepare an end 2176 if 'suspend_prepare' in dm an 2177 dm['suspend_prepare'] 2178 # assume resume machine ends 2179 if 'resume_machine' in dm and 2180 np = self.nextPhase(' 2181 if np: 2182 dm['resume_ma 2183 # if kernel resume end not fo 2184 if self.tKernRes == 0.0: 2185 self.tKernRes = time 2186 # if kernel suspend start not 2187 if self.tKernSus == 0.0: 2188 self.tKernSus = time 2189 # set resume complete to end 2190 if 'resume_complete' in dm: 2191 dm['resume_complete'] 2192 def initcall_debug_call(self, line, q 2193 m = re.match(r'.*(\[ *)(?P<t> 2194 r'PM: *calling .* @ ( 2195 if not m: 2196 m = re.match(r'.*(\[ 2197 r'calling .* 2198 if not m: 2199 m = re.match(r'.*(\[ 2200 r'(?P<f>.*)\+ 2201 if m: 2202 return True if quick 2203 return False if quick else (' 2204 def initcall_debug_return(self, line, 2205 m = re.match(r'.*(\[ *)(?P<t> 2206 r'.* returned (?P<r>[ 2207 if not m: 2208 m = re.match(r'.*(\[ 2209 r'.* returned 2210 if not m: 2211 m = re.match(r'.*(\[ 2212 r'(?P<f>.*)\+ 2213 if m: 2214 return True if quick 2215 return False if quick else (' 2216 def debugPrint(self): 2217 for p in self.sortedPhases(): 2218 list = self.dmesg[p][ 2219 for devname in sorted 2220 dev = list[de 2221 if 'ftrace' i 2222 dev[' 2223 2224 # Class: DevFunction 2225 # Description: 2226 # A container for kprobe function data 2227 class DevFunction: 2228 def __init__(self, name, args, caller 2229 self.row = 0 2230 self.count = 1 2231 self.name = name 2232 self.args = args 2233 self.caller = caller 2234 self.ret = ret 2235 self.time = start 2236 self.length = end - start 2237 self.end = end 2238 self.ubiquitous = u 2239 self.proc = proc 2240 self.pid = pid 2241 self.color = color 2242 def title(self): 2243 cnt = '' 2244 if self.count > 1: 2245 cnt = '(x%d)' % self. 2246 l = '%0.3fms' % (self.length 2247 if self.ubiquitous: 2248 title = '%s(%s)%s <- 2249 (self.name, s 2250 else: 2251 title = '%s(%s) %s%s( 2252 return title.replace('"', '') 2253 def text(self): 2254 if self.count > 1: 2255 text = '%s(x%d)' % (s 2256 else: 2257 text = self.name 2258 return text 2259 def repeat(self, tgt): 2260 # is the tgt call just a repe 2261 dt = self.time - tgt.end 2262 # only combine calls if -all- 2263 if tgt.caller == self.caller 2264 tgt.name == self.name 2265 tgt.proc == self.proc 2266 tgt.ret == self.ret a 2267 dt <= sysvals.callloo 2268 self.length < sysvals 2269 return True 2270 return False 2271 2272 # Class: FTraceLine 2273 # Description: 2274 # A container for a single line of ftr 2275 # callgraph line: 2276 # call: " dpm_run_ca 2277 # return: " }" 2278 # leaf: " dpm_run_cal 2279 # trace event: 2280 # tracing_mark_write: 2281 # suspend_resume: phas 2282 # device_pm_callback: 2283 class FTraceLine: 2284 def __init__(self, t, m='', d=''): 2285 self.length = 0.0 2286 self.fcall = False 2287 self.freturn = False 2288 self.fevent = False 2289 self.fkprobe = False 2290 self.depth = 0 2291 self.name = '' 2292 self.type = '' 2293 self.time = float(t) 2294 if not m and not d: 2295 return 2296 # is this a trace event 2297 if(d == 'traceevent' or re.ma 2298 if(d == 'traceevent') 2299 # nop format 2300 msg = m 2301 else: 2302 # function_gr 2303 em = re.match 2304 msg = em.grou 2305 2306 emm = re.match(r'^(?P 2307 if(emm): 2308 self.name = e 2309 self.type = e 2310 else: 2311 self.name = m 2312 km = re.match(r'^(?P< 2313 if km: 2314 self.fcall = 2315 self.fkprobe 2316 self.type = k 2317 return 2318 km = re.match(r'^(?P< 2319 if km: 2320 self.freturn 2321 self.fkprobe 2322 self.type = k 2323 return 2324 self.fevent = True 2325 return 2326 # convert the duration to sec 2327 if(d): 2328 self.length = float(d 2329 # the indentation determines 2330 match = re.match(r'^(?P<d> *) 2331 if(not match): 2332 return 2333 self.depth = self.getDepth(ma 2334 m = match.group('o') 2335 # function return 2336 if(m[0] == '}'): 2337 self.freturn = True 2338 if(len(m) > 1): 2339 # includes co 2340 match = re.ma 2341 if(match): 2342 self. 2343 # function call 2344 else: 2345 self.fcall = True 2346 # function call with 2347 if(m[-1] == '{'): 2348 match = re.ma 2349 if(match): 2350 self. 2351 # function call with 2352 elif(m[-1] == ';'): 2353 self.freturn 2354 match = re.ma 2355 if(match): 2356 self. 2357 # something else (pos 2358 else: 2359 self.name = m 2360 def isCall(self): 2361 return self.fcall and not sel 2362 def isReturn(self): 2363 return self.freturn and not s 2364 def isLeaf(self): 2365 return self.fcall and self.fr 2366 def getDepth(self, str): 2367 return len(str)/2 2368 def debugPrint(self, info=''): 2369 if self.isLeaf(): 2370 pprint(' -- %12.6f (d 2371 self.depth, s 2372 elif self.freturn: 2373 pprint(' -- %12.6f (d 2374 self.depth, s 2375 else: 2376 pprint(' -- %12.6f (d 2377 self.depth, s 2378 def startMarker(self): 2379 # Is this the starting line o 2380 if not self.fevent: 2381 return False 2382 if sysvals.usetracemarkers: 2383 if(self.name.startswi 2384 return True 2385 return False 2386 else: 2387 if(self.type == 'susp 2388 re.match(r'su 2389 return True 2390 return False 2391 def endMarker(self): 2392 # Is this the ending line of 2393 if not self.fevent: 2394 return False 2395 if sysvals.usetracemarkers: 2396 if(self.name.startswi 2397 return True 2398 return False 2399 else: 2400 if(self.type == 'susp 2401 re.match(r'th 2402 return True 2403 return False 2404 2405 # Class: FTraceCallGraph 2406 # Description: 2407 # A container for the ftrace callgraph 2408 # This can be a dpm_run_callback, dpm_ 2409 # Each instance is tied to a single de 2410 # comprised of an ordered list of FTra 2411 class FTraceCallGraph: 2412 vfname = 'missing_function_name' 2413 def __init__(self, pid, sv): 2414 self.id = '' 2415 self.invalid = False 2416 self.name = '' 2417 self.partial = False 2418 self.ignore = False 2419 self.start = -1.0 2420 self.end = -1.0 2421 self.list = [] 2422 self.depth = 0 2423 self.pid = pid 2424 self.sv = sv 2425 def addLine(self, line): 2426 # if this is already invalid, 2427 if(self.invalid): 2428 if(line.depth == 0 an 2429 return 1 2430 return 0 2431 # invalidate on bad depth 2432 if(self.depth < 0): 2433 self.invalidate(line) 2434 return 0 2435 # ignore data til we return t 2436 if self.ignore: 2437 if line.depth > self. 2438 return 0 2439 else: 2440 self.list[-1] 2441 self.list[-1] 2442 self.ignore = 2443 # if this is 2444 if line.depth 2445 if li 2446 2447 2448 retur 2449 # compare current depth with 2450 prelinedep = line.depth 2451 if line.isReturn(): 2452 prelinedep += 1 2453 last = 0 2454 lasttime = line.time 2455 if len(self.list) > 0: 2456 last = self.list[-1] 2457 lasttime = last.time 2458 if last.isLeaf(): 2459 lasttime += l 2460 # handle low misalignments by 2461 mismatch = prelinedep - self. 2462 warning = self.sv.verbose and 2463 info = [] 2464 if mismatch < 0: 2465 idx = 0 2466 # add return calls to 2467 while prelinedep < se 2468 self.depth -= 2469 if idx == 0 a 2470 # spe 2471 last. 2472 last. 2473 last. 2474 if wa 2475 2476 else: 2477 vline 2478 vline 2479 vline 2480 vline 2481 self. 2482 if wa 2483 2484 2485 2486 idx += 1 2487 if warning: 2488 info.append(( 2489 # handle high misalignments b 2490 elif mismatch > 0: 2491 idx = 0 2492 if warning: 2493 info.append(( 2494 # add calls to get th 2495 while prelinedep > se 2496 if idx == 0 a 2497 # spe 2498 line. 2499 preli 2500 if wa 2501 2502 else: 2503 vline 2504 vline 2505 vline 2506 vline 2507 self. 2508 self. 2509 if no 2510 2511 if wa 2512 2513 idx += 1 2514 if warning and ('[mak 2515 info.append(( 2516 if warning: 2517 pprint('WARNING: ftra 2518 for i in info: 2519 t, obj = i 2520 if obj: 2521 obj.d 2522 # process the call and set th 2523 skipadd = False 2524 md = self.sv.max_graph_depth 2525 if line.isCall(): 2526 # ignore blacklisted/ 2527 if (md and self.depth 2528 self.ignore = 2529 else: 2530 self.depth += 2531 elif line.isReturn(): 2532 self.depth -= 1 2533 # remove blacklisted/ 2534 if (last and last.isC 2535 (md and last 2536 (line.name in 2537 while len(sel 2538 self. 2539 if len(self.l 2540 self. 2541 retur 2542 self.list[-1] 2543 self.list[-1] 2544 self.list[-1] 2545 skipadd = Tru 2546 if len(self.list) < 1: 2547 self.start = line.tim 2548 # check for a mismatch that r 2549 res = 1 2550 if mismatch < 0 and self.list 2551 line = self.list[-1] 2552 skipadd = True 2553 res = -1 2554 if not skipadd: 2555 self.list.append(line 2556 if(line.depth == 0 and line.f 2557 if(self.start < 0): 2558 self.start = 2559 self.end = line.time 2560 if line.fcall: 2561 self.end += l 2562 if self.list[0].name 2563 self.invalid 2564 if res == -1: 2565 self.partial 2566 return res 2567 return 0 2568 def invalidate(self, line): 2569 if(len(self.list) > 0): 2570 first = self.list[0] 2571 self.list = [] 2572 self.list.append(firs 2573 self.invalid = True 2574 id = 'task %s' % (self.pid) 2575 window = '(%f - %f)' % (self. 2576 if(self.depth < 0): 2577 pprint('Data misalign 2578 ' (buffer ove 2579 else: 2580 pprint('Too much data 2581 ' '+window+', 2582 def slice(self, dev): 2583 minicg = FTraceCallGraph(dev[ 2584 minicg.name = self.name 2585 mydepth = -1 2586 good = False 2587 for l in self.list: 2588 if(l.time < dev['star 2589 continue 2590 if mydepth < 0: 2591 if l.name == 2592 mydep 2593 continue 2594 elif l.depth == mydep 2595 good = True 2596 break 2597 l.depth -= mydepth 2598 minicg.addLine(l) 2599 if not good or len(minicg.lis 2600 return 0 2601 return minicg 2602 def repair(self, enddepth): 2603 # bring the depth back to 0 w 2604 fixed = False 2605 last = self.list[-1] 2606 for i in reversed(range(endde 2607 t = FTraceLine(last.t 2608 t.depth = i 2609 t.freturn = True 2610 fixed = self.addLine( 2611 if fixed != 0: 2612 self.end = la 2613 return True 2614 return False 2615 def postProcess(self): 2616 if len(self.list) > 0: 2617 self.name = self.list 2618 stack = dict() 2619 cnt = 0 2620 last = 0 2621 for l in self.list: 2622 # ftrace bug: reporte 2623 # check each leaf and 2624 if last and last.isLe 2625 if last.lengt 2626 last. 2627 if l.isCall(): 2628 stack[l.depth 2629 cnt += 1 2630 elif l.isReturn(): 2631 if(l.depth no 2632 if se 2633 2634 2635 retur 2636 # calculate c 2637 cl = stack[l. 2638 cl.length = l 2639 if cl.name == 2640 cl.na 2641 stack.pop(l.d 2642 l.length = 0 2643 cnt -= 1 2644 last = l 2645 if(cnt == 0): 2646 # trace caught the wh 2647 return True 2648 elif(cnt < 0): 2649 if self.sv.verbose: 2650 pprint('Post 2651 return False 2652 # trace ended before call tre 2653 return self.repair(cnt) 2654 def deviceMatch(self, pid, data): 2655 found = '' 2656 # add the callgraph data to t 2657 borderphase = { 2658 'dpm_prepare': 'suspe 2659 'dpm_complete': 'resu 2660 } 2661 if(self.name in borderphase): 2662 p = borderphase[self. 2663 list = data.dmesg[p][ 2664 for devname in list: 2665 dev = list[de 2666 if(pid == dev 2667 self. 2668 self. 2669 cg = 2670 if cg 2671 2672 found 2673 return found 2674 for p in data.sortedPhases(): 2675 if(data.dmesg[p]['sta 2676 self.start <= 2677 list = data.d 2678 for devname i 2679 dev = 2680 if(pi 2681 2682 2683 2684 2685 2686 break 2687 return found 2688 def newActionFromFunction(self, data) 2689 name = self.name 2690 if name in ['dpm_run_callback 2691 return 2692 fs = self.start 2693 fe = self.end 2694 if fs < data.start or fe > da 2695 return 2696 phase = '' 2697 for p in data.sortedPhases(): 2698 if(data.dmesg[p]['sta 2699 self.start < 2700 phase = p 2701 break 2702 if not phase: 2703 return 2704 out = data.newActionGlobal(na 2705 if out: 2706 phase, myname = out 2707 data.dmesg[phase]['li 2708 def debugPrint(self, info=''): 2709 pprint('%s pid=%d [%f - %f] % 2710 (self.name, self.pid, 2711 (self.end - self.star 2712 for l in self.list: 2713 if l.isLeaf(): 2714 pprint('%f (% 2715 l.dep 2716 elif l.freturn: 2717 pprint('%f (% 2718 l.dep 2719 else: 2720 pprint('%f (% 2721 l.dep 2722 pprint(' ') 2723 2724 class DevItem: 2725 def __init__(self, test, phase, dev): 2726 self.test = test 2727 self.phase = phase 2728 self.dev = dev 2729 def isa(self, cls): 2730 if 'htmlclass' in self.dev an 2731 return True 2732 return False 2733 2734 # Class: Timeline 2735 # Description: 2736 # A container for a device timeline wh 2737 # all the html properties to display i 2738 class Timeline: 2739 html_tblock = '<div id="block{0}" cla 2740 html_device = '<div id="{0}" title="{ 2741 html_phase = '<div class="phase" styl 2742 html_phaselet = '<div id="{0}" class= 2743 html_legend = '<div id="p{3}" class=" 2744 def __init__(self, rowheight, scalehe 2745 self.html = '' 2746 self.height = 0 # total time 2747 self.scaleH = scaleheight # t 2748 self.rowH = rowheight # d 2749 self.bodyH = 0 # body heigh 2750 self.rows = 0 # total time 2751 self.rowlines = dict() 2752 self.rowheight = dict() 2753 def createHeader(self, sv, stamp): 2754 if(not stamp['time']): 2755 return 2756 self.html += '<div class="ver 2757 % (sv.title, sv.versi 2758 if sv.logmsg and sv.testlog: 2759 self.html += '<button 2760 if sv.dmesglog: 2761 self.html += '<button 2762 if sv.ftracelog: 2763 self.html += '<button 2764 headline_stamp = '<div class= 2765 self.html += headline_stamp.f 2766 stamp['mode'], stamp[ 2767 if 'man' in stamp and 'plat' 2768 stamp['man'] and stam 2769 headline_sysinfo = '< 2770 self.html += headline 2771 2772 # Function: getDeviceRows 2773 # Description: 2774 # determine how may rows the devic 2775 # Arguments: 2776 # rawlist: the list of devices 2777 # Output: 2778 # The total number of rows nee 2779 def getDeviceRows(self, rawlist): 2780 # clear all rows and set them 2781 sortdict = dict() 2782 for item in rawlist: 2783 item.row = -1 2784 sortdict[item] = item 2785 sortlist = sorted(sortdict, k 2786 remaining = len(sortlist) 2787 rowdata = dict() 2788 row = 1 2789 # try to pack each row with a 2790 while(remaining > 0): 2791 if(row not in rowdata 2792 rowdata[row] 2793 for i in sortlist: 2794 if(i.row >= 0 2795 conti 2796 s = i.time 2797 e = i.time + 2798 valid = True 2799 for ritem in 2800 rs = 2801 re = 2802 if(no 2803 2804 2805 2806 if(valid): 2807 rowda 2808 i.row 2809 remai 2810 row += 1 2811 return row 2812 # Function: getPhaseRows 2813 # Description: 2814 # Organize the timeline entrie 2815 # number of rows possible, wit 2816 # Arguments: 2817 # devlist: the list of devices 2818 # Output: 2819 # The total number of rows nee 2820 def getPhaseRows(self, devlist, row=0 2821 # clear all rows and set them 2822 remaining = len(devlist) 2823 rowdata = dict() 2824 sortdict = dict() 2825 myphases = [] 2826 # initialize all device rows 2827 for item in devlist: 2828 dev = item.dev 2829 tp = (item.test, item 2830 if tp not in myphases 2831 myphases.appe 2832 dev['row'] = -1 2833 if sortby == 'start': 2834 # sort by sta 2835 sortdict[item 2836 else: 2837 # sort by len 2838 sortdict[item 2839 if 'src' in dev: 2840 dev['devrows' 2841 # sort the devlist by length 2842 sortlist = sorted(sortdict, k 2843 orderedlist = [] 2844 for item in sortlist: 2845 if item.dev['pid'] == 2846 orderedlist.a 2847 for item in sortlist: 2848 if item not in ordere 2849 orderedlist.a 2850 # try to pack each row with a 2851 while(remaining > 0): 2852 rowheight = 1 2853 if(row not in rowdata 2854 rowdata[row] 2855 for item in orderedli 2856 dev = item.de 2857 if(dev['row'] 2858 s = d 2859 e = d 2860 valid 2861 for r 2862 2863 2864 2865 2866 2867 2868 if(va 2869 2870 2871 2872 2873 2874 for t, p in myphases: 2875 if t not in s 2876 self. 2877 self. 2878 if p not in s 2879 self. 2880 self. 2881 rh = self.row 2882 # section hea 2883 if len(rowdat 2884 'html 2885 'sec' 2886 rh = 2887 self.rowlines 2888 self.rowheigh 2889 row += 1 2890 if(row > self.rows): 2891 self.rows = int(row) 2892 return row 2893 def phaseRowHeight(self, test, phase, 2894 return self.rowheight[test][p 2895 def phaseRowTop(self, test, phase, ro 2896 top = 0 2897 for i in sorted(self.rowheigh 2898 if i >= row: 2899 break 2900 top += self.rowheight 2901 return top 2902 def calcTotalRows(self): 2903 # Calculate the heights and o 2904 maxrows = 0 2905 standardphases = [] 2906 for t in self.rowlines: 2907 for p in self.rowline 2908 total = 0 2909 for i in sort 2910 total 2911 if total > ma 2912 maxro 2913 if total == l 2914 stand 2915 self.height = self.scaleH + ( 2916 self.bodyH = self.height - se 2917 # if there is 1 line per row, 2918 for t, p in standardphases: 2919 for i in sorted(self. 2920 self.rowheigh 2921 def createZoomBox(self, mode='command 2922 # Create bounding box, add bu 2923 html_zoombox = '<center><butt 2924 html_timeline = '<div id="dme 2925 html_devlist1 = '<button id=" 2926 html_devlist2 = '<button id=" 2927 if mode != 'command': 2928 if testcount > 1: 2929 self.html += 2930 self.html += 2931 else: 2932 self.html += 2933 self.html += html_zoombox 2934 self.html += html_timeline.fo 2935 # Function: createTimeScale 2936 # Description: 2937 # Create the timescale for a t 2938 # Arguments: 2939 # m0: start time (mode begin) 2940 # mMax: end time (mode end) 2941 # tTotal: total timeline time 2942 # mode: suspend or resume 2943 # Output: 2944 # The html code needed to disp 2945 def createTimeScale(self, m0, mMax, t 2946 timescale = '<div class="t" s 2947 rline = '<div class="t" style 2948 output = '<div class="timesca 2949 # set scale for timeline 2950 mTotal = mMax - m0 2951 tS = 0.1 2952 if(tTotal <= 0): 2953 return output+'</div> 2954 if(tTotal > 4): 2955 tS = 1 2956 divTotal = int(mTotal/tS) + 1 2957 divEdge = (mTotal - tS*(divTo 2958 for i in range(divTotal): 2959 htmlline = '' 2960 if(mode == 'suspend') 2961 pos = '%0.3f' 2962 val = '%0.fms 2963 if(i == divTo 2964 val = 2965 htmlline = ti 2966 else: 2967 pos = '%0.3f' 2968 val = '%0.fms 2969 htmlline = ti 2970 if(i == 0): 2971 htmll 2972 output += htmlline 2973 self.html += output+'</div>\n 2974 2975 # Class: TestProps 2976 # Description: 2977 # A list of values describing the prop 2978 class TestProps: 2979 stampfmt = r'# [a-z]*-(?P<m>[0-9]{2}) 2980 r'(?P<H>[0-9] 2981 r' (?P<host>. 2982 wififmt = r'^# wifi *(?P<d>\S*) *( 2983 tstatfmt = r'^# turbostat (?P<t>\S* 2984 testerrfmt = r'^# enter_sleep_error ( 2985 sysinfofmt = r'^# sysinfo .*' 2986 cmdlinefmt = r'^# command \| (?P<cmd> 2987 kparamsfmt = r'^# kparams \| (?P<kp>. 2988 devpropfmt = r'# Device Properties: . 2989 pinfofmt = r'# platform-(?P<val>[a- 2990 tracertypefmt = r'# tracer: (?P<t>.*) 2991 firmwarefmt = r'# fwsuspend (?P<s>[0- 2992 procexecfmt = r'ps - (?P<ps>.*)$' 2993 procmultifmt = r'@(?P<n>[0-9]*)\|(?P< 2994 ftrace_line_fmt_fg = \ 2995 r'^ *(?P<time>[0-9\.]*) *\| * 2996 r' *(?P<proc>.*)-(?P<pid>[0-9 2997 r'[ +!#\*@$]*(?P<dur>[0-9\.]* 2998 ftrace_line_fmt_nop = \ 2999 r' *(?P<proc>.*)-(?P<pid>[0-9 3000 r'(?P<flags>\S*) *(?P<time>[0 3001 r'(?P<msg>.*)' 3002 machinesuspend = r'machine_suspend\[. 3003 multiproclist = dict() 3004 multiproctime = 0.0 3005 multiproccnt = 0 3006 def __init__(self): 3007 self.stamp = '' 3008 self.sysinfo = '' 3009 self.cmdline = '' 3010 self.testerror = [] 3011 self.turbostat = [] 3012 self.wifi = [] 3013 self.fwdata = [] 3014 self.ftrace_line_fmt = self.f 3015 self.cgformat = False 3016 self.data = 0 3017 self.ktemp = dict() 3018 def setTracerType(self, tracer): 3019 if(tracer == 'function_graph' 3020 self.cgformat = True 3021 self.ftrace_line_fmt 3022 elif(tracer == 'nop'): 3023 self.ftrace_line_fmt 3024 else: 3025 doError('Invalid trac 3026 def stampInfo(self, line, sv): 3027 if re.match(self.stampfmt, li 3028 self.stamp = line 3029 return True 3030 elif re.match(self.sysinfofmt 3031 self.sysinfo = line 3032 return True 3033 elif re.match(self.tstatfmt, 3034 self.turbostat.append 3035 return True 3036 elif re.match(self.wififmt, l 3037 self.wifi.append(line 3038 return True 3039 elif re.match(self.testerrfmt 3040 self.testerror.append 3041 return True 3042 elif re.match(self.firmwarefm 3043 self.fwdata.append(li 3044 return True 3045 elif(re.match(self.devpropfmt 3046 self.parseDevprops(li 3047 return True 3048 elif(re.match(self.pinfofmt, 3049 self.parsePlatformInf 3050 return True 3051 m = re.match(self.cmdlinefmt, 3052 if m: 3053 self.cmdline = m.grou 3054 return True 3055 m = re.match(self.tracertypef 3056 if(m): 3057 self.setTracerType(m. 3058 return True 3059 return False 3060 def parseStamp(self, data, sv): 3061 # global test data 3062 m = re.match(self.stampfmt, s 3063 if not self.stamp or not m: 3064 doError('data does no 3065 data.stamp = {'time': '', 'ho 3066 dt = datetime(int(m.group('y' 3067 int(m.group('d')), in 3068 int(m.group('S'))) 3069 data.stamp['time'] = dt.strft 3070 data.stamp['host'] = m.group( 3071 data.stamp['mode'] = m.group( 3072 data.stamp['kernel'] = m.grou 3073 if re.match(self.sysinfofmt, 3074 for f in self.sysinfo 3075 if '#' in f: 3076 conti 3077 tmp = f.strip 3078 key = tmp[0] 3079 val = tmp[1] 3080 data.stamp[ke 3081 sv.hostname = data.stamp['hos 3082 sv.suspendmode = data.stamp[' 3083 if sv.suspendmode == 'freeze' 3084 self.machinesuspend = 3085 else: 3086 self.machinesuspend = 3087 if sv.suspendmode == 'command 3088 modes = ['on', 'freez 3089 fp = sv.openlog(sv.ft 3090 for line in fp: 3091 m = re.match( 3092 if m and m.gr 3093 sv.su 3094 data. 3095 break 3096 fp.close() 3097 sv.cmdline = self.cmdline 3098 if not sv.stamp: 3099 sv.stamp = data.stamp 3100 # firmware data 3101 if sv.suspendmode == 'mem' an 3102 m = re.match(self.fir 3103 if m: 3104 data.fwSuspen 3105 if(data.fwSus 3106 data. 3107 # turbostat data 3108 if len(self.turbostat) > data 3109 m = re.match(self.tst 3110 if m: 3111 data.turbosta 3112 # wifi data 3113 if len(self.wifi) > data.test 3114 m = re.match(self.wif 3115 if m: 3116 data.wifi = { 3117 'time 3118 data.stamp['w 3119 # sleep mode enter errors 3120 if len(self.testerror) > data 3121 m = re.match(self.tes 3122 if m: 3123 data.enterfai 3124 def devprops(self, data): 3125 props = dict() 3126 devlist = data.split(';') 3127 for dev in devlist: 3128 f = dev.split(',') 3129 if len(f) < 3: 3130 continue 3131 dev = f[0] 3132 props[dev] = DevProps 3133 props[dev].altname = 3134 if int(f[2]): 3135 props[dev].is 3136 else: 3137 props[dev].is 3138 return props 3139 def parseDevprops(self, line, sv): 3140 idx = line.index(': ') + 2 3141 if idx >= len(line): 3142 return 3143 props = self.devprops(line[id 3144 if sv.suspendmode == 'command 3145 sv.testcommand = prop 3146 sv.devprops = props 3147 def parsePlatformInfo(self, line, sv) 3148 m = re.match(self.pinfofmt, l 3149 if not m: 3150 return 3151 name, info = m.group('val'), 3152 if name == 'devinfo': 3153 sv.devprops = self.de 3154 return 3155 elif name == 'testcmd': 3156 sv.testcommand = info 3157 return 3158 field = info.split('|') 3159 if len(field) < 2: 3160 return 3161 cmdline = field[0].strip() 3162 output = sv.b64unzip(field[1] 3163 sv.platinfo.append([name, cmd 3164 3165 # Class: TestRun 3166 # Description: 3167 # A container for a suspend/resume tes 3168 # there could be more than one, and th 3169 class TestRun: 3170 def __init__(self, dataobj): 3171 self.data = dataobj 3172 self.ftemp = dict() 3173 self.ttemp = dict() 3174 3175 class ProcessMonitor: 3176 maxchars = 512 3177 def __init__(self): 3178 self.proclist = dict() 3179 self.running = False 3180 def procstat(self): 3181 c = ['cat /proc/[1-9]*/stat 2 3182 process = Popen(c, shell=True 3183 running = dict() 3184 for line in process.stdout: 3185 data = ascii(line).sp 3186 pid = data[0] 3187 name = re.sub('[()]', 3188 user = int(data[13]) 3189 kern = int(data[14]) 3190 kjiff = ujiff = 0 3191 if pid not in self.pr 3192 self.proclist 3193 else: 3194 val = self.pr 3195 ujiff = user 3196 kjiff = kern 3197 val['user'] = 3198 val['kern'] = 3199 if ujiff > 0 or kjiff 3200 running[pid] 3201 process.wait() 3202 out = [''] 3203 for pid in running: 3204 jiffies = running[pid 3205 val = self.proclist[p 3206 if len(out[-1]) > sel 3207 out.append('' 3208 elif len(out[-1]) > 0 3209 out[-1] += ', 3210 out[-1] += '%s-%s %d' 3211 if len(out) > 1: 3212 for line in out: 3213 sysvals.fsetV 3214 else: 3215 sysvals.fsetVal('ps - 3216 def processMonitor(self, tid): 3217 while self.running: 3218 self.procstat() 3219 def start(self): 3220 self.thread = Thread(target=s 3221 self.running = True 3222 self.thread.start() 3223 def stop(self): 3224 self.running = False 3225 3226 # ----------------- FUNCTIONS --------------- 3227 3228 # Function: doesTraceLogHaveTraceEvents 3229 # Description: 3230 # Quickly determine if the ftrace log 3231 # markers, and/or kprobes required for 3232 def doesTraceLogHaveTraceEvents(): 3233 kpcheck = ['_cal: (', '_ret: ('] 3234 techeck = ['suspend_resume', 'device_ 3235 tmcheck = ['SUSPEND START', 'RESUME C 3236 sysvals.usekprobes = False 3237 fp = sysvals.openlog(sysvals.ftracefi 3238 for line in fp: 3239 # check for kprobes 3240 if not sysvals.usekprobes: 3241 for i in kpcheck: 3242 if i in line: 3243 sysva 3244 # check for all necessary tra 3245 check = techeck[:] 3246 for i in techeck: 3247 if i in line: 3248 check.remove( 3249 techeck = check 3250 # check for all necessary tra 3251 check = tmcheck[:] 3252 for i in tmcheck: 3253 if i in line: 3254 check.remove( 3255 tmcheck = check 3256 fp.close() 3257 sysvals.usetraceevents = True if len( 3258 sysvals.usetracemarkers = True if len 3259 3260 # Function: appendIncompleteTraceLog 3261 # Description: 3262 # Adds callgraph data which lacks trac 3263 # for timelines generated from 3.15 or 3264 # Arguments: 3265 # testruns: the array of Data objects 3266 def appendIncompleteTraceLog(testruns): 3267 # create TestRun vessels for ftrace p 3268 testcnt = len(testruns) 3269 testidx = 0 3270 testrun = [] 3271 for data in testruns: 3272 testrun.append(TestRun(data)) 3273 3274 # extract the callgraph and traceeven 3275 sysvals.vprint('Analyzing the ftrace 3276 os.path.basename(sysvals.ftra 3277 tp = TestProps() 3278 tf = sysvals.openlog(sysvals.ftracefi 3279 data = 0 3280 for line in tf: 3281 # remove any latent carriage 3282 line = line.replace('\r\n', ' 3283 if tp.stampInfo(line, sysvals 3284 continue 3285 # parse only valid lines, if 3286 m = re.match(tp.ftrace_line_f 3287 if(not m): 3288 continue 3289 # gather the basic message da 3290 m_time = m.group('time') 3291 m_pid = m.group('pid') 3292 m_msg = m.group('msg') 3293 if(tp.cgformat): 3294 m_param3 = m.group('d 3295 else: 3296 m_param3 = 'traceeven 3297 if(m_time and m_pid and m_msg 3298 t = FTraceLine(m_time 3299 pid = int(m_pid) 3300 else: 3301 continue 3302 # the line should be a call, 3303 if(not t.fcall and not t.fret 3304 continue 3305 # look for the suspend start 3306 if(t.startMarker()): 3307 data = testrun[testid 3308 tp.parseStamp(data, s 3309 data.setStart(t.time, 3310 continue 3311 if(not data): 3312 continue 3313 # find the end of resume 3314 if(t.endMarker()): 3315 data.setEnd(t.time, t 3316 testidx += 1 3317 if(testidx >= testcnt 3318 break 3319 continue 3320 # trace event processing 3321 if(t.fevent): 3322 continue 3323 # call/return processing 3324 elif sysvals.usecallgraph: 3325 # create a callgraph 3326 if(pid not in testrun 3327 testrun[testi 3328 testrun[testi 3329 # when the call is fi 3330 cg = testrun[testidx] 3331 res = cg.addLine(t) 3332 if(res != 0): 3333 testrun[testi 3334 if(res == -1): 3335 testrun[testi 3336 tf.close() 3337 3338 for test in testrun: 3339 # add the callgraph data to t 3340 for pid in test.ftemp: 3341 for cg in test.ftemp[ 3342 if len(cg.lis 3343 conti 3344 if(not cg.pos 3345 id = 3346 sysva 3347 3348 conti 3349 callstart = c 3350 callend = cg. 3351 for p in test 3352 if(te 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 # Function: loadTraceLog 3364 # Description: 3365 # load the ftrace file into memory and 3366 # Output: 3367 # TestProps instance and an array of l 3368 def loadTraceLog(): 3369 tp, data, lines, trace = TestProps(), 3370 tf = sysvals.openlog(sysvals.ftracefi 3371 for line in tf: 3372 # remove any latent carriage 3373 line = line.replace('\r\n', ' 3374 if tp.stampInfo(line, sysvals 3375 continue 3376 # ignore all other commented 3377 if line[0] == '#': 3378 continue 3379 # ftrace line: parse only val 3380 m = re.match(tp.ftrace_line_f 3381 if(not m): 3382 continue 3383 dur = m.group('dur') if tp.cg 3384 info = (m.group('time'), m.gr 3385 m.group('msg'), dur) 3386 # group the data by timestamp 3387 t = float(info[0]) 3388 if t in data: 3389 data[t].append(info) 3390 else: 3391 data[t] = [info] 3392 # we only care about trace ev 3393 if (info[3].startswith('suspe 3394 info[3].startswith('t 3395 trace.append( 3396 tf.close() 3397 for t in sorted(data): 3398 first, last, blk = [], [], da 3399 if len(blk) > 1 and t in trac 3400 # move certain lines 3401 for i in range(len(bl 3402 if 'SUSPEND S 3403 first 3404 elif re.match 3405 last. 3406 elif re.match 3407 first 3408 elif 'RESUME 3409 last. 3410 if len(first) == 1 an 3411 blk.insert(0, 3412 elif len(last) == 1 a 3413 blk.append(bl 3414 for info in blk: 3415 lines.append(info) 3416 return (tp, lines) 3417 3418 # Function: parseTraceLog 3419 # Description: 3420 # Analyze an ftrace log output file ge 3421 # the execution phase. Used when the f 3422 # and includes the suspend_resume and 3423 # The ftrace filename is taken from sy 3424 # Output: 3425 # An array of Data objects 3426 def parseTraceLog(live=False): 3427 sysvals.vprint('Analyzing the ftrace 3428 os.path.basename(sysvals.ftra 3429 if(os.path.exists(sysvals.ftracefile) 3430 doError('%s does not exist' % 3431 if not live: 3432 sysvals.setupAllKprobes() 3433 ksuscalls = ['ksys_sync', 'pm_prepare 3434 krescalls = ['pm_restore_console'] 3435 tracewatch = ['irq_wakeup'] 3436 if sysvals.usekprobes: 3437 tracewatch += ['sync_filesyst 3438 'syscore_resume', 're 3439 'CPU_OFF', 'acpi_susp 3440 3441 # extract the callgraph and traceeven 3442 s2idle_enter = hwsus = False 3443 testruns, testdata = [], [] 3444 testrun, data, limbo = 0, 0, True 3445 phase = 'suspend_prepare' 3446 tp, tf = loadTraceLog() 3447 for m_time, m_proc, m_pid, m_msg, m_p 3448 # gather the basic message da 3449 if(m_time and m_pid and m_msg 3450 t = FTraceLine(m_time 3451 pid = int(m_pid) 3452 else: 3453 continue 3454 # the line should be a call, 3455 if(not t.fcall and not t.fret 3456 continue 3457 # find the start of suspend 3458 if(t.startMarker()): 3459 data, limbo = Data(le 3460 testdata.append(data) 3461 testrun = TestRun(dat 3462 testruns.append(testr 3463 tp.parseStamp(data, s 3464 data.setStart(t.time, 3465 data.first_suspend_pr 3466 phase = data.setPhase 3467 continue 3468 if(not data or limbo): 3469 continue 3470 # process cpu exec line 3471 if t.type == 'tracing_mark_wr 3472 if t.name == 'CMD COM 3473 data.tKernRes 3474 m = re.match(tp.proce 3475 if(m): 3476 parts, msg = 3477 m = re.match( 3478 if(m): 3479 parts 3480 if tp 3481 3482 3483 procl 3484 tp.mu 3485 else: 3486 procl 3487 tp.mu 3488 for ps in msg 3489 val = 3490 if no 3491 3492 name 3493 procl 3494 if parts == 1 3495 data. 3496 elif parts == 3497 data. 3498 tp.mu 3499 continue 3500 # find the end of resume 3501 if(t.endMarker()): 3502 if data.tKernRes == 0 3503 data.tKernRes 3504 data.handleEndMarker( 3505 if(not sysvals.usetra 3506 # no trace ma 3507 # the event w 3508 if('thaw_proc 3509 # if 3510 testr 3511 limbo = True 3512 continue 3513 # trace event processing 3514 if(t.fevent): 3515 if(t.type == 'suspend 3516 # suspend_res 3517 if(re.match(r 3518 isbeg 3519 elif(re.match 3520 isbeg 3521 else: 3522 conti 3523 if '[' in t.n 3524 m = r 3525 else: 3526 m = r 3527 name = m.grou 3528 # ignore thes 3529 if(name.split 3530 conti 3531 # -- phase ch 3532 # start of ke 3533 if(re.match(r 3534 if(is 3535 3536 conti 3537 # suspend_pre 3538 elif(re.match 3539 if is 3540 3541 3542 3543 3544 phase 3545 conti 3546 # suspend sta 3547 elif(re.match 3548 phase 3549 conti 3550 # suspend_lat 3551 elif(re.match 3552 phase 3553 conti 3554 # suspend_noi 3555 elif(re.match 3556 phase 3557 conti 3558 # suspend_mac 3559 elif(re.match 3560 lp = 3561 if(is 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 else: 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 conti 3591 # resume_noir 3592 elif(re.match 3593 phase 3594 conti 3595 # resume_earl 3596 elif(re.match 3597 phase 3598 conti 3599 # resume star 3600 elif(re.match 3601 phase 3602 conti 3603 # resume comp 3604 elif(re.match 3605 phase 3606 conti 3607 # skip trace 3608 if(not data.i 3609 conti 3610 # global even 3611 if(name not i 3612 testr 3613 # special han 3614 if name == 'm 3615 if hw 3616 3617 elif 3618 3619 3620 3621 elif 3622 3623 3624 3625 conti 3626 if(isbegin): 3627 # cre 3628 testr 3629 3630 else: 3631 if(le 3632 3633 3634 # device callback sta 3635 elif(t.type == 'devic 3636 if phase not 3637 conti 3638 m = re.match( 3639 t.nam 3640 if(not m): 3641 conti 3642 drv = m.group 3643 n = m.group(' 3644 p = m.group(' 3645 if(n and p): 3646 data. 3647 if pi 3648 3649 # device callback fin 3650 elif(t.type == 'devic 3651 if phase not 3652 conti 3653 m = re.match( 3654 if(not m): 3655 conti 3656 n = m.group(' 3657 dev = data.fi 3658 if dev: 3659 dev[' 3660 dev[' 3661 # kprobe event processing 3662 elif(t.fkprobe): 3663 kprobename = t.type 3664 kprobedata = t.name 3665 key = (kprobename, pi 3666 # displayname is gene 3667 displayname = '' 3668 if(t.fcall): 3669 displayname = 3670 if not displa 3671 conti 3672 if(key not in 3673 tp.kt 3674 tp.ktemp[key] 3675 'pid' 3676 'begi 3677 'end' 3678 'name 3679 'cdat 3680 'proc 3681 }) 3682 # start of ke 3683 if(data.tKern 3684 and k 3685 data. 3686 elif(t.freturn): 3687 if(key not in 3688 conti 3689 e = next((x f 3690 if not e: 3691 conti 3692 if (t.time - 3693 tp.kt 3694 conti 3695 e['end'] = t. 3696 e['rdata'] = 3697 # end of kern 3698 if(phase != ' 3699 if ph 3700 3701 data. 3702 3703 # callgraph processing 3704 elif sysvals.usecallgraph: 3705 # create a callgraph 3706 key = (m_proc, pid) 3707 if(key not in testrun 3708 testrun.ftemp 3709 testrun.ftemp 3710 # when the call is fi 3711 cg = testrun.ftemp[ke 3712 res = cg.addLine(t) 3713 if(res != 0): 3714 testrun.ftemp 3715 if(res == -1): 3716 testrun.ftemp 3717 if len(testdata) < 1: 3718 sysvals.vprint('WARNING: ftra 3719 if data and not data.devicegroups: 3720 sysvals.vprint('WARNING: ftra 3721 data.handleEndMarker(t.time, 3722 3723 if sysvals.suspendmode == 'command': 3724 for test in testruns: 3725 for p in test.data.so 3726 if p == 'susp 3727 test. 3728 test. 3729 else: 3730 test. 3731 test. 3732 test.data.tSuspended 3733 test.data.tResumed = 3734 test.data.fwValid = F 3735 3736 # dev source and procmon events can b 3737 if sysvals.usedevsrc or sysvals.usepr 3738 sysvals.mixedphaseheight = Fa 3739 3740 # expand phase boundaries so there ar 3741 for data in testdata: 3742 lp = data.sortedPhases()[0] 3743 for p in data.sortedPhases(): 3744 if(p != lp and not (' 3745 data.dmesg[lp 3746 lp = p 3747 3748 for i in range(len(testruns)): 3749 test = testruns[i] 3750 data = test.data 3751 # find the total time range f 3752 tlb, tle = data.start, data.e 3753 if i < len(testruns) - 1: 3754 tle = testruns[i+1].d 3755 # add the process usage data 3756 if sysvals.useprocmon: 3757 data.createProcessUsa 3758 # add the traceevent data to 3759 if(sysvals.usetraceevents): 3760 # add actual trace fu 3761 for name in sorted(te 3762 for event in 3763 if ev 3764 3765 title 3766 if na 3767 3768 data. 3769 # add the kprobe base 3770 for key in sorted(tp. 3771 name, pid = k 3772 if name not i 3773 conti 3774 if pid not in 3775 data. 3776 for e in tp.k 3777 kb, k 3778 if ke 3779 3780 color 3781 data. 3782 # add config base kpr 3783 if sysvals.usedevsrc: 3784 for key in so 3785 name, 3786 if na 3787 3788 for e 3789 3790 3791 3792 3793 3794 if sysvals.usecallgraph: 3795 # add the callgraph d 3796 sortlist = dict() 3797 for key in sorted(tes 3798 proc, pid = k 3799 for cg in tes 3800 if le 3801 3802 if(no 3803 3804 3805 3806 3807 # mat 3808 devna 3809 if sy 3810 3811 if no 3812 3813 3814 elif 3815 3816 3817 # create blocks for o 3818 for sortkey in sorted 3819 cg = sortlist 3820 name = cg.nam 3821 if sysvals.is 3822 sysva 3823 cg.ne 3824 if sysvals.suspendmode == 'command': 3825 return (testdata, '') 3826 3827 # fill in any missing phases 3828 error = [] 3829 for data in testdata: 3830 tn = '' if len(testdata) == 1 3831 terr = '' 3832 phasedef = data.phasedef 3833 lp = 'suspend_prepare' 3834 for p in sorted(phasedef, key 3835 if p not in data.dmes 3836 if not terr: 3837 ph = 3838 if p 3839 3840 3841 3842 3843 else: 3844 3845 pprin 3846 error 3847 if da 3848 3849 if da 3850 3851 data. 3852 sysvals.vprin 3853 lp = p 3854 if not terr and 'dev' in data 3855 terr = '%s%s failed i 3856 (sysvals.susp 3857 error.append(terr) 3858 if not terr and data.enterfai 3859 pprint('test%s FAILED 3860 terr = 'test%s failed 3861 error.append(terr) 3862 if data.tSuspended == 0: 3863 data.tSuspended = dat 3864 if data.tResumed == 0: 3865 data.tResumed = data. 3866 3867 if(len(sysvals.devicefilter) 3868 data.deviceFilter(sys 3869 data.fixupInitcallsThatDidntR 3870 if sysvals.usedevsrc: 3871 data.optimizeDevSrc() 3872 3873 # x2: merge any overlapping devices b 3874 if sysvals.usedevsrc and len(testdata 3875 tc = len(testdata) 3876 for i in range(tc - 1): 3877 devlist = testdata[i] 3878 for j in range(i + 1, 3879 testdata[j].m 3880 testdata[0].stitchTouchingThr 3881 return (testdata, ', '.join(error)) 3882 3883 # Function: loadKernelLog 3884 # Description: 3885 # load the dmesg file into memory and 3886 # Output: 3887 # An array of empty Data objects with 3888 def loadKernelLog(): 3889 sysvals.vprint('Analyzing the dmesg d 3890 os.path.basename(sysvals.dmes 3891 if(os.path.exists(sysvals.dmesgfile) 3892 doError('%s does not exist' % 3893 3894 # there can be multiple test runs in 3895 tp = TestProps() 3896 tp.stamp = datetime.now().strftime('# 3897 testruns = [] 3898 data = 0 3899 lf = sysvals.openlog(sysvals.dmesgfil 3900 for line in lf: 3901 line = line.replace('\r\n', ' 3902 idx = line.find('[') 3903 if idx > 1: 3904 line = line[idx:] 3905 if tp.stampInfo(line, sysvals 3906 continue 3907 m = re.match(r'[ \t]*(\[ *)(? 3908 if(not m): 3909 continue 3910 msg = m.group("msg") 3911 if re.match(r'PM: Syncing fil 3912 re.match(r'PM: suspen 3913 if(data): 3914 testruns.appe 3915 data = Data(len(testr 3916 tp.parseStamp(data, s 3917 if(not data): 3918 continue 3919 m = re.match(r'.* *(?P<k>[0-9 3920 if(m): 3921 sysvals.stamp['kernel 3922 m = re.match(r'PM: Preparing 3923 if not m: 3924 m = re.match(r'PM: Pr 3925 if m: 3926 sysvals.stamp['mode'] 3927 data.dmesgtext.append(line) 3928 lf.close() 3929 3930 if sysvals.suspendmode == 's2idle': 3931 sysvals.suspendmode = 'freeze 3932 elif sysvals.suspendmode == 'deep': 3933 sysvals.suspendmode = 'mem' 3934 if data: 3935 testruns.append(data) 3936 if len(testruns) < 1: 3937 doError('dmesg log has no sus 3938 % sysvals.dmesgfile) 3939 3940 # fix lines with same timestamp/funct 3941 for data in testruns: 3942 last = '' 3943 for line in data.dmesgtext: 3944 ct, cf, n, p = data.i 3945 rt, rf, l = data.init 3946 if ct and rt and ct = 3947 i = data.dmes 3948 j = data.dmes 3949 data.dmesgtex 3950 data.dmesgtex 3951 last = line 3952 return testruns 3953 3954 # Function: parseKernelLog 3955 # Description: 3956 # Analyse a dmesg log output file gene 3957 # the execution phase. Create a set of 3958 # for subsequent formatting in the htm 3959 # This call is only for legacy support 3960 # data lacks the suspend_resume or dev 3961 # Arguments: 3962 # data: an empty Data object (with dme 3963 # Output: 3964 # The filled Data object 3965 def parseKernelLog(data): 3966 phase = 'suspend_runtime' 3967 3968 if(data.fwValid): 3969 sysvals.vprint('Firmware Susp 3970 (data.fwSuspend, data 3971 3972 # dmesg phase match table 3973 dm = { 3974 'suspend_prepare': ['PM: Sync 3975 'suspend': ['PM: Ente 3976 'PM: Susp 3977 'suspend_late': ['PM: susp 3978 3979 'suspend_noirq': ['PM: late 3980 3981 'suspend_machine': ['PM: susp 3982 3983 3984 'resume_machine': ['[PM: ]*T 3985 3986 3987 3988 'resume_noirq': ['PM: resu 3989 3990 'resume_early': ['PM: noir 3991 3992 'resume': ['PM: earl 3993 3994 'resume_complete': ['PM: resu 3995 3996 'post_resume': [r'.*Resta 3997 } 3998 3999 # action table (expected events that 4000 at = { 4001 'sync_filesystems': { 4002 'smsg': '.*[Ff]+ilesy 4003 'emsg': 'PM: Preparin 4004 'freeze_user_processes': { 4005 'smsg': 'Freezing use 4006 'emsg': 'Freezing rem 4007 'freeze_tasks': { 4008 'smsg': 'Freezing rem 4009 'emsg': 'PM: Suspendi 4010 'ACPI prepare': { 4011 'smsg': 'ACPI: Prepar 4012 'emsg': 'PM: Saving p 4013 'PM vns': { 4014 'smsg': 'PM: Saving p 4015 'emsg': 'Disabling no 4016 } 4017 4018 t0 = -1.0 4019 cpu_start = -1.0 4020 prevktime = -1.0 4021 actions = dict() 4022 for line in data.dmesgtext: 4023 # parse each dmesg line into 4024 m = re.match(r'[ \t]*(\[ *)(? 4025 if(m): 4026 val = m.group('ktime' 4027 try: 4028 ktime = float 4029 except: 4030 continue 4031 msg = m.group('msg') 4032 # initialize data sta 4033 if t0 < 0: 4034 data.setStart 4035 t0 = ktime 4036 else: 4037 continue 4038 4039 # check for a phase change li 4040 phasechange = False 4041 for p in dm: 4042 for s in dm[p]: 4043 if(re.match(s 4044 phase 4045 dm[p] 4046 break 4047 4048 # hack for determining resume 4049 if(not sysvals.usetraceevents 4050 and phase == 'resume_ 4051 data.initcall_debug_c 4052 data.setPhase(phase, 4053 phase = 'resume_noirq 4054 data.setPhase(phase, 4055 4056 if phasechange: 4057 if phase == 'suspend_ 4058 data.setPhase 4059 data.setStart 4060 data.tKernSus 4061 elif phase == 'suspen 4062 lp = data.las 4063 if lp: 4064 data. 4065 data.setPhase 4066 elif phase == 'suspen 4067 lp = data.las 4068 if lp: 4069 data. 4070 data.setPhase 4071 elif phase == 'suspen 4072 lp = data.las 4073 if lp: 4074 data. 4075 data.setPhase 4076 elif phase == 'suspen 4077 lp = data.las 4078 if lp: 4079 data. 4080 data.setPhase 4081 elif phase == 'resume 4082 lp = data.las 4083 if(sysvals.su 4084 data. 4085 if lp 4086 4087 else: 4088 data. 4089 if lp 4090 4091 data.tResumed 4092 data.setPhase 4093 elif phase == 'resume 4094 lp = data.las 4095 if lp: 4096 data. 4097 data.setPhase 4098 elif phase == 'resume 4099 lp = data.las 4100 if lp: 4101 data. 4102 data.setPhase 4103 elif phase == 'resume 4104 lp = data.las 4105 if lp: 4106 data. 4107 data.setPhase 4108 elif phase == 'resume 4109 lp = data.las 4110 if lp: 4111 data. 4112 data.setPhase 4113 elif phase == 'post_r 4114 lp = data.las 4115 if lp: 4116 data. 4117 data.setEnd(k 4118 data.tKernRes 4119 break 4120 4121 # -- device callbacks -- 4122 if(phase in data.sortedPhases 4123 # device init call 4124 t, f, n, p = data.ini 4125 if t and f and n and 4126 data.newActio 4127 else: 4128 # device init 4129 t, f, l = dat 4130 if t and f an 4131 list 4132 if(f 4133 4134 4135 4136 4137 # if trace events are not ava 4138 if(not sysvals.usetraceevents 4139 # look for known acti 4140 for a in sorted(at): 4141 if(re.match(a 4142 if(a 4143 4144 if(re.match(a 4145 if(a 4146 4147 # now look for CPU on 4148 if(re.match(r'Disabli 4149 # start of fi 4150 cpu_start = k 4151 elif(re.match(r'Enabl 4152 # start of fi 4153 cpu_start = k 4154 elif(re.match(r'smpbo 4155 or re.match(r 4156 # end of a cp 4157 m = re.match( 4158 if(not m): 4159 m = r 4160 cpu = 'CPU'+m 4161 if(cpu not in 4162 actio 4163 actions[cpu]. 4164 cpu_start = k 4165 elif(re.match(r'CPU(? 4166 # end of a cp 4167 m = re.match( 4168 cpu = 'CPU'+m 4169 if(cpu not in 4170 actio 4171 actions[cpu]. 4172 cpu_start = k 4173 prevktime = ktime 4174 data.initDevicegroups() 4175 4176 # fill in any missing phases 4177 phasedef = data.phasedef 4178 terr, lp = '', 'suspend_prepare' 4179 if lp not in data.dmesg: 4180 doError('dmesg log format has 4181 for p in sorted(phasedef, key=lambda 4182 if p not in data.dmesg: 4183 if not terr: 4184 pprint('TEST 4185 terr = '%s fa 4186 if data.tSusp 4187 data. 4188 if data.tResu 4189 data. 4190 sysvals.vprint('WARNI 4191 lp = p 4192 lp = data.sortedPhases()[0] 4193 for p in data.sortedPhases(): 4194 if(p != lp and not ('machine' 4195 data.dmesg[lp]['end'] 4196 lp = p 4197 if data.tSuspended == 0: 4198 data.tSuspended = data.tKernR 4199 if data.tResumed == 0: 4200 data.tResumed = data.tSuspend 4201 4202 # fill in any actions we've found 4203 for name in sorted(actions): 4204 for event in actions[name]: 4205 data.newActionGlobal( 4206 4207 if(len(sysvals.devicefilter) > 0): 4208 data.deviceFilter(sysvals.dev 4209 data.fixupInitcallsThatDidntReturn() 4210 return True 4211 4212 def callgraphHTML(sv, hf, num, cg, title, col 4213 html_func_top = '<article id="{0}" cl 4214 html_func_start = '<article>\n<input 4215 html_func_end = '</article>\n' 4216 html_func_leaf = '<article>{0} {1}</a 4217 4218 cgid = devid 4219 if cg.id: 4220 cgid += cg.id 4221 cglen = (cg.end - cg.start) * 1000 4222 if cglen < sv.mincglen: 4223 return num 4224 4225 fmt = '<r>(%.3f ms @ '+sv.timeformat+' 4226 flen = fmt % (cglen, cg.start, cg.end 4227 hf.write(html_func_top.format(cgid, c 4228 num += 1 4229 for line in cg.list: 4230 if(line.length < 0.000000001) 4231 flen = '' 4232 else: 4233 fmt = '<n>(%.3f ms @ ' 4234 flen = fmt % (line.le 4235 if line.isLeaf(): 4236 if line.length * 1000 4237 continue 4238 hf.write(html_func_le 4239 elif line.freturn: 4240 hf.write(html_func_en 4241 else: 4242 hf.write(html_func_st 4243 num += 1 4244 hf.write(html_func_end) 4245 return num 4246 4247 def addCallgraphs(sv, hf, data): 4248 hf.write('<section id="callgraphs" cl 4249 # write out the ftrace data converted 4250 num = 0 4251 for p in data.sortedPhases(): 4252 if sv.cgphase and p != sv.cgp 4253 continue 4254 list = data.dmesg[p]['list'] 4255 for d in data.sortedDevices(p 4256 if len(sv.cgfilter) > 4257 continue 4258 dev = list[d] 4259 color = 'white' 4260 if 'color' in data.dm 4261 color = data. 4262 if 'color' in dev: 4263 color = dev[' 4264 name = d if '[' not i 4265 if(d in sv.devprops): 4266 name = sv.dev 4267 if 'drv' in dev and d 4268 name += ' {%s 4269 if sv.suspendmode in 4270 name += ' '+p 4271 if('ftrace' in dev): 4272 cg = dev['ftr 4273 if cg.name == 4274 name 4275 num = callgra 4276 name, 4277 if('ftraces' in dev): 4278 for cg in dev 4279 num = 4280 4281 hf.write('\n\n </section>\n') 4282 4283 def summaryCSS(title, center=True): 4284 tdcenter = 'text-align:center;' if ce 4285 out = '<!DOCTYPE html>\n<html>\n<head 4286 <meta http-equiv="content-type" conte 4287 <title>'+title+'</title>\n\ 4288 <style type=\'text/css\'>\n\ 4289 .stamp {width: 100%;text-alig 4290 table {width:100%;border-coll 4291 th {border: 1px solid black;b 4292 td {font: 14px "Times New Rom 4293 tr.head td {border: 1px solid 4294 tr.alt {background-color:#ddd 4295 tr.notice {color:red;}\n\ 4296 .minval {background-color:#BB 4297 .medval {background-color:#BB 4298 .maxval {background-color:#FF 4299 .head a {color:#000;text-deco 4300 </style>\n</head>\n<body>\n' 4301 return out 4302 4303 # Function: createHTMLSummarySimple 4304 # Description: 4305 # Create summary html file for a serie 4306 # Arguments: 4307 # testruns: array of Data objects from 4308 def createHTMLSummarySimple(testruns, htmlfil 4309 # write the html header first (html h 4310 html = summaryCSS('Summary - SleepGra 4311 4312 # extract the test data into list 4313 list = dict() 4314 tAvg, tMin, tMax, tMed = [0.0, 0.0], 4315 iMin, iMed, iMax = [0, 0], [0, 0], [0 4316 num = 0 4317 useturbo = usewifi = False 4318 lastmode = '' 4319 cnt = dict() 4320 for data in sorted(testruns, key=lamb 4321 mode = data['mode'] 4322 if mode not in list: 4323 list[mode] = {'data': 4324 if lastmode and lastmode != m 4325 for i in range(2): 4326 s = sorted(tM 4327 list[lastmode 4328 iMed[i] = tMe 4329 list[lastmode]['avg'] 4330 list[lastmode]['min'] 4331 list[lastmode]['max'] 4332 list[lastmode]['idx'] 4333 tAvg, tMin, tMax, tMe 4334 iMin, iMed, iMax = [0 4335 num = 0 4336 pkgpc10 = syslpi = wifi = '' 4337 if 'pkgpc10' in data and 'sys 4338 pkgpc10, syslpi, uset 4339 if 'wifi' in data: 4340 wifi, usewifi = data[ 4341 res = data['result'] 4342 tVal = [float(data['suspend'] 4343 list[mode]['data'].append([da 4344 data['time'], tVal[0] 4345 data['issues'], data[ 4346 data['res_worst'], da 4347 (data['fullmode'] if 4348 idx = len(list[mode]['data']) 4349 if res.startswith('fail in'): 4350 res = 'fail' 4351 if res not in cnt: 4352 cnt[res] = 1 4353 else: 4354 cnt[res] += 1 4355 if res == 'pass': 4356 for i in range(2): 4357 tMed[i][tVal[ 4358 tAvg[i] += tV 4359 if tMin[i] == 4360 iMin[ 4361 tMin[ 4362 if tMax[i] == 4363 iMax[ 4364 tMax[ 4365 num += 1 4366 lastmode = mode 4367 if lastmode and num > 0: 4368 for i in range(2): 4369 s = sorted(tMed[i]) 4370 list[lastmode]['med'] 4371 iMed[i] = tMed[i][lis 4372 list[lastmode]['avg'] = [tAvg 4373 list[lastmode]['min'] = tMin 4374 list[lastmode]['max'] = tMax 4375 list[lastmode]['idx'] = (iMin 4376 4377 # group test header 4378 desc = [] 4379 for ilk in sorted(cnt, reverse=True): 4380 if cnt[ilk] > 0: 4381 desc.append('%d %s' % 4382 html += '<div class="stamp">%s (%d te 4383 th = '\t<th>{0}</th>\n' 4384 td = '\t<td>{0}</td>\n' 4385 tdh = '\t<td{1}>{0}</td>\n' 4386 tdlink = '\t<td><a href="{0}">html</a 4387 cols = 12 4388 if useturbo: 4389 cols += 2 4390 if usewifi: 4391 cols += 1 4392 colspan = '%d' % cols 4393 4394 # table header 4395 html += '<table>\n<tr>\n' + th.format 4396 th.format('Mode') + th.format 4397 th.format('Test Time') + th.f 4398 th.format('Suspend') + th.for 4399 th.format('Worst Suspend Devi 4400 th.format('Worst Resume Devic 4401 if useturbo: 4402 html += th.format('PkgPC10') 4403 if usewifi: 4404 html += th.format('Wifi') 4405 html += th.format('Detail')+'</tr>\n' 4406 # export list into html 4407 head = '<tr class="head"><td>{0}</td> 4408 '<td colspan='+colspan+' clas 4409 '<span class=minval><a href=" 4410 '<span class=medval><a href=" 4411 '<span class=maxval><a href=" 4412 'Resume Avg={6} '+\ 4413 '<span class=minval><a href=" 4414 '<span class=medval><a href=" 4415 '<span class=maxval><a href=" 4416 '</tr>\n' 4417 headnone = '<tr class="head"><td>{0}< 4418 colspan+'></td></tr>\n' 4419 for mode in sorted(list): 4420 # header line for each suspen 4421 num = 0 4422 tAvg, tMin, tMax, tMed = list 4423 list[mode]['max'], li 4424 count = len(list[mode]['data' 4425 if 'idx' in list[mode]: 4426 iMin, iMed, iMax = li 4427 html += head.format(' 4428 '%.3f' % tAvg 4429 '%.3f' % tAvg 4430 mode.lower() 4431 ) 4432 else: 4433 iMin = iMed = iMax = 4434 html += headnone.form 4435 for d in list[mode]['data']: 4436 # row classes - alter 4437 rcls = ['alt'] if num 4438 if d[6] != 'pass': 4439 rcls.append(' 4440 html += '<tr class="' 4441 # figure out if the l 4442 idx = list[mode]['dat 4443 tHigh = ['', ''] 4444 for i in range(2): 4445 tag = 's%s' % 4446 if idx == iMi 4447 tHigh 4448 elif idx == i 4449 tHigh 4450 elif idx == i 4451 tHigh 4452 html += td.format("%d 4453 html += td.format(d[1 4454 html += td.format(d[0 4455 html += td.format(d[1 4456 html += td.format(d[2 4457 html += td.format(d[6 4458 html += td.format(d[7 4459 html += tdh.format('% 4460 html += tdh.format('% 4461 html += td.format(d[8 4462 html += td.format('%. 4463 html += td.format(d[1 4464 html += td.format('%. 4465 if useturbo: 4466 html += td.fo 4467 html += td.fo 4468 if usewifi: 4469 html += td.fo 4470 html += tdlink.format 4471 html += '</tr>\n' 4472 num += 1 4473 4474 # flush the data to file 4475 hf = open(htmlfile, 'w') 4476 hf.write(html+'</table>\n</body>\n</h 4477 hf.close() 4478 4479 def createHTMLDeviceSummary(testruns, htmlfil 4480 html = summaryCSS('Device Summary - S 4481 4482 # create global device list from all 4483 devall = dict() 4484 for data in testruns: 4485 host, url, devlist = data['ho 4486 for type in devlist: 4487 if type not in devall 4488 devall[type] 4489 mdevlist, devlist = d 4490 for name in devlist: 4491 length = devl 4492 if name not i 4493 mdevl 4494 4495 4496 else: 4497 if le 4498 4499 4500 4501 mdevl 4502 mdevl 4503 4504 # generate the html 4505 th = '\t<th>{0}</th>\n' 4506 td = '\t<td align=center>{0}</td>\n' 4507 tdr = '\t<td align=right>{0}</td>\n' 4508 tdlink = '\t<td align=center><a href= 4509 limit = 1 4510 for type in sorted(devall, reverse=Tr 4511 num = 0 4512 devlist = devall[type] 4513 # table header 4514 html += '<div class="stamp">% 4515 (title, type.upper(), 4516 html += '<tr>\n' + '<th align 4517 th.format('Average Ti 4518 th.format('Worst Time 4519 th.format('Link (wors 4520 for name in sorted(devlist, k 4521 devlist[k]['total'], 4522 data = devall[type][n 4523 data['average'] = dat 4524 if data['average'] < 4525 continue 4526 # row classes - alter 4527 rcls = ['alt'] if num 4528 html += '<tr class="' 4529 html += tdr.format(da 4530 html += td.format('%. 4531 html += td.format(dat 4532 html += td.format('%. 4533 html += td.format(dat 4534 html += tdlink.format 4535 html += '</tr>\n' 4536 num += 1 4537 html += '</table>\n' 4538 4539 # flush the data to file 4540 hf = open(htmlfile, 'w') 4541 hf.write(html+'</body>\n</html>\n') 4542 hf.close() 4543 return devall 4544 4545 def createHTMLIssuesSummary(testruns, issues, 4546 multihost = len([e for e in issues if 4547 html = summaryCSS('Issues Summary - S 4548 total = len(testruns) 4549 4550 # generate the html 4551 th = '\t<th>{0}</th>\n' 4552 td = '\t<td align={0}>{1}</td>\n' 4553 tdlink = '<a href="{1}">{0}</a>' 4554 subtitle = '%d issues' % len(issues) 4555 html += '<div class="stamp">%s (%s)</ 4556 html += '<tr>\n' + th.format('Issue') 4557 if multihost: 4558 html += th.format('Hosts') 4559 html += th.format('Tests') + th.forma 4560 th.format('First Instance') + 4561 4562 num = 0 4563 for e in sorted(issues, key=lambda v: 4564 testtotal = 0 4565 links = [] 4566 for host in sorted(e['urls']) 4567 links.append(tdlink.f 4568 testtotal += len(e['u 4569 rate = '%d/%d (%.2f%%)' % (te 4570 # row classes - alternate row 4571 rcls = ['alt'] if num % 2 == 4572 html += '<tr class="'+(' '.jo 4573 html += td.format('left', e[' 4574 html += td.format('center', e 4575 if multihost: 4576 html += td.format('ce 4577 html += td.format('center', t 4578 html += td.format('center', r 4579 html += td.format('center now 4580 html += '</tr>\n' 4581 num += 1 4582 4583 # flush the data to file 4584 hf = open(htmlfile, 'w') 4585 hf.write(html+'</table>\n'+extra+'</b 4586 hf.close() 4587 return issues 4588 4589 def ordinal(value): 4590 suffix = 'th' 4591 if value < 10 or value > 19: 4592 if value % 10 == 1: 4593 suffix = 'st' 4594 elif value % 10 == 2: 4595 suffix = 'nd' 4596 elif value % 10 == 3: 4597 suffix = 'rd' 4598 return '%d%s' % (value, suffix) 4599 4600 # Function: createHTML 4601 # Description: 4602 # Create the output html file from the 4603 # Arguments: 4604 # testruns: array of Data objects from 4605 # Output: 4606 # True if the html file was created, f 4607 def createHTML(testruns, testfail): 4608 if len(testruns) < 1: 4609 pprint('ERROR: Not enough tes 4610 return 4611 4612 kerror = False 4613 for data in testruns: 4614 if data.kerror: 4615 kerror = True 4616 if(sysvals.suspendmode in ['f 4617 data.trimFreezeTime(t 4618 else: 4619 data.getMemTime() 4620 4621 # html function templates 4622 html_error = '<div id="{1}" title="ke 4623 html_traceevent = '<div title="{0}" c 4624 html_cpuexec = '<div class="jiffie" s 4625 html_timetotal = '<table class="time1 4626 '<td class="green" title="{3} 4627 '<td class="yellow" title="{4 4628 '</tr>\n</table>\n' 4629 html_timetotal2 = '<table class="time 4630 '<td class="green" title="{4} 4631 '<td class="gray" title="time 4632 '<td class="yellow" title="{5 4633 '</tr>\n</table>\n' 4634 html_timetotal3 = '<table class="time 4635 '<td class="green">Execution 4636 '<td class="yellow">Command: 4637 '</tr>\n</table>\n' 4638 html_fail = '<table class="testfail"> 4639 html_kdesc = '<td class="{3}" title=" 4640 html_fwdesc = '<td class="{3}" title= 4641 html_wifdesc = '<td class="yellow" ti 4642 4643 # html format variables 4644 scaleH = 20 4645 if kerror: 4646 scaleH = 40 4647 4648 # device timeline 4649 devtl = Timeline(30, scaleH) 4650 4651 # write the test title and general in 4652 devtl.createHeader(sysvals, testruns[ 4653 4654 # Generate the header for this timeli 4655 for data in testruns: 4656 tTotal = data.end - data.star 4657 if(tTotal == 0): 4658 doError('No timeline 4659 if sysvals.suspendmode == 'co 4660 run_time = '%.0f' % ( 4661 if sysvals.testcomman 4662 testdesc = sy 4663 else: 4664 testdesc = 'u 4665 if(len(testruns) > 1) 4666 testdesc = or 4667 thtml = html_timetota 4668 devtl.html += thtml 4669 continue 4670 # typical full suspend/resume 4671 stot, rtot = sktime, rktime = 4672 ssrc, rsrc, testdesc, testdes 4673 if data.fwValid: 4674 stot += (data.fwSuspe 4675 rtot += (data.fwResum 4676 ssrc.append('firmware 4677 rsrc.append('firmware 4678 testdesc = 'Total' 4679 if 'time' in data.wifi and da 4680 rtot += data.end - da 4681 rsrc.append('wifi') 4682 testdesc = 'Total' 4683 suspend_time, resume_time = ' 4684 stitle = 'time from kernel su 4685 (sysvals.suspendmode, 4686 rtitle = 'time from %s mode t 4687 (sysvals.suspendmode, 4688 if(len(testruns) > 1): 4689 testdesc = testdesc2 4690 testdesc2 += ' ' 4691 if(len(data.tLow) == 0): 4692 thtml = html_timetota 4693 resume_time, 4694 else: 4695 low_time = '+'.join(d 4696 thtml = html_timetota 4697 resume_time, 4698 devtl.html += thtml 4699 if not data.fwValid and 'dev' 4700 continue 4701 # extra detail when the times 4702 thtml = '<table class="time2" 4703 thtml += html_kdesc.format(te 4704 if data.fwValid: 4705 sftime = '%.3f'%(data 4706 rftime = '%.3f'%(data 4707 thtml += html_fwdesc. 4708 thtml += html_fwdesc. 4709 thtml += html_kdesc.format(te 4710 if 'time' in data.wifi: 4711 if data.wifi['stat'] 4712 wtime = '%.0f 4713 else: 4714 wtime = 'TIME 4715 thtml += html_wifdesc 4716 thtml += '</tr>\n</table>\n' 4717 devtl.html += thtml 4718 if testfail: 4719 devtl.html += html_fail.forma 4720 4721 # time scale for potentially multiple 4722 t0 = testruns[0].start 4723 tMax = testruns[-1].end 4724 tTotal = tMax - t0 4725 4726 # determine the maximum number of row 4727 fulllist = [] 4728 threadlist = [] 4729 pscnt = 0 4730 devcnt = 0 4731 for data in testruns: 4732 data.selectTimelineDevices('% 4733 for group in data.devicegroup 4734 devlist = [] 4735 for phase in group: 4736 for devname i 4737 d = D 4738 devli 4739 if d. 4740 4741 else: 4742 4743 4744 4745 4746 4747 if sysvals.mixedphase 4748 devtl.getPhas 4749 if not sysvals.mixedphaseheight: 4750 if len(threadlist) > 0 and le 4751 if pscnt > 0 and devc 4752 msg = 'user p 4753 elif pscnt > 0: 4754 msg = 'user p 4755 else: 4756 msg = 'device 4757 d = testruns[0].addHo 4758 fulllist.insert(0, d) 4759 devtl.getPhaseRows(fulllist) 4760 if len(threadlist) > 0: 4761 d = testruns[0].addHo 4762 threadlist.insert(0, 4763 devtl.getPhaseRows(th 4764 devtl.calcTotalRows() 4765 4766 # draw the full timeline 4767 devtl.createZoomBox(sysvals.suspendmo 4768 for data in testruns: 4769 # draw each test run and bloc 4770 phases = {'suspend':[],'resum 4771 for phase in data.sortedPhase 4772 if data.dmesg[phase][ 4773 phases['resum 4774 else: 4775 phases['suspe 4776 # now draw the actual timelin 4777 for dir in phases: 4778 # draw suspend and re 4779 bname = '%s%d' % (dir 4780 if dir == 'suspend': 4781 m0 = data.sta 4782 mMax = data.t 4783 left = '%f' % 4784 else: 4785 m0 = data.tSu 4786 mMax = data.e 4787 # in an x2 ru 4788 if len(testru 4789 mMax 4790 left = '%f' % 4791 mTotal = mMax - m0 4792 # if a timeline block 4793 if mTotal == 0: 4794 continue 4795 width = '%f' % (((mTo 4796 devtl.html += devtl.h 4797 for b in phases[dir]: 4798 # draw the ph 4799 phase = data. 4800 length = phas 4801 left = '%f' % 4802 width = '%f' 4803 devtl.html += 4804 '%.3f 4805 data. 4806 for e in data.errorin 4807 # draw red li 4808 type, t, idx1 4809 id = '%d_%d' 4810 right = '%f' 4811 devtl.html += 4812 for b in phases[dir]: 4813 # draw the de 4814 phaselist = d 4815 for d in sort 4816 dname 4817 name, 4818 drv = 4819 if 'h 4820 4821 if 'c 4822 4823 if(d 4824 4825 4826 4827 elif 4828 4829 if('d 4830 4831 rowhe 4832 rowto 4833 top = 4834 left 4835 width 4836 lengt 4837 title 4838 if sy 4839 4840 elif 4841 4842 4843 4844 4845 else: 4846 4847 devtl 4848 4849 4850 if('c 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 if('s 4861 4862 # dra 4863 for e 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 # draw the time scale 4877 devtl.createTimeScale 4878 devtl.html += '</div> 4879 4880 # timeline is finished 4881 devtl.html += '</div>\n</div>\n' 4882 4883 # draw a legend which describes the p 4884 if sysvals.suspendmode != 'command': 4885 phasedef = testruns[-1].phase 4886 devtl.html += '<div class="le 4887 pdelta = 100.0/len(phasedef.k 4888 pmargin = pdelta / 4.0 4889 for phase in sorted(phasedef, 4890 id, p = '', phasedef[ 4891 for word in phase.spl 4892 id += word[0] 4893 order = '%.2f' % ((p[ 4894 name = phase.replace( 4895 devtl.html += devtl.h 4896 devtl.html += '</div>\n' 4897 4898 hf = open(sysvals.htmlfile, 'w') 4899 addCSS(hf, sysvals, len(testruns), ke 4900 4901 # write the device timeline 4902 hf.write(devtl.html) 4903 hf.write('<div id="devicedetailtitle" 4904 hf.write('<div id="devicedetail" styl 4905 # draw the colored boxes for the devi 4906 for data in testruns: 4907 hf.write('<div id="devicedeta 4908 pscolor = 'linear-gradient(to 4909 hf.write(devtl.html_phaselet. 4910 '0', '0', pscolor)) 4911 for b in data.sortedPhases(): 4912 phase = data.dmesg[b] 4913 length = phase['end'] 4914 left = '%.3f' % (((ph 4915 width = '%.3f' % ((le 4916 hf.write(devtl.html_p 4917 data.dmesg[b] 4918 hf.write(devtl.html_phaselet. 4919 '0', '0', pscolor)) 4920 if sysvals.suspendmode == 'co 4921 hf.write(devtl.html_p 4922 hf.write('</div>\n') 4923 hf.write('</div>\n') 4924 4925 # write the ftrace data (callgraph) 4926 if sysvals.cgtest >= 0 and len(testru 4927 data = testruns[sysvals.cgtes 4928 else: 4929 data = testruns[-1] 4930 if sysvals.usecallgraph: 4931 addCallgraphs(sysvals, hf, da 4932 4933 # add the test log as a hidden div 4934 if sysvals.testlog and sysvals.logmsg 4935 hf.write('<div id="testlog" s 4936 # add the dmesg log as a hidden div 4937 if sysvals.dmesglog and sysvals.dmesg 4938 hf.write('<div id="dmesglog" 4939 lf = sysvals.openlog(sysvals. 4940 for line in lf: 4941 line = line.replace(' 4942 hf.write(line) 4943 lf.close() 4944 hf.write('</div>\n') 4945 # add the ftrace log as a hidden div 4946 if sysvals.ftracelog and sysvals.ftra 4947 hf.write('<div id="ftracelog" 4948 lf = sysvals.openlog(sysvals. 4949 for line in lf: 4950 hf.write(line) 4951 lf.close() 4952 hf.write('</div>\n') 4953 4954 # write the footer and close 4955 addScriptCode(hf, testruns) 4956 hf.write('</body>\n</html>\n') 4957 hf.close() 4958 return True 4959 4960 def addCSS(hf, sv, testcount=1, kerror=False, 4961 kernel = sv.stamp['kernel'] 4962 host = sv.hostname[0].upper()+sv.host 4963 mode = sv.suspendmode 4964 if sv.suspendmode in suspendmodename: 4965 mode = suspendmodename[sv.sus 4966 title = host+' '+mode+' '+kernel 4967 4968 # various format changes by flags 4969 cgchk = 'checked' 4970 cgnchk = 'not(:checked)' 4971 if sv.cgexp: 4972 cgchk = 'not(:checked)' 4973 cgnchk = 'checked' 4974 4975 hoverZ = 'z-index:8;' 4976 if sv.usedevsrc: 4977 hoverZ = '' 4978 4979 devlistpos = 'absolute' 4980 if testcount > 1: 4981 devlistpos = 'relative' 4982 4983 scaleTH = 20 4984 if kerror: 4985 scaleTH = 60 4986 4987 # write the html header first (html h 4988 html_header = '<!DOCTYPE html>\n<html 4989 <meta http-equiv="content-type" conte 4990 <title>'+title+'</title>\n\ 4991 <style type=\'text/css\'>\n\ 4992 body {overflow-y:scroll;}\n\ 4993 .stamp {width:100%;text-align 4994 .stamp.sysinfo {font:10px Ari 4995 .callgraph {margin-top:30px;b 4996 .callgraph article * {padding 4997 h1 {color:black;font:bold 30p 4998 t0 {color:black;font:bold 30p 4999 t1 {color:black;font:30px Tim 5000 t2 {color:black;font:25px Tim 5001 t3 {color:black;font:20px Tim 5002 t4 {color:black;font:bold 30p 5003 cS {font:bold 13px Times;}\n\ 5004 table {width:100%;}\n\ 5005 .gray {background:rgba(80,80, 5006 .green {background:rgba(204,2 5007 .purple {background:rgba(128, 5008 .yellow {background:rgba(255, 5009 .blue {background:rgba(169,20 5010 .time1 {font:22px Arial;borde 5011 .time2 {font:15px Arial;borde 5012 .testfail {font:bold 22px Ari 5013 td {text-align:center;}\n\ 5014 r {color:#500000;font:15px Ta 5015 n {color:#505050;font:15px Ta 5016 .tdhl {color:red;}\n\ 5017 .hide {display:none;}\n\ 5018 .pf {display:none;}\n\ 5019 .pf:'+cgchk+' + label {backgr 5020 .pf:'+cgnchk+' ~ label {backg 5021 .pf:'+cgchk+' ~ *:not(:nth-ch 5022 .zoombox {position:relative;w 5023 .timeline {position:relative; 5024 .thread {position:absolute;he 5025 .thread.ps {border-radius:3px 5026 .thread:hover {background:whi 5027 .thread.sec,.thread.sec:hover 5028 .hover {background:white;bord 5029 .hover.sync {background:white 5030 .hover.bg,.hover.kth,.hover.s 5031 .jiffie {position:absolute;po 5032 .traceevent {position:absolut 5033 .traceevent:hover {color:whit 5034 .phase {position:absolute;ove 5035 .phaselet {float:left;overflo 5036 .t {position:absolute;line-he 5037 .err {position:absolute;top:0 5038 .legend {position:relative; w 5039 .legend .square {position:abs 5040 button {height:40px;width:200 5041 .btnfmt {position:relative;fl 5042 .devlist {position:'+devlistp 5043 a:link {color:white;text-deco 5044 a:visited {color:white;}\n\ 5045 a:hover {color:white;}\n\ 5046 a:active {color:white;}\n\ 5047 .version {position:relative;f 5048 #devicedetail {min-height:100 5049 .tblock {position:absolute;he 5050 .tback {position:absolute;wid 5051 .bg {z-index:1;}\n\ 5052 '+extra+'\ 5053 </style>\n</head>\n<body>\n' 5054 hf.write(html_header) 5055 5056 # Function: addScriptCode 5057 # Description: 5058 # Adds the javascript code to the outp 5059 # Arguments: 5060 # hf: the open html file pointer 5061 # testruns: array of Data objects from 5062 def addScriptCode(hf, testruns): 5063 t0 = testruns[0].start * 1000 5064 tMax = testruns[-1].end * 1000 5065 hf.write('<script type="text/javascri 5066 # create an array in javascript memor 5067 detail = ' var devtable = [];\n' 5068 for data in testruns: 5069 topo = data.deviceTopology() 5070 detail += ' devtable[%d] 5071 detail += ' var bounds = [%f,%f]; 5072 # add the code which will manipulate 5073 hf.write(detail); 5074 script_code = r""" var resolutio 5075 var dragval = [0, 0]; 5076 function redrawTimescale(t0, tMax, tS 5077 var rline = '<div class="t" s 5078 var tTotal = tMax - t0; 5079 var list = document.getElemen 5080 for (var i = 0; i < list.leng 5081 var timescale = list[ 5082 var m0 = t0 + (tTotal 5083 var mTotal = tTotal*p 5084 var mMax = m0 + mTota 5085 var html = ""; 5086 var divTotal = Math.f 5087 if(divTotal > 1000) c 5088 var divEdge = (mTotal 5089 var pos = 0.0, val = 5090 for (var j = 0; j < d 5091 var htmlline 5092 var mode = li 5093 if(mode == "s 5094 pos = 5095 val = 5096 if(j 5097 5098 else 5099 5100 } else { 5101 pos = 5102 val = 5103 htmll 5104 if(j 5105 5106 5107 5108 5109 } 5110 html += htmll 5111 } 5112 timescale.innerHTML = 5113 } 5114 } 5115 function zoomTimeline() { 5116 var dmesg = document.getEleme 5117 var zoombox = document.getEle 5118 var left = zoombox.scrollLeft 5119 var val = parseFloat(dmesg.st 5120 var newval = 100; 5121 var sh = window.outerWidth / 5122 if(this.id == "zoomin") { 5123 newval = val * 1.2; 5124 if(newval > 910034) n 5125 dmesg.style.width = n 5126 zoombox.scrollLeft = 5127 } else if (this.id == "zoomou 5128 newval = val / 1.2; 5129 if(newval < 100) newv 5130 dmesg.style.width = n 5131 zoombox.scrollLeft = 5132 } else { 5133 zoombox.scrollLeft = 5134 dmesg.style.width = " 5135 } 5136 var tS = [10000, 5000, 2000, 5137 var t0 = bounds[0]; 5138 var tMax = bounds[1]; 5139 var tTotal = tMax - t0; 5140 var wTotal = tTotal * 100.0 / 5141 var idx = 7*window.innerWidth 5142 for(var i = 0; (i < tS.length 5143 if(i >= tS.length) i = tS.len 5144 if(tS[i] == resolution) retur 5145 resolution = tS[i]; 5146 redrawTimescale(t0, tMax, tS[ 5147 } 5148 function deviceName(title) { 5149 var name = title.slice(0, tit 5150 return name; 5151 } 5152 function deviceHover() { 5153 var name = deviceName(this.ti 5154 var dmesg = document.getEleme 5155 var dev = dmesg.getElementsBy 5156 var cpu = -1; 5157 if(name.match("CPU_ON\[[0-9]* 5158 cpu = parseInt(name.s 5159 else if(name.match("CPU_OFF\[ 5160 cpu = parseInt(name.s 5161 for (var i = 0; i < dev.lengt 5162 dname = deviceName(de 5163 var cname = dev[i].cl 5164 if((cpu >= 0 && dname 5165 (name == dnam 5166 { 5167 dev[i].classN 5168 } else { 5169 dev[i].classN 5170 } 5171 } 5172 } 5173 function deviceUnhover() { 5174 var dmesg = document.getEleme 5175 var dev = dmesg.getElementsBy 5176 for (var i = 0; i < dev.lengt 5177 dev[i].className = de 5178 } 5179 } 5180 function deviceTitle(title, total, cp 5181 var prefix = "Total"; 5182 if(total.length > 3) { 5183 prefix = "Average"; 5184 total[1] = (total[1]+ 5185 total[2] = (total[2]+ 5186 } 5187 var devtitle = document.getEl 5188 var name = deviceName(title); 5189 if(cpu >= 0) name = "CPU"+cpu 5190 var driver = ""; 5191 var tS = "<t2>(</t2>"; 5192 var tR = "<t2>)</t2>"; 5193 if(total[1] > 0) 5194 tS = "<t2>("+prefix+" 5195 if(total[2] > 0) 5196 tR = " <t2>"+prefix+" 5197 var s = title.indexOf("{"); 5198 var e = title.indexOf("}"); 5199 if((s >= 0) && (e >= 0)) 5200 driver = title.slice(< 5201 if(total[1] > 0 && total[2] > 5202 devtitle.innerHTML = 5203 else 5204 devtitle.innerHTML = 5205 return name; 5206 } 5207 function deviceDetail() { 5208 var devinfo = document.getEle 5209 devinfo.style.display = "bloc 5210 var name = deviceName(this.ti 5211 var cpu = -1; 5212 if(name.match("CPU_ON\[[0-9]* 5213 cpu = parseInt(name.s 5214 else if(name.match("CPU_OFF\[ 5215 cpu = parseInt(name.s 5216 var dmesg = document.getEleme 5217 var dev = dmesg.getElementsBy 5218 var idlist = []; 5219 var pdata = [[]]; 5220 if(document.getElementById("d 5221 pdata = [[], []]; 5222 var pd = pdata[0]; 5223 var total = [0.0, 0.0, 0.0]; 5224 for (var i = 0; i < dev.lengt 5225 dname = deviceName(de 5226 if((cpu >= 0 && dname 5227 (name == dnam 5228 { 5229 idlist[idlist 5230 var tidx = 1; 5231 if(dev[i].id[ 5232 pd = 5233 } else { 5234 if(pd 5235 if(to 5236 pd = 5237 tidx 5238 } 5239 var info = de 5240 var pname = i 5241 pd[pname] = p 5242 total[0] += p 5243 if(pname.inde 5244 total 5245 else 5246 total 5247 } 5248 } 5249 var devname = deviceTitle(thi 5250 var left = 0.0; 5251 for (var t = 0; t < pdata.len 5252 pd = pdata[t]; 5253 devinfo = document.ge 5254 var phases = devinfo. 5255 for (var i = 0; i < p 5256 if(phases[i]. 5257 var w 5258 var f 5259 if(w 5260 var f 5261 phase 5262 phase 5263 phase 5264 left 5265 var t 5266 var p 5267 phase 5268 } else { 5269 phase 5270 phase 5271 } 5272 } 5273 } 5274 if(typeof devstats !== 'undef 5275 callDetail(this.id, t 5276 var cglist = document.getElem 5277 if(!cglist) return; 5278 var cg = cglist.getElementsBy 5279 if(cg.length < 10) return; 5280 for (var i = 0; i < cg.length 5281 cgid = cg[i].id.split 5282 if(idlist.indexOf(cgi 5283 cg[i].style.d 5284 } else { 5285 cg[i].style.d 5286 } 5287 } 5288 } 5289 function callDetail(devid, devtitle) 5290 if(!(devid in devstats) || de 5291 return; 5292 var list = devstats[devid]; 5293 var tmp = devtitle.split(" ") 5294 var name = tmp[0], phase = tm 5295 var dd = document.getElementB 5296 var total = parseFloat(tmp[1] 5297 var mlist = []; 5298 var maxlen = 0; 5299 var info = [] 5300 for(var i in list) { 5301 if(list[i][0] == "@") 5302 info = list[i 5303 continue; 5304 } 5305 var tmp = list[i].spl 5306 var t = parseFloat(tm 5307 var p = (t*100.0/tota 5308 mlist[mlist.length] = 5309 if(f.length > maxlen) 5310 maxlen = f.le 5311 } 5312 var pad = 5; 5313 if(mlist.length == 0) pad = 3 5314 var html = '<div style="paddi 5315 if(info.length > 2) 5316 html += " start=<b>"+ 5317 if(info.length > 3) 5318 html += ", length<i>( 5319 if(info.length > 4) 5320 html += ", return=<b> 5321 html += "</t3></div>"; 5322 if(mlist.length > 0) { 5323 html += '<table class 5324 for(var i in mlist) 5325 html += "<td 5326 html += "</tr><tr><th 5327 for(var i in mlist) 5328 html += "<td> 5329 html += "</tr><tr><th 5330 for(var i in mlist) 5331 html += "<td> 5332 html += "</tr><tr><th 5333 for(var i in mlist) 5334 html += "<td> 5335 html += "</tr></table 5336 } 5337 dd.innerHTML = html; 5338 var height = (maxlen*5)+100; 5339 dd.style.height = height+"px" 5340 document.getElementById("devi 5341 } 5342 function callSelect() { 5343 var cglist = document.getElem 5344 if(!cglist) return; 5345 var cg = cglist.getElementsBy 5346 for (var i = 0; i < cg.length 5347 if(this.id == cg[i].i 5348 cg[i].style.d 5349 } else { 5350 cg[i].style.d 5351 } 5352 } 5353 } 5354 function devListWindow(e) { 5355 var win = window.open(); 5356 var html = "<title>"+e.target 5357 "<style type=\"text/c 5358 " ul {list-style-ty 5359 "</style>" 5360 var dt = devtable[0]; 5361 if(e.target.id != "devlist1") 5362 dt = devtable[1]; 5363 win.document.write(html+dt); 5364 } 5365 function errWindow() { 5366 var range = this.id.split("_" 5367 var idx1 = parseInt(range[0]) 5368 var idx2 = parseInt(range[1]) 5369 var win = window.open(); 5370 var log = document.getElement 5371 var title = "<title>dmesg log 5372 var text = log.innerHTML.spli 5373 var html = ""; 5374 for(var i = 0; i < text.lengt 5375 if(i == idx1) { 5376 html += "<e i 5377 } else if(i > idx1 && 5378 html += "<e>" 5379 } else { 5380 html += text[ 5381 } 5382 } 5383 win.document.write("<style>e{ 5384 win.location.hash = "#target" 5385 win.document.close(); 5386 } 5387 function logWindow(e) { 5388 var name = e.target.id.slice( 5389 var win = window.open(); 5390 var log = document.getElement 5391 var title = "<title>"+documen 5392 win.document.write(title+"<pr 5393 win.document.close(); 5394 } 5395 function onMouseDown(e) { 5396 dragval[0] = e.clientX; 5397 dragval[1] = document.getElem 5398 document.onmousemove = onMous 5399 } 5400 function onMouseMove(e) { 5401 var zoombox = document.getEle 5402 zoombox.scrollLeft = dragval[ 5403 } 5404 function onMouseUp(e) { 5405 document.onmousemove = null; 5406 } 5407 function onKeyPress(e) { 5408 var c = e.charCode; 5409 if(c != 42 && c != 43 && c != 5410 var click = document.createEv 5411 click.initEvent("click", true 5412 if(c == 43) 5413 document.getElementBy 5414 else if(c == 45) 5415 document.getElementBy 5416 else if(c == 42) 5417 document.getElementBy 5418 } 5419 window.addEventListener("resize", fun 5420 window.addEventListener("load", funct 5421 var dmesg = document.getEleme 5422 dmesg.style.width = "100%" 5423 dmesg.onmousedown = onMouseDo 5424 document.onmouseup = onMouseU 5425 document.onkeypress = onKeyPr 5426 document.getElementById("zoom 5427 document.getElementById("zoom 5428 document.getElementById("zoom 5429 var list = document.getElemen 5430 for (var i = 0; i < list.leng 5431 list[i].onclick = err 5432 var list = document.getElemen 5433 for (var i = 0; i < list.leng 5434 list[i].onclick = log 5435 list = document.getElementsBy 5436 for (var i = 0; i < list.leng 5437 list[i].onclick = dev 5438 var dev = dmesg.getElementsBy 5439 for (var i = 0; i < dev.lengt 5440 dev[i].onclick = devi 5441 dev[i].onmouseover = 5442 dev[i].onmouseout = d 5443 } 5444 var dev = dmesg.getElementsBy 5445 for (var i = 0; i < dev.lengt 5446 dev[i].onclick = call 5447 zoomTimeline(); 5448 }); 5449 </script> """ 5450 hf.write(script_code); 5451 5452 # Function: executeSuspend 5453 # Description: 5454 # Execute system suspend through the s 5455 # dmesg and ftrace files to the test o 5456 def executeSuspend(quiet=False): 5457 sv, tp, pm = sysvals, sysvals.tpath, 5458 if sv.wifi: 5459 wifi = sv.checkWifi() 5460 sv.dlog('wifi check, connecte 5461 testdata = [] 5462 # run these commands to prepare the s 5463 if sv.display: 5464 if not quiet: 5465 pprint('SET DISPLAY T 5466 ret = sv.displayControl(sv.di 5467 sv.dlog('xset display %s, ret 5468 time.sleep(1) 5469 if sv.sync: 5470 if not quiet: 5471 pprint('SYNCING FILES 5472 sv.dlog('syncing filesystems' 5473 call('sync', shell=True) 5474 sv.dlog('read dmesg') 5475 sv.initdmesg() 5476 sv.dlog('cmdinfo before') 5477 sv.cmdinfo(True) 5478 sv.start(pm) 5479 # execute however many s/r runs reque 5480 for count in range(1,sv.execcount+1): 5481 # x2delay in between test run 5482 if(count > 1 and sv.x2delay > 5483 sv.fsetVal('WAIT %d' 5484 time.sleep(sv.x2delay 5485 sv.fsetVal('WAIT END' 5486 # start message 5487 if sv.testcommand != '': 5488 pprint('COMMAND START 5489 else: 5490 if(sv.rtcwake): 5491 pprint('SUSPE 5492 else: 5493 pprint('SUSPE 5494 # set rtcwake 5495 if(sv.rtcwake): 5496 if not quiet: 5497 pprint('will 5498 sv.dlog('enable RTC w 5499 sv.rtcWakeAlarmOn() 5500 # start of suspend trace mark 5501 sv.fsetVal(datetime.now().str 5502 # predelay delay 5503 if(count == 1 and sv.predelay 5504 sv.fsetVal('WAIT %d' 5505 time.sleep(sv.predela 5506 sv.fsetVal('WAIT END' 5507 # initiate suspend or command 5508 sv.dlog('system executing a s 5509 tdata = {'error': ''} 5510 if sv.testcommand != '': 5511 res = call(sv.testcom 5512 if res != 0: 5513 tdata['error' 5514 else: 5515 s0ixready = sv.s0ixSu 5516 mode = sv.suspendmode 5517 if sv.memmode and os. 5518 mode = 'mem' 5519 sv.testVal(sv 5520 if sv.diskmode and os 5521 mode = 'disk' 5522 sv.testVal(sv 5523 if sv.acpidebug: 5524 sv.testVal(sv 5525 if ((mode == 'freeze' 5526 and sv.haveTu 5527 # execution w 5528 retval, turbo 5529 if retval != 5530 tdata 5531 if turbo: 5532 tdata 5533 else: 5534 pf = open(sv. 5535 pf.write(mode 5536 # execution w 5537 try: 5538 pf.fl 5539 pf.cl 5540 except Except 5541 tdata 5542 sv.fsetVal('CMD COMPLETE', 't 5543 sv.dlog('system returned') 5544 # reset everything 5545 sv.testVal('restoreall') 5546 if(sv.rtcwake): 5547 sv.dlog('disable RTC 5548 sv.rtcWakeAlarmOff() 5549 # postdelay delay 5550 if(count == sv.execcount and 5551 sv.fsetVal('WAIT %d' 5552 time.sleep(sv.postdel 5553 sv.fsetVal('WAIT END' 5554 # return from suspend 5555 pprint('RESUME COMPLETE') 5556 if(count < sv.execcount): 5557 sv.fsetVal(datetime.n 5558 elif(not sv.wifitrace): 5559 sv.fsetVal(datetime.n 5560 sv.stop(pm) 5561 if sv.wifi and wifi: 5562 tdata['wifi'] = sv.po 5563 sv.dlog('wifi check, 5564 if(count == sv.execcount and 5565 sv.fsetVal(datetime.n 5566 sv.stop(pm) 5567 if sv.netfix: 5568 tdata['netfix'] = sv. 5569 sv.dlog('netfix, %s' 5570 if(sv.suspendmode == 'mem' or 5571 sv.dlog('read the ACP 5572 tdata['fw'] = getFPDT 5573 testdata.append(tdata) 5574 sv.dlog('cmdinfo after') 5575 cmdafter = sv.cmdinfo(False) 5576 # grab a copy of the dmesg output 5577 if not quiet: 5578 pprint('CAPTURING DMESG') 5579 sv.getdmesg(testdata) 5580 # grab a copy of the ftrace output 5581 if sv.useftrace: 5582 if not quiet: 5583 pprint('CAPTURING TRA 5584 op = sv.writeDatafileHeader(s 5585 fp = open(tp+'trace', 'rb') 5586 op.write(ascii(fp.read())) 5587 op.close() 5588 sv.fsetVal('', 'trace') 5589 sv.platforminfo(cmdafter) 5590 5591 def readFile(file): 5592 if os.path.islink(file): 5593 return os.readlink(file).spli 5594 else: 5595 return sysvals.getVal(file).s 5596 5597 # Function: ms2nice 5598 # Description: 5599 # Print out a very concise time string 5600 # Output: 5601 # The time string, e.g. "1901m16s" 5602 def ms2nice(val): 5603 val = int(val) 5604 h = val // 3600000 5605 m = (val // 60000) % 60 5606 s = (val // 1000) % 60 5607 if h > 0: 5608 return '%d:%02d:%02d' % (h, m 5609 if m > 0: 5610 return '%02d:%02d' % (m, s) 5611 return '%ds' % s 5612 5613 def yesno(val): 5614 list = {'enabled':'A', 'disabled':'S' 5615 'active':'A', 'suspended':'S' 5616 if val not in list: 5617 return ' ' 5618 return list[val] 5619 5620 # Function: deviceInfo 5621 # Description: 5622 # Detect all the USB hosts and devices 5623 # a list of USB device names to sysval 5624 def deviceInfo(output=''): 5625 if not output: 5626 pprint('LEGEND\n'\ 5627 '---------------------------- 5628 ' A = async/sync PM queue (A 5629 ' R = runtime suspend enable 5630 ' S = runtime status active/ 5631 ' U = runtime usage count\n' 5632 '---------------------------- 5633 'DEVICE N 5634 '---------------------------- 5635 5636 res = [] 5637 tgtval = 'runtime_status' 5638 lines = dict() 5639 for dirname, dirnames, filenames in o 5640 if(not re.match(r'.*/power', 5641 'control' not in file 5642 tgtval not in filenam 5643 continue 5644 name = '' 5645 dirname = dirname[:-6] 5646 device = dirname.split('/')[- 5647 power = dict() 5648 power[tgtval] = readFile('%s/ 5649 # only list devices which sup 5650 if power[tgtval] not in ['act 5651 continue 5652 for i in ['product', 'driver' 5653 file = '%s/%s' % (dir 5654 if os.path.exists(fil 5655 name = readFi 5656 break 5657 for i in ['async', 'control', 5658 'runtime_active_kids' 5659 'runtime_suspended_ti 5660 if i in filenames: 5661 power[i] = re 5662 if output: 5663 if power['control'] = 5664 res.append('% 5665 continue 5666 lines[dirname] = '%-26s %-26s 5667 (device[:26], name[:2 5668 yesno(power['async']) 5669 yesno(power['control' 5670 yesno(power['runtime_ 5671 power['runtime_usage' 5672 power['runtime_active 5673 ms2nice(power['runtim 5674 ms2nice(power['runtim 5675 for i in sorted(lines): 5676 print(lines[i]) 5677 return res 5678 5679 # Function: getModes 5680 # Description: 5681 # Determine the supported power modes 5682 # Output: 5683 # A string list of the available modes 5684 def getModes(): 5685 modes = [] 5686 if(os.path.exists(sysvals.powerfile)) 5687 fp = open(sysvals.powerfile, 5688 modes = fp.read().split() 5689 fp.close() 5690 if(os.path.exists(sysvals.mempowerfil 5691 deep = False 5692 fp = open(sysvals.mempowerfil 5693 for m in fp.read().split(): 5694 memmode = m.strip('[] 5695 if memmode == 'deep': 5696 deep = True 5697 else: 5698 modes.append( 5699 fp.close() 5700 if 'mem' in modes and not dee 5701 modes.remove('mem') 5702 if('disk' in modes and os.path.exists 5703 fp = open(sysvals.diskpowerfi 5704 for m in fp.read().split(): 5705 modes.append('disk-%s 5706 fp.close() 5707 return modes 5708 5709 def dmidecode_backup(out, fatal=False): 5710 cpath, spath, info = '/proc/cpuinfo', 5711 'bios-vendor': 'bios_vendor', 5712 'bios-version': 'bios_version 5713 'bios-release-date': 'bios_da 5714 'system-manufacturer': 'sys_v 5715 'system-product-name': 'produ 5716 'system-version': 'product_ve 5717 'system-serial-number': 'prod 5718 'baseboard-manufacturer': 'bo 5719 'baseboard-product-name': 'bo 5720 'baseboard-version': 'board_v 5721 'baseboard-serial-number': 'b 5722 'chassis-manufacturer': 'chas 5723 'chassis-version': 'chassis_v 5724 'chassis-serial-number': 'cha 5725 } 5726 for key in info: 5727 if key not in out: 5728 val = sysvals.getVal( 5729 if val and val.lower( 5730 out[key] = va 5731 if 'processor-version' not in out and 5732 with open(cpath, 'r') as fp: 5733 for line in fp: 5734 m = re.match( 5735 if m: 5736 out[' 5737 break 5738 if fatal and len(out) < 1: 5739 doError('dmidecode failed to 5740 (sysvals.mempath, spa 5741 return out 5742 5743 # Function: dmidecode 5744 # Description: 5745 # Read the bios tables and pull out sy 5746 # Arguments: 5747 # mempath: /dev/mem or custom mem path 5748 # fatal: True to exit on error, False 5749 # Output: 5750 # A dict object with all available key 5751 def dmidecode(mempath, fatal=False): 5752 out = dict() 5753 if(not (os.path.exists(mempath) and o 5754 return dmidecode_backup(out, 5755 5756 # the list of values to retrieve, wit 5757 info = { 5758 'bios-vendor': (0, 4), 5759 'bios-version': (0, 5), 5760 'bios-release-date': (0, 8), 5761 'system-manufacturer': (1, 4) 5762 'system-product-name': (1, 5) 5763 'system-version': (1, 6), 5764 'system-serial-number': (1, 7 5765 'baseboard-manufacturer': (2, 5766 'baseboard-product-name': (2, 5767 'baseboard-version': (2, 6), 5768 'baseboard-serial-number': (2 5769 'chassis-manufacturer': (3, 4 5770 'chassis-version': (3, 6), 5771 'chassis-serial-number': (3, 5772 'processor-manufacturer': (4, 5773 'processor-version': (4, 16), 5774 } 5775 5776 # by default use legacy scan, but try 5777 memaddr, memsize = 0xf0000, 0x10000 5778 for ep in ['/sys/firmware/efi/systab' 5779 if not os.path.exists(ep) or 5780 continue 5781 fp = open(ep, 'r') 5782 buf = fp.read() 5783 fp.close() 5784 i = buf.find('SMBIOS=') 5785 if i >= 0: 5786 try: 5787 memaddr = int 5788 memsize = 0x2 5789 except: 5790 continue 5791 5792 # read in the memory for scanning 5793 try: 5794 fp = open(mempath, 'rb') 5795 fp.seek(memaddr) 5796 buf = fp.read(memsize) 5797 except: 5798 return dmidecode_backup(out, 5799 fp.close() 5800 5801 # search for either an SM table or DM 5802 i = base = length = num = 0 5803 while(i < memsize): 5804 if buf[i:i+4] == b'_SM_' and 5805 length = struct.unpac 5806 base, num = struct.un 5807 break 5808 elif buf[i:i+5] == b'_DMI_': 5809 length = struct.unpac 5810 base, num = struct.un 5811 break 5812 i += 16 5813 if base == 0 and length == 0 and num 5814 return dmidecode_backup(out, 5815 5816 # read in the SM or DMI table 5817 try: 5818 fp = open(mempath, 'rb') 5819 fp.seek(base) 5820 buf = fp.read(length) 5821 except: 5822 return dmidecode_backup(out, 5823 fp.close() 5824 5825 # scan the table for the values we wa 5826 count = i = 0 5827 while(count < num and i <= len(buf) - 5828 type, size, handle = struct.u 5829 n = i + size 5830 while n < len(buf) - 1: 5831 if 0 == struct.unpack 5832 break 5833 n += 1 5834 data = buf[i+size:n+2].split( 5835 for name in info: 5836 itype, idxadr = info[ 5837 if itype == type: 5838 idx = struct. 5839 if idx > 0 an 5840 s = d 5841 if s. 5842 5843 i = n + 2 5844 count += 1 5845 return out 5846 5847 # Function: getFPDT 5848 # Description: 5849 # Read the acpi bios tables and pull o 5850 # Arguments: 5851 # output: True to output the info to s 5852 def getFPDT(output): 5853 rectype = {} 5854 rectype[0] = 'Firmware Basic Boot Per 5855 rectype[1] = 'S3 Performance Table Re 5856 prectype = {} 5857 prectype[0] = 'Basic S3 Resume Perfor 5858 prectype[1] = 'Basic S3 Suspend Perfo 5859 5860 sysvals.rootCheck(True) 5861 if(not os.path.exists(sysvals.fpdtpat 5862 if(output): 5863 doError('file does no 5864 return False 5865 if(not os.access(sysvals.fpdtpath, os 5866 if(output): 5867 doError('file is not 5868 return False 5869 if(not os.path.exists(sysvals.mempath 5870 if(output): 5871 doError('file does no 5872 return False 5873 if(not os.access(sysvals.mempath, os. 5874 if(output): 5875 doError('file is not 5876 return False 5877 5878 fp = open(sysvals.fpdtpath, 'rb') 5879 buf = fp.read() 5880 fp.close() 5881 5882 if(len(buf) < 36): 5883 if(output): 5884 doError('Invalid FPDT 5885 'be at least 5886 return False 5887 5888 table = struct.unpack('4sIBB6s8sI4sI' 5889 if(output): 5890 pprint('\n'\ 5891 'Firmware Performance Data Ta 5892 ' Signature 5893 ' Table Length 5894 ' Revision 5895 ' Checksum 5896 ' OEM ID 5897 ' OEM Table ID 5898 ' OEM Revision 5899 ' Creator ID 5900 ' Creator Revision 5901 '' % (ascii(table[0]), ascii( 5902 table[3], ascii(table 5903 ascii(table[7]), tabl 5904 5905 if(table[0] != b'FPDT'): 5906 if(output): 5907 doError('Invalid FPDT 5908 return False 5909 if(len(buf) <= 36): 5910 return False 5911 i = 0 5912 fwData = [0, 0] 5913 records = buf[36:] 5914 try: 5915 fp = open(sysvals.mempath, 'r 5916 except: 5917 pprint('WARNING: /dev/mem is 5918 return False 5919 while(i < len(records)): 5920 header = struct.unpack('HBB', 5921 if(header[0] not in rectype): 5922 i += header[1] 5923 continue 5924 if(header[1] != 16): 5925 i += header[1] 5926 continue 5927 addr = struct.unpack('Q', rec 5928 try: 5929 fp.seek(addr) 5930 first = fp.read(8) 5931 except: 5932 if(output): 5933 pprint('Bad a 5934 return [0, 0] 5935 rechead = struct.unpack('4sI' 5936 recdata = fp.read(rechead[1]- 5937 if(rechead[0] == b'FBPT'): 5938 record = struct.unpac 5939 if(output): 5940 pprint('%s (% 5941 ' 5942 ' OS Loader 5943 ' OS Loader S 5944 ' ExitBoo 5945 ' ExitBo 5946 '' % (rectype 5947 recor 5948 elif(rechead[0] == b'S3PT'): 5949 if(output): 5950 pprint('%s (% 5951 j = 0 5952 while(j < len(recdata 5953 prechead = st 5954 if(prechead[0 5955 conti 5956 if(prechead[0 5957 recor 5958 fwDat 5959 if(ou 5960 5961 5962 5963 5964 5965 5966 elif(prechead 5967 recor 5968 fwDat 5969 if(ou 5970 5971 5972 5973 5974 5975 5976 5977 j += prechead 5978 if(output): 5979 pprint('') 5980 i += header[1] 5981 fp.close() 5982 return fwData 5983 5984 # Function: statusCheck 5985 # Description: 5986 # Verify that the requested command an 5987 # print the results to the terminal 5988 # Output: 5989 # True if the test will work, False if 5990 def statusCheck(probecheck=False): 5991 status = '' 5992 5993 pprint('Checking this system (%s)...' 5994 5995 # check we have root access 5996 res = sysvals.colorText('NO (No featu 5997 if(sysvals.rootCheck(False)): 5998 res = 'YES' 5999 pprint(' have root access: %s' % r 6000 if(res != 'YES'): 6001 pprint(' Try running this 6002 return 'missing root access' 6003 6004 # check sysfs is mounted 6005 res = sysvals.colorText('NO (No featu 6006 if(os.path.exists(sysvals.powerfile)) 6007 res = 'YES' 6008 pprint(' is sysfs mounted: %s' % r 6009 if(res != 'YES'): 6010 return 'sysfs is missing' 6011 6012 # check target mode is a valid mode 6013 if sysvals.suspendmode != 'command': 6014 res = sysvals.colorText('NO') 6015 modes = getModes() 6016 if(sysvals.suspendmode in mod 6017 res = 'YES' 6018 else: 6019 status = '%s mode is 6020 pprint(' is "%s" a valid p 6021 if(res == 'NO'): 6022 pprint(' valid p 6023 pprint(' please 6024 6025 # check if ftrace is available 6026 if sysvals.useftrace: 6027 res = sysvals.colorText('NO') 6028 sysvals.useftrace = sysvals.v 6029 efmt = '"{0}" uses ftrace, an 6030 if sysvals.useftrace: 6031 res = 'YES' 6032 elif sysvals.usecallgraph: 6033 status = efmt.format( 6034 elif sysvals.usedevsrc: 6035 status = efmt.format( 6036 elif sysvals.useprocmon: 6037 status = efmt.format( 6038 pprint(' is ftrace support 6039 6040 # check if kprobes are available 6041 if sysvals.usekprobes: 6042 res = sysvals.colorText('NO') 6043 sysvals.usekprobes = sysvals. 6044 if(sysvals.usekprobes): 6045 res = 'YES' 6046 else: 6047 sysvals.usedevsrc = F 6048 pprint(' are kprobes suppo 6049 6050 # what data source are we using 6051 res = 'DMESG (very limited, ftrace is 6052 if sysvals.useftrace: 6053 sysvals.usetraceevents = True 6054 for e in sysvals.traceevents: 6055 if not os.path.exists 6056 sysvals.usetr 6057 if(sysvals.usetraceevents): 6058 res = 'FTRACE (all tr 6059 pprint(' timeline data source: %s' 6060 6061 # check if rtcwake 6062 res = sysvals.colorText('NO') 6063 if(sysvals.rtcpath != ''): 6064 res = 'YES' 6065 elif(sysvals.rtcwake): 6066 status = 'rtcwake is not prop 6067 pprint(' is rtcwake supported: %s' 6068 6069 # check info commands 6070 pprint(' optional commands this to 6071 no = sysvals.colorText('MISSING') 6072 yes = sysvals.colorText('FOUND', 32) 6073 for c in ['turbostat', 'mcelog', 'lsp 6074 if c == 'turbostat': 6075 res = yes if sysvals. 6076 else: 6077 res = yes if sysvals. 6078 pprint(' %s: %s' % (c, 6079 6080 if not probecheck: 6081 return status 6082 6083 # verify kprobes 6084 if sysvals.usekprobes: 6085 for name in sysvals.tracefunc 6086 sysvals.defaultKprobe 6087 if sysvals.usedevsrc: 6088 for name in sysvals.d 6089 sysvals.defau 6090 sysvals.addKprobes(True) 6091 6092 return status 6093 6094 # Function: doError 6095 # Description: 6096 # generic error function for catastrph 6097 # Arguments: 6098 # msg: the error message to print 6099 # help: True if printHelp should be ca 6100 def doError(msg, help=False): 6101 if(help == True): 6102 printHelp() 6103 pprint('ERROR: %s\n' % msg) 6104 sysvals.outputResult({'error':msg}) 6105 sys.exit(1) 6106 6107 # Function: getArgInt 6108 # Description: 6109 # pull out an integer argument from th 6110 def getArgInt(name, args, min, max, main=True 6111 if main: 6112 try: 6113 arg = next(args) 6114 except: 6115 doError(name+': no ar 6116 else: 6117 arg = args 6118 try: 6119 val = int(arg) 6120 except: 6121 doError(name+': non-integer v 6122 if(val < min or val > max): 6123 doError(name+': value should 6124 return val 6125 6126 # Function: getArgFloat 6127 # Description: 6128 # pull out a float argument from the c 6129 def getArgFloat(name, args, min, max, main=Tr 6130 if main: 6131 try: 6132 arg = next(args) 6133 except: 6134 doError(name+': no ar 6135 else: 6136 arg = args 6137 try: 6138 val = float(arg) 6139 except: 6140 doError(name+': non-numerical 6141 if(val < min or val > max): 6142 doError(name+': value should 6143 return val 6144 6145 def processData(live=False, quiet=False): 6146 if not quiet: 6147 pprint('PROCESSING: %s' % sys 6148 sysvals.vprint('usetraceevents=%s, us 6149 (sysvals.usetraceevents, sysv 6150 error = '' 6151 if(sysvals.usetraceevents): 6152 testruns, error = parseTraceL 6153 if sysvals.dmesgfile: 6154 for data in testruns: 6155 data.extractE 6156 else: 6157 testruns = loadKernelLog() 6158 for data in testruns: 6159 parseKernelLog(data) 6160 if(sysvals.ftracefile and (sy 6161 appendIncompleteTrace 6162 if not sysvals.stamp: 6163 pprint('ERROR: data does not 6164 return (testruns, {'error': ' 6165 shown = ['os', 'bios', 'biosdate', 'c 6166 'memsz', 'mode', 'num 6167 sysvals.vprint('System Info:') 6168 for key in sorted(sysvals.stamp): 6169 if key in shown: 6170 sysvals.vprint(' % 6171 sysvals.vprint('Command:\n %s' % s 6172 for data in testruns: 6173 if data.turbostat: 6174 idx, s = 0, 'Turbosta 6175 for val in data.turbo 6176 idx += len(va 6177 if idx >= 80: 6178 idx = 6179 s += 6180 s += val + ' 6181 sysvals.vprint(s) 6182 data.printDetails() 6183 if len(sysvals.platinfo) > 0: 6184 sysvals.vprint('\nPlatform In 6185 for info in sysvals.platinfo: 6186 sysvals.vprint('[%s - 6187 sysvals.vprint(info[2 6188 sysvals.vprint('') 6189 if sysvals.cgdump: 6190 for data in testruns: 6191 data.debugPrint() 6192 sys.exit(0) 6193 if len(testruns) < 1: 6194 pprint('ERROR: Not enough tes 6195 return (testruns, {'error': ' 6196 sysvals.vprint('Creating the html tim 6197 createHTML(testruns, error) 6198 if not quiet: 6199 pprint('DONE: %s' % sys 6200 data = testruns[0] 6201 stamp = data.stamp 6202 stamp['suspend'], stamp['resume'] = d 6203 if data.fwValid: 6204 stamp['fwsuspend'], stamp['fw 6205 if error: 6206 stamp['error'] = error 6207 return (testruns, stamp) 6208 6209 # Function: rerunTest 6210 # Description: 6211 # generate an output from an existing 6212 def rerunTest(htmlfile=''): 6213 if sysvals.ftracefile: 6214 doesTraceLogHaveTraceEvents() 6215 if not sysvals.dmesgfile and not sysv 6216 doError('recreating this html 6217 if htmlfile: 6218 sysvals.htmlfile = htmlfile 6219 else: 6220 sysvals.setOutputFile() 6221 if os.path.exists(sysvals.htmlfile): 6222 if not os.path.isfile(sysvals 6223 doError('a directory 6224 elif not os.access(sysvals.ht 6225 doError('missing perm 6226 testruns, stamp = processData() 6227 sysvals.resetlog() 6228 return stamp 6229 6230 # Function: runTest 6231 # Description: 6232 # execute a suspend/resume, gather the 6233 def runTest(n=0, quiet=False): 6234 # prepare for the test 6235 sysvals.initTestOutput('suspend') 6236 op = sysvals.writeDatafileHeader(sysv 6237 op.write('# EXECUTION TRACE START\n') 6238 op.close() 6239 if n <= 1: 6240 if sysvals.rs != 0: 6241 sysvals.dlog('%sablin 6242 sysvals.setRuntimeSus 6243 if sysvals.display: 6244 ret = sysvals.display 6245 sysvals.dlog('xset di 6246 sysvals.testVal(sysvals.pmdpath, 'bas 6247 sysvals.testVal(sysvals.s0ixpath, 'ba 6248 sysvals.dlog('initialize ftrace') 6249 sysvals.initFtrace(quiet) 6250 6251 # execute the test 6252 executeSuspend(quiet) 6253 sysvals.cleanupFtrace() 6254 if sysvals.skiphtml: 6255 sysvals.outputResult({}, n) 6256 sysvals.sudoUserchown(sysvals 6257 return 6258 testruns, stamp = processData(True, q 6259 for data in testruns: 6260 del data 6261 sysvals.sudoUserchown(sysvals.testdir 6262 sysvals.outputResult(stamp, n) 6263 if 'error' in stamp: 6264 return 2 6265 return 0 6266 6267 def find_in_html(html, start, end, firstonly= 6268 cnt, out, list = len(html), [], [] 6269 if firstonly: 6270 m = re.search(start, html) 6271 if m: 6272 list.append(m) 6273 else: 6274 list = re.finditer(start, htm 6275 for match in list: 6276 s = match.end() 6277 e = cnt if (len(out) < 1 or s 6278 m = re.search(end, html[s:e]) 6279 if not m: 6280 break 6281 e = s + m.start() 6282 str = html[s:e] 6283 if end == 'ms': 6284 num = re.search(r'[-+ 6285 str = num.group() if 6286 if firstonly: 6287 return str 6288 out.append(str) 6289 if firstonly: 6290 return '' 6291 return out 6292 6293 def data_from_html(file, outpath, issues, ful 6294 try: 6295 html = open(file, 'r').read() 6296 except: 6297 html = ascii(open(file, 'rb') 6298 sysvals.htmlfile = os.path.relpath(fi 6299 # extract general info 6300 suspend = find_in_html(html, 'Kernel 6301 resume = find_in_html(html, 'Kernel R 6302 sysinfo = find_in_html(html, '<div cl 6303 line = find_in_html(html, '<div class 6304 stmp = line.split() 6305 if not suspend or not resume or len(s 6306 return False 6307 try: 6308 dt = datetime.strptime(' '.jo 6309 except: 6310 return False 6311 sysvals.hostname = stmp[0] 6312 tstr = dt.strftime('%Y/%m/%d %H:%M:%S 6313 error = find_in_html(html, '<table cl 6314 if error: 6315 m = re.match(r'[a-z0-9]* fail 6316 if m: 6317 result = 'fail in %s' 6318 else: 6319 result = 'fail' 6320 else: 6321 result = 'pass' 6322 # extract error info 6323 tp, ilist = False, [] 6324 extra = dict() 6325 log = find_in_html(html, '<div id="dm 6326 '</div>').strip() 6327 if log: 6328 d = Data(0) 6329 d.end = 999999999 6330 d.dmesgtext = log.split('\n') 6331 tp = d.extractErrorInfo() 6332 if len(issues) < 100: 6333 for msg in tp.msglist 6334 sysvals.error 6335 if stmp[2] == 'freeze': 6336 extra = d.turbostatIn 6337 elist = dict() 6338 for dir in d.errorinfo: 6339 for err in d.errorinf 6340 if err[0] not 6341 elist 6342 elist[err[0]] 6343 for i in elist: 6344 ilist.append('%sx%d' 6345 line = find_in_html(log, '# w 6346 if line: 6347 extra['wifi'] = line 6348 line = find_in_html(log, '# n 6349 if line: 6350 extra['netfix'] = lin 6351 line = find_in_html(log, '# c 6352 if line: 6353 m = re.match(r'.* -m 6354 if m: 6355 extra['fullmo 6356 low = find_in_html(html, 'freeze time 6357 for lowstr in ['waking', '+']: 6358 if not low: 6359 break 6360 if lowstr not in low: 6361 continue 6362 if lowstr == '+': 6363 issue = 'S2LOOPx%d' % 6364 else: 6365 m = re.match(r'.*waki 6366 issue = 'S2WAKEx%s' % 6367 match = [i for i in issues if 6368 if len(match) > 0: 6369 match[0]['count'] += 6370 if sysvals.hostname n 6371 match[0]['url 6372 elif sysvals.htmlfile 6373 match[0]['url 6374 else: 6375 issues.append({ 6376 'match': issu 6377 'urls': {sysv 6378 }) 6379 ilist.append(issue) 6380 # extract device info 6381 devices = dict() 6382 for line in html.split('\n'): 6383 m = re.match(r' *<div id=\"[a 6384 if not m or 'thread kth' in l 6385 continue 6386 m = re.match(r'(?P<n>.*) \((? 6387 if not m: 6388 continue 6389 name, time, phase = m.group(' 6390 if name == 'async_synchronize 6391 continue 6392 if ' async' in name or ' sync 6393 name = ' '.join(name. 6394 if phase.startswith('suspend' 6395 d = 'suspend' 6396 elif phase.startswith('resume 6397 d = 'resume' 6398 else: 6399 continue 6400 if d not in devices: 6401 devices[d] = dict() 6402 if name not in devices[d]: 6403 devices[d][name] = 0. 6404 devices[d][name] += float(tim 6405 # create worst device info 6406 worst = dict() 6407 for d in ['suspend', 'resume']: 6408 worst[d] = {'name':'', 'time' 6409 dev = devices[d] if d in devi 6410 if dev and len(dev.keys()) > 6411 n = sorted(dev, key=l 6412 worst[d]['name'], wor 6413 data = { 6414 'mode': stmp[2], 6415 'host': stmp[0], 6416 'kernel': stmp[1], 6417 'sysinfo': sysinfo, 6418 'time': tstr, 6419 'result': result, 6420 'issues': ' '.join(ilist), 6421 'suspend': suspend, 6422 'resume': resume, 6423 'devlist': devices, 6424 'sus_worst': worst['suspend'] 6425 'sus_worsttime': worst['suspe 6426 'res_worst': worst['resume'][ 6427 'res_worsttime': worst['resum 6428 'url': sysvals.htmlfile, 6429 } 6430 for key in extra: 6431 data[key] = extra[key] 6432 if fulldetail: 6433 data['funclist'] = find_in_ht 6434 if tp: 6435 for arg in ['-multi ', '-info 6436 if arg in tp.cmdline: 6437 data['target' 6438 break 6439 return data 6440 6441 def genHtml(subdir, force=False): 6442 for dirname, dirnames, filenames in o 6443 sysvals.dmesgfile = sysvals.f 6444 for filename in filenames: 6445 file = os.path.join(d 6446 if sysvals.usable(fil 6447 if(re.match(r 6448 sysva 6449 elif(re.match 6450 sysva 6451 sysvals.setOutputFile() 6452 if (sysvals.dmesgfile or sysv 6453 (force or not sysvals 6454 pprint('FTRACE: %s' % 6455 if sysvals.dmesgfile: 6456 pprint('DMESG 6457 rerunTest() 6458 6459 # Function: runSummary 6460 # Description: 6461 # create a summary of tests in a sub-d 6462 def runSummary(subdir, local=True, genhtml=Fa 6463 inpath = os.path.abspath(subdir) 6464 outpath = os.path.abspath('.') if loc 6465 pprint('Generating a summary of folde 6466 if genhtml: 6467 genHtml(subdir) 6468 target, issues, testruns = '', [], [] 6469 desc = {'host':[],'mode':[],'kernel': 6470 for dirname, dirnames, filenames in o 6471 for filename in filenames: 6472 if(not re.match(r'.*. 6473 continue 6474 data = data_from_html 6475 if(not data): 6476 continue 6477 if 'target' in data: 6478 target = data 6479 testruns.append(data) 6480 for key in desc: 6481 if data[key] 6482 desc[ 6483 pprint('Summary files:') 6484 if len(desc['host']) == len(desc['mod 6485 title = '%s %s %s' % (desc['h 6486 if target: 6487 title += ' %s' % targ 6488 else: 6489 title = inpath 6490 createHTMLSummarySimple(testruns, os. 6491 pprint(' summary.html - tab 6492 createHTMLDeviceSummary(testruns, os. 6493 pprint(' summary-devices.html - ker 6494 createHTMLIssuesSummary(testruns, iss 6495 pprint(' summary-issues.html - ker 6496 6497 # Function: checkArgBool 6498 # Description: 6499 # check if a boolean string value is t 6500 def checkArgBool(name, value): 6501 if value in switchvalues: 6502 if value in switchoff: 6503 return False 6504 return True 6505 doError('invalid boolean --> (%s: %s) 6506 return False 6507 6508 # Function: configFromFile 6509 # Description: 6510 # Configure the script via the info in 6511 def configFromFile(file): 6512 Config = configparser.ConfigParser() 6513 6514 Config.read(file) 6515 sections = Config.sections() 6516 overridekprobes = False 6517 overridedevkprobes = False 6518 if 'Settings' in sections: 6519 for opt in Config.options('Se 6520 value = Config.get('S 6521 option = opt.lower() 6522 if(option == 'verbose 6523 sysvals.verbo 6524 elif(option == 'addlo 6525 sysvals.dmesg 6526 elif(option == 'dev') 6527 sysvals.usede 6528 elif(option == 'proc' 6529 sysvals.usepr 6530 elif(option == 'x2'): 6531 if checkArgBo 6532 sysva 6533 elif(option == 'callg 6534 sysvals.useca 6535 elif(option == 'overr 6536 overridekprob 6537 elif(option == 'overr 6538 overridedevkp 6539 elif(option == 'skiph 6540 sysvals.skiph 6541 elif(option == 'sync' 6542 sysvals.sync 6543 elif(option == 'rs' o 6544 if value in s 6545 if va 6546 6547 else: 6548 6549 else: 6550 doErr 6551 elif(option == 'displ 6552 disopt = ['on 6553 if value not 6554 doErr 6555 sysvals.displ 6556 elif(option == 'gzip' 6557 sysvals.gzip 6558 elif(option == 'cgfil 6559 sysvals.setCa 6560 elif(option == 'cgski 6561 if value in s 6562 sysva 6563 else: 6564 sysva 6565 if(no 6566 6567 elif(option == 'cgtes 6568 sysvals.cgtes 6569 elif(option == 'cgpha 6570 d = Data(0) 6571 if value not 6572 doErr 6573 6574 sysvals.cgpha 6575 elif(option == 'fadd' 6576 file = sysval 6577 if(not file): 6578 doErr 6579 sysvals.addFt 6580 elif(option == 'resul 6581 sysvals.resul 6582 elif(option == 'multi 6583 nums = value. 6584 if len(nums) 6585 doErr 6586 sysvals.multi 6587 elif(option == 'devic 6588 sysvals.setDe 6589 elif(option == 'expan 6590 sysvals.cgexp 6591 elif(option == 'srgap 6592 if checkArgBo 6593 sysva 6594 elif(option == 'mode' 6595 sysvals.suspe 6596 elif(option == 'comma 6597 sysvals.testc 6598 elif(option == 'x2del 6599 sysvals.x2del 6600 elif(option == 'prede 6601 sysvals.prede 6602 elif(option == 'postd 6603 sysvals.postd 6604 elif(option == 'maxde 6605 sysvals.max_g 6606 elif(option == 'rtcwa 6607 if value in s 6608 sysva 6609 else: 6610 sysva 6611 sysva 6612 elif(option == 'timep 6613 sysvals.setPr 6614 elif(option == 'minde 6615 sysvals.minde 6616 elif(option == 'calll 6617 sysvals.calll 6618 elif(option == 'calll 6619 sysvals.calll 6620 elif(option == 'mincg 6621 sysvals.mincg 6622 elif(option == 'bufsi 6623 sysvals.bufsi 6624 elif(option == 'outpu 6625 sysvals.outdi 6626 6627 if sysvals.suspendmode == 'command' a 6628 doError('No command supplied 6629 6630 # compatibility errors 6631 if sysvals.usedevsrc and sysvals.usec 6632 doError('-dev is not compatib 6633 if sysvals.usecallgraph and sysvals.u 6634 doError('-proc is not compati 6635 6636 if overridekprobes: 6637 sysvals.tracefuncs = dict() 6638 if overridedevkprobes: 6639 sysvals.dev_tracefuncs = dict 6640 6641 kprobes = dict() 6642 kprobesec = 'dev_timeline_functions_' 6643 if kprobesec in sections: 6644 for name in Config.options(kp 6645 text = Config.get(kpr 6646 kprobes[name] = (text 6647 kprobesec = 'timeline_functions_'+pla 6648 if kprobesec in sections: 6649 for name in Config.options(kp 6650 if name in kprobes: 6651 doError('Dupl 6652 text = Config.get(kpr 6653 kprobes[name] = (text 6654 6655 for name in kprobes: 6656 function = name 6657 format = name 6658 color = '' 6659 args = dict() 6660 text, dev = kprobes[name] 6661 data = text.split() 6662 i = 0 6663 for val in data: 6664 # bracketted strings 6665 if val[0] == '[' and 6666 for prop in v 6667 p = p 6668 if p[ 6669 6670 6671 6672 6673 6674 continue 6675 # first real arg shou 6676 if i == 0: 6677 format = val 6678 # all other args are 6679 else: 6680 d = val.split 6681 args[d[0]] = 6682 i += 1 6683 if not function or not format 6684 doError('Invalid kpro 6685 for arg in re.findall('{(?P<n 6686 if arg not in args: 6687 doError('Kpro 6688 if (dev and name in sysvals.d 6689 doError('Duplicate ti 6690 6691 kp = { 6692 'name': name, 6693 'func': function, 6694 'format': format, 6695 sysvals.archargs: arg 6696 } 6697 if color: 6698 kp['color'] = color 6699 if dev: 6700 sysvals.dev_tracefunc 6701 else: 6702 sysvals.tracefuncs[na 6703 6704 # Function: printHelp 6705 # Description: 6706 # print out the help text 6707 def printHelp(): 6708 pprint('\n%s v%s\n'\ 6709 'Usage: sudo sleepgraph <options> <co 6710 '\n'\ 6711 'Description:\n'\ 6712 ' This tool is designed to assist ke 6713 ' their linux stack\'s suspend/resum 6714 ' with a few extra options enabled, 6715 ' capture dmesg and ftrace data unti 6716 ' transformed into a device timeline 6717 ' a detailed view of which devices/s 6718 ' time in suspend/resume.\n'\ 6719 '\n'\ 6720 ' If no specific command is given, t 6721 ' a suspend/resume and capture the d 6722 '\n'\ 6723 ' Generates output files in subdirec 6724 ' HTML output: < 6725 ' raw dmesg output: < 6726 ' raw ftrace output: < 6727 '\n'\ 6728 'Options:\n'\ 6729 ' -h Print this help text 6730 ' -v Print the current to 6731 ' -config fn Pull arguments and c 6732 ' -verbose Print extra informat 6733 ' -m mode Mode to initiate for 6734 ' -o name Overrides the output 6735 ' default: suspend-{da 6736 ' -rtcwake t Wakeup t seconds aft 6737 ' -addlogs Add the dmesg and ft 6738 ' -noturbostat Dont use turbostat i 6739 ' -srgap Add a visible gap in 6740 ' -skiphtml Run the test and cap 6741 ' -result fn Export a results tab 6742 ' -wifi If a wifi connection 6743 ' -wifitrace Trace kernel executi 6744 ' -netfix Use netfix to reset 6745 ' [testprep]\n'\ 6746 ' -sync Sync the filesystems 6747 ' -rs on/off Enable/disable runti 6748 ' -display m Change the display m 6749 ' [advanced]\n'\ 6750 ' -gzip Gzip the trace and d 6751 ' -cmd {s} Run the timeline ove 6752 ' -proc Add usermode process 6753 ' -dev Add kernel function 6754 ' -x2 Run two suspend/resu 6755 ' -x2delay t Include t ms delay b 6756 ' -predelay t Include t ms delay b 6757 ' -postdelay t Include t ms delay a 6758 ' -mindev ms Discard all device b 6759 ' -multi n d Execute <n> consecut 6760 ' by a "d", "h", or "m 6761 ' The outputs will be 6762 ' -maxfail n Abort a -multi run a 6763 ' [debug]\n'\ 6764 ' -f Use ftrace to create 6765 ' -ftop Use ftrace on the to 6766 ' -maxdepth N limit the callgraph 6767 ' -expandcg pre-expand the callg 6768 ' -fadd file Add functions to be 6769 ' -filter "d1,d2,..." Filter out al 6770 ' -mincg ms Discard all callgrap 6771 ' -cgphase P Only show callgraph 6772 ' -cgtest N Only show callgraph 6773 ' -timeprec N Number of significan 6774 ' -cgfilter S Filter the callgraph 6775 ' -cgskip file Callgraph functions 6776 ' -bufsize N Set trace buffer siz 6777 ' -devdump Print out all the ra 6778 ' -cgdump Print out all the ra 6779 '\n'\ 6780 'Other commands:\n'\ 6781 ' -modes List available suspe 6782 ' -status Test to see if the s 6783 ' -fpdt Print out the conten 6784 ' -wificheck Print out wifi conne 6785 ' -x<mode> Test xset by togglin 6786 ' -sysinfo Print out system inf 6787 ' -devinfo Print out the pm set 6788 ' -cmdinfo Print out all the pl 6789 ' -flist Print the list of fu 6790 ' -flistall Print all functions 6791 ' -summary dir Create a summary of 6792 ' [redo]\n'\ 6793 ' -ftrace ftracefile Create HTML o 6794 ' -dmesg dmesgfile Create HTML o 6795 '' % (sysvals.title, sysvals.version, 6796 return True 6797 6798 # ----------------- MAIN -------------------- 6799 # exec start (skipped if script is loaded as 6800 if __name__ == '__main__': 6801 genhtml = False 6802 cmd = '' 6803 simplecmds = ['-sysinfo', '-modes', ' 6804 '-devinfo', '-status', '-xon' 6805 '-xinit', '-xreset', '-xstat' 6806 if '-f' in sys.argv: 6807 sysvals.cgskip = sysvals.conf 6808 # loop through the command line argum 6809 args = iter(sys.argv[1:]) 6810 for arg in args: 6811 if(arg == '-m'): 6812 try: 6813 val = next(ar 6814 except: 6815 doError('No m 6816 if val == 'command' a 6817 doError('No c 6818 sysvals.suspendmode = 6819 elif(arg in simplecmds): 6820 cmd = arg[1:] 6821 elif(arg == '-h'): 6822 printHelp() 6823 sys.exit(0) 6824 elif(arg == '-v'): 6825 pprint("Version %s" % 6826 sys.exit(0) 6827 elif(arg == '-debugtiming'): 6828 debugtiming = True 6829 elif(arg == '-x2'): 6830 sysvals.execcount = 2 6831 elif(arg == '-x2delay'): 6832 sysvals.x2delay = get 6833 elif(arg == '-predelay'): 6834 sysvals.predelay = ge 6835 elif(arg == '-postdelay'): 6836 sysvals.postdelay = g 6837 elif(arg == '-f'): 6838 sysvals.usecallgraph 6839 elif(arg == '-ftop'): 6840 sysvals.usecallgraph 6841 sysvals.ftop = True 6842 sysvals.usekprobes = 6843 elif(arg == '-skiphtml'): 6844 sysvals.skiphtml = Tr 6845 elif(arg == '-cgdump'): 6846 sysvals.cgdump = True 6847 elif(arg == '-devdump'): 6848 sysvals.devdump = Tru 6849 elif(arg == '-genhtml'): 6850 genhtml = True 6851 elif(arg == '-addlogs'): 6852 sysvals.dmesglog = sy 6853 elif(arg == '-nologs'): 6854 sysvals.dmesglog = sy 6855 elif(arg == '-addlogdmesg'): 6856 sysvals.dmesglog = Tr 6857 elif(arg == '-addlogftrace'): 6858 sysvals.ftracelog = T 6859 elif(arg == '-noturbostat'): 6860 sysvals.tstat = False 6861 elif(arg == '-verbose'): 6862 sysvals.verbose = Tru 6863 elif(arg == '-proc'): 6864 sysvals.useprocmon = 6865 elif(arg == '-dev'): 6866 sysvals.usedevsrc = T 6867 elif(arg == '-sync'): 6868 sysvals.sync = True 6869 elif(arg == '-wifi'): 6870 sysvals.wifi = True 6871 elif(arg == '-wifitrace'): 6872 sysvals.wifitrace = T 6873 elif(arg == '-netfix'): 6874 sysvals.netfix = True 6875 elif(arg == '-gzip'): 6876 sysvals.gzip = True 6877 elif(arg == '-info'): 6878 try: 6879 val = next(ar 6880 except: 6881 doError('-inf 6882 elif(arg == '-desc'): 6883 try: 6884 val = next(ar 6885 except: 6886 doError('-des 6887 elif(arg == '-rs'): 6888 try: 6889 val = next(ar 6890 except: 6891 doError('-rs 6892 if val.lower() in swi 6893 if val.lower( 6894 sysva 6895 else: 6896 sysva 6897 else: 6898 doError('inva 6899 elif(arg == '-display'): 6900 try: 6901 val = next(ar 6902 except: 6903 doError('-dis 6904 disopt = ['on', 'off' 6905 if val.lower() not in 6906 doError('vali 6907 sysvals.display = val 6908 elif(arg == '-maxdepth'): 6909 sysvals.max_graph_dep 6910 elif(arg == '-rtcwake'): 6911 try: 6912 val = next(ar 6913 except: 6914 doError('No r 6915 if val.lower() in swi 6916 sysvals.rtcwa 6917 else: 6918 sysvals.rtcwa 6919 sysvals.rtcwa 6920 elif(arg == '-timeprec'): 6921 sysvals.setPrecision( 6922 elif(arg == '-mindev'): 6923 sysvals.mindevlen = g 6924 elif(arg == '-mincg'): 6925 sysvals.mincglen = ge 6926 elif(arg == '-bufsize'): 6927 sysvals.bufsize = get 6928 elif(arg == '-cgtest'): 6929 sysvals.cgtest = getA 6930 elif(arg == '-cgphase'): 6931 try: 6932 val = next(ar 6933 except: 6934 doError('No p 6935 d = Data(0) 6936 if val not in d.phase 6937 doError('inva 6938 % (ar 6939 sysvals.cgphase = val 6940 elif(arg == '-cgfilter'): 6941 try: 6942 val = next(ar 6943 except: 6944 doError('No c 6945 sysvals.setCallgraphF 6946 elif(arg == '-skipkprobe'): 6947 try: 6948 val = next(ar 6949 except: 6950 doError('No k 6951 sysvals.skipKprobes(v 6952 elif(arg == '-cgskip'): 6953 try: 6954 val = next(ar 6955 except: 6956 doError('No f 6957 if val.lower() in swi 6958 sysvals.cgski 6959 else: 6960 sysvals.cgski 6961 if(not sysval 6962 doErr 6963 elif(arg == '-callloop-maxgap 6964 sysvals.callloopmaxga 6965 elif(arg == '-callloop-maxlen 6966 sysvals.callloopmaxle 6967 elif(arg == '-cmd'): 6968 try: 6969 val = next(ar 6970 except: 6971 doError('No c 6972 sysvals.testcommand = 6973 sysvals.suspendmode = 6974 elif(arg == '-expandcg'): 6975 sysvals.cgexp = True 6976 elif(arg == '-srgap'): 6977 sysvals.srgap = 5 6978 elif(arg == '-maxfail'): 6979 sysvals.maxfail = get 6980 elif(arg == '-multi'): 6981 try: 6982 c, d = next(a 6983 except: 6984 doError('-mul 6985 sysvals.multiinit(c, 6986 elif(arg == '-o'): 6987 try: 6988 val = next(ar 6989 except: 6990 doError('No s 6991 sysvals.outdir = sysv 6992 elif(arg == '-config'): 6993 try: 6994 val = next(ar 6995 except: 6996 doError('No t 6997 file = sysvals.config 6998 if(not file): 6999 doError('%s d 7000 configFromFile(file) 7001 elif(arg == '-fadd'): 7002 try: 7003 val = next(ar 7004 except: 7005 doError('No t 7006 file = sysvals.config 7007 if(not file): 7008 doError('%s d 7009 sysvals.addFtraceFilt 7010 elif(arg == '-dmesg'): 7011 try: 7012 val = next(ar 7013 except: 7014 doError('No d 7015 sysvals.notestrun = T 7016 sysvals.dmesgfile = v 7017 if(os.path.exists(sys 7018 doError('%s d 7019 elif(arg == '-ftrace'): 7020 try: 7021 val = next(ar 7022 except: 7023 doError('No f 7024 sysvals.notestrun = T 7025 sysvals.ftracefile = 7026 if(os.path.exists(sys 7027 doError('%s d 7028 elif(arg == '-summary'): 7029 try: 7030 val = next(ar 7031 except: 7032 doError('No d 7033 cmd = 'summary' 7034 sysvals.outdir = val 7035 sysvals.notestrun = T 7036 if(os.path.isdir(val) 7037 doError('%s i 7038 elif(arg == '-filter'): 7039 try: 7040 val = next(ar 7041 except: 7042 doError('No d 7043 sysvals.setDeviceFilt 7044 elif(arg == '-result'): 7045 try: 7046 val = next(ar 7047 except: 7048 doError('No r 7049 sysvals.result = val 7050 sysvals.signalHandler 7051 else: 7052 doError('Invalid argu 7053 7054 # compatibility errors 7055 if(sysvals.usecallgraph and sysvals.u 7056 doError('-dev is not compatib 7057 if(sysvals.usecallgraph and sysvals.u 7058 doError('-proc is not compati 7059 7060 if sysvals.usecallgraph and sysvals.c 7061 sysvals.vprint('Using cgskip 7062 sysvals.setCallgraphBlacklist 7063 7064 # callgraph size cannot exceed device 7065 if sysvals.mincglen < sysvals.mindevl 7066 sysvals.mincglen = sysvals.mi 7067 7068 # remove existing buffers before calc 7069 if(sysvals.usecallgraph or sysvals.us 7070 sysvals.fsetVal('16', 'buffer 7071 sysvals.cpuInfo() 7072 7073 # just run a utility command and exit 7074 if(cmd != ''): 7075 ret = 0 7076 if(cmd == 'status'): 7077 if not statusCheck(Tr 7078 ret = 1 7079 elif(cmd == 'fpdt'): 7080 if not getFPDT(True): 7081 ret = 1 7082 elif(cmd == 'sysinfo'): 7083 sysvals.printSystemIn 7084 elif(cmd == 'devinfo'): 7085 deviceInfo() 7086 elif(cmd == 'modes'): 7087 pprint(getModes()) 7088 elif(cmd == 'flist'): 7089 sysvals.getFtraceFilt 7090 elif(cmd == 'flistall'): 7091 sysvals.getFtraceFilt 7092 elif(cmd == 'summary'): 7093 runSummary(sysvals.ou 7094 elif(cmd in ['xon', 'xoff', ' 7095 sysvals.verbose = Tru 7096 ret = sysvals.display 7097 elif(cmd == 'xstat'): 7098 pprint('Display Statu 7099 elif(cmd == 'wificheck'): 7100 dev = sysvals.checkWi 7101 if dev: 7102 print('%s is 7103 else: 7104 print('No wif 7105 elif(cmd == 'cmdinfo'): 7106 for out in sysvals.cm 7107 print('[%s - 7108 sys.exit(ret) 7109 7110 # if instructed, re-analyze existing 7111 if(sysvals.notestrun): 7112 stamp = rerunTest(sysvals.out 7113 sysvals.outputResult(stamp) 7114 sys.exit(0) 7115 7116 # verify that we can run a test 7117 error = statusCheck() 7118 if(error): 7119 doError(error) 7120 7121 # extract mem/disk extra modes and co 7122 mode = sysvals.suspendmode 7123 if mode.startswith('mem'): 7124 memmode = mode.split('-', 1)[ 7125 if memmode == 'shallow': 7126 mode = 'standby' 7127 elif memmode == 's2idle': 7128 mode = 'freeze' 7129 else: 7130 mode = 'mem' 7131 sysvals.memmode = memmode 7132 sysvals.suspendmode = mode 7133 if mode.startswith('disk-'): 7134 sysvals.diskmode = mode.split 7135 sysvals.suspendmode = 'disk' 7136 sysvals.systemInfo(dmidecode(sysvals. 7137 7138 failcnt, ret = 0, 0 7139 if sysvals.multitest['run']: 7140 # run multiple tests in a sep 7141 if not sysvals.outdir: 7142 if 'time' in sysvals. 7143 s = '-%dm' % 7144 else: 7145 s = '-x%d' % 7146 sysvals.outdir = date 7147 if not os.path.isdir(sysvals. 7148 os.makedirs(sysvals.o 7149 sysvals.sudoUserchown(sysvals 7150 finish = datetime.now() 7151 if 'time' in sysvals.multites 7152 finish += timedelta(m 7153 for i in range(sysvals.multit 7154 sysvals.multistat(Tru 7155 if i != 0 and sysvals 7156 pprint('Waiti 7157 time.sleep(sy 7158 fmt = 'suspend-%y%m%d 7159 sysvals.testdir = os. 7160 ret = runTest(i+1, no 7161 failcnt = 0 if not re 7162 if sysvals.maxfail > 7163 pprint('Maxim 7164 break 7165 sysvals.resetlog() 7166 sysvals.multistat(Fal 7167 if 'time' in sysvals. 7168 break 7169 if not sysvals.skiphtml: 7170 runSummary(sysvals.ou 7171 sysvals.sudoUserchown(sysvals 7172 else: 7173 if sysvals.outdir: 7174 sysvals.testdir = sys 7175 # run the test in the current 7176 ret = runTest() 7177 7178 # reset to default values after testi 7179 if sysvals.display: 7180 sysvals.displayControl('reset 7181 if sysvals.rs != 0: 7182 sysvals.setRuntimeSuspend(Fal 7183 sys.exit(ret)
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.