1 #!/usr/bin/env python3 !! 1 #!/usr/bin/python2 2 # SPDX-License-Identifier: GPL-2.0-only 2 # SPDX-License-Identifier: GPL-2.0-only 3 # 3 # 4 # Tool for analyzing suspend/resume timing 4 # Tool for analyzing suspend/resume timing 5 # Copyright (c) 2013, Intel Corporation. 5 # Copyright (c) 2013, Intel Corporation. 6 # 6 # 7 # This program is free software; you can 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: 7 # Authors: 17 # Todd Brandt <todd.e.brandt@linux.intel 8 # Todd Brandt <todd.e.brandt@linux.intel.com> 18 # 9 # 19 # Links: 10 # Links: 20 # Home Page 11 # Home Page 21 # https://01.org/pm-graph 12 # https://01.org/pm-graph 22 # Source repo 13 # Source repo 23 # git@github.com:intel/pm-graph 14 # git@github.com:intel/pm-graph 24 # 15 # 25 # Description: 16 # Description: 26 # This tool is designed to assist kerne 17 # This tool is designed to assist kernel and OS developers in optimizing 27 # their linux stack's suspend/resume ti 18 # their linux stack's suspend/resume time. Using a kernel image built 28 # with a few extra options enabled, the 19 # with a few extra options enabled, the tool will execute a suspend and 29 # will capture dmesg and ftrace data un 20 # will capture dmesg and ftrace data until resume is complete. This data 30 # is transformed into a device timeline 21 # is transformed into a device timeline and a callgraph to give a quick 31 # and detailed view of which devices an 22 # and detailed view of which devices and callbacks are taking the most 32 # time in suspend/resume. The output is 23 # time in suspend/resume. The output is a single html file which can be 33 # viewed in firefox or chrome. 24 # viewed in firefox or chrome. 34 # 25 # 35 # The following kernel build options ar 26 # The following kernel build options are required: 36 # CONFIG_DEVMEM=y 27 # CONFIG_DEVMEM=y 37 # CONFIG_PM_DEBUG=y 28 # CONFIG_PM_DEBUG=y 38 # CONFIG_PM_SLEEP_DEBUG=y 29 # CONFIG_PM_SLEEP_DEBUG=y 39 # CONFIG_FTRACE=y 30 # CONFIG_FTRACE=y 40 # CONFIG_FUNCTION_TRACER=y 31 # CONFIG_FUNCTION_TRACER=y 41 # CONFIG_FUNCTION_GRAPH_TRACER= 32 # CONFIG_FUNCTION_GRAPH_TRACER=y 42 # CONFIG_KPROBES=y 33 # CONFIG_KPROBES=y 43 # CONFIG_KPROBES_ON_FTRACE=y 34 # CONFIG_KPROBES_ON_FTRACE=y 44 # 35 # 45 # For kernel versions older than 3.15: 36 # For kernel versions older than 3.15: 46 # The following additional kernel param 37 # The following additional kernel parameters are required: 47 # (e.g. in file /etc/default/gr 38 # (e.g. in file /etc/default/grub) 48 # GRUB_CMDLINE_LINUX_DEFAULT=". 39 # GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=16M ..." 49 # 40 # 50 41 51 # ----------------- LIBRARIES ---------------- 42 # ----------------- LIBRARIES -------------------- 52 43 53 import sys 44 import sys 54 import time 45 import time 55 import os 46 import os 56 import string 47 import string 57 import re 48 import re 58 import platform 49 import platform 59 import signal 50 import signal 60 import codecs !! 51 from datetime import datetime 61 from datetime import datetime, timedelta << 62 import struct 52 import struct 63 import configparser !! 53 import ConfigParser 64 import gzip 54 import gzip 65 from threading import Thread 55 from threading import Thread 66 from subprocess import call, Popen, PIPE 56 from subprocess import call, Popen, PIPE 67 import base64 57 import base64 68 58 69 debugtiming = False << 70 mystarttime = time.time() << 71 def pprint(msg): 59 def pprint(msg): 72 if debugtiming: !! 60 print(msg) 73 print('[%09.3f] %s' % (time.ti << 74 else: << 75 print(msg) << 76 sys.stdout.flush() 61 sys.stdout.flush() 77 62 78 def ascii(text): << 79 return text.decode('ascii', 'ignore') << 80 << 81 # ----------------- CLASSES ------------------ 63 # ----------------- CLASSES -------------------- 82 64 83 # Class: SystemValues 65 # Class: SystemValues 84 # Description: 66 # Description: 85 # A global, single-instance container u 67 # A global, single-instance container used to 86 # store system values and test paramete 68 # store system values and test parameters 87 class SystemValues: 69 class SystemValues: 88 title = 'SleepGraph' 70 title = 'SleepGraph' 89 version = '5.12' !! 71 version = '5.4' 90 ansi = False 72 ansi = False 91 rs = 0 73 rs = 0 92 display = '' 74 display = '' 93 gzip = False 75 gzip = False 94 sync = False 76 sync = False 95 wifi = False << 96 netfix = False << 97 verbose = False 77 verbose = False 98 testlog = True 78 testlog = True 99 dmesglog = True 79 dmesglog = True 100 ftracelog = False 80 ftracelog = False 101 acpidebug = True !! 81 tstat = False 102 tstat = True !! 82 mindevlen = 0.0 103 wifitrace = False << 104 mindevlen = 0.0001 << 105 mincglen = 0.0 83 mincglen = 0.0 106 cgphase = '' 84 cgphase = '' 107 cgtest = -1 85 cgtest = -1 108 cgskip = '' 86 cgskip = '' 109 maxfail = 0 !! 87 multitest = {'run': False, 'count': 0, 'delay': 0} 110 multitest = {'run': False, 'count': 10 << 111 max_graph_depth = 0 88 max_graph_depth = 0 112 callloopmaxgap = 0.0001 89 callloopmaxgap = 0.0001 113 callloopmaxlen = 0.005 90 callloopmaxlen = 0.005 114 bufsize = 0 91 bufsize = 0 115 cpucount = 0 92 cpucount = 0 116 memtotal = 204800 93 memtotal = 204800 117 memfree = 204800 94 memfree = 204800 118 osversion = '' << 119 srgap = 0 95 srgap = 0 120 cgexp = False 96 cgexp = False 121 testdir = '' 97 testdir = '' 122 outdir = '' 98 outdir = '' 123 tpath = '/sys/kernel/tracing/' !! 99 tpath = '/sys/kernel/debug/tracing/' 124 fpdtpath = '/sys/firmware/acpi/tables/ 100 fpdtpath = '/sys/firmware/acpi/tables/FPDT' 125 epath = '/sys/kernel/tracing/events/po !! 101 epath = '/sys/kernel/debug/tracing/events/power/' 126 pmdpath = '/sys/power/pm_debug_message 102 pmdpath = '/sys/power/pm_debug_messages' 127 s0ixpath = '/sys/module/intel_pmc_core << 128 s0ixres = '/sys/devices/system/cpu/cpu << 129 acpipath='/sys/module/acpi/parameters/ << 130 traceevents = [ 103 traceevents = [ 131 'suspend_resume', 104 'suspend_resume', 132 'wakeup_source_activate', 105 'wakeup_source_activate', 133 'wakeup_source_deactivate', 106 'wakeup_source_deactivate', 134 'device_pm_callback_end', 107 'device_pm_callback_end', 135 'device_pm_callback_start' 108 'device_pm_callback_start' 136 ] 109 ] 137 logmsg = '' 110 logmsg = '' 138 testcommand = '' 111 testcommand = '' 139 mempath = '/dev/mem' 112 mempath = '/dev/mem' 140 powerfile = '/sys/power/state' 113 powerfile = '/sys/power/state' 141 mempowerfile = '/sys/power/mem_sleep' 114 mempowerfile = '/sys/power/mem_sleep' 142 diskpowerfile = '/sys/power/disk' 115 diskpowerfile = '/sys/power/disk' 143 suspendmode = 'mem' 116 suspendmode = 'mem' 144 memmode = '' 117 memmode = '' 145 diskmode = '' 118 diskmode = '' 146 hostname = 'localhost' 119 hostname = 'localhost' 147 prefix = 'test' 120 prefix = 'test' 148 teststamp = '' 121 teststamp = '' 149 sysstamp = '' 122 sysstamp = '' 150 dmesgstart = 0.0 123 dmesgstart = 0.0 151 dmesgfile = '' 124 dmesgfile = '' 152 ftracefile = '' 125 ftracefile = '' 153 htmlfile = 'output.html' 126 htmlfile = 'output.html' 154 result = '' 127 result = '' 155 rtcwake = True 128 rtcwake = True 156 rtcwaketime = 15 129 rtcwaketime = 15 157 rtcpath = '' 130 rtcpath = '' 158 devicefilter = [] 131 devicefilter = [] 159 cgfilter = [] 132 cgfilter = [] 160 stamp = 0 133 stamp = 0 161 execcount = 1 134 execcount = 1 162 x2delay = 0 135 x2delay = 0 163 skiphtml = False 136 skiphtml = False 164 usecallgraph = False 137 usecallgraph = False 165 ftopfunc = 'pm_suspend' !! 138 ftopfunc = 'suspend_devices_and_enter' 166 ftop = False 139 ftop = False 167 usetraceevents = False 140 usetraceevents = False 168 usetracemarkers = True 141 usetracemarkers = True 169 useftrace = True << 170 usekprobes = True 142 usekprobes = True 171 usedevsrc = False 143 usedevsrc = False 172 useprocmon = False 144 useprocmon = False 173 notestrun = False 145 notestrun = False 174 cgdump = False 146 cgdump = False 175 devdump = False 147 devdump = False 176 mixedphaseheight = True 148 mixedphaseheight = True 177 devprops = dict() 149 devprops = dict() 178 cfgdef = dict() << 179 platinfo = [] << 180 predelay = 0 150 predelay = 0 181 postdelay = 0 151 postdelay = 0 182 tmstart = 'SUSPEND START %Y%m%d-%H:%M: !! 152 pmdebug = '' 183 tmend = 'RESUME COMPLETE %Y%m%d-%H:%M: << 184 tracefuncs = { 153 tracefuncs = { 185 'async_synchronize_full': {}, << 186 'sys_sync': {}, 154 'sys_sync': {}, 187 'ksys_sync': {}, 155 'ksys_sync': {}, 188 '__pm_notifier_call_chain': {} 156 '__pm_notifier_call_chain': {}, 189 'pm_prepare_console': {}, 157 'pm_prepare_console': {}, 190 'pm_notifier_call_chain': {}, 158 'pm_notifier_call_chain': {}, 191 'freeze_processes': {}, 159 'freeze_processes': {}, 192 'freeze_kernel_threads': {}, 160 'freeze_kernel_threads': {}, 193 'pm_restrict_gfp_mask': {}, 161 'pm_restrict_gfp_mask': {}, 194 'acpi_suspend_begin': {}, 162 'acpi_suspend_begin': {}, 195 'acpi_hibernation_begin': {}, 163 'acpi_hibernation_begin': {}, 196 'acpi_hibernation_enter': {}, 164 'acpi_hibernation_enter': {}, 197 'acpi_hibernation_leave': {}, 165 'acpi_hibernation_leave': {}, 198 'acpi_pm_freeze': {}, 166 'acpi_pm_freeze': {}, 199 'acpi_pm_thaw': {}, 167 'acpi_pm_thaw': {}, 200 'acpi_s2idle_end': {}, 168 'acpi_s2idle_end': {}, 201 'acpi_s2idle_sync': {}, 169 'acpi_s2idle_sync': {}, 202 'acpi_s2idle_begin': {}, 170 'acpi_s2idle_begin': {}, 203 'acpi_s2idle_prepare': {}, 171 'acpi_s2idle_prepare': {}, 204 'acpi_s2idle_prepare_late': {} << 205 'acpi_s2idle_wake': {}, 172 'acpi_s2idle_wake': {}, 206 'acpi_s2idle_wakeup': {}, 173 'acpi_s2idle_wakeup': {}, 207 'acpi_s2idle_restore': {}, 174 'acpi_s2idle_restore': {}, 208 'acpi_s2idle_restore_early': { << 209 'hibernate_preallocate_memory' 175 'hibernate_preallocate_memory': {}, 210 'create_basic_memory_bitmaps': 176 'create_basic_memory_bitmaps': {}, 211 'swsusp_write': {}, 177 'swsusp_write': {}, 212 'suspend_console': {}, 178 'suspend_console': {}, 213 'acpi_pm_prepare': {}, 179 'acpi_pm_prepare': {}, 214 'syscore_suspend': {}, 180 'syscore_suspend': {}, 215 'arch_enable_nonboot_cpus_end' 181 'arch_enable_nonboot_cpus_end': {}, 216 'syscore_resume': {}, 182 'syscore_resume': {}, 217 'acpi_pm_finish': {}, 183 'acpi_pm_finish': {}, 218 'resume_console': {}, 184 'resume_console': {}, 219 'acpi_pm_end': {}, 185 'acpi_pm_end': {}, 220 'pm_restore_gfp_mask': {}, 186 'pm_restore_gfp_mask': {}, 221 'thaw_processes': {}, 187 'thaw_processes': {}, 222 'pm_restore_console': {}, 188 'pm_restore_console': {}, 223 'CPU_OFF': { 189 'CPU_OFF': { 224 'func':'_cpu_down', 190 'func':'_cpu_down', 225 'args_x86_64': {'cpu': 191 'args_x86_64': {'cpu':'%di:s32'}, 226 'format': 'CPU_OFF[{cp 192 'format': 'CPU_OFF[{cpu}]' 227 }, 193 }, 228 'CPU_ON': { 194 'CPU_ON': { 229 'func':'_cpu_up', 195 'func':'_cpu_up', 230 'args_x86_64': {'cpu': 196 'args_x86_64': {'cpu':'%di:s32'}, 231 'format': 'CPU_ON[{cpu 197 'format': 'CPU_ON[{cpu}]' 232 }, 198 }, 233 } 199 } 234 dev_tracefuncs = { 200 dev_tracefuncs = { 235 # general wait/delay/sleep 201 # general wait/delay/sleep 236 'msleep': { 'args_x86_64': {'t 202 'msleep': { 'args_x86_64': {'time':'%di:s32'}, 'ub': 1 }, 237 'schedule_timeout': { 'args_x8 203 'schedule_timeout': { 'args_x86_64': {'timeout':'%di:s32'}, 'ub': 1 }, 238 'udelay': { 'func':'__const_ud 204 'udelay': { 'func':'__const_udelay', 'args_x86_64': {'loops':'%di:s32'}, 'ub': 1 }, 239 'usleep_range': { 'args_x86_64 205 'usleep_range': { 'args_x86_64': {'min':'%di:s32', 'max':'%si:s32'}, 'ub': 1 }, 240 'mutex_lock_slowpath': { 'func 206 'mutex_lock_slowpath': { 'func':'__mutex_lock_slowpath', 'ub': 1 }, 241 'acpi_os_stall': {'ub': 1}, 207 'acpi_os_stall': {'ub': 1}, 242 'rt_mutex_slowlock': {'ub': 1} 208 'rt_mutex_slowlock': {'ub': 1}, 243 # ACPI 209 # ACPI 244 'acpi_resume_power_resources': 210 'acpi_resume_power_resources': {}, 245 'acpi_ps_execute_method': { 'a 211 'acpi_ps_execute_method': { 'args_x86_64': { 246 'fullpath':'+0(+40(%di 212 'fullpath':'+0(+40(%di)):string', 247 }}, 213 }}, 248 # mei_me 214 # mei_me 249 'mei_reset': {}, 215 'mei_reset': {}, 250 # filesystem 216 # filesystem 251 'ext4_sync_fs': {}, 217 'ext4_sync_fs': {}, 252 # 80211 218 # 80211 253 'ath10k_bmi_read_memory': { 'a 219 'ath10k_bmi_read_memory': { 'args_x86_64': {'length':'%cx:s32'} }, 254 'ath10k_bmi_write_memory': { ' 220 'ath10k_bmi_write_memory': { 'args_x86_64': {'length':'%cx:s32'} }, 255 'ath10k_bmi_fast_download': { 221 'ath10k_bmi_fast_download': { 'args_x86_64': {'length':'%cx:s32'} }, 256 'iwlagn_mac_start': {}, 222 'iwlagn_mac_start': {}, 257 'iwlagn_alloc_bcast_station': 223 'iwlagn_alloc_bcast_station': {}, 258 'iwl_trans_pcie_start_hw': {}, 224 'iwl_trans_pcie_start_hw': {}, 259 'iwl_trans_pcie_start_fw': {}, 225 'iwl_trans_pcie_start_fw': {}, 260 'iwl_run_init_ucode': {}, 226 'iwl_run_init_ucode': {}, 261 'iwl_load_ucode_wait_alive': { 227 'iwl_load_ucode_wait_alive': {}, 262 'iwl_alive_start': {}, 228 'iwl_alive_start': {}, 263 'iwlagn_mac_stop': {}, 229 'iwlagn_mac_stop': {}, 264 'iwlagn_mac_suspend': {}, 230 'iwlagn_mac_suspend': {}, 265 'iwlagn_mac_resume': {}, 231 'iwlagn_mac_resume': {}, 266 'iwlagn_mac_add_interface': {} 232 'iwlagn_mac_add_interface': {}, 267 'iwlagn_mac_remove_interface': 233 'iwlagn_mac_remove_interface': {}, 268 'iwlagn_mac_change_interface': 234 'iwlagn_mac_change_interface': {}, 269 'iwlagn_mac_config': {}, 235 'iwlagn_mac_config': {}, 270 'iwlagn_configure_filter': {}, 236 'iwlagn_configure_filter': {}, 271 'iwlagn_mac_hw_scan': {}, 237 'iwlagn_mac_hw_scan': {}, 272 'iwlagn_bss_info_changed': {}, 238 'iwlagn_bss_info_changed': {}, 273 'iwlagn_mac_channel_switch': { 239 'iwlagn_mac_channel_switch': {}, 274 'iwlagn_mac_flush': {}, 240 'iwlagn_mac_flush': {}, 275 # ATA 241 # ATA 276 'ata_eh_recover': { 'args_x86_ 242 'ata_eh_recover': { 'args_x86_64': {'port':'+36(%di):s32'} }, 277 # i915 243 # i915 278 'i915_gem_resume': {}, 244 'i915_gem_resume': {}, 279 'i915_restore_state': {}, 245 'i915_restore_state': {}, 280 'intel_opregion_setup': {}, 246 'intel_opregion_setup': {}, 281 'g4x_pre_enable_dp': {}, 247 'g4x_pre_enable_dp': {}, 282 'vlv_pre_enable_dp': {}, 248 'vlv_pre_enable_dp': {}, 283 'chv_pre_enable_dp': {}, 249 'chv_pre_enable_dp': {}, 284 'g4x_enable_dp': {}, 250 'g4x_enable_dp': {}, 285 'vlv_enable_dp': {}, 251 'vlv_enable_dp': {}, 286 'intel_hpd_init': {}, 252 'intel_hpd_init': {}, 287 'intel_opregion_register': {}, 253 'intel_opregion_register': {}, 288 'intel_dp_detect': {}, 254 'intel_dp_detect': {}, 289 'intel_hdmi_detect': {}, 255 'intel_hdmi_detect': {}, 290 'intel_opregion_init': {}, 256 'intel_opregion_init': {}, 291 'intel_fbdev_set_suspend': {}, 257 'intel_fbdev_set_suspend': {}, 292 } 258 } 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 = [] 259 cgblacklist = [] 314 kprobes = dict() 260 kprobes = dict() 315 timeformat = '%.3f' 261 timeformat = '%.3f' 316 cmdline = '%s %s' % \ 262 cmdline = '%s %s' % \ 317 (os.path.basename(sys. 263 (os.path.basename(sys.argv[0]), ' '.join(sys.argv[1:])) >> 264 kparams = '' 318 sudouser = '' 265 sudouser = '' 319 def __init__(self): 266 def __init__(self): 320 self.archargs = 'args_'+platfo 267 self.archargs = 'args_'+platform.machine() 321 self.hostname = platform.node( 268 self.hostname = platform.node() 322 if(self.hostname == ''): 269 if(self.hostname == ''): 323 self.hostname = 'local 270 self.hostname = 'localhost' 324 rtc = "rtc0" 271 rtc = "rtc0" 325 if os.path.exists('/dev/rtc'): 272 if os.path.exists('/dev/rtc'): 326 rtc = os.readlink('/de 273 rtc = os.readlink('/dev/rtc') 327 rtc = '/sys/class/rtc/'+rtc 274 rtc = '/sys/class/rtc/'+rtc 328 if os.path.exists(rtc) and os. 275 if os.path.exists(rtc) and os.path.exists(rtc+'/date') and \ 329 os.path.exists(rtc+'/t 276 os.path.exists(rtc+'/time') and os.path.exists(rtc+'/wakealarm'): 330 self.rtcpath = rtc 277 self.rtcpath = rtc 331 if (hasattr(sys.stdout, 'isatt 278 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()): 332 self.ansi = True 279 self.ansi = True 333 self.testdir = datetime.now(). 280 self.testdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S') 334 if os.getuid() == 0 and 'SUDO_ 281 if os.getuid() == 0 and 'SUDO_USER' in os.environ and \ 335 os.environ['SUDO_USER' 282 os.environ['SUDO_USER']: 336 self.sudouser = os.env 283 self.sudouser = os.environ['SUDO_USER'] 337 def resetlog(self): << 338 self.logmsg = '' << 339 self.platinfo = [] << 340 def vprint(self, msg): 284 def vprint(self, msg): 341 self.logmsg += msg+'\n' 285 self.logmsg += msg+'\n' 342 if self.verbose or msg.startsw 286 if self.verbose or msg.startswith('WARNING:'): 343 pprint(msg) 287 pprint(msg) 344 def signalHandler(self, signum, frame) 288 def signalHandler(self, signum, frame): 345 if not self.result: 289 if not self.result: 346 return 290 return 347 signame = self.signames[signum 291 signame = self.signames[signum] if signum in self.signames else 'UNKNOWN' 348 msg = 'Signal %s caused a tool 292 msg = 'Signal %s caused a tool exit, line %d' % (signame, frame.f_lineno) 349 self.outputResult({'error':msg !! 293 sysvals.outputResult({'error':msg}) 350 sys.exit(3) 294 sys.exit(3) 351 def signalHandlerInit(self): 295 def signalHandlerInit(self): 352 capture = ['BUS', 'SYS', 'XCPU 296 capture = ['BUS', 'SYS', 'XCPU', 'XFSZ', 'PWR', 'HUP', 'INT', 'QUIT', 353 'ILL', 'ABRT', 'FPE', !! 297 'ILL', 'ABRT', 'FPE', 'SEGV', 'TERM', 'TSTP'] 354 self.signames = dict() 298 self.signames = dict() 355 for i in capture: 299 for i in capture: 356 s = 'SIG'+i 300 s = 'SIG'+i 357 try: 301 try: 358 signum = getat 302 signum = getattr(signal, s) 359 signal.signal( 303 signal.signal(signum, self.signalHandler) 360 except: 304 except: 361 continue 305 continue 362 self.signames[signum] 306 self.signames[signum] = s 363 def rootCheck(self, fatal=True): 307 def rootCheck(self, fatal=True): 364 if(os.access(self.powerfile, o 308 if(os.access(self.powerfile, os.W_OK)): 365 return True 309 return True 366 if fatal: 310 if fatal: 367 msg = 'This command re 311 msg = 'This command requires sysfs mount and root access' 368 pprint('ERROR: %s\n' % 312 pprint('ERROR: %s\n' % msg) 369 self.outputResult({'er 313 self.outputResult({'error':msg}) 370 sys.exit(1) 314 sys.exit(1) 371 return False 315 return False 372 def rootUser(self, fatal=False): 316 def rootUser(self, fatal=False): 373 if 'USER' in os.environ and os 317 if 'USER' in os.environ and os.environ['USER'] == 'root': 374 return True 318 return True 375 if fatal: 319 if fatal: 376 msg = 'This command mu 320 msg = 'This command must be run as root' 377 pprint('ERROR: %s\n' % 321 pprint('ERROR: %s\n' % msg) 378 self.outputResult({'er 322 self.outputResult({'error':msg}) 379 sys.exit(1) 323 sys.exit(1) 380 return False 324 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): 325 def getExec(self, cmd): 395 try: !! 326 dirlist = ['/sbin', '/bin', '/usr/sbin', '/usr/bin', 396 fp = Popen(['which', c !! 327 '/usr/local/sbin', '/usr/local/bin'] 397 out = ascii(fp.read()) !! 328 for path in dirlist: 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 329 cmdfull = os.path.join(path, cmd) 406 if os.path.exists(cmdf 330 if os.path.exists(cmdfull): 407 return cmdfull 331 return cmdfull 408 return out !! 332 return '' 409 def setPrecision(self, num): 333 def setPrecision(self, num): 410 if num < 0 or num > 6: 334 if num < 0 or num > 6: 411 return 335 return 412 self.timeformat = '%.{0}f'.for 336 self.timeformat = '%.{0}f'.format(num) 413 def setOutputFolder(self, value): 337 def setOutputFolder(self, value): 414 args = dict() 338 args = dict() 415 n = datetime.now() 339 n = datetime.now() 416 args['date'] = n.strftime('%y% 340 args['date'] = n.strftime('%y%m%d') 417 args['time'] = n.strftime('%H% 341 args['time'] = n.strftime('%H%M%S') 418 args['hostname'] = args['host' 342 args['hostname'] = args['host'] = self.hostname 419 args['mode'] = self.suspendmod 343 args['mode'] = self.suspendmode 420 return value.format(**args) 344 return value.format(**args) 421 def setOutputFile(self): 345 def setOutputFile(self): 422 if self.dmesgfile != '': 346 if self.dmesgfile != '': 423 m = re.match(r'(?P<nam !! 347 m = re.match('(?P<name>.*)_dmesg\.txt.*', self.dmesgfile) 424 if(m): 348 if(m): 425 self.htmlfile 349 self.htmlfile = m.group('name')+'.html' 426 if self.ftracefile != '': 350 if self.ftracefile != '': 427 m = re.match(r'(?P<nam !! 351 m = re.match('(?P<name>.*)_ftrace\.txt.*', self.ftracefile) 428 if(m): 352 if(m): 429 self.htmlfile 353 self.htmlfile = m.group('name')+'.html' 430 def systemInfo(self, info): 354 def systemInfo(self, info): 431 p = m = '' 355 p = m = '' 432 if 'baseboard-manufacturer' in 356 if 'baseboard-manufacturer' in info: 433 m = info['baseboard-ma 357 m = info['baseboard-manufacturer'] 434 elif 'system-manufacturer' in 358 elif 'system-manufacturer' in info: 435 m = info['system-manuf 359 m = info['system-manufacturer'] 436 if 'system-product-name' in in 360 if 'system-product-name' in info: 437 p = info['system-produ 361 p = info['system-product-name'] 438 elif 'baseboard-product-name' 362 elif 'baseboard-product-name' in info: 439 p = info['baseboard-pr 363 p = info['baseboard-product-name'] 440 if m[:5].lower() == 'intel' an 364 if m[:5].lower() == 'intel' and 'baseboard-product-name' in info: 441 p = info['baseboard-pr 365 p = info['baseboard-product-name'] 442 c = info['processor-version'] 366 c = info['processor-version'] if 'processor-version' in info else '' 443 b = info['bios-version'] if 'b 367 b = info['bios-version'] if 'bios-version' in info else '' 444 r = info['bios-release-date'] 368 r = info['bios-release-date'] if 'bios-release-date' in info else '' 445 self.sysstamp = '# sysinfo | m 369 self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | biosdate:%s | numcpu:%d | memsz:%d | memfr:%d' % \ 446 (m, p, c, b, r, self.c 370 (m, p, c, b, r, self.cpucount, self.memtotal, self.memfree) 447 if self.osversion: !! 371 try: 448 self.sysstamp += ' | o !! 372 kcmd = open('/proc/cmdline', 'r').read().strip() >> 373 except: >> 374 kcmd = '' >> 375 if kcmd: >> 376 self.sysstamp += '\n# kparams | %s' % kcmd 449 def printSystemInfo(self, fatal=False) 377 def printSystemInfo(self, fatal=False): 450 self.rootCheck(True) 378 self.rootCheck(True) 451 out = dmidecode(self.mempath, 379 out = dmidecode(self.mempath, fatal) 452 if len(out) < 1: 380 if len(out) < 1: 453 return 381 return 454 fmt = '%-24s: %s' 382 fmt = '%-24s: %s' 455 if self.osversion: << 456 print(fmt % ('os-versi << 457 for name in sorted(out): 383 for name in sorted(out): 458 print(fmt % (name, out 384 print(fmt % (name, out[name])) 459 print(fmt % ('cpucount', ('%d' 385 print(fmt % ('cpucount', ('%d' % self.cpucount))) 460 print(fmt % ('memtotal', ('%d 386 print(fmt % ('memtotal', ('%d kB' % self.memtotal))) 461 print(fmt % ('memfree', ('%d k 387 print(fmt % ('memfree', ('%d kB' % self.memfree))) 462 def cpuInfo(self): 388 def cpuInfo(self): 463 self.cpucount = 0 389 self.cpucount = 0 464 if os.path.exists('/proc/cpuin !! 390 fp = open('/proc/cpuinfo', 'r') 465 with open('/proc/cpuin !! 391 for line in fp: 466 for line in fp !! 392 if re.match('^processor[ \t]*:[ \t]*[0-9]*', line): 467 if re. !! 393 self.cpucount += 1 468 !! 394 fp.close() 469 if os.path.exists('/proc/memin !! 395 fp = open('/proc/meminfo', 'r') 470 with open('/proc/memin !! 396 for line in fp: 471 for line in fp !! 397 m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line) 472 m = re !! 398 if m: 473 if m: !! 399 self.memtotal = int(m.group('sz')) 474 !! 400 m = re.match('^MemFree:[ \t]*(?P<sz>[0-9]*) *kB', line) 475 m = re !! 401 if m: 476 if m: !! 402 self.memfree = int(m.group('sz')) 477 !! 403 fp.close() 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): 404 def initTestOutput(self, name): 484 self.prefix = self.hostname 405 self.prefix = self.hostname 485 v = open('/proc/version', 'r') 406 v = open('/proc/version', 'r').read().strip() 486 kver = v.split()[2] 407 kver = v.split()[2] 487 fmt = name+'-%m%d%y-%H%M%S' 408 fmt = name+'-%m%d%y-%H%M%S' 488 testtime = datetime.now().strf 409 testtime = datetime.now().strftime(fmt) 489 self.teststamp = \ 410 self.teststamp = \ 490 '# '+testtime+' '+self 411 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver 491 ext = '' 412 ext = '' 492 if self.gzip: 413 if self.gzip: 493 ext = '.gz' 414 ext = '.gz' 494 self.dmesgfile = \ 415 self.dmesgfile = \ 495 self.testdir+'/'+self. 416 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt'+ext 496 self.ftracefile = \ 417 self.ftracefile = \ 497 self.testdir+'/'+self. 418 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt'+ext 498 self.htmlfile = \ 419 self.htmlfile = \ 499 self.testdir+'/'+self. 420 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html' 500 if not os.path.isdir(self.test 421 if not os.path.isdir(self.testdir): 501 os.makedirs(self.testd 422 os.makedirs(self.testdir) 502 self.sudoUserchown(self.testdi << 503 def getValueList(self, value): 423 def getValueList(self, value): 504 out = [] 424 out = [] 505 for i in value.split(','): 425 for i in value.split(','): 506 if i.strip(): 426 if i.strip(): 507 out.append(i.s 427 out.append(i.strip()) 508 return out 428 return out 509 def setDeviceFilter(self, value): 429 def setDeviceFilter(self, value): 510 self.devicefilter = self.getVa 430 self.devicefilter = self.getValueList(value) 511 def setCallgraphFilter(self, value): 431 def setCallgraphFilter(self, value): 512 self.cgfilter = self.getValueL 432 self.cgfilter = self.getValueList(value) 513 def skipKprobes(self, value): 433 def skipKprobes(self, value): 514 for k in self.getValueList(val 434 for k in self.getValueList(value): 515 if k in self.tracefunc 435 if k in self.tracefuncs: 516 del self.trace 436 del self.tracefuncs[k] 517 if k in self.dev_trace 437 if k in self.dev_tracefuncs: 518 del self.dev_t 438 del self.dev_tracefuncs[k] 519 def setCallgraphBlacklist(self, file): 439 def setCallgraphBlacklist(self, file): 520 self.cgblacklist = self.listFr 440 self.cgblacklist = self.listFromFile(file) 521 def rtcWakeAlarmOn(self): 441 def rtcWakeAlarmOn(self): 522 call('echo 0 > '+self.rtcpath+ 442 call('echo 0 > '+self.rtcpath+'/wakealarm', shell=True) 523 nowtime = open(self.rtcpath+'/ 443 nowtime = open(self.rtcpath+'/since_epoch', 'r').read().strip() 524 if nowtime: 444 if nowtime: 525 nowtime = int(nowtime) 445 nowtime = int(nowtime) 526 else: 446 else: 527 # if hardware time fai 447 # if hardware time fails, use the software time 528 nowtime = int(datetime 448 nowtime = int(datetime.now().strftime('%s')) 529 alarm = nowtime + self.rtcwake 449 alarm = nowtime + self.rtcwaketime 530 call('echo %d > %s/wakealarm' 450 call('echo %d > %s/wakealarm' % (alarm, self.rtcpath), shell=True) 531 def rtcWakeAlarmOff(self): 451 def rtcWakeAlarmOff(self): 532 call('echo 0 > %s/wakealarm' % 452 call('echo 0 > %s/wakealarm' % self.rtcpath, shell=True) 533 def initdmesg(self): 453 def initdmesg(self): 534 # get the latest time stamp fr 454 # get the latest time stamp from the dmesg log 535 lines = Popen('dmesg', stdout= !! 455 fp = Popen('dmesg', stdout=PIPE).stdout 536 ktime = '0' 456 ktime = '0' 537 for line in reversed(lines): !! 457 for line in fp: 538 line = ascii(line).rep !! 458 line = line.replace('\r\n', '') 539 idx = line.find('[') 459 idx = line.find('[') 540 if idx > 1: 460 if idx > 1: 541 line = line[id 461 line = line[idx:] 542 m = re.match(r'[ \t]*( !! 462 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 543 if(m): 463 if(m): 544 ktime = m.grou 464 ktime = m.group('ktime') 545 break !! 465 fp.close() 546 self.dmesgstart = float(ktime) 466 self.dmesgstart = float(ktime) 547 def getdmesg(self, testdata): 467 def getdmesg(self, testdata): 548 op = self.writeDatafileHeader( !! 468 op = self.writeDatafileHeader(sysvals.dmesgfile, testdata) 549 # store all new dmesg lines si 469 # store all new dmesg lines since initdmesg was called 550 fp = Popen('dmesg', stdout=PIP 470 fp = Popen('dmesg', stdout=PIPE).stdout 551 for line in fp: 471 for line in fp: 552 line = ascii(line).rep !! 472 line = line.replace('\r\n', '') 553 idx = line.find('[') 473 idx = line.find('[') 554 if idx > 1: 474 if idx > 1: 555 line = line[id 475 line = line[idx:] 556 m = re.match(r'[ \t]*( !! 476 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 557 if(not m): 477 if(not m): 558 continue 478 continue 559 ktime = float(m.group( 479 ktime = float(m.group('ktime')) 560 if ktime > self.dmesgs 480 if ktime > self.dmesgstart: 561 op.write(line) 481 op.write(line) 562 fp.close() 482 fp.close() 563 op.close() 483 op.close() 564 def listFromFile(self, file): 484 def listFromFile(self, file): 565 list = [] 485 list = [] 566 fp = open(file) 486 fp = open(file) 567 for i in fp.read().split('\n') 487 for i in fp.read().split('\n'): 568 i = i.strip() 488 i = i.strip() 569 if i and i[0] != '#': 489 if i and i[0] != '#': 570 list.append(i) 490 list.append(i) 571 fp.close() 491 fp.close() 572 return list 492 return list 573 def addFtraceFilterFunctions(self, fil 493 def addFtraceFilterFunctions(self, file): 574 for i in self.listFromFile(fil 494 for i in self.listFromFile(file): 575 if len(i) < 2: 495 if len(i) < 2: 576 continue 496 continue 577 self.tracefuncs[i] = d 497 self.tracefuncs[i] = dict() 578 def getFtraceFilterFunctions(self, cur 498 def getFtraceFilterFunctions(self, current): 579 self.rootCheck(True) 499 self.rootCheck(True) 580 if not current: 500 if not current: 581 call('cat '+self.tpath 501 call('cat '+self.tpath+'available_filter_functions', shell=True) 582 return 502 return 583 master = self.listFromFile(sel 503 master = self.listFromFile(self.tpath+'available_filter_functions') 584 for i in sorted(self.tracefunc !! 504 for i in self.tracefuncs: 585 if 'func' in self.trac 505 if 'func' in self.tracefuncs[i]: 586 i = self.trace 506 i = self.tracefuncs[i]['func'] 587 if i in master: 507 if i in master: 588 print(i) 508 print(i) 589 else: 509 else: 590 print(self.col 510 print(self.colorText(i)) 591 def setFtraceFilterFunctions(self, lis 511 def setFtraceFilterFunctions(self, list): 592 master = self.listFromFile(sel 512 master = self.listFromFile(self.tpath+'available_filter_functions') 593 flist = '' 513 flist = '' 594 for i in list: 514 for i in list: 595 if i not in master: 515 if i not in master: 596 continue 516 continue 597 if ' [' in i: 517 if ' [' in i: 598 flist += i.spl 518 flist += i.split(' ')[0]+'\n' 599 else: 519 else: 600 flist += i+'\n 520 flist += i+'\n' 601 fp = open(self.tpath+'set_grap 521 fp = open(self.tpath+'set_graph_function', 'w') 602 fp.write(flist) 522 fp.write(flist) 603 fp.close() 523 fp.close() 604 def basicKprobe(self, name): 524 def basicKprobe(self, name): 605 self.kprobes[name] = {'name': 525 self.kprobes[name] = {'name': name,'func': name,'args': dict(),'format': name} 606 def defaultKprobe(self, name, kdata): 526 def defaultKprobe(self, name, kdata): 607 k = kdata 527 k = kdata 608 for field in ['name', 'format' 528 for field in ['name', 'format', 'func']: 609 if field not in k: 529 if field not in k: 610 k[field] = nam 530 k[field] = name 611 if self.archargs in k: 531 if self.archargs in k: 612 k['args'] = k[self.arc 532 k['args'] = k[self.archargs] 613 else: 533 else: 614 k['args'] = dict() 534 k['args'] = dict() 615 k['format'] = name 535 k['format'] = name 616 self.kprobes[name] = k 536 self.kprobes[name] = k 617 def kprobeColor(self, name): 537 def kprobeColor(self, name): 618 if name not in self.kprobes or 538 if name not in self.kprobes or 'color' not in self.kprobes[name]: 619 return '' 539 return '' 620 return self.kprobes[name]['col 540 return self.kprobes[name]['color'] 621 def kprobeDisplayName(self, name, data 541 def kprobeDisplayName(self, name, dataraw): 622 if name not in self.kprobes: 542 if name not in self.kprobes: 623 self.basicKprobe(name) 543 self.basicKprobe(name) 624 data = '' 544 data = '' 625 quote=0 545 quote=0 626 # first remvoe any spaces insi 546 # first remvoe any spaces inside quotes, and the quotes 627 for c in dataraw: 547 for c in dataraw: 628 if c == '"': 548 if c == '"': 629 quote = (quote 549 quote = (quote + 1) % 2 630 if quote and c == ' ': 550 if quote and c == ' ': 631 data += '_' 551 data += '_' 632 elif c != '"': 552 elif c != '"': 633 data += c 553 data += c 634 fmt, args = self.kprobes[name] 554 fmt, args = self.kprobes[name]['format'], self.kprobes[name]['args'] 635 arglist = dict() 555 arglist = dict() 636 # now process the args 556 # now process the args 637 for arg in sorted(args): 557 for arg in sorted(args): 638 arglist[arg] = '' 558 arglist[arg] = '' 639 m = re.match(r'.* '+ar !! 559 m = re.match('.* '+arg+'=(?P<arg>.*) ', data); 640 if m: 560 if m: 641 arglist[arg] = 561 arglist[arg] = m.group('arg') 642 else: 562 else: 643 m = re.match(r !! 563 m = re.match('.* '+arg+'=(?P<arg>.*)', data); 644 if m: 564 if m: 645 arglis 565 arglist[arg] = m.group('arg') 646 out = fmt.format(**arglist) 566 out = fmt.format(**arglist) 647 out = out.replace(' ', '_').re 567 out = out.replace(' ', '_').replace('"', '') 648 return out 568 return out 649 def kprobeText(self, kname, kprobe): 569 def kprobeText(self, kname, kprobe): 650 name = fmt = func = kname 570 name = fmt = func = kname 651 args = dict() 571 args = dict() 652 if 'name' in kprobe: 572 if 'name' in kprobe: 653 name = kprobe['name'] 573 name = kprobe['name'] 654 if 'format' in kprobe: 574 if 'format' in kprobe: 655 fmt = kprobe['format'] 575 fmt = kprobe['format'] 656 if 'func' in kprobe: 576 if 'func' in kprobe: 657 func = kprobe['func'] 577 func = kprobe['func'] 658 if self.archargs in kprobe: 578 if self.archargs in kprobe: 659 args = kprobe[self.arc 579 args = kprobe[self.archargs] 660 if 'args' in kprobe: 580 if 'args' in kprobe: 661 args = kprobe['args'] 581 args = kprobe['args'] 662 if re.findall('{(?P<n>[a-z,A-Z 582 if re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', func): 663 doError('Kprobe "%s" h 583 doError('Kprobe "%s" has format info in the function name "%s"' % (name, func)) 664 for arg in re.findall('{(?P<n> 584 for arg in re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', fmt): 665 if arg not in args: 585 if arg not in args: 666 doError('Kprob 586 doError('Kprobe "%s" is missing argument "%s"' % (name, arg)) 667 val = 'p:%s_cal %s' % (name, f 587 val = 'p:%s_cal %s' % (name, func) 668 for i in sorted(args): 588 for i in sorted(args): 669 val += ' %s=%s' % (i, 589 val += ' %s=%s' % (i, args[i]) 670 val += '\nr:%s_ret %s $retval\ 590 val += '\nr:%s_ret %s $retval\n' % (name, func) 671 return val 591 return val 672 def addKprobes(self, output=False): 592 def addKprobes(self, output=False): 673 if len(self.kprobes) < 1: 593 if len(self.kprobes) < 1: 674 return 594 return 675 if output: 595 if output: 676 pprint(' kprobe fun 596 pprint(' kprobe functions in this kernel:') 677 # first test each kprobe 597 # first test each kprobe 678 rejects = [] 598 rejects = [] 679 # sort kprobes: trace, ub-dev, 599 # sort kprobes: trace, ub-dev, custom, dev 680 kpl = [[], [], [], []] 600 kpl = [[], [], [], []] 681 linesout = len(self.kprobes) 601 linesout = len(self.kprobes) 682 for name in sorted(self.kprobe 602 for name in sorted(self.kprobes): 683 res = self.colorText(' 603 res = self.colorText('YES', 32) 684 if not self.testKprobe 604 if not self.testKprobe(name, self.kprobes[name]): 685 res = self.col 605 res = self.colorText('NO') 686 rejects.append 606 rejects.append(name) 687 else: 607 else: 688 if name in sel 608 if name in self.tracefuncs: 689 kpl[0] 609 kpl[0].append(name) 690 elif name in s 610 elif name in self.dev_tracefuncs: 691 if 'ub 611 if 'ub' in self.dev_tracefuncs[name]: 692 612 kpl[1].append(name) 693 else: 613 else: 694 614 kpl[3].append(name) 695 else: 615 else: 696 kpl[2] 616 kpl[2].append(name) 697 if output: 617 if output: 698 pprint(' 618 pprint(' %s: %s' % (name, res)) 699 kplist = kpl[0] + kpl[1] + kpl 619 kplist = kpl[0] + kpl[1] + kpl[2] + kpl[3] 700 # remove all failed ones from 620 # remove all failed ones from the list 701 for name in rejects: 621 for name in rejects: 702 self.kprobes.pop(name) 622 self.kprobes.pop(name) 703 # set the kprobes all at once 623 # set the kprobes all at once 704 self.fsetVal('', 'kprobe_event 624 self.fsetVal('', 'kprobe_events') 705 kprobeevents = '' 625 kprobeevents = '' 706 for kp in kplist: 626 for kp in kplist: 707 kprobeevents += self.k 627 kprobeevents += self.kprobeText(kp, self.kprobes[kp]) 708 self.fsetVal(kprobeevents, 'kp 628 self.fsetVal(kprobeevents, 'kprobe_events') 709 if output: 629 if output: 710 check = self.fgetVal(' 630 check = self.fgetVal('kprobe_events') 711 linesack = (len(check. !! 631 linesack = (len(check.split('\n')) - 1) / 2 712 pprint(' kprobe fun 632 pprint(' kprobe functions enabled: %d/%d' % (linesack, linesout)) 713 self.fsetVal('1', 'events/kpro 633 self.fsetVal('1', 'events/kprobes/enable') 714 def testKprobe(self, kname, kprobe): 634 def testKprobe(self, kname, kprobe): 715 self.fsetVal('0', 'events/kpro 635 self.fsetVal('0', 'events/kprobes/enable') 716 kprobeevents = self.kprobeText 636 kprobeevents = self.kprobeText(kname, kprobe) 717 if not kprobeevents: 637 if not kprobeevents: 718 return False 638 return False 719 try: 639 try: 720 self.fsetVal(kprobeeve 640 self.fsetVal(kprobeevents, 'kprobe_events') 721 check = self.fgetVal(' 641 check = self.fgetVal('kprobe_events') 722 except: 642 except: 723 return False 643 return False 724 linesout = len(kprobeevents.sp 644 linesout = len(kprobeevents.split('\n')) 725 linesack = len(check.split('\n 645 linesack = len(check.split('\n')) 726 if linesack < linesout: 646 if linesack < linesout: 727 return False 647 return False 728 return True 648 return True 729 def setVal(self, val, file): !! 649 def setVal(self, val, file, mode='w'): 730 if not os.path.exists(file): 650 if not os.path.exists(file): 731 return False 651 return False 732 try: 652 try: 733 fp = open(file, 'wb', !! 653 fp = open(file, mode, 0) 734 fp.write(val.encode()) !! 654 fp.write(val) 735 fp.flush() 655 fp.flush() 736 fp.close() 656 fp.close() 737 except: 657 except: 738 return False 658 return False 739 return True 659 return True 740 def fsetVal(self, val, path): !! 660 def fsetVal(self, val, path, mode='w'): 741 if not self.useftrace: !! 661 return self.setVal(val, self.tpath+path, mode) 742 return False << 743 return self.setVal(val, self.t << 744 def getVal(self, file): 662 def getVal(self, file): 745 res = '' 663 res = '' 746 if not os.path.exists(file): 664 if not os.path.exists(file): 747 return res 665 return res 748 try: 666 try: 749 fp = open(file, 'r') 667 fp = open(file, 'r') 750 res = fp.read() 668 res = fp.read() 751 fp.close() 669 fp.close() 752 except: 670 except: 753 pass 671 pass 754 return res 672 return res 755 def fgetVal(self, path): 673 def fgetVal(self, path): 756 if not self.useftrace: << 757 return '' << 758 return self.getVal(self.tpath+ 674 return self.getVal(self.tpath+path) 759 def cleanupFtrace(self): 675 def cleanupFtrace(self): 760 if self.useftrace: !! 676 if(self.usecallgraph or self.usetraceevents or self.usedevsrc): 761 self.fsetVal('0', 'eve 677 self.fsetVal('0', 'events/kprobes/enable') 762 self.fsetVal('', 'kpro 678 self.fsetVal('', 'kprobe_events') 763 self.fsetVal('1024', ' 679 self.fsetVal('1024', 'buffer_size_kb') >> 680 if self.pmdebug: >> 681 self.setVal(self.pmdebug, self.pmdpath) 764 def setupAllKprobes(self): 682 def setupAllKprobes(self): 765 for name in self.tracefuncs: 683 for name in self.tracefuncs: 766 self.defaultKprobe(nam 684 self.defaultKprobe(name, self.tracefuncs[name]) 767 for name in self.dev_tracefunc 685 for name in self.dev_tracefuncs: 768 self.defaultKprobe(nam 686 self.defaultKprobe(name, self.dev_tracefuncs[name]) 769 def isCallgraphFunc(self, name): 687 def isCallgraphFunc(self, name): 770 if len(self.tracefuncs) < 1 an 688 if len(self.tracefuncs) < 1 and self.suspendmode == 'command': 771 return True 689 return True 772 for i in self.tracefuncs: 690 for i in self.tracefuncs: 773 if 'func' in self.trac 691 if 'func' in self.tracefuncs[i]: 774 f = self.trace 692 f = self.tracefuncs[i]['func'] 775 else: 693 else: 776 f = i 694 f = i 777 if name == f: 695 if name == f: 778 return True 696 return True 779 return False 697 return False 780 def initFtrace(self, quiet=False): !! 698 def initFtrace(self): 781 if not self.useftrace: !! 699 self.printSystemInfo(False) 782 return !! 700 pprint('INITIALIZING FTRACE...') 783 if not quiet: << 784 sysvals.printSystemInf << 785 pprint('INITIALIZING F << 786 # turn trace off 701 # turn trace off 787 self.fsetVal('0', 'tracing_on' 702 self.fsetVal('0', 'tracing_on') 788 self.cleanupFtrace() 703 self.cleanupFtrace() >> 704 # pm debug messages >> 705 pv = self.getVal(self.pmdpath) >> 706 if pv != '1': >> 707 self.setVal('1', self.pmdpath) >> 708 self.pmdebug = pv 789 # set the trace clock to globa 709 # set the trace clock to global 790 self.fsetVal('global', 'trace_ 710 self.fsetVal('global', 'trace_clock') 791 self.fsetVal('nop', 'current_t 711 self.fsetVal('nop', 'current_tracer') 792 # set trace buffer to an appro 712 # set trace buffer to an appropriate value 793 cpus = max(1, self.cpucount) 713 cpus = max(1, self.cpucount) 794 if self.bufsize > 0: 714 if self.bufsize > 0: 795 tgtsize = self.bufsize 715 tgtsize = self.bufsize 796 elif self.usecallgraph or self 716 elif self.usecallgraph or self.usedevsrc: 797 bmax = (1*1024*1024) i 717 bmax = (1*1024*1024) if self.suspendmode in ['disk', 'command'] \ 798 else (3*1024*1 718 else (3*1024*1024) 799 tgtsize = min(self.mem 719 tgtsize = min(self.memfree, bmax) 800 else: 720 else: 801 tgtsize = 65536 721 tgtsize = 65536 802 while not self.fsetVal('%d' % !! 722 while not self.fsetVal('%d' % (tgtsize / cpus), 'buffer_size_kb'): 803 # if the size failed t 723 # if the size failed to set, lower it and keep trying 804 tgtsize -= 65536 724 tgtsize -= 65536 805 if tgtsize < 65536: 725 if tgtsize < 65536: 806 tgtsize = int( 726 tgtsize = int(self.fgetVal('buffer_size_kb')) * cpus 807 break 727 break 808 self.vprint('Setting trace buf !! 728 pprint('Setting trace buffers to %d kB (%d kB per cpu)' % (tgtsize, tgtsize/cpus)) 809 # initialize the callgraph tra 729 # initialize the callgraph trace 810 if(self.usecallgraph): 730 if(self.usecallgraph): 811 # set trace type 731 # set trace type 812 self.fsetVal('function 732 self.fsetVal('function_graph', 'current_tracer') 813 self.fsetVal('', 'set_ 733 self.fsetVal('', 'set_ftrace_filter') 814 # temporary hack to fi << 815 fp = open(self.tpath+' << 816 fp.write('native_queue << 817 fp.close() << 818 # set trace format opt 734 # set trace format options 819 self.fsetVal('print-pa 735 self.fsetVal('print-parent', 'trace_options') 820 self.fsetVal('funcgrap 736 self.fsetVal('funcgraph-abstime', 'trace_options') 821 self.fsetVal('funcgrap 737 self.fsetVal('funcgraph-cpu', 'trace_options') 822 self.fsetVal('funcgrap 738 self.fsetVal('funcgraph-duration', 'trace_options') 823 self.fsetVal('funcgrap 739 self.fsetVal('funcgraph-proc', 'trace_options') 824 self.fsetVal('funcgrap 740 self.fsetVal('funcgraph-tail', 'trace_options') 825 self.fsetVal('nofuncgr 741 self.fsetVal('nofuncgraph-overhead', 'trace_options') 826 self.fsetVal('context- 742 self.fsetVal('context-info', 'trace_options') 827 self.fsetVal('graph-ti 743 self.fsetVal('graph-time', 'trace_options') 828 self.fsetVal('%d' % se 744 self.fsetVal('%d' % self.max_graph_depth, 'max_graph_depth') 829 cf = ['dpm_run_callbac 745 cf = ['dpm_run_callback'] 830 if(self.usetraceevents 746 if(self.usetraceevents): 831 cf += ['dpm_pr 747 cf += ['dpm_prepare', 'dpm_complete'] 832 for fn in self.tracefu 748 for fn in self.tracefuncs: 833 if 'func' in s 749 if 'func' in self.tracefuncs[fn]: 834 cf.app 750 cf.append(self.tracefuncs[fn]['func']) 835 else: 751 else: 836 cf.app 752 cf.append(fn) 837 if self.ftop: 753 if self.ftop: 838 self.setFtrace 754 self.setFtraceFilterFunctions([self.ftopfunc]) 839 else: 755 else: 840 self.setFtrace 756 self.setFtraceFilterFunctions(cf) 841 # initialize the kprobe trace 757 # initialize the kprobe trace 842 elif self.usekprobes: 758 elif self.usekprobes: 843 for name in self.trace 759 for name in self.tracefuncs: 844 self.defaultKp 760 self.defaultKprobe(name, self.tracefuncs[name]) 845 if self.usedevsrc: 761 if self.usedevsrc: 846 for name in se 762 for name in self.dev_tracefuncs: 847 self.d 763 self.defaultKprobe(name, self.dev_tracefuncs[name]) 848 if not quiet: !! 764 pprint('INITIALIZING KPROBES...') 849 pprint('INITIA << 850 self.addKprobes(self.v 765 self.addKprobes(self.verbose) 851 if(self.usetraceevents): 766 if(self.usetraceevents): 852 # turn trace events on 767 # turn trace events on 853 events = iter(self.tra 768 events = iter(self.traceevents) 854 for e in events: 769 for e in events: 855 self.fsetVal(' 770 self.fsetVal('1', 'events/power/'+e+'/enable') 856 # clear the trace buffer 771 # clear the trace buffer 857 self.fsetVal('', 'trace') 772 self.fsetVal('', 'trace') 858 def verifyFtrace(self): 773 def verifyFtrace(self): 859 # files needed for any trace d 774 # files needed for any trace data 860 files = ['buffer_size_kb', 'cu 775 files = ['buffer_size_kb', 'current_tracer', 'trace', 'trace_clock', 861 'trace_marker 776 'trace_marker', 'trace_options', 'tracing_on'] 862 # files needed for callgraph t 777 # files needed for callgraph trace data 863 tp = self.tpath 778 tp = self.tpath 864 if(self.usecallgraph): 779 if(self.usecallgraph): 865 files += [ 780 files += [ 866 'available_fil 781 'available_filter_functions', 867 'set_ftrace_fi 782 'set_ftrace_filter', 868 'set_graph_fun 783 'set_graph_function' 869 ] 784 ] 870 for f in files: 785 for f in files: 871 if(os.path.exists(tp+f 786 if(os.path.exists(tp+f) == False): 872 return False 787 return False 873 return True 788 return True 874 def verifyKprobes(self): 789 def verifyKprobes(self): 875 # files needed for kprobes to 790 # files needed for kprobes to work 876 files = ['kprobe_events', 'eve 791 files = ['kprobe_events', 'events'] 877 tp = self.tpath 792 tp = self.tpath 878 for f in files: 793 for f in files: 879 if(os.path.exists(tp+f 794 if(os.path.exists(tp+f) == False): 880 return False 795 return False 881 return True 796 return True 882 def colorText(self, str, color=31): 797 def colorText(self, str, color=31): 883 if not self.ansi: 798 if not self.ansi: 884 return str 799 return str 885 return '\x1B[%d;40m%s\x1B[m' % 800 return '\x1B[%d;40m%s\x1B[m' % (color, str) 886 def writeDatafileHeader(self, filename 801 def writeDatafileHeader(self, filename, testdata): 887 fp = self.openlog(filename, 'w 802 fp = self.openlog(filename, 'w') 888 fp.write('%s\n%s\n# command | 803 fp.write('%s\n%s\n# command | %s\n' % (self.teststamp, self.sysstamp, self.cmdline)) 889 for test in testdata: 804 for test in testdata: 890 if 'fw' in test: 805 if 'fw' in test: 891 fw = test['fw' 806 fw = test['fw'] 892 if(fw): 807 if(fw): 893 fp.wri 808 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1])) >> 809 if 'mcelog' in test: >> 810 fp.write('# mcelog %s\n' % test['mcelog']) 894 if 'turbo' in test: 811 if 'turbo' in test: 895 fp.write('# tu 812 fp.write('# turbostat %s\n' % test['turbo']) >> 813 if 'bat' in test: >> 814 (a1, c1), (a2, c2) = test['bat'] >> 815 fp.write('# battery %s %d %s %d\n' % (a1, c1, a2, c2)) 896 if 'wifi' in test: 816 if 'wifi' in test: 897 fp.write('# wi !! 817 wstr = [] 898 if 'netfix' in test: !! 818 for wifi in test['wifi']: 899 fp.write('# ne !! 819 tmp = [] >> 820 for key in sorted(wifi): >> 821 tmp.append('%s:%s' % (key, wifi[key])) >> 822 wstr.append('|'.join(tmp)) >> 823 fp.write('# wifi %s\n' % (','.join(wstr))) 900 if test['error'] or le 824 if test['error'] or len(testdata) > 1: 901 fp.write('# en 825 fp.write('# enter_sleep_error %s\n' % test['error']) 902 return fp 826 return fp 903 def sudoUserchown(self, dir): 827 def sudoUserchown(self, dir): 904 if os.path.exists(dir) and sel 828 if os.path.exists(dir) and self.sudouser: 905 cmd = 'chown -R {0}:{0 829 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1' 906 call(cmd.format(self.s 830 call(cmd.format(self.sudouser, dir), shell=True) 907 def outputResult(self, testdata, num=0 831 def outputResult(self, testdata, num=0): 908 if not self.result: 832 if not self.result: 909 return 833 return 910 n = '' 834 n = '' 911 if num > 0: 835 if num > 0: 912 n = '%d' % num 836 n = '%d' % num 913 fp = open(self.result, 'a') 837 fp = open(self.result, 'a') 914 if 'error' in testdata: 838 if 'error' in testdata: 915 fp.write('result%s: fa 839 fp.write('result%s: fail\n' % n) 916 fp.write('error%s: %s\ 840 fp.write('error%s: %s\n' % (n, testdata['error'])) 917 else: 841 else: 918 fp.write('result%s: pa 842 fp.write('result%s: pass\n' % n) 919 if 'mode' in testdata: << 920 fp.write('mode%s: %s\n << 921 for v in ['suspend', 'resume', 843 for v in ['suspend', 'resume', 'boot', 'lastinit']: 922 if v in testdata: 844 if v in testdata: 923 fp.write('%s%s 845 fp.write('%s%s: %.3f\n' % (v, n, testdata[v])) 924 for v in ['fwsuspend', 'fwresu 846 for v in ['fwsuspend', 'fwresume']: 925 if v in testdata: 847 if v in testdata: 926 fp.write('%s%s 848 fp.write('%s%s: %.3f\n' % (v, n, testdata[v] / 1000000.0)) 927 if 'bugurl' in testdata: 849 if 'bugurl' in testdata: 928 fp.write('url%s: %s\n' 850 fp.write('url%s: %s\n' % (n, testdata['bugurl'])) 929 fp.close() 851 fp.close() 930 self.sudoUserchown(self.result 852 self.sudoUserchown(self.result) 931 def configFile(self, file): 853 def configFile(self, file): 932 dir = os.path.dirname(os.path. 854 dir = os.path.dirname(os.path.realpath(__file__)) 933 if os.path.exists(file): 855 if os.path.exists(file): 934 return file 856 return file 935 elif os.path.exists(dir+'/'+fi 857 elif os.path.exists(dir+'/'+file): 936 return dir+'/'+file 858 return dir+'/'+file 937 elif os.path.exists(dir+'/conf 859 elif os.path.exists(dir+'/config/'+file): 938 return dir+'/config/'+ 860 return dir+'/config/'+file 939 return '' 861 return '' 940 def openlog(self, filename, mode): 862 def openlog(self, filename, mode): 941 isgz = self.gzip 863 isgz = self.gzip 942 if mode == 'r': 864 if mode == 'r': 943 try: 865 try: 944 with gzip.open !! 866 with gzip.open(filename, mode+'b') as fp: 945 test = 867 test = fp.read(64) 946 isgz = True 868 isgz = True 947 except: 869 except: 948 isgz = False 870 isgz = False 949 if isgz: 871 if isgz: 950 return gzip.open(filen !! 872 return gzip.open(filename, mode+'b') 951 return open(filename, mode) 873 return open(filename, mode) 952 def putlog(self, filename, text): !! 874 def mcelog(self, clear=False): 953 with self.openlog(filename, 'a !! 875 cmd = self.getExec('mcelog') 954 fp.write(text) !! 876 if not cmd: 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 '' 877 return '' 1056 prefix = list[0] !! 878 if clear: 1057 for s in list[1:]: !! 879 call(cmd+' > /dev/null 2>&1', shell=True) 1058 while s[:len(prefix)] !! 880 return '' 1059 prefix = pref !! 881 fp = Popen([cmd], stdout=PIPE, stderr=PIPE).stdout 1060 if not prefix: !! 882 out = fp.read().strip() 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() 883 fp.close() 1164 if '[s2idle]' in data: !! 884 if not out: 1165 return True !! 885 return '' 1166 return False !! 886 return base64.b64encode(out.encode('zlib')) 1167 def haveTurbostat(self): 887 def haveTurbostat(self): 1168 if not self.tstat: 888 if not self.tstat: 1169 return False 889 return False 1170 cmd = self.getExec('turbostat 890 cmd = self.getExec('turbostat') 1171 if not cmd: 891 if not cmd: 1172 return False 892 return False 1173 fp = Popen([cmd, '-v'], stdou 893 fp = Popen([cmd, '-v'], stdout=PIPE, stderr=PIPE).stderr 1174 out = ascii(fp.read()).strip( !! 894 out = fp.read().strip() 1175 fp.close() 895 fp.close() 1176 if re.match(r'turbostat versi !! 896 return re.match('turbostat version [0-9\.]* .*', out) 1177 self.vprint(out) !! 897 def turbostat(self): 1178 return True << 1179 return False << 1180 def turbostat(self, s0ixready): << 1181 cmd = self.getExec('turbostat 898 cmd = self.getExec('turbostat') 1182 rawout = keyline = valline = !! 899 if not cmd: >> 900 return 'missing turbostat executable' >> 901 text = [] 1183 fullcmd = '%s -q -S echo free 902 fullcmd = '%s -q -S echo freeze > %s' % (cmd, self.powerfile) 1184 fp = Popen(['sh', '-c', fullc !! 903 fp = Popen(['sh', '-c', fullcmd], stdout=PIPE, stderr=PIPE).stderr 1185 for line in fp.stderr: !! 904 for line in fp: 1186 line = ascii(line) !! 905 if re.match('[0-9.]* sec', line): 1187 rawout += line << 1188 if keyline and vallin << 1189 continue 906 continue 1190 if re.match(r'(?i)Avg !! 907 text.append(line.split()) 1191 keyline = lin !! 908 fp.close() 1192 elif keyline: !! 909 if len(text) < 2: 1193 valline = lin !! 910 return 'turbostat output format error' 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 = [] 911 out = [] 1204 for key in keyline: !! 912 for key in text[0]: 1205 idx = keyline.index(k !! 913 values = [] 1206 val = valline[idx] !! 914 idx = text[0].index(key) 1207 if key == 'SYS%LPI' a !! 915 for line in text[1:]: >> 916 if len(line) > idx: >> 917 values.append(line[idx]) >> 918 out.append('%s=%s' % (key, ','.join(values))) >> 919 return '|'.join(out) >> 920 def checkWifi(self): >> 921 out = dict() >> 922 iwcmd, ifcmd = self.getExec('iwconfig'), self.getExec('ifconfig') >> 923 if not iwcmd or not ifcmd: >> 924 return out >> 925 fp = Popen(iwcmd, stdout=PIPE, stderr=PIPE).stdout >> 926 for line in fp: >> 927 m = re.match('(?P<dev>\S*) .* ESSID:(?P<ess>\S*)', line) >> 928 if not m: 1208 continue 929 continue 1209 out.append('%s=%s' % !! 930 out['device'] = m.group('dev') 1210 return (fp.returncode, '|'.jo !! 931 if '"' in m.group('ess'): 1211 def netfixon(self, net='both'): !! 932 out['essid'] = m.group('ess').strip('"') 1212 cmd = self.getExec('netfix') !! 933 break 1213 if not cmd: << 1214 return '' << 1215 fp = Popen([cmd, '-s', net, ' << 1216 out = ascii(fp.read()).strip( << 1217 fp.close() 934 fp.close() >> 935 if 'device' in out: >> 936 fp = Popen([ifcmd, out['device']], stdout=PIPE, stderr=PIPE).stdout >> 937 for line in fp: >> 938 m = re.match('.* inet (?P<ip>[0-9\.]*)', line) >> 939 if m: >> 940 out['ip'] = m.group('ip') >> 941 break >> 942 fp.close() 1218 return out 943 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): 944 def errorSummary(self, errinfo, msg): 1250 found = False 945 found = False 1251 for entry in errinfo: 946 for entry in errinfo: 1252 if re.match(entry['ma 947 if re.match(entry['match'], msg): 1253 entry['count' 948 entry['count'] += 1 1254 if self.hostn 949 if self.hostname not in entry['urls']: 1255 entry 950 entry['urls'][self.hostname] = [self.htmlfile] 1256 elif self.htm 951 elif self.htmlfile not in entry['urls'][self.hostname]: 1257 entry 952 entry['urls'][self.hostname].append(self.htmlfile) 1258 found = True 953 found = True 1259 break 954 break 1260 if found: 955 if found: 1261 return 956 return 1262 arr = msg.split() 957 arr = msg.split() 1263 for j in range(len(arr)): 958 for j in range(len(arr)): 1264 if re.match(r'^[0-9,\ !! 959 if re.match('^[0-9,\-\.]*$', arr[j]): 1265 arr[j] = r'[0 !! 960 arr[j] = '[0-9,\-\.]*' 1266 else: 961 else: 1267 arr[j] = arr[ 962 arr[j] = arr[j]\ 1268 .repl !! 963 .replace('\\', '\\\\').replace(']', '\]').replace('[', '\[')\ 1269 .repl !! 964 .replace('.', '\.').replace('+', '\+').replace('*', '\*')\ 1270 .repl !! 965 .replace('(', '\(').replace(')', '\)') 1271 .repl !! 966 mstr = ' '.join(arr) 1272 mstr = ' *'.join(arr) << 1273 entry = { 967 entry = { 1274 'line': msg, 968 'line': msg, 1275 'match': mstr, 969 'match': mstr, 1276 'count': 1, 970 'count': 1, 1277 'urls': {self.hostnam 971 'urls': {self.hostname: [self.htmlfile]} 1278 } 972 } 1279 errinfo.append(entry) 973 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 974 1384 sysvals = SystemValues() 975 sysvals = SystemValues() 1385 switchvalues = ['enable', 'disable', 'on', 'o 976 switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0'] 1386 switchoff = ['disable', 'off', 'false', '0'] 977 switchoff = ['disable', 'off', 'false', '0'] 1387 suspendmodename = { 978 suspendmodename = { 1388 'standby': 'standby (S1)', !! 979 'freeze': 'Freeze (S0)', 1389 'freeze': 'freeze (S2idle)', !! 980 'standby': 'Standby (S1)', 1390 'mem': 'suspend (S3)', !! 981 'mem': 'Suspend (S3)', 1391 'disk': 'hibernate (S4)' !! 982 'disk': 'Hibernate (S4)' 1392 } 983 } 1393 984 1394 # Class: DevProps 985 # Class: DevProps 1395 # Description: 986 # Description: 1396 # Simple class which holds property va 987 # Simple class which holds property values collected 1397 # for all the devices used in the time 988 # for all the devices used in the timeline. 1398 class DevProps: 989 class DevProps: 1399 def __init__(self): 990 def __init__(self): 1400 self.syspath = '' 991 self.syspath = '' 1401 self.altname = '' 992 self.altname = '' 1402 self.isasync = True !! 993 self.async = True 1403 self.xtraclass = '' 994 self.xtraclass = '' 1404 self.xtrainfo = '' 995 self.xtrainfo = '' 1405 def out(self, dev): 996 def out(self, dev): 1406 return '%s,%s,%d;' % (dev, se !! 997 return '%s,%s,%d;' % (dev, self.altname, self.async) 1407 def debug(self, dev): 998 def debug(self, dev): 1408 pprint('%s:\n\taltname = %s\n !! 999 pprint('%s:\n\taltname = %s\n\t async = %s' % (dev, self.altname, self.async)) 1409 def altName(self, dev): 1000 def altName(self, dev): 1410 if not self.altname or self.a 1001 if not self.altname or self.altname == dev: 1411 return dev 1002 return dev 1412 return '%s [%s]' % (self.altn 1003 return '%s [%s]' % (self.altname, dev) 1413 def xtraClass(self): 1004 def xtraClass(self): 1414 if self.xtraclass: 1005 if self.xtraclass: 1415 return ' '+self.xtrac 1006 return ' '+self.xtraclass 1416 if not self.isasync: !! 1007 if not self.async: 1417 return ' sync' 1008 return ' sync' 1418 return '' 1009 return '' 1419 def xtraInfo(self): 1010 def xtraInfo(self): 1420 if self.xtraclass: 1011 if self.xtraclass: 1421 return ' '+self.xtrac 1012 return ' '+self.xtraclass 1422 if self.isasync: !! 1013 if self.async: 1423 return ' (async)' !! 1014 return ' async_device' 1424 return ' (sync)' !! 1015 return ' sync_device' 1425 1016 1426 # Class: DeviceNode 1017 # Class: DeviceNode 1427 # Description: 1018 # Description: 1428 # A container used to create a device 1019 # A container used to create a device hierachy, with a single root node 1429 # and a tree of child nodes. Used by D 1020 # and a tree of child nodes. Used by Data.deviceTopology() 1430 class DeviceNode: 1021 class DeviceNode: 1431 def __init__(self, nodename, nodedept 1022 def __init__(self, nodename, nodedepth): 1432 self.name = nodename 1023 self.name = nodename 1433 self.children = [] 1024 self.children = [] 1434 self.depth = nodedepth 1025 self.depth = nodedepth 1435 1026 1436 # Class: Data 1027 # Class: Data 1437 # Description: 1028 # Description: 1438 # The primary container for suspend/re 1029 # The primary container for suspend/resume test data. There is one for 1439 # each test run. The data is organized 1030 # each test run. The data is organized into a cronological hierarchy: 1440 # Data.dmesg { 1031 # Data.dmesg { 1441 # phases { 1032 # phases { 1442 # 10 sequential, non-ov 1033 # 10 sequential, non-overlapping phases of S/R 1443 # contents: times for p 1034 # contents: times for phase start/end, order/color data for html 1444 # devlist { 1035 # devlist { 1445 # device callba 1036 # device callback or action list for this phase 1446 # device { 1037 # device { 1447 # a sin 1038 # a single device callback or generic action 1448 # conte 1039 # contents: start/stop times, pid/cpu/driver info 1449 # 1040 # parents/children, html id for timeline/callgraph 1450 # 1041 # optionally includes an ftrace callgraph 1451 # 1042 # optionally includes dev/ps data 1452 # } 1043 # } 1453 # } 1044 # } 1454 # } 1045 # } 1455 # } 1046 # } 1456 # 1047 # 1457 class Data: 1048 class Data: 1458 phasedef = { 1049 phasedef = { 1459 'suspend_prepare': {'order': 1050 'suspend_prepare': {'order': 0, 'color': '#CCFFCC'}, 1460 'suspend': {'order': 1051 'suspend': {'order': 1, 'color': '#88FF88'}, 1461 'suspend_late': {'order': 1052 'suspend_late': {'order': 2, 'color': '#00AA00'}, 1462 'suspend_noirq': {'order': 1053 'suspend_noirq': {'order': 3, 'color': '#008888'}, 1463 'suspend_machine': {'order': 1054 'suspend_machine': {'order': 4, 'color': '#0000FF'}, 1464 'resume_machine': {'order': 1055 'resume_machine': {'order': 5, 'color': '#FF0000'}, 1465 'resume_noirq': {'order': 1056 'resume_noirq': {'order': 6, 'color': '#FF9900'}, 1466 'resume_early': {'order': 1057 'resume_early': {'order': 7, 'color': '#FFCC00'}, 1467 'resume': {'order': 1058 'resume': {'order': 8, 'color': '#FFFF88'}, 1468 'resume_complete': {'order': 1059 'resume_complete': {'order': 9, 'color': '#FFFFCC'}, 1469 } 1060 } 1470 errlist = { 1061 errlist = { 1471 'HWERROR' : r'.*\[ *Hardware !! 1062 'HWERROR' : '.*\[ *Hardware Error *\].*', 1472 'FWBUG' : r'.*\[ *Firmware !! 1063 'FWBUG' : '.*\[ *Firmware Bug *\].*', 1473 'TASKFAIL': r'.*Freezing .*af !! 1064 'BUG' : '.*BUG.*', 1474 'BUG' : r'(?i).*\bBUG\b.* !! 1065 'ERROR' : '.*ERROR.*', 1475 'ERROR' : r'(?i).*\bERROR\b !! 1066 'WARNING' : '.*WARNING.*', 1476 'WARNING' : r'(?i).*\bWARNING !! 1067 'IRQ' : '.*genirq: .*', 1477 'FAULT' : r'(?i).*\bFAULT\b !! 1068 'TASKFAIL': '.*Freezing of tasks *.*', 1478 'FAIL' : r'(?i).*\bFAILED\ !! 1069 'ACPI' : '.*ACPI *(?P<b>[A-Za-z]*) *Error[: ].*', 1479 'INVALID' : r'(?i).*\bINVALID !! 1070 'DEVFAIL' : '.* failed to (?P<b>[a-z]*) async: .*', 1480 'CRASH' : r'(?i).*\bCRASHED !! 1071 'DISKFULL': '.*No space left on device.*', 1481 'TIMEOUT' : r'(?i).*\bTIMEOUT !! 1072 'USBERR' : '.*usb .*device .*, error [0-9-]*', 1482 'ABORT' : r'(?i).*\bABORT\b !! 1073 'ATAERR' : ' *ata[0-9\.]*: .*failed.*', 1483 'IRQ' : r'.*\bgenirq: .*' !! 1074 'MEIERR' : ' *mei.*: .*failed.*', 1484 'ACPI' : r'.*\bACPI *(?P<b !! 1075 'TPMERR' : '(?i) *tpm *tpm[0-9]*: .*error.*', 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 } 1076 } 1491 def __init__(self, num): 1077 def __init__(self, num): 1492 idchar = 'abcdefghij' 1078 idchar = 'abcdefghij' 1493 self.start = 0.0 # test start 1079 self.start = 0.0 # test start 1494 self.end = 0.0 # test end 1080 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 1081 self.tSuspended = 0.0 # low-level suspend start 1498 self.tResumed = 0.0 # low-l 1082 self.tResumed = 0.0 # low-level resume start 1499 self.tKernSus = 0.0 # kerne 1083 self.tKernSus = 0.0 # kernel level suspend start 1500 self.tKernRes = 0.0 # kerne 1084 self.tKernRes = 0.0 # kernel level resume end 1501 self.fwValid = False # is fi 1085 self.fwValid = False # is firmware data available 1502 self.fwSuspend = 0 # time 1086 self.fwSuspend = 0 # time spent in firmware suspend 1503 self.fwResume = 0 # time 1087 self.fwResume = 0 # time spent in firmware resume 1504 self.html_device_id = 0 1088 self.html_device_id = 0 1505 self.stamp = 0 1089 self.stamp = 0 1506 self.outfile = '' 1090 self.outfile = '' 1507 self.kerror = False 1091 self.kerror = False 1508 self.wifi = dict() !! 1092 self.battery = 0 >> 1093 self.wifi = 0 1509 self.turbostat = 0 1094 self.turbostat = 0 >> 1095 self.mcelog = 0 1510 self.enterfail = '' 1096 self.enterfail = '' 1511 self.currphase = '' 1097 self.currphase = '' 1512 self.pstl = dict() # proce 1098 self.pstl = dict() # process timeline 1513 self.testnumber = num 1099 self.testnumber = num 1514 self.idstr = idchar[num] 1100 self.idstr = idchar[num] 1515 self.dmesgtext = [] # dmesg 1101 self.dmesgtext = [] # dmesg text file in memory 1516 self.dmesg = dict() # root 1102 self.dmesg = dict() # root data structure 1517 self.errorinfo = {'suspend':[ 1103 self.errorinfo = {'suspend':[],'resume':[]} 1518 self.tLow = [] # time 1104 self.tLow = [] # time spent in low-level suspends (standby/freeze) 1519 self.devpids = [] 1105 self.devpids = [] 1520 self.devicegroups = 0 1106 self.devicegroups = 0 1521 def sortedPhases(self): 1107 def sortedPhases(self): 1522 return sorted(self.dmesg, key 1108 return sorted(self.dmesg, key=lambda k:self.dmesg[k]['order']) 1523 def initDevicegroups(self): 1109 def initDevicegroups(self): 1524 # called when phases are all 1110 # called when phases are all finished being added 1525 for phase in sorted(self.dmes !! 1111 for phase in self.dmesg.keys(): 1526 if '*' in phase: 1112 if '*' in phase: 1527 p = phase.spl 1113 p = phase.split('*') 1528 pnew = '%s%d' 1114 pnew = '%s%d' % (p[0], len(p)) 1529 self.dmesg[pn 1115 self.dmesg[pnew] = self.dmesg.pop(phase) 1530 self.devicegroups = [] 1116 self.devicegroups = [] 1531 for phase in self.sortedPhase 1117 for phase in self.sortedPhases(): 1532 self.devicegroups.app 1118 self.devicegroups.append([phase]) 1533 def nextPhase(self, phase, offset): 1119 def nextPhase(self, phase, offset): 1534 order = self.dmesg[phase]['or 1120 order = self.dmesg[phase]['order'] + offset 1535 for p in self.dmesg: 1121 for p in self.dmesg: 1536 if self.dmesg[p]['ord 1122 if self.dmesg[p]['order'] == order: 1537 return p 1123 return p 1538 return '' 1124 return '' 1539 def lastPhase(self, depth=1): !! 1125 def lastPhase(self): 1540 plist = self.sortedPhases() 1126 plist = self.sortedPhases() 1541 if len(plist) < depth: !! 1127 if len(plist) < 1: 1542 return '' 1128 return '' 1543 return plist[-1*depth] !! 1129 return plist[-1] 1544 def turbostatInfo(self): 1130 def turbostatInfo(self): 1545 tp = TestProps() 1131 tp = TestProps() 1546 out = {'syslpi':'N/A','pkgpc1 1132 out = {'syslpi':'N/A','pkgpc10':'N/A'} 1547 for line in self.dmesgtext: 1133 for line in self.dmesgtext: 1548 m = re.match(tp.tstat 1134 m = re.match(tp.tstatfmt, line) 1549 if not m: 1135 if not m: 1550 continue 1136 continue 1551 for i in m.group('t') 1137 for i in m.group('t').split('|'): 1552 if 'SYS%LPI' 1138 if 'SYS%LPI' in i: 1553 out[' 1139 out['syslpi'] = i.split('=')[-1]+'%' 1554 elif 'pc10' i 1140 elif 'pc10' in i: 1555 out[' 1141 out['pkgpc10'] = i.split('=')[-1]+'%' 1556 break 1142 break 1557 return out 1143 return out 1558 def extractErrorInfo(self): 1144 def extractErrorInfo(self): 1559 lf = self.dmesgtext 1145 lf = self.dmesgtext 1560 if len(self.dmesgtext) < 1 an 1146 if len(self.dmesgtext) < 1 and sysvals.dmesgfile: 1561 lf = sysvals.openlog( 1147 lf = sysvals.openlog(sysvals.dmesgfile, 'r') 1562 i = 0 1148 i = 0 1563 tp = TestProps() << 1564 list = [] 1149 list = [] 1565 for line in lf: 1150 for line in lf: 1566 i += 1 1151 i += 1 1567 if tp.stampInfo(line, !! 1152 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 1568 continue << 1569 m = re.match(r'[ \t]* << 1570 if not m: 1153 if not m: 1571 continue 1154 continue 1572 t = float(m.group('kt 1155 t = float(m.group('ktime')) 1573 if t < self.start or 1156 if t < self.start or t > self.end: 1574 continue 1157 continue 1575 dir = 'suspend' if t 1158 dir = 'suspend' if t < self.tSuspended else 'resume' 1576 msg = m.group('msg') 1159 msg = m.group('msg') 1577 if re.match(r'capabil << 1578 continue << 1579 for err in self.errli 1160 for err in self.errlist: 1580 if re.match(s 1161 if re.match(self.errlist[err], msg): 1581 list. 1162 list.append((msg, err, dir, t, i, i)) 1582 self. 1163 self.kerror = True 1583 break 1164 break 1584 tp.msglist = [] !! 1165 msglist = [] 1585 for msg, type, dir, t, idx1, 1166 for msg, type, dir, t, idx1, idx2 in list: 1586 tp.msglist.append(msg !! 1167 msglist.append(msg) >> 1168 sysvals.vprint('kernel %s found in %s at %f' % (type, dir, t)) 1587 self.errorinfo[dir].a 1169 self.errorinfo[dir].append((type, t, idx1, idx2)) 1588 if self.kerror: 1170 if self.kerror: 1589 sysvals.dmesglog = Tr 1171 sysvals.dmesglog = True 1590 if len(self.dmesgtext) < 1 an 1172 if len(self.dmesgtext) < 1 and sysvals.dmesgfile: 1591 lf.close() 1173 lf.close() 1592 return tp !! 1174 return msglist 1593 def setStart(self, time, msg=''): !! 1175 def setStart(self, time): 1594 self.start = time 1176 self.start = time 1595 if msg: !! 1177 def setEnd(self, time): 1596 try: << 1597 self.hwstart << 1598 except: << 1599 self.hwstart << 1600 def setEnd(self, time, msg=''): << 1601 self.end = time 1178 self.end = time 1602 if msg: << 1603 try: << 1604 self.hwend = << 1605 except: << 1606 self.hwend = << 1607 def isTraceEventOutsideDeviceCalls(se 1179 def isTraceEventOutsideDeviceCalls(self, pid, time): 1608 for phase in self.sortedPhase 1180 for phase in self.sortedPhases(): 1609 list = self.dmesg[pha 1181 list = self.dmesg[phase]['list'] 1610 for dev in list: 1182 for dev in list: 1611 d = list[dev] 1183 d = list[dev] 1612 if(d['pid'] = 1184 if(d['pid'] == pid and time >= d['start'] and 1613 time 1185 time < d['end']): 1614 retur 1186 return False 1615 return True 1187 return True 1616 def sourcePhase(self, start): 1188 def sourcePhase(self, start): 1617 for phase in self.sortedPhase 1189 for phase in self.sortedPhases(): 1618 if 'machine' in phase 1190 if 'machine' in phase: 1619 continue 1191 continue 1620 pend = self.dmesg[pha 1192 pend = self.dmesg[phase]['end'] 1621 if start <= pend: 1193 if start <= pend: 1622 return phase 1194 return phase 1623 return 'resume_complete' if ' !! 1195 return 'resume_complete' 1624 def sourceDevice(self, phaselist, sta 1196 def sourceDevice(self, phaselist, start, end, pid, type): 1625 tgtdev = '' 1197 tgtdev = '' 1626 for phase in phaselist: 1198 for phase in phaselist: 1627 list = self.dmesg[pha 1199 list = self.dmesg[phase]['list'] 1628 for devname in list: 1200 for devname in list: 1629 dev = list[de 1201 dev = list[devname] 1630 # pid must ma 1202 # pid must match 1631 if dev['pid'] 1203 if dev['pid'] != pid: 1632 conti 1204 continue 1633 devS = dev['s 1205 devS = dev['start'] 1634 devE = dev['e 1206 devE = dev['end'] 1635 if type == 'd 1207 if type == 'device': 1636 # dev 1208 # device target event is entirely inside the source boundary 1637 if(st 1209 if(start < devS or start >= devE or end <= devS or end > devE): 1638 1210 continue 1639 elif type == 1211 elif type == 'thread': 1640 # thr 1212 # thread target event will expand the source boundary 1641 if st 1213 if start < devS: 1642 1214 dev['start'] = start 1643 if en 1215 if end > devE: 1644 1216 dev['end'] = end 1645 tgtdev = dev 1217 tgtdev = dev 1646 break 1218 break 1647 return tgtdev 1219 return tgtdev 1648 def addDeviceFunctionCall(self, displ 1220 def addDeviceFunctionCall(self, displayname, kprobename, proc, pid, start, end, cdata, rdata): 1649 # try to place the call in a 1221 # try to place the call in a device 1650 phases = self.sortedPhases() 1222 phases = self.sortedPhases() 1651 tgtdev = self.sourceDevice(ph 1223 tgtdev = self.sourceDevice(phases, start, end, pid, 'device') 1652 # calls with device pids that 1224 # calls with device pids that occur outside device bounds are dropped 1653 # TODO: include these somehow 1225 # TODO: include these somehow 1654 if not tgtdev and pid in self 1226 if not tgtdev and pid in self.devpids: 1655 return False 1227 return False 1656 # try to place the call in a 1228 # try to place the call in a thread 1657 if not tgtdev: 1229 if not tgtdev: 1658 tgtdev = self.sourceD 1230 tgtdev = self.sourceDevice(phases, start, end, pid, 'thread') 1659 # create new thread blocks, e 1231 # create new thread blocks, expand as new calls are found 1660 if not tgtdev: 1232 if not tgtdev: 1661 if proc == '<...>': 1233 if proc == '<...>': 1662 threadname = 1234 threadname = 'kthread-%d' % (pid) 1663 else: 1235 else: 1664 threadname = 1236 threadname = '%s-%d' % (proc, pid) 1665 tgtphase = self.sourc 1237 tgtphase = self.sourcePhase(start) 1666 if not tgtphase: << 1667 return False << 1668 self.newAction(tgtpha 1238 self.newAction(tgtphase, threadname, pid, '', start, end, '', ' kth', '') 1669 return self.addDevice 1239 return self.addDeviceFunctionCall(displayname, kprobename, proc, pid, start, end, cdata, rdata) 1670 # this should not happen 1240 # this should not happen 1671 if not tgtdev: 1241 if not tgtdev: 1672 sysvals.vprint('[%f - 1242 sysvals.vprint('[%f - %f] %s-%d %s %s %s' % \ 1673 (start, end, 1243 (start, end, proc, pid, kprobename, cdata, rdata)) 1674 return False 1244 return False 1675 # place the call data inside 1245 # place the call data inside the src element of the tgtdev 1676 if('src' not in tgtdev): 1246 if('src' not in tgtdev): 1677 tgtdev['src'] = [] 1247 tgtdev['src'] = [] 1678 dtf = sysvals.dev_tracefuncs 1248 dtf = sysvals.dev_tracefuncs 1679 ubiquitous = False 1249 ubiquitous = False 1680 if kprobename in dtf and 'ub' 1250 if kprobename in dtf and 'ub' in dtf[kprobename]: 1681 ubiquitous = True 1251 ubiquitous = True 1682 mc = re.match(r'\(.*\) *(?P<a !! 1252 title = cdata+' '+rdata 1683 mr = re.match(r'\((?P<caller> !! 1253 mstr = '\(.*\) *(?P<args>.*) *\((?P<caller>.*)\+.* arg1=(?P<ret>.*)' 1684 if mc and mr: !! 1254 m = re.match(mstr, title) 1685 c = mr.group('caller' !! 1255 if m: 1686 a = mc.group('args'). !! 1256 c = m.group('caller') 1687 r = mr.group('ret') !! 1257 a = m.group('args').strip() >> 1258 r = m.group('ret') 1688 if len(r) > 6: 1259 if len(r) > 6: 1689 r = '' 1260 r = '' 1690 else: 1261 else: 1691 r = 'ret=%s ' 1262 r = 'ret=%s ' % r 1692 if ubiquitous and c i 1263 if ubiquitous and c in dtf and 'ub' in dtf[c]: 1693 return False 1264 return False 1694 else: << 1695 return False << 1696 color = sysvals.kprobeColor(k 1265 color = sysvals.kprobeColor(kprobename) 1697 e = DevFunction(displayname, 1266 e = DevFunction(displayname, a, c, r, start, end, ubiquitous, proc, pid, color) 1698 tgtdev['src'].append(e) 1267 tgtdev['src'].append(e) 1699 return True 1268 return True 1700 def overflowDevices(self): 1269 def overflowDevices(self): 1701 # get a list of devices that 1270 # get a list of devices that extend beyond the end of this test run 1702 devlist = [] 1271 devlist = [] 1703 for phase in self.sortedPhase 1272 for phase in self.sortedPhases(): 1704 list = self.dmesg[pha 1273 list = self.dmesg[phase]['list'] 1705 for devname in list: 1274 for devname in list: 1706 dev = list[de 1275 dev = list[devname] 1707 if dev['end'] 1276 if dev['end'] > self.end: 1708 devli 1277 devlist.append(dev) 1709 return devlist 1278 return devlist 1710 def mergeOverlapDevices(self, devlist 1279 def mergeOverlapDevices(self, devlist): 1711 # merge any devices that over 1280 # merge any devices that overlap devlist 1712 for dev in devlist: 1281 for dev in devlist: 1713 devname = dev['name'] 1282 devname = dev['name'] 1714 for phase in self.sor 1283 for phase in self.sortedPhases(): 1715 list = self.d 1284 list = self.dmesg[phase]['list'] 1716 if devname no 1285 if devname not in list: 1717 conti 1286 continue 1718 tdev = list[d 1287 tdev = list[devname] 1719 o = min(dev[' 1288 o = min(dev['end'], tdev['end']) - max(dev['start'], tdev['start']) 1720 if o <= 0: 1289 if o <= 0: 1721 conti 1290 continue 1722 dev['end'] = 1291 dev['end'] = tdev['end'] 1723 if 'src' not 1292 if 'src' not in dev or 'src' not in tdev: 1724 conti 1293 continue 1725 dev['src'] += 1294 dev['src'] += tdev['src'] 1726 del list[devn 1295 del list[devname] 1727 def usurpTouchingThread(self, name, d 1296 def usurpTouchingThread(self, name, dev): 1728 # the caller test has priorit 1297 # the caller test has priority of this thread, give it to him 1729 for phase in self.sortedPhase 1298 for phase in self.sortedPhases(): 1730 list = self.dmesg[pha 1299 list = self.dmesg[phase]['list'] 1731 if name in list: 1300 if name in list: 1732 tdev = list[n 1301 tdev = list[name] 1733 if tdev['star 1302 if tdev['start'] - dev['end'] < 0.1: 1734 dev[' 1303 dev['end'] = tdev['end'] 1735 if 's 1304 if 'src' not in dev: 1736 1305 dev['src'] = [] 1737 if 's 1306 if 'src' in tdev: 1738 1307 dev['src'] += tdev['src'] 1739 del l 1308 del list[name] 1740 break 1309 break 1741 def stitchTouchingThreads(self, testl 1310 def stitchTouchingThreads(self, testlist): 1742 # merge any threads between t 1311 # merge any threads between tests that touch 1743 for phase in self.sortedPhase 1312 for phase in self.sortedPhases(): 1744 list = self.dmesg[pha 1313 list = self.dmesg[phase]['list'] 1745 for devname in list: 1314 for devname in list: 1746 dev = list[de 1315 dev = list[devname] 1747 if 'htmlclass 1316 if 'htmlclass' not in dev or 'kth' not in dev['htmlclass']: 1748 conti 1317 continue 1749 for data in t 1318 for data in testlist: 1750 data. 1319 data.usurpTouchingThread(devname, dev) 1751 def optimizeDevSrc(self): 1320 def optimizeDevSrc(self): 1752 # merge any src call loops to 1321 # merge any src call loops to reduce timeline size 1753 for phase in self.sortedPhase 1322 for phase in self.sortedPhases(): 1754 list = self.dmesg[pha 1323 list = self.dmesg[phase]['list'] 1755 for dev in list: 1324 for dev in list: 1756 if 'src' not 1325 if 'src' not in list[dev]: 1757 conti 1326 continue 1758 src = list[de 1327 src = list[dev]['src'] 1759 p = 0 1328 p = 0 1760 for e in sort 1329 for e in sorted(src, key=lambda event: event.time): 1761 if no 1330 if not p or not e.repeat(p): 1762 1331 p = e 1763 1332 continue 1764 # e i 1333 # e is another iteration of p, move it into p 1765 p.end 1334 p.end = e.end 1766 p.len 1335 p.length = p.end - p.time 1767 p.cou 1336 p.count += 1 1768 src.r 1337 src.remove(e) 1769 def trimTimeVal(self, t, t0, dT, left 1338 def trimTimeVal(self, t, t0, dT, left): 1770 if left: 1339 if left: 1771 if(t > t0): 1340 if(t > t0): 1772 if(t - dT < t 1341 if(t - dT < t0): 1773 retur 1342 return t0 1774 return t - dT 1343 return t - dT 1775 else: 1344 else: 1776 return t 1345 return t 1777 else: 1346 else: 1778 if(t < t0 + dT): 1347 if(t < t0 + dT): 1779 if(t > t0): 1348 if(t > t0): 1780 retur 1349 return t0 + dT 1781 return t + dT 1350 return t + dT 1782 else: 1351 else: 1783 return t 1352 return t 1784 def trimTime(self, t0, dT, left): 1353 def trimTime(self, t0, dT, left): 1785 self.tSuspended = self.trimTi 1354 self.tSuspended = self.trimTimeVal(self.tSuspended, t0, dT, left) 1786 self.tResumed = self.trimTime 1355 self.tResumed = self.trimTimeVal(self.tResumed, t0, dT, left) 1787 self.start = self.trimTimeVal 1356 self.start = self.trimTimeVal(self.start, t0, dT, left) 1788 self.tKernSus = self.trimTime 1357 self.tKernSus = self.trimTimeVal(self.tKernSus, t0, dT, left) 1789 self.tKernRes = self.trimTime 1358 self.tKernRes = self.trimTimeVal(self.tKernRes, t0, dT, left) 1790 self.end = self.trimTimeVal(s 1359 self.end = self.trimTimeVal(self.end, t0, dT, left) 1791 for phase in self.sortedPhase 1360 for phase in self.sortedPhases(): 1792 p = self.dmesg[phase] 1361 p = self.dmesg[phase] 1793 p['start'] = self.tri 1362 p['start'] = self.trimTimeVal(p['start'], t0, dT, left) 1794 p['end'] = self.trimT 1363 p['end'] = self.trimTimeVal(p['end'], t0, dT, left) 1795 list = p['list'] 1364 list = p['list'] 1796 for name in list: 1365 for name in list: 1797 d = list[name 1366 d = list[name] 1798 d['start'] = 1367 d['start'] = self.trimTimeVal(d['start'], t0, dT, left) 1799 d['end'] = se 1368 d['end'] = self.trimTimeVal(d['end'], t0, dT, left) 1800 d['length'] = 1369 d['length'] = d['end'] - d['start'] 1801 if('ftrace' i 1370 if('ftrace' in d): 1802 cg = 1371 cg = d['ftrace'] 1803 cg.st 1372 cg.start = self.trimTimeVal(cg.start, t0, dT, left) 1804 cg.en 1373 cg.end = self.trimTimeVal(cg.end, t0, dT, left) 1805 for l 1374 for line in cg.list: 1806 1375 line.time = self.trimTimeVal(line.time, t0, dT, left) 1807 if('src' in d 1376 if('src' in d): 1808 for e 1377 for e in d['src']: 1809 1378 e.time = self.trimTimeVal(e.time, t0, dT, left) 1810 << 1811 << 1812 if('cpuexec' << 1813 cpuex << 1814 for e << 1815 << 1816 << 1817 << 1818 << 1819 d['cp << 1820 for dir in ['suspend', 'resum 1379 for dir in ['suspend', 'resume']: 1821 list = [] 1380 list = [] 1822 for e in self.errorin 1381 for e in self.errorinfo[dir]: 1823 type, tm, idx 1382 type, tm, idx1, idx2 = e 1824 tm = self.tri 1383 tm = self.trimTimeVal(tm, t0, dT, left) 1825 list.append(( 1384 list.append((type, tm, idx1, idx2)) 1826 self.errorinfo[dir] = 1385 self.errorinfo[dir] = list 1827 def trimFreezeTime(self, tZero): 1386 def trimFreezeTime(self, tZero): 1828 # trim out any standby or fre 1387 # trim out any standby or freeze clock time 1829 lp = '' 1388 lp = '' 1830 for phase in self.sortedPhase 1389 for phase in self.sortedPhases(): 1831 if 'resume_machine' i 1390 if 'resume_machine' in phase and 'suspend_machine' in lp: 1832 tS, tR = self 1391 tS, tR = self.dmesg[lp]['end'], self.dmesg[phase]['start'] 1833 tL = tR - tS 1392 tL = tR - tS 1834 if tL <= 0: !! 1393 if tL > 0: 1835 conti !! 1394 left = True if tR > tZero else False 1836 left = True i !! 1395 self.trimTime(tS, tL, left) 1837 self.trimTime !! 1396 self.tLow.append('%.0f'%(tL*1000)) 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 1397 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): 1398 def getTimeValues(self): 1858 s = (self.tSuspended - self.t !! 1399 sktime = (self.tSuspended - self.tKernSus) * 1000 1859 r = (self.tKernRes - self.tRe !! 1400 rktime = (self.tKernRes - self.tResumed) * 1000 1860 return (max(s, 0), max(r, 0)) !! 1401 return (sktime, rktime) 1861 def setPhase(self, phase, ktime, isbe 1402 def setPhase(self, phase, ktime, isbegin, order=-1): 1862 if(isbegin): 1403 if(isbegin): 1863 # phase start over cu 1404 # phase start over current phase 1864 if self.currphase: 1405 if self.currphase: 1865 if 'resume_ma 1406 if 'resume_machine' not in self.currphase: 1866 sysva 1407 sysvals.vprint('WARNING: phase %s failed to end' % self.currphase) 1867 self.dmesg[se 1408 self.dmesg[self.currphase]['end'] = ktime 1868 phases = self.dmesg.k 1409 phases = self.dmesg.keys() 1869 color = self.phasedef 1410 color = self.phasedef[phase]['color'] 1870 count = len(phases) i 1411 count = len(phases) if order < 0 else order 1871 # create unique name 1412 # create unique name for every new phase 1872 while phase in phases 1413 while phase in phases: 1873 phase += '*' 1414 phase += '*' 1874 self.dmesg[phase] = { 1415 self.dmesg[phase] = {'list': dict(), 'start': -1.0, 'end': -1.0, 1875 'row': 0, 'co 1416 'row': 0, 'color': color, 'order': count} 1876 self.dmesg[phase]['st 1417 self.dmesg[phase]['start'] = ktime 1877 self.currphase = phas 1418 self.currphase = phase 1878 else: 1419 else: 1879 # phase end without a 1420 # phase end without a start 1880 if phase not in self. 1421 if phase not in self.currphase: 1881 if self.currp 1422 if self.currphase: 1882 sysva 1423 sysvals.vprint('WARNING: %s ended instead of %s, ftrace corruption?' % (phase, self.currphase)) 1883 else: 1424 else: 1884 sysva 1425 sysvals.vprint('WARNING: %s ended without a start, ftrace corruption?' % phase) 1885 retur 1426 return phase 1886 phase = self.currphas 1427 phase = self.currphase 1887 self.dmesg[phase]['en 1428 self.dmesg[phase]['end'] = ktime 1888 self.currphase = '' 1429 self.currphase = '' 1889 return phase 1430 return phase 1890 def sortedDevices(self, phase): 1431 def sortedDevices(self, phase): 1891 list = self.dmesg[phase]['lis 1432 list = self.dmesg[phase]['list'] 1892 return sorted(list, key=lambd !! 1433 slist = [] >> 1434 tmp = dict() >> 1435 for devname in list: >> 1436 dev = list[devname] >> 1437 if dev['length'] == 0: >> 1438 continue >> 1439 tmp[dev['start']] = devname >> 1440 for t in sorted(tmp): >> 1441 slist.append(tmp[t]) >> 1442 return slist 1893 def fixupInitcalls(self, phase): 1443 def fixupInitcalls(self, phase): 1894 # if any calls never returned 1444 # if any calls never returned, clip them at system resume end 1895 phaselist = self.dmesg[phase] 1445 phaselist = self.dmesg[phase]['list'] 1896 for devname in phaselist: 1446 for devname in phaselist: 1897 dev = phaselist[devna 1447 dev = phaselist[devname] 1898 if(dev['end'] < 0): 1448 if(dev['end'] < 0): 1899 for p in self 1449 for p in self.sortedPhases(): 1900 if se 1450 if self.dmesg[p]['end'] > dev['start']: 1901 1451 dev['end'] = self.dmesg[p]['end'] 1902 1452 break 1903 sysvals.vprin 1453 sysvals.vprint('%s (%s): callback didnt return' % (devname, phase)) 1904 def deviceFilter(self, devicefilter): 1454 def deviceFilter(self, devicefilter): 1905 for phase in self.sortedPhase 1455 for phase in self.sortedPhases(): 1906 list = self.dmesg[pha 1456 list = self.dmesg[phase]['list'] 1907 rmlist = [] 1457 rmlist = [] 1908 for name in list: 1458 for name in list: 1909 keep = False 1459 keep = False 1910 for filter in 1460 for filter in devicefilter: 1911 if fi 1461 if filter in name or \ 1912 1462 ('drv' in list[name] and filter in list[name]['drv']): 1913 1463 keep = True 1914 if not keep: 1464 if not keep: 1915 rmlis 1465 rmlist.append(name) 1916 for name in rmlist: 1466 for name in rmlist: 1917 del list[name 1467 del list[name] 1918 def fixupInitcallsThatDidntReturn(sel 1468 def fixupInitcallsThatDidntReturn(self): 1919 # if any calls never returned 1469 # if any calls never returned, clip them at system resume end 1920 for phase in self.sortedPhase 1470 for phase in self.sortedPhases(): 1921 self.fixupInitcalls(p 1471 self.fixupInitcalls(phase) 1922 def phaseOverlap(self, phases): 1472 def phaseOverlap(self, phases): 1923 rmgroups = [] 1473 rmgroups = [] 1924 newgroup = [] 1474 newgroup = [] 1925 for group in self.devicegroup 1475 for group in self.devicegroups: 1926 for phase in phases: 1476 for phase in phases: 1927 if phase not 1477 if phase not in group: 1928 conti 1478 continue 1929 for p in grou 1479 for p in group: 1930 if p 1480 if p not in newgroup: 1931 1481 newgroup.append(p) 1932 if group not 1482 if group not in rmgroups: 1933 rmgro 1483 rmgroups.append(group) 1934 for group in rmgroups: 1484 for group in rmgroups: 1935 self.devicegroups.rem 1485 self.devicegroups.remove(group) 1936 self.devicegroups.append(newg 1486 self.devicegroups.append(newgroup) 1937 def newActionGlobal(self, name, start 1487 def newActionGlobal(self, name, start, end, pid=-1, color=''): 1938 # which phase is this device 1488 # which phase is this device callback or action in 1939 phases = self.sortedPhases() 1489 phases = self.sortedPhases() 1940 targetphase = 'none' 1490 targetphase = 'none' 1941 htmlclass = '' 1491 htmlclass = '' 1942 overlap = 0.0 1492 overlap = 0.0 1943 myphases = [] 1493 myphases = [] 1944 for phase in phases: 1494 for phase in phases: 1945 pstart = self.dmesg[p 1495 pstart = self.dmesg[phase]['start'] 1946 pend = self.dmesg[pha 1496 pend = self.dmesg[phase]['end'] 1947 # see if the action o 1497 # see if the action overlaps this phase 1948 o = max(0, min(end, p 1498 o = max(0, min(end, pend) - max(start, pstart)) 1949 if o > 0: 1499 if o > 0: 1950 myphases.appe 1500 myphases.append(phase) 1951 # set the target phas 1501 # set the target phase to the one that overlaps most 1952 if o > overlap: 1502 if o > overlap: 1953 if overlap > 1503 if overlap > 0 and phase == 'post_resume': 1954 conti 1504 continue 1955 targetphase = 1505 targetphase = phase 1956 overlap = o 1506 overlap = o 1957 # if no target phase was foun 1507 # if no target phase was found, pin it to the edge 1958 if targetphase == 'none': 1508 if targetphase == 'none': 1959 p0start = self.dmesg[ 1509 p0start = self.dmesg[phases[0]]['start'] 1960 if start <= p0start: 1510 if start <= p0start: 1961 targetphase = 1511 targetphase = phases[0] 1962 else: 1512 else: 1963 targetphase = 1513 targetphase = phases[-1] 1964 if pid == -2: 1514 if pid == -2: 1965 htmlclass = ' bg' 1515 htmlclass = ' bg' 1966 elif pid == -3: 1516 elif pid == -3: 1967 htmlclass = ' ps' 1517 htmlclass = ' ps' 1968 if len(myphases) > 1: 1518 if len(myphases) > 1: 1969 htmlclass = ' bg' 1519 htmlclass = ' bg' 1970 self.phaseOverlap(myp 1520 self.phaseOverlap(myphases) 1971 if targetphase in phases: 1521 if targetphase in phases: 1972 newname = self.newAct 1522 newname = self.newAction(targetphase, name, pid, '', start, end, '', htmlclass, color) 1973 return (targetphase, 1523 return (targetphase, newname) 1974 return False 1524 return False 1975 def newAction(self, phase, name, pid, 1525 def newAction(self, phase, name, pid, parent, start, end, drv, htmlclass='', color=''): 1976 # new device callback for a s 1526 # new device callback for a specific phase 1977 self.html_device_id += 1 1527 self.html_device_id += 1 1978 devid = '%s%d' % (self.idstr, 1528 devid = '%s%d' % (self.idstr, self.html_device_id) 1979 list = self.dmesg[phase]['lis 1529 list = self.dmesg[phase]['list'] 1980 length = -1.0 1530 length = -1.0 1981 if(start >= 0 and end >= 0): 1531 if(start >= 0 and end >= 0): 1982 length = end - start 1532 length = end - start 1983 if pid == -2 or name not in s !! 1533 if pid == -2: 1984 i = 2 1534 i = 2 1985 origname = name 1535 origname = name 1986 while(name in list): 1536 while(name in list): 1987 name = '%s[%d 1537 name = '%s[%d]' % (origname, i) 1988 i += 1 1538 i += 1 1989 list[name] = {'name': name, ' 1539 list[name] = {'name': name, 'start': start, 'end': end, 'pid': pid, 1990 'par': parent, 'lengt 1540 'par': parent, 'length': length, 'row': 0, 'id': devid, 'drv': drv } 1991 if htmlclass: 1541 if htmlclass: 1992 list[name]['htmlclass 1542 list[name]['htmlclass'] = htmlclass 1993 if color: 1543 if color: 1994 list[name]['color'] = 1544 list[name]['color'] = color 1995 return name 1545 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 1546 def deviceChildren(self, devname, phase): 2006 devlist = [] 1547 devlist = [] 2007 list = self.dmesg[phase]['lis 1548 list = self.dmesg[phase]['list'] 2008 for child in list: 1549 for child in list: 2009 if(list[child]['par'] 1550 if(list[child]['par'] == devname): 2010 devlist.appen 1551 devlist.append(child) 2011 return devlist 1552 return devlist 2012 def maxDeviceNameSize(self, phase): 1553 def maxDeviceNameSize(self, phase): 2013 size = 0 1554 size = 0 2014 for name in self.dmesg[phase] 1555 for name in self.dmesg[phase]['list']: 2015 if len(name) > size: 1556 if len(name) > size: 2016 size = len(na 1557 size = len(name) 2017 return size 1558 return size 2018 def printDetails(self): 1559 def printDetails(self): 2019 sysvals.vprint('Timeline Deta 1560 sysvals.vprint('Timeline Details:') 2020 sysvals.vprint(' tes 1561 sysvals.vprint(' test start: %f' % self.start) 2021 sysvals.vprint('kernel suspen 1562 sysvals.vprint('kernel suspend start: %f' % self.tKernSus) 2022 tS = tR = False 1563 tS = tR = False 2023 for phase in self.sortedPhase 1564 for phase in self.sortedPhases(): 2024 devlist = self.dmesg[ 1565 devlist = self.dmesg[phase]['list'] 2025 dc, ps, pe = len(devl 1566 dc, ps, pe = len(devlist), self.dmesg[phase]['start'], self.dmesg[phase]['end'] 2026 if not tS and ps >= s 1567 if not tS and ps >= self.tSuspended: 2027 sysvals.vprin 1568 sysvals.vprint(' machine suspended: %f' % self.tSuspended) 2028 tS = True 1569 tS = True 2029 if not tR and ps >= s 1570 if not tR and ps >= self.tResumed: 2030 sysvals.vprin 1571 sysvals.vprint(' machine resumed: %f' % self.tResumed) 2031 tR = True 1572 tR = True 2032 sysvals.vprint('%20s: 1573 sysvals.vprint('%20s: %f - %f (%d devices)' % (phase, ps, pe, dc)) 2033 if sysvals.devdump: 1574 if sysvals.devdump: 2034 sysvals.vprin 1575 sysvals.vprint(''.join('-' for i in range(80))) 2035 maxname = '%d 1576 maxname = '%d' % self.maxDeviceNameSize(phase) 2036 fmt = '%3d) % 1577 fmt = '%3d) %'+maxname+'s - %f - %f' 2037 c = 1 1578 c = 1 2038 for name in s !! 1579 for name in devlist: 2039 s = d 1580 s = devlist[name]['start'] 2040 e = d 1581 e = devlist[name]['end'] 2041 sysva 1582 sysvals.vprint(fmt % (c, name, s, e)) 2042 c += 1583 c += 1 2043 sysvals.vprin 1584 sysvals.vprint(''.join('-' for i in range(80))) 2044 sysvals.vprint(' kernel res 1585 sysvals.vprint(' kernel resume end: %f' % self.tKernRes) 2045 sysvals.vprint(' t 1586 sysvals.vprint(' test end: %f' % self.end) 2046 def deviceChildrenAllPhases(self, dev 1587 def deviceChildrenAllPhases(self, devname): 2047 devlist = [] 1588 devlist = [] 2048 for phase in self.sortedPhase 1589 for phase in self.sortedPhases(): 2049 list = self.deviceChi 1590 list = self.deviceChildren(devname, phase) 2050 for dev in sorted(lis !! 1591 for dev in list: 2051 if dev not in 1592 if dev not in devlist: 2052 devli 1593 devlist.append(dev) 2053 return devlist 1594 return devlist 2054 def masterTopology(self, name, list, 1595 def masterTopology(self, name, list, depth): 2055 node = DeviceNode(name, depth 1596 node = DeviceNode(name, depth) 2056 for cname in list: 1597 for cname in list: 2057 # avoid recursions 1598 # avoid recursions 2058 if name == cname: 1599 if name == cname: 2059 continue 1600 continue 2060 clist = self.deviceCh 1601 clist = self.deviceChildrenAllPhases(cname) 2061 cnode = self.masterTo 1602 cnode = self.masterTopology(cname, clist, depth+1) 2062 node.children.append( 1603 node.children.append(cnode) 2063 return node 1604 return node 2064 def printTopology(self, node): 1605 def printTopology(self, node): 2065 html = '' 1606 html = '' 2066 if node.name: 1607 if node.name: 2067 info = '' 1608 info = '' 2068 drv = '' 1609 drv = '' 2069 for phase in self.sor 1610 for phase in self.sortedPhases(): 2070 list = self.d 1611 list = self.dmesg[phase]['list'] 2071 if node.name 1612 if node.name in list: 2072 s = l 1613 s = list[node.name]['start'] 2073 e = l 1614 e = list[node.name]['end'] 2074 if li 1615 if list[node.name]['drv']: 2075 1616 drv = ' {'+list[node.name]['drv']+'}' 2076 info 1617 info += ('<li>%s: %.3fms</li>' % (phase, (e-s)*1000)) 2077 html += '<li><b>'+nod 1618 html += '<li><b>'+node.name+drv+'</b>' 2078 if info: 1619 if info: 2079 html += '<ul> 1620 html += '<ul>'+info+'</ul>' 2080 html += '</li>' 1621 html += '</li>' 2081 if len(node.children) > 0: 1622 if len(node.children) > 0: 2082 html += '<ul>' 1623 html += '<ul>' 2083 for cnode in node.chi 1624 for cnode in node.children: 2084 html += self. 1625 html += self.printTopology(cnode) 2085 html += '</ul>' 1626 html += '</ul>' 2086 return html 1627 return html 2087 def rootDeviceList(self): 1628 def rootDeviceList(self): 2088 # list of devices graphed 1629 # list of devices graphed 2089 real = [] 1630 real = [] 2090 for phase in self.sortedPhase !! 1631 for phase in self.dmesg: 2091 list = self.dmesg[pha 1632 list = self.dmesg[phase]['list'] 2092 for dev in sorted(lis !! 1633 for dev in list: 2093 if list[dev][ 1634 if list[dev]['pid'] >= 0 and dev not in real: 2094 real. 1635 real.append(dev) 2095 # list of top-most root devic 1636 # list of top-most root devices 2096 rootlist = [] 1637 rootlist = [] 2097 for phase in self.sortedPhase !! 1638 for phase in self.dmesg: 2098 list = self.dmesg[pha 1639 list = self.dmesg[phase]['list'] 2099 for dev in sorted(lis !! 1640 for dev in list: 2100 pdev = list[d 1641 pdev = list[dev]['par'] 2101 pid = list[de 1642 pid = list[dev]['pid'] 2102 if(pid < 0 or !! 1643 if(pid < 0 or re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)): 2103 conti 1644 continue 2104 if pdev and p 1645 if pdev and pdev not in real and pdev not in rootlist: 2105 rootl 1646 rootlist.append(pdev) 2106 return rootlist 1647 return rootlist 2107 def deviceTopology(self): 1648 def deviceTopology(self): 2108 rootlist = self.rootDeviceLis 1649 rootlist = self.rootDeviceList() 2109 master = self.masterTopology( 1650 master = self.masterTopology('', rootlist, 0) 2110 return self.printTopology(mas 1651 return self.printTopology(master) 2111 def selectTimelineDevices(self, widfm 1652 def selectTimelineDevices(self, widfmt, tTotal, mindevlen): 2112 # only select devices that wi 1653 # only select devices that will actually show up in html 2113 self.tdevlist = dict() 1654 self.tdevlist = dict() 2114 for phase in self.dmesg: 1655 for phase in self.dmesg: 2115 devlist = [] 1656 devlist = [] 2116 list = self.dmesg[pha 1657 list = self.dmesg[phase]['list'] 2117 for dev in list: 1658 for dev in list: 2118 length = (lis 1659 length = (list[dev]['end'] - list[dev]['start']) * 1000 2119 width = widfm 1660 width = widfmt % (((list[dev]['end']-list[dev]['start'])*100)/tTotal) 2120 if length >= !! 1661 if width != '0.000000' and length >= mindevlen: 2121 devli 1662 devlist.append(dev) 2122 self.tdevlist[phase] 1663 self.tdevlist[phase] = devlist 2123 def addHorizontalDivider(self, devnam 1664 def addHorizontalDivider(self, devname, devend): 2124 phase = 'suspend_prepare' 1665 phase = 'suspend_prepare' 2125 self.newAction(phase, devname 1666 self.newAction(phase, devname, -2, '', \ 2126 self.start, devend, ' 1667 self.start, devend, '', ' sec', '') 2127 if phase not in self.tdevlist 1668 if phase not in self.tdevlist: 2128 self.tdevlist[phase] 1669 self.tdevlist[phase] = [] 2129 self.tdevlist[phase].append(d 1670 self.tdevlist[phase].append(devname) 2130 d = DevItem(0, phase, self.dm 1671 d = DevItem(0, phase, self.dmesg[phase]['list'][devname]) 2131 return d 1672 return d 2132 def addProcessUsageEvent(self, name, 1673 def addProcessUsageEvent(self, name, times): 2133 # get the start and end times 1674 # get the start and end times for this process 2134 cpuexec = dict() !! 1675 maxC = 0 2135 tlast = start = end = -1 !! 1676 tlast = 0 >> 1677 start = -1 >> 1678 end = -1 2136 for t in sorted(times): 1679 for t in sorted(times): 2137 if tlast < 0: !! 1680 if tlast == 0: 2138 tlast = t 1681 tlast = t 2139 continue 1682 continue 2140 if name in self.pstl[ !! 1683 if name in self.pstl[t]: 2141 if start < 0: !! 1684 if start == -1 or tlast < start: 2142 start 1685 start = tlast 2143 end, key = t, !! 1686 if end == -1 or t > end: 2144 maxj = (t - t !! 1687 end = t 2145 cpuexec[key] << 2146 tlast = t 1688 tlast = t 2147 if start < 0 or end < 0: !! 1689 if start == -1 or end == -1: 2148 return !! 1690 return 0 2149 # add a new action for this p 1691 # add a new action for this process and get the object 2150 out = self.newActionGlobal(na 1692 out = self.newActionGlobal(name, start, end, -3) 2151 if out: !! 1693 if not out: 2152 phase, devname = out !! 1694 return 0 2153 dev = self.dmesg[phas !! 1695 phase, devname = out 2154 dev['cpuexec'] = cpue !! 1696 dev = self.dmesg[phase]['list'][devname] >> 1697 # get the cpu exec data >> 1698 tlast = 0 >> 1699 clast = 0 >> 1700 cpuexec = dict() >> 1701 for t in sorted(times): >> 1702 if tlast == 0 or t <= start or t > end: >> 1703 tlast = t >> 1704 continue >> 1705 list = self.pstl[t] >> 1706 c = 0 >> 1707 if name in list: >> 1708 c = list[name] >> 1709 if c > maxC: >> 1710 maxC = c >> 1711 if c != clast: >> 1712 key = (tlast, t) >> 1713 cpuexec[key] = c >> 1714 tlast = t >> 1715 clast = c >> 1716 dev['cpuexec'] = cpuexec >> 1717 return maxC 2155 def createProcessUsageEvents(self): 1718 def createProcessUsageEvents(self): 2156 # get an array of process nam !! 1719 # get an array of process names 2157 proclist = {'sus': dict(), 'r !! 1720 proclist = [] 2158 tdata = {'sus': [], 'res': [] !! 1721 for t in self.pstl: >> 1722 pslist = self.pstl[t] >> 1723 for ps in pslist: >> 1724 if ps not in proclist: >> 1725 proclist.append(ps) >> 1726 # get a list of data points for suspend and resume >> 1727 tsus = [] >> 1728 tres = [] 2159 for t in sorted(self.pstl): 1729 for t in sorted(self.pstl): 2160 dir = 'sus' if t < se !! 1730 if t < self.tSuspended: 2161 for ps in sorted(self !! 1731 tsus.append(t) 2162 if ps not in !! 1732 else: 2163 procl !! 1733 tres.append(t) 2164 tdata[dir].append(t) << 2165 # process the events for susp 1734 # process the events for suspend and resume 2166 if len(proclist['sus']) > 0 o !! 1735 if len(proclist) > 0: 2167 sysvals.vprint('Proce 1736 sysvals.vprint('Process Execution:') 2168 for dir in ['sus', 'res']: !! 1737 for ps in proclist: 2169 for ps in sorted(proc !! 1738 c = self.addProcessUsageEvent(ps, tsus) 2170 self.addProce !! 1739 if c > 0: 2171 def handleEndMarker(self, time, msg=' !! 1740 sysvals.vprint('%25s (sus): %d' % (ps, c)) >> 1741 c = self.addProcessUsageEvent(ps, tres) >> 1742 if c > 0: >> 1743 sysvals.vprint('%25s (res): %d' % (ps, c)) >> 1744 def handleEndMarker(self, time): 2172 dm = self.dmesg 1745 dm = self.dmesg 2173 self.setEnd(time, msg) !! 1746 self.setEnd(time) 2174 self.initDevicegroups() 1747 self.initDevicegroups() 2175 # give suspend_prepare an end 1748 # give suspend_prepare an end if needed 2176 if 'suspend_prepare' in dm an 1749 if 'suspend_prepare' in dm and dm['suspend_prepare']['end'] < 0: 2177 dm['suspend_prepare'] 1750 dm['suspend_prepare']['end'] = time 2178 # assume resume machine ends 1751 # assume resume machine ends at next phase start 2179 if 'resume_machine' in dm and 1752 if 'resume_machine' in dm and dm['resume_machine']['end'] < 0: 2180 np = self.nextPhase(' 1753 np = self.nextPhase('resume_machine', 1) 2181 if np: 1754 if np: 2182 dm['resume_ma 1755 dm['resume_machine']['end'] = dm[np]['start'] 2183 # if kernel resume end not fo 1756 # if kernel resume end not found, assume its the end marker 2184 if self.tKernRes == 0.0: 1757 if self.tKernRes == 0.0: 2185 self.tKernRes = time 1758 self.tKernRes = time 2186 # if kernel suspend start not 1759 # if kernel suspend start not found, assume its the end marker 2187 if self.tKernSus == 0.0: 1760 if self.tKernSus == 0.0: 2188 self.tKernSus = time 1761 self.tKernSus = time 2189 # set resume complete to end 1762 # set resume complete to end at end marker 2190 if 'resume_complete' in dm: 1763 if 'resume_complete' in dm: 2191 dm['resume_complete'] 1764 dm['resume_complete']['end'] = time 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): 1765 def debugPrint(self): 2217 for p in self.sortedPhases(): 1766 for p in self.sortedPhases(): 2218 list = self.dmesg[p][ 1767 list = self.dmesg[p]['list'] 2219 for devname in sorted !! 1768 for devname in list: 2220 dev = list[de 1769 dev = list[devname] 2221 if 'ftrace' i 1770 if 'ftrace' in dev: 2222 dev[' 1771 dev['ftrace'].debugPrint(' [%s]' % devname) 2223 1772 2224 # Class: DevFunction 1773 # Class: DevFunction 2225 # Description: 1774 # Description: 2226 # A container for kprobe function data 1775 # A container for kprobe function data we want in the dev timeline 2227 class DevFunction: 1776 class DevFunction: 2228 def __init__(self, name, args, caller 1777 def __init__(self, name, args, caller, ret, start, end, u, proc, pid, color): 2229 self.row = 0 1778 self.row = 0 2230 self.count = 1 1779 self.count = 1 2231 self.name = name 1780 self.name = name 2232 self.args = args 1781 self.args = args 2233 self.caller = caller 1782 self.caller = caller 2234 self.ret = ret 1783 self.ret = ret 2235 self.time = start 1784 self.time = start 2236 self.length = end - start 1785 self.length = end - start 2237 self.end = end 1786 self.end = end 2238 self.ubiquitous = u 1787 self.ubiquitous = u 2239 self.proc = proc 1788 self.proc = proc 2240 self.pid = pid 1789 self.pid = pid 2241 self.color = color 1790 self.color = color 2242 def title(self): 1791 def title(self): 2243 cnt = '' 1792 cnt = '' 2244 if self.count > 1: 1793 if self.count > 1: 2245 cnt = '(x%d)' % self. 1794 cnt = '(x%d)' % self.count 2246 l = '%0.3fms' % (self.length 1795 l = '%0.3fms' % (self.length * 1000) 2247 if self.ubiquitous: 1796 if self.ubiquitous: 2248 title = '%s(%s)%s <- 1797 title = '%s(%s)%s <- %s, %s(%s)' % \ 2249 (self.name, s 1798 (self.name, self.args, cnt, self.caller, self.ret, l) 2250 else: 1799 else: 2251 title = '%s(%s) %s%s( 1800 title = '%s(%s) %s%s(%s)' % (self.name, self.args, self.ret, cnt, l) 2252 return title.replace('"', '') 1801 return title.replace('"', '') 2253 def text(self): 1802 def text(self): 2254 if self.count > 1: 1803 if self.count > 1: 2255 text = '%s(x%d)' % (s 1804 text = '%s(x%d)' % (self.name, self.count) 2256 else: 1805 else: 2257 text = self.name 1806 text = self.name 2258 return text 1807 return text 2259 def repeat(self, tgt): 1808 def repeat(self, tgt): 2260 # is the tgt call just a repe 1809 # is the tgt call just a repeat of this call (e.g. are we in a loop) 2261 dt = self.time - tgt.end 1810 dt = self.time - tgt.end 2262 # only combine calls if -all- 1811 # only combine calls if -all- attributes are identical 2263 if tgt.caller == self.caller 1812 if tgt.caller == self.caller and \ 2264 tgt.name == self.name 1813 tgt.name == self.name and tgt.args == self.args and \ 2265 tgt.proc == self.proc 1814 tgt.proc == self.proc and tgt.pid == self.pid and \ 2266 tgt.ret == self.ret a 1815 tgt.ret == self.ret and dt >= 0 and \ 2267 dt <= sysvals.callloo 1816 dt <= sysvals.callloopmaxgap and \ 2268 self.length < sysvals 1817 self.length < sysvals.callloopmaxlen: 2269 return True 1818 return True 2270 return False 1819 return False 2271 1820 2272 # Class: FTraceLine 1821 # Class: FTraceLine 2273 # Description: 1822 # Description: 2274 # A container for a single line of ftr 1823 # A container for a single line of ftrace data. There are six basic types: 2275 # callgraph line: 1824 # callgraph line: 2276 # call: " dpm_run_ca 1825 # call: " dpm_run_callback() {" 2277 # return: " }" 1826 # return: " }" 2278 # leaf: " dpm_run_cal 1827 # leaf: " dpm_run_callback();" 2279 # trace event: 1828 # trace event: 2280 # tracing_mark_write: 1829 # tracing_mark_write: SUSPEND START or RESUME COMPLETE 2281 # suspend_resume: phas 1830 # suspend_resume: phase or custom exec block data 2282 # device_pm_callback: 1831 # device_pm_callback: device callback info 2283 class FTraceLine: 1832 class FTraceLine: 2284 def __init__(self, t, m='', d=''): 1833 def __init__(self, t, m='', d=''): 2285 self.length = 0.0 1834 self.length = 0.0 2286 self.fcall = False 1835 self.fcall = False 2287 self.freturn = False 1836 self.freturn = False 2288 self.fevent = False 1837 self.fevent = False 2289 self.fkprobe = False 1838 self.fkprobe = False 2290 self.depth = 0 1839 self.depth = 0 2291 self.name = '' 1840 self.name = '' 2292 self.type = '' 1841 self.type = '' 2293 self.time = float(t) 1842 self.time = float(t) 2294 if not m and not d: 1843 if not m and not d: 2295 return 1844 return 2296 # is this a trace event 1845 # is this a trace event 2297 if(d == 'traceevent' or re.ma !! 1846 if(d == 'traceevent' or re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m)): 2298 if(d == 'traceevent') 1847 if(d == 'traceevent'): 2299 # nop format 1848 # nop format trace event 2300 msg = m 1849 msg = m 2301 else: 1850 else: 2302 # function_gr 1851 # function_graph format trace event 2303 em = re.match !! 1852 em = re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m) 2304 msg = em.grou 1853 msg = em.group('msg') 2305 1854 2306 emm = re.match(r'^(?P !! 1855 emm = re.match('^(?P<call>.*?): (?P<msg>.*)', msg) 2307 if(emm): 1856 if(emm): 2308 self.name = e 1857 self.name = emm.group('msg') 2309 self.type = e 1858 self.type = emm.group('call') 2310 else: 1859 else: 2311 self.name = m 1860 self.name = msg 2312 km = re.match(r'^(?P< !! 1861 km = re.match('^(?P<n>.*)_cal$', self.type) 2313 if km: 1862 if km: 2314 self.fcall = 1863 self.fcall = True 2315 self.fkprobe 1864 self.fkprobe = True 2316 self.type = k 1865 self.type = km.group('n') 2317 return 1866 return 2318 km = re.match(r'^(?P< !! 1867 km = re.match('^(?P<n>.*)_ret$', self.type) 2319 if km: 1868 if km: 2320 self.freturn 1869 self.freturn = True 2321 self.fkprobe 1870 self.fkprobe = True 2322 self.type = k 1871 self.type = km.group('n') 2323 return 1872 return 2324 self.fevent = True 1873 self.fevent = True 2325 return 1874 return 2326 # convert the duration to sec 1875 # convert the duration to seconds 2327 if(d): 1876 if(d): 2328 self.length = float(d 1877 self.length = float(d)/1000000 2329 # the indentation determines 1878 # the indentation determines the depth 2330 match = re.match(r'^(?P<d> *) !! 1879 match = re.match('^(?P<d> *)(?P<o>.*)$', m) 2331 if(not match): 1880 if(not match): 2332 return 1881 return 2333 self.depth = self.getDepth(ma 1882 self.depth = self.getDepth(match.group('d')) 2334 m = match.group('o') 1883 m = match.group('o') 2335 # function return 1884 # function return 2336 if(m[0] == '}'): 1885 if(m[0] == '}'): 2337 self.freturn = True 1886 self.freturn = True 2338 if(len(m) > 1): 1887 if(len(m) > 1): 2339 # includes co 1888 # includes comment with function name 2340 match = re.ma !! 1889 match = re.match('^} *\/\* *(?P<n>.*) *\*\/$', m) 2341 if(match): 1890 if(match): 2342 self. 1891 self.name = match.group('n').strip() 2343 # function call 1892 # function call 2344 else: 1893 else: 2345 self.fcall = True 1894 self.fcall = True 2346 # function call with 1895 # function call with children 2347 if(m[-1] == '{'): 1896 if(m[-1] == '{'): 2348 match = re.ma !! 1897 match = re.match('^(?P<n>.*) *\(.*', m) 2349 if(match): 1898 if(match): 2350 self. 1899 self.name = match.group('n').strip() 2351 # function call with 1900 # function call with no children (leaf) 2352 elif(m[-1] == ';'): 1901 elif(m[-1] == ';'): 2353 self.freturn 1902 self.freturn = True 2354 match = re.ma !! 1903 match = re.match('^(?P<n>.*) *\(.*', m) 2355 if(match): 1904 if(match): 2356 self. 1905 self.name = match.group('n').strip() 2357 # something else (pos 1906 # something else (possibly a trace marker) 2358 else: 1907 else: 2359 self.name = m 1908 self.name = m 2360 def isCall(self): 1909 def isCall(self): 2361 return self.fcall and not sel 1910 return self.fcall and not self.freturn 2362 def isReturn(self): 1911 def isReturn(self): 2363 return self.freturn and not s 1912 return self.freturn and not self.fcall 2364 def isLeaf(self): 1913 def isLeaf(self): 2365 return self.fcall and self.fr 1914 return self.fcall and self.freturn 2366 def getDepth(self, str): 1915 def getDepth(self, str): 2367 return len(str)/2 1916 return len(str)/2 2368 def debugPrint(self, info=''): 1917 def debugPrint(self, info=''): 2369 if self.isLeaf(): 1918 if self.isLeaf(): 2370 pprint(' -- %12.6f (d 1919 pprint(' -- %12.6f (depth=%02d): %s(); (%.3f us) %s' % (self.time, \ 2371 self.depth, s 1920 self.depth, self.name, self.length*1000000, info)) 2372 elif self.freturn: 1921 elif self.freturn: 2373 pprint(' -- %12.6f (d 1922 pprint(' -- %12.6f (depth=%02d): %s} (%.3f us) %s' % (self.time, \ 2374 self.depth, s 1923 self.depth, self.name, self.length*1000000, info)) 2375 else: 1924 else: 2376 pprint(' -- %12.6f (d 1925 pprint(' -- %12.6f (depth=%02d): %s() { (%.3f us) %s' % (self.time, \ 2377 self.depth, s 1926 self.depth, self.name, self.length*1000000, info)) 2378 def startMarker(self): 1927 def startMarker(self): 2379 # Is this the starting line o 1928 # Is this the starting line of a suspend? 2380 if not self.fevent: 1929 if not self.fevent: 2381 return False 1930 return False 2382 if sysvals.usetracemarkers: 1931 if sysvals.usetracemarkers: 2383 if(self.name.startswi !! 1932 if(self.name == 'SUSPEND START'): 2384 return True 1933 return True 2385 return False 1934 return False 2386 else: 1935 else: 2387 if(self.type == 'susp 1936 if(self.type == 'suspend_resume' and 2388 re.match(r'su !! 1937 re.match('suspend_enter\[.*\] begin', self.name)): 2389 return True 1938 return True 2390 return False 1939 return False 2391 def endMarker(self): 1940 def endMarker(self): 2392 # Is this the ending line of 1941 # Is this the ending line of a resume? 2393 if not self.fevent: 1942 if not self.fevent: 2394 return False 1943 return False 2395 if sysvals.usetracemarkers: 1944 if sysvals.usetracemarkers: 2396 if(self.name.startswi !! 1945 if(self.name == 'RESUME COMPLETE'): 2397 return True 1946 return True 2398 return False 1947 return False 2399 else: 1948 else: 2400 if(self.type == 'susp 1949 if(self.type == 'suspend_resume' and 2401 re.match(r'th !! 1950 re.match('thaw_processes\[.*\] end', self.name)): 2402 return True 1951 return True 2403 return False 1952 return False 2404 1953 2405 # Class: FTraceCallGraph 1954 # Class: FTraceCallGraph 2406 # Description: 1955 # Description: 2407 # A container for the ftrace callgraph 1956 # A container for the ftrace callgraph of a single recursive function. 2408 # This can be a dpm_run_callback, dpm_ 1957 # This can be a dpm_run_callback, dpm_prepare, or dpm_complete callgraph 2409 # Each instance is tied to a single de 1958 # Each instance is tied to a single device in a single phase, and is 2410 # comprised of an ordered list of FTra 1959 # comprised of an ordered list of FTraceLine objects 2411 class FTraceCallGraph: 1960 class FTraceCallGraph: 2412 vfname = 'missing_function_name' 1961 vfname = 'missing_function_name' 2413 def __init__(self, pid, sv): 1962 def __init__(self, pid, sv): 2414 self.id = '' 1963 self.id = '' 2415 self.invalid = False 1964 self.invalid = False 2416 self.name = '' 1965 self.name = '' 2417 self.partial = False 1966 self.partial = False 2418 self.ignore = False 1967 self.ignore = False 2419 self.start = -1.0 1968 self.start = -1.0 2420 self.end = -1.0 1969 self.end = -1.0 2421 self.list = [] 1970 self.list = [] 2422 self.depth = 0 1971 self.depth = 0 2423 self.pid = pid 1972 self.pid = pid 2424 self.sv = sv 1973 self.sv = sv 2425 def addLine(self, line): 1974 def addLine(self, line): 2426 # if this is already invalid, 1975 # if this is already invalid, just leave 2427 if(self.invalid): 1976 if(self.invalid): 2428 if(line.depth == 0 an 1977 if(line.depth == 0 and line.freturn): 2429 return 1 1978 return 1 2430 return 0 1979 return 0 2431 # invalidate on bad depth 1980 # invalidate on bad depth 2432 if(self.depth < 0): 1981 if(self.depth < 0): 2433 self.invalidate(line) 1982 self.invalidate(line) 2434 return 0 1983 return 0 2435 # ignore data til we return t 1984 # ignore data til we return to the current depth 2436 if self.ignore: 1985 if self.ignore: 2437 if line.depth > self. 1986 if line.depth > self.depth: 2438 return 0 1987 return 0 2439 else: 1988 else: 2440 self.list[-1] 1989 self.list[-1].freturn = True 2441 self.list[-1] 1990 self.list[-1].length = line.time - self.list[-1].time 2442 self.ignore = 1991 self.ignore = False 2443 # if this is 1992 # if this is a return at self.depth, no more work is needed 2444 if line.depth 1993 if line.depth == self.depth and line.isReturn(): 2445 if li 1994 if line.depth == 0: 2446 1995 self.end = line.time 2447 1996 return 1 2448 retur 1997 return 0 2449 # compare current depth with 1998 # compare current depth with this lines pre-call depth 2450 prelinedep = line.depth 1999 prelinedep = line.depth 2451 if line.isReturn(): 2000 if line.isReturn(): 2452 prelinedep += 1 2001 prelinedep += 1 2453 last = 0 2002 last = 0 2454 lasttime = line.time 2003 lasttime = line.time 2455 if len(self.list) > 0: 2004 if len(self.list) > 0: 2456 last = self.list[-1] 2005 last = self.list[-1] 2457 lasttime = last.time 2006 lasttime = last.time 2458 if last.isLeaf(): 2007 if last.isLeaf(): 2459 lasttime += l 2008 lasttime += last.length 2460 # handle low misalignments by 2009 # handle low misalignments by inserting returns 2461 mismatch = prelinedep - self. 2010 mismatch = prelinedep - self.depth 2462 warning = self.sv.verbose and 2011 warning = self.sv.verbose and abs(mismatch) > 1 2463 info = [] 2012 info = [] 2464 if mismatch < 0: 2013 if mismatch < 0: 2465 idx = 0 2014 idx = 0 2466 # add return calls to 2015 # add return calls to get the depth down 2467 while prelinedep < se 2016 while prelinedep < self.depth: 2468 self.depth -= 2017 self.depth -= 1 2469 if idx == 0 a 2018 if idx == 0 and last and last.isCall(): 2470 # spe 2019 # special case, turn last call into a leaf 2471 last. 2020 last.depth = self.depth 2472 last. 2021 last.freturn = True 2473 last. 2022 last.length = line.time - last.time 2474 if wa 2023 if warning: 2475 2024 info.append(('[make leaf]', last)) 2476 else: 2025 else: 2477 vline 2026 vline = FTraceLine(lasttime) 2478 vline 2027 vline.depth = self.depth 2479 vline 2028 vline.name = self.vfname 2480 vline 2029 vline.freturn = True 2481 self. 2030 self.list.append(vline) 2482 if wa 2031 if warning: 2483 2032 if idx == 0: 2484 2033 info.append(('', last)) 2485 2034 info.append(('[add return]', vline)) 2486 idx += 1 2035 idx += 1 2487 if warning: 2036 if warning: 2488 info.append(( 2037 info.append(('', line)) 2489 # handle high misalignments b 2038 # handle high misalignments by inserting calls 2490 elif mismatch > 0: 2039 elif mismatch > 0: 2491 idx = 0 2040 idx = 0 2492 if warning: 2041 if warning: 2493 info.append(( 2042 info.append(('', last)) 2494 # add calls to get th 2043 # add calls to get the depth up 2495 while prelinedep > se 2044 while prelinedep > self.depth: 2496 if idx == 0 a 2045 if idx == 0 and line.isReturn(): 2497 # spe 2046 # special case, turn this return into a leaf 2498 line. 2047 line.fcall = True 2499 preli 2048 prelinedep -= 1 2500 if wa 2049 if warning: 2501 2050 info.append(('[make leaf]', line)) 2502 else: 2051 else: 2503 vline 2052 vline = FTraceLine(lasttime) 2504 vline 2053 vline.depth = self.depth 2505 vline 2054 vline.name = self.vfname 2506 vline 2055 vline.fcall = True 2507 self. 2056 self.list.append(vline) 2508 self. 2057 self.depth += 1 2509 if no 2058 if not last: 2510 2059 self.start = vline.time 2511 if wa 2060 if warning: 2512 2061 info.append(('[add call]', vline)) 2513 idx += 1 2062 idx += 1 2514 if warning and ('[mak 2063 if warning and ('[make leaf]', line) not in info: 2515 info.append(( 2064 info.append(('', line)) 2516 if warning: 2065 if warning: 2517 pprint('WARNING: ftra 2066 pprint('WARNING: ftrace data missing, corrections made:') 2518 for i in info: 2067 for i in info: 2519 t, obj = i 2068 t, obj = i 2520 if obj: 2069 if obj: 2521 obj.d 2070 obj.debugPrint(t) 2522 # process the call and set th 2071 # process the call and set the new depth 2523 skipadd = False 2072 skipadd = False 2524 md = self.sv.max_graph_depth 2073 md = self.sv.max_graph_depth 2525 if line.isCall(): 2074 if line.isCall(): 2526 # ignore blacklisted/ 2075 # ignore blacklisted/overdepth funcs 2527 if (md and self.depth 2076 if (md and self.depth >= md - 1) or (line.name in self.sv.cgblacklist): 2528 self.ignore = 2077 self.ignore = True 2529 else: 2078 else: 2530 self.depth += 2079 self.depth += 1 2531 elif line.isReturn(): 2080 elif line.isReturn(): 2532 self.depth -= 1 2081 self.depth -= 1 2533 # remove blacklisted/ 2082 # remove blacklisted/overdepth/empty funcs that slipped through 2534 if (last and last.isC 2083 if (last and last.isCall() and last.depth == line.depth) or \ 2535 (md and last 2084 (md and last and last.depth >= md) or \ 2536 (line.name in 2085 (line.name in self.sv.cgblacklist): 2537 while len(sel 2086 while len(self.list) > 0 and self.list[-1].depth > line.depth: 2538 self. 2087 self.list.pop(-1) 2539 if len(self.l 2088 if len(self.list) == 0: 2540 self. 2089 self.invalid = True 2541 retur 2090 return 1 2542 self.list[-1] 2091 self.list[-1].freturn = True 2543 self.list[-1] 2092 self.list[-1].length = line.time - self.list[-1].time 2544 self.list[-1] 2093 self.list[-1].name = line.name 2545 skipadd = Tru 2094 skipadd = True 2546 if len(self.list) < 1: 2095 if len(self.list) < 1: 2547 self.start = line.tim 2096 self.start = line.time 2548 # check for a mismatch that r 2097 # check for a mismatch that returned all the way to callgraph end 2549 res = 1 2098 res = 1 2550 if mismatch < 0 and self.list 2099 if mismatch < 0 and self.list[-1].depth == 0 and self.list[-1].freturn: 2551 line = self.list[-1] 2100 line = self.list[-1] 2552 skipadd = True 2101 skipadd = True 2553 res = -1 2102 res = -1 2554 if not skipadd: 2103 if not skipadd: 2555 self.list.append(line 2104 self.list.append(line) 2556 if(line.depth == 0 and line.f 2105 if(line.depth == 0 and line.freturn): 2557 if(self.start < 0): 2106 if(self.start < 0): 2558 self.start = 2107 self.start = line.time 2559 self.end = line.time 2108 self.end = line.time 2560 if line.fcall: 2109 if line.fcall: 2561 self.end += l 2110 self.end += line.length 2562 if self.list[0].name 2111 if self.list[0].name == self.vfname: 2563 self.invalid 2112 self.invalid = True 2564 if res == -1: 2113 if res == -1: 2565 self.partial 2114 self.partial = True 2566 return res 2115 return res 2567 return 0 2116 return 0 2568 def invalidate(self, line): 2117 def invalidate(self, line): 2569 if(len(self.list) > 0): 2118 if(len(self.list) > 0): 2570 first = self.list[0] 2119 first = self.list[0] 2571 self.list = [] 2120 self.list = [] 2572 self.list.append(firs 2121 self.list.append(first) 2573 self.invalid = True 2122 self.invalid = True 2574 id = 'task %s' % (self.pid) 2123 id = 'task %s' % (self.pid) 2575 window = '(%f - %f)' % (self. 2124 window = '(%f - %f)' % (self.start, line.time) 2576 if(self.depth < 0): 2125 if(self.depth < 0): 2577 pprint('Data misalign 2126 pprint('Data misalignment for '+id+\ 2578 ' (buffer ove 2127 ' (buffer overflow), ignoring this callback') 2579 else: 2128 else: 2580 pprint('Too much data 2129 pprint('Too much data for '+id+\ 2581 ' '+window+', 2130 ' '+window+', ignoring this callback') 2582 def slice(self, dev): 2131 def slice(self, dev): 2583 minicg = FTraceCallGraph(dev[ 2132 minicg = FTraceCallGraph(dev['pid'], self.sv) 2584 minicg.name = self.name 2133 minicg.name = self.name 2585 mydepth = -1 2134 mydepth = -1 2586 good = False 2135 good = False 2587 for l in self.list: 2136 for l in self.list: 2588 if(l.time < dev['star 2137 if(l.time < dev['start'] or l.time > dev['end']): 2589 continue 2138 continue 2590 if mydepth < 0: 2139 if mydepth < 0: 2591 if l.name == 2140 if l.name == 'mutex_lock' and l.freturn: 2592 mydep 2141 mydepth = l.depth 2593 continue 2142 continue 2594 elif l.depth == mydep 2143 elif l.depth == mydepth and l.name == 'mutex_unlock' and l.fcall: 2595 good = True 2144 good = True 2596 break 2145 break 2597 l.depth -= mydepth 2146 l.depth -= mydepth 2598 minicg.addLine(l) 2147 minicg.addLine(l) 2599 if not good or len(minicg.lis 2148 if not good or len(minicg.list) < 1: 2600 return 0 2149 return 0 2601 return minicg 2150 return minicg 2602 def repair(self, enddepth): 2151 def repair(self, enddepth): 2603 # bring the depth back to 0 w 2152 # bring the depth back to 0 with additional returns 2604 fixed = False 2153 fixed = False 2605 last = self.list[-1] 2154 last = self.list[-1] 2606 for i in reversed(range(endde 2155 for i in reversed(range(enddepth)): 2607 t = FTraceLine(last.t 2156 t = FTraceLine(last.time) 2608 t.depth = i 2157 t.depth = i 2609 t.freturn = True 2158 t.freturn = True 2610 fixed = self.addLine( 2159 fixed = self.addLine(t) 2611 if fixed != 0: 2160 if fixed != 0: 2612 self.end = la 2161 self.end = last.time 2613 return True 2162 return True 2614 return False 2163 return False 2615 def postProcess(self): 2164 def postProcess(self): 2616 if len(self.list) > 0: 2165 if len(self.list) > 0: 2617 self.name = self.list 2166 self.name = self.list[0].name 2618 stack = dict() 2167 stack = dict() 2619 cnt = 0 2168 cnt = 0 2620 last = 0 2169 last = 0 2621 for l in self.list: 2170 for l in self.list: 2622 # ftrace bug: reporte 2171 # ftrace bug: reported duration is not reliable 2623 # check each leaf and 2172 # check each leaf and clip it at max possible length 2624 if last and last.isLe 2173 if last and last.isLeaf(): 2625 if last.lengt 2174 if last.length > l.time - last.time: 2626 last. 2175 last.length = l.time - last.time 2627 if l.isCall(): 2176 if l.isCall(): 2628 stack[l.depth 2177 stack[l.depth] = l 2629 cnt += 1 2178 cnt += 1 2630 elif l.isReturn(): 2179 elif l.isReturn(): 2631 if(l.depth no 2180 if(l.depth not in stack): 2632 if se 2181 if self.sv.verbose: 2633 2182 pprint('Post Process Error: Depth missing') 2634 2183 l.debugPrint() 2635 retur 2184 return False 2636 # calculate c 2185 # calculate call length from call/return lines 2637 cl = stack[l. 2186 cl = stack[l.depth] 2638 cl.length = l 2187 cl.length = l.time - cl.time 2639 if cl.name == 2188 if cl.name == self.vfname: 2640 cl.na 2189 cl.name = l.name 2641 stack.pop(l.d 2190 stack.pop(l.depth) 2642 l.length = 0 2191 l.length = 0 2643 cnt -= 1 2192 cnt -= 1 2644 last = l 2193 last = l 2645 if(cnt == 0): 2194 if(cnt == 0): 2646 # trace caught the wh 2195 # trace caught the whole call tree 2647 return True 2196 return True 2648 elif(cnt < 0): 2197 elif(cnt < 0): 2649 if self.sv.verbose: 2198 if self.sv.verbose: 2650 pprint('Post 2199 pprint('Post Process Error: Depth is less than 0') 2651 return False 2200 return False 2652 # trace ended before call tre 2201 # trace ended before call tree finished 2653 return self.repair(cnt) 2202 return self.repair(cnt) 2654 def deviceMatch(self, pid, data): 2203 def deviceMatch(self, pid, data): 2655 found = '' 2204 found = '' 2656 # add the callgraph data to t 2205 # add the callgraph data to the device hierarchy 2657 borderphase = { 2206 borderphase = { 2658 'dpm_prepare': 'suspe 2207 'dpm_prepare': 'suspend_prepare', 2659 'dpm_complete': 'resu 2208 'dpm_complete': 'resume_complete' 2660 } 2209 } 2661 if(self.name in borderphase): 2210 if(self.name in borderphase): 2662 p = borderphase[self. 2211 p = borderphase[self.name] 2663 list = data.dmesg[p][ 2212 list = data.dmesg[p]['list'] 2664 for devname in list: 2213 for devname in list: 2665 dev = list[de 2214 dev = list[devname] 2666 if(pid == dev 2215 if(pid == dev['pid'] and 2667 self. 2216 self.start <= dev['start'] and 2668 self. 2217 self.end >= dev['end']): 2669 cg = 2218 cg = self.slice(dev) 2670 if cg 2219 if cg: 2671 2220 dev['ftrace'] = cg 2672 found 2221 found = devname 2673 return found 2222 return found 2674 for p in data.sortedPhases(): 2223 for p in data.sortedPhases(): 2675 if(data.dmesg[p]['sta 2224 if(data.dmesg[p]['start'] <= self.start and 2676 self.start <= 2225 self.start <= data.dmesg[p]['end']): 2677 list = data.d 2226 list = data.dmesg[p]['list'] 2678 for devname i 2227 for devname in sorted(list, key=lambda k:list[k]['start']): 2679 dev = 2228 dev = list[devname] 2680 if(pi 2229 if(pid == dev['pid'] and 2681 2230 self.start <= dev['start'] and 2682 2231 self.end >= dev['end']): 2683 2232 dev['ftrace'] = self 2684 2233 found = devname 2685 2234 break 2686 break 2235 break 2687 return found 2236 return found 2688 def newActionFromFunction(self, data) 2237 def newActionFromFunction(self, data): 2689 name = self.name 2238 name = self.name 2690 if name in ['dpm_run_callback 2239 if name in ['dpm_run_callback', 'dpm_prepare', 'dpm_complete']: 2691 return 2240 return 2692 fs = self.start 2241 fs = self.start 2693 fe = self.end 2242 fe = self.end 2694 if fs < data.start or fe > da 2243 if fs < data.start or fe > data.end: 2695 return 2244 return 2696 phase = '' 2245 phase = '' 2697 for p in data.sortedPhases(): 2246 for p in data.sortedPhases(): 2698 if(data.dmesg[p]['sta 2247 if(data.dmesg[p]['start'] <= self.start and 2699 self.start < 2248 self.start < data.dmesg[p]['end']): 2700 phase = p 2249 phase = p 2701 break 2250 break 2702 if not phase: 2251 if not phase: 2703 return 2252 return 2704 out = data.newActionGlobal(na 2253 out = data.newActionGlobal(name, fs, fe, -2) 2705 if out: 2254 if out: 2706 phase, myname = out 2255 phase, myname = out 2707 data.dmesg[phase]['li 2256 data.dmesg[phase]['list'][myname]['ftrace'] = self 2708 def debugPrint(self, info=''): 2257 def debugPrint(self, info=''): 2709 pprint('%s pid=%d [%f - %f] % 2258 pprint('%s pid=%d [%f - %f] %.3f us' % \ 2710 (self.name, self.pid, 2259 (self.name, self.pid, self.start, self.end, 2711 (self.end - self.star 2260 (self.end - self.start)*1000000)) 2712 for l in self.list: 2261 for l in self.list: 2713 if l.isLeaf(): 2262 if l.isLeaf(): 2714 pprint('%f (% 2263 pprint('%f (%02d): %s(); (%.3f us)%s' % (l.time, \ 2715 l.dep 2264 l.depth, l.name, l.length*1000000, info)) 2716 elif l.freturn: 2265 elif l.freturn: 2717 pprint('%f (% 2266 pprint('%f (%02d): %s} (%.3f us)%s' % (l.time, \ 2718 l.dep 2267 l.depth, l.name, l.length*1000000, info)) 2719 else: 2268 else: 2720 pprint('%f (% 2269 pprint('%f (%02d): %s() { (%.3f us)%s' % (l.time, \ 2721 l.dep 2270 l.depth, l.name, l.length*1000000, info)) 2722 pprint(' ') 2271 pprint(' ') 2723 2272 2724 class DevItem: 2273 class DevItem: 2725 def __init__(self, test, phase, dev): 2274 def __init__(self, test, phase, dev): 2726 self.test = test 2275 self.test = test 2727 self.phase = phase 2276 self.phase = phase 2728 self.dev = dev 2277 self.dev = dev 2729 def isa(self, cls): 2278 def isa(self, cls): 2730 if 'htmlclass' in self.dev an 2279 if 'htmlclass' in self.dev and cls in self.dev['htmlclass']: 2731 return True 2280 return True 2732 return False 2281 return False 2733 2282 2734 # Class: Timeline 2283 # Class: Timeline 2735 # Description: 2284 # Description: 2736 # A container for a device timeline wh 2285 # A container for a device timeline which calculates 2737 # all the html properties to display i 2286 # all the html properties to display it correctly 2738 class Timeline: 2287 class Timeline: 2739 html_tblock = '<div id="block{0}" cla 2288 html_tblock = '<div id="block{0}" class="tblock" style="left:{1}%;width:{2}%;"><div class="tback" style="height:{3}px"></div>\n' 2740 html_device = '<div id="{0}" title="{ 2289 html_device = '<div id="{0}" title="{1}" class="thread{7}" style="left:{2}%;top:{3}px;height:{4}px;width:{5}%;{8}">{6}</div>\n' 2741 html_phase = '<div class="phase" styl 2290 html_phase = '<div class="phase" style="left:{0}%;width:{1}%;top:{2}px;height:{3}px;background:{4}">{5}</div>\n' 2742 html_phaselet = '<div id="{0}" class= 2291 html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background:{3}"></div>\n' 2743 html_legend = '<div id="p{3}" class=" 2292 html_legend = '<div id="p{3}" class="square" style="left:{0}%;background:{1}"> {2}</div>\n' 2744 def __init__(self, rowheight, scalehe 2293 def __init__(self, rowheight, scaleheight): 2745 self.html = '' 2294 self.html = '' 2746 self.height = 0 # total time 2295 self.height = 0 # total timeline height 2747 self.scaleH = scaleheight # t 2296 self.scaleH = scaleheight # timescale (top) row height 2748 self.rowH = rowheight # d 2297 self.rowH = rowheight # device row height 2749 self.bodyH = 0 # body heigh 2298 self.bodyH = 0 # body height 2750 self.rows = 0 # total time 2299 self.rows = 0 # total timeline rows 2751 self.rowlines = dict() 2300 self.rowlines = dict() 2752 self.rowheight = dict() 2301 self.rowheight = dict() 2753 def createHeader(self, sv, stamp): 2302 def createHeader(self, sv, stamp): 2754 if(not stamp['time']): 2303 if(not stamp['time']): 2755 return 2304 return 2756 self.html += '<div class="ver !! 2305 self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \ 2757 % (sv.title, sv.versi 2306 % (sv.title, sv.version) 2758 if sv.logmsg and sv.testlog: 2307 if sv.logmsg and sv.testlog: 2759 self.html += '<button 2308 self.html += '<button id="showtest" class="logbtn btnfmt">log</button>' 2760 if sv.dmesglog: 2309 if sv.dmesglog: 2761 self.html += '<button 2310 self.html += '<button id="showdmesg" class="logbtn btnfmt">dmesg</button>' 2762 if sv.ftracelog: 2311 if sv.ftracelog: 2763 self.html += '<button 2312 self.html += '<button id="showftrace" class="logbtn btnfmt">ftrace</button>' 2764 headline_stamp = '<div class= 2313 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n' 2765 self.html += headline_stamp.f 2314 self.html += headline_stamp.format(stamp['host'], stamp['kernel'], 2766 stamp['mode'], stamp[ 2315 stamp['mode'], stamp['time']) 2767 if 'man' in stamp and 'plat' 2316 if 'man' in stamp and 'plat' in stamp and 'cpu' in stamp and \ 2768 stamp['man'] and stam 2317 stamp['man'] and stamp['plat'] and stamp['cpu']: 2769 headline_sysinfo = '< 2318 headline_sysinfo = '<div class="stamp sysinfo">{0} {1} <i>with</i> {2}</div>\n' 2770 self.html += headline 2319 self.html += headline_sysinfo.format(stamp['man'], stamp['plat'], stamp['cpu']) 2771 2320 2772 # Function: getDeviceRows 2321 # Function: getDeviceRows 2773 # Description: 2322 # Description: 2774 # determine how may rows the devic 2323 # determine how may rows the device funcs will take 2775 # Arguments: 2324 # Arguments: 2776 # rawlist: the list of devices 2325 # rawlist: the list of devices/actions for a single phase 2777 # Output: 2326 # Output: 2778 # The total number of rows nee 2327 # The total number of rows needed to display this phase of the timeline 2779 def getDeviceRows(self, rawlist): 2328 def getDeviceRows(self, rawlist): 2780 # clear all rows and set them 2329 # clear all rows and set them to undefined 2781 sortdict = dict() 2330 sortdict = dict() 2782 for item in rawlist: 2331 for item in rawlist: 2783 item.row = -1 2332 item.row = -1 2784 sortdict[item] = item 2333 sortdict[item] = item.length 2785 sortlist = sorted(sortdict, k 2334 sortlist = sorted(sortdict, key=sortdict.get, reverse=True) 2786 remaining = len(sortlist) 2335 remaining = len(sortlist) 2787 rowdata = dict() 2336 rowdata = dict() 2788 row = 1 2337 row = 1 2789 # try to pack each row with a 2338 # try to pack each row with as many ranges as possible 2790 while(remaining > 0): 2339 while(remaining > 0): 2791 if(row not in rowdata 2340 if(row not in rowdata): 2792 rowdata[row] 2341 rowdata[row] = [] 2793 for i in sortlist: 2342 for i in sortlist: 2794 if(i.row >= 0 2343 if(i.row >= 0): 2795 conti 2344 continue 2796 s = i.time 2345 s = i.time 2797 e = i.time + 2346 e = i.time + i.length 2798 valid = True 2347 valid = True 2799 for ritem in 2348 for ritem in rowdata[row]: 2800 rs = 2349 rs = ritem.time 2801 re = 2350 re = ritem.time + ritem.length 2802 if(no 2351 if(not (((s <= rs) and (e <= rs)) or 2803 2352 ((s >= re) and (e >= re)))): 2804 2353 valid = False 2805 2354 break 2806 if(valid): 2355 if(valid): 2807 rowda 2356 rowdata[row].append(i) 2808 i.row 2357 i.row = row 2809 remai 2358 remaining -= 1 2810 row += 1 2359 row += 1 2811 return row 2360 return row 2812 # Function: getPhaseRows 2361 # Function: getPhaseRows 2813 # Description: 2362 # Description: 2814 # Organize the timeline entrie 2363 # Organize the timeline entries into the smallest 2815 # number of rows possible, wit 2364 # number of rows possible, with no entry overlapping 2816 # Arguments: 2365 # Arguments: 2817 # devlist: the list of devices 2366 # devlist: the list of devices/actions in a group of contiguous phases 2818 # Output: 2367 # Output: 2819 # The total number of rows nee 2368 # The total number of rows needed to display this phase of the timeline 2820 def getPhaseRows(self, devlist, row=0 2369 def getPhaseRows(self, devlist, row=0, sortby='length'): 2821 # clear all rows and set them 2370 # clear all rows and set them to undefined 2822 remaining = len(devlist) 2371 remaining = len(devlist) 2823 rowdata = dict() 2372 rowdata = dict() 2824 sortdict = dict() 2373 sortdict = dict() 2825 myphases = [] 2374 myphases = [] 2826 # initialize all device rows 2375 # initialize all device rows to -1 and calculate devrows 2827 for item in devlist: 2376 for item in devlist: 2828 dev = item.dev 2377 dev = item.dev 2829 tp = (item.test, item 2378 tp = (item.test, item.phase) 2830 if tp not in myphases 2379 if tp not in myphases: 2831 myphases.appe 2380 myphases.append(tp) 2832 dev['row'] = -1 2381 dev['row'] = -1 2833 if sortby == 'start': 2382 if sortby == 'start': 2834 # sort by sta 2383 # sort by start 1st, then length 2nd 2835 sortdict[item 2384 sortdict[item] = (-1*float(dev['start']), float(dev['end']) - float(dev['start'])) 2836 else: 2385 else: 2837 # sort by len 2386 # sort by length 1st, then name 2nd 2838 sortdict[item 2387 sortdict[item] = (float(dev['end']) - float(dev['start']), item.dev['name']) 2839 if 'src' in dev: 2388 if 'src' in dev: 2840 dev['devrows' 2389 dev['devrows'] = self.getDeviceRows(dev['src']) 2841 # sort the devlist by length 2390 # sort the devlist by length so that large items graph on top 2842 sortlist = sorted(sortdict, k 2391 sortlist = sorted(sortdict, key=sortdict.get, reverse=True) 2843 orderedlist = [] 2392 orderedlist = [] 2844 for item in sortlist: 2393 for item in sortlist: 2845 if item.dev['pid'] == 2394 if item.dev['pid'] == -2: 2846 orderedlist.a 2395 orderedlist.append(item) 2847 for item in sortlist: 2396 for item in sortlist: 2848 if item not in ordere 2397 if item not in orderedlist: 2849 orderedlist.a 2398 orderedlist.append(item) 2850 # try to pack each row with a 2399 # try to pack each row with as many devices as possible 2851 while(remaining > 0): 2400 while(remaining > 0): 2852 rowheight = 1 2401 rowheight = 1 2853 if(row not in rowdata 2402 if(row not in rowdata): 2854 rowdata[row] 2403 rowdata[row] = [] 2855 for item in orderedli 2404 for item in orderedlist: 2856 dev = item.de 2405 dev = item.dev 2857 if(dev['row'] 2406 if(dev['row'] < 0): 2858 s = d 2407 s = dev['start'] 2859 e = d 2408 e = dev['end'] 2860 valid 2409 valid = True 2861 for r 2410 for ritem in rowdata[row]: 2862 2411 rs = ritem.dev['start'] 2863 2412 re = ritem.dev['end'] 2864 2413 if(not (((s <= rs) and (e <= rs)) or 2865 2414 ((s >= re) and (e >= re)))): 2866 2415 valid = False 2867 2416 break 2868 if(va 2417 if(valid): 2869 2418 rowdata[row].append(item) 2870 2419 dev['row'] = row 2871 2420 remaining -= 1 2872 2421 if 'devrows' in dev and dev['devrows'] > rowheight: 2873 2422 rowheight = dev['devrows'] 2874 for t, p in myphases: 2423 for t, p in myphases: 2875 if t not in s 2424 if t not in self.rowlines or t not in self.rowheight: 2876 self. 2425 self.rowlines[t] = dict() 2877 self. 2426 self.rowheight[t] = dict() 2878 if p not in s 2427 if p not in self.rowlines[t] or p not in self.rowheight[t]: 2879 self. 2428 self.rowlines[t][p] = dict() 2880 self. 2429 self.rowheight[t][p] = dict() 2881 rh = self.row 2430 rh = self.rowH 2882 # section hea 2431 # section headers should use a different row height 2883 if len(rowdat 2432 if len(rowdata[row]) == 1 and \ 2884 'html 2433 'htmlclass' in rowdata[row][0].dev and \ 2885 'sec' 2434 'sec' in rowdata[row][0].dev['htmlclass']: 2886 rh = 2435 rh = 15 2887 self.rowlines 2436 self.rowlines[t][p][row] = rowheight 2888 self.rowheigh 2437 self.rowheight[t][p][row] = rowheight * rh 2889 row += 1 2438 row += 1 2890 if(row > self.rows): 2439 if(row > self.rows): 2891 self.rows = int(row) 2440 self.rows = int(row) 2892 return row 2441 return row 2893 def phaseRowHeight(self, test, phase, 2442 def phaseRowHeight(self, test, phase, row): 2894 return self.rowheight[test][p 2443 return self.rowheight[test][phase][row] 2895 def phaseRowTop(self, test, phase, ro 2444 def phaseRowTop(self, test, phase, row): 2896 top = 0 2445 top = 0 2897 for i in sorted(self.rowheigh 2446 for i in sorted(self.rowheight[test][phase]): 2898 if i >= row: 2447 if i >= row: 2899 break 2448 break 2900 top += self.rowheight 2449 top += self.rowheight[test][phase][i] 2901 return top 2450 return top 2902 def calcTotalRows(self): 2451 def calcTotalRows(self): 2903 # Calculate the heights and o 2452 # Calculate the heights and offsets for the header and rows 2904 maxrows = 0 2453 maxrows = 0 2905 standardphases = [] 2454 standardphases = [] 2906 for t in self.rowlines: 2455 for t in self.rowlines: 2907 for p in self.rowline 2456 for p in self.rowlines[t]: 2908 total = 0 2457 total = 0 2909 for i in sort 2458 for i in sorted(self.rowlines[t][p]): 2910 total 2459 total += self.rowlines[t][p][i] 2911 if total > ma 2460 if total > maxrows: 2912 maxro 2461 maxrows = total 2913 if total == l 2462 if total == len(self.rowlines[t][p]): 2914 stand 2463 standardphases.append((t, p)) 2915 self.height = self.scaleH + ( 2464 self.height = self.scaleH + (maxrows*self.rowH) 2916 self.bodyH = self.height - se 2465 self.bodyH = self.height - self.scaleH 2917 # if there is 1 line per row, 2466 # if there is 1 line per row, draw them the standard way 2918 for t, p in standardphases: 2467 for t, p in standardphases: 2919 for i in sorted(self. 2468 for i in sorted(self.rowheight[t][p]): 2920 self.rowheigh !! 2469 self.rowheight[t][p][i] = self.bodyH/len(self.rowlines[t][p]) 2921 def createZoomBox(self, mode='command 2470 def createZoomBox(self, mode='command', testcount=1): 2922 # Create bounding box, add bu 2471 # Create bounding box, add buttons 2923 html_zoombox = '<center><butt 2472 html_zoombox = '<center><button id="zoomin">ZOOM IN +</button><button id="zoomout">ZOOM OUT -</button><button id="zoomdef">ZOOM 1:1</button></center>\n' 2924 html_timeline = '<div id="dme 2473 html_timeline = '<div id="dmesgzoombox" class="zoombox">\n<div id="{0}" class="timeline" style="height:{1}px">\n' 2925 html_devlist1 = '<button id=" 2474 html_devlist1 = '<button id="devlist1" class="devlist" style="float:left;">Device Detail{0}</button>' 2926 html_devlist2 = '<button id=" 2475 html_devlist2 = '<button id="devlist2" class="devlist" style="float:right;">Device Detail2</button>\n' 2927 if mode != 'command': 2476 if mode != 'command': 2928 if testcount > 1: 2477 if testcount > 1: 2929 self.html += 2478 self.html += html_devlist2 2930 self.html += 2479 self.html += html_devlist1.format('1') 2931 else: 2480 else: 2932 self.html += 2481 self.html += html_devlist1.format('') 2933 self.html += html_zoombox 2482 self.html += html_zoombox 2934 self.html += html_timeline.fo 2483 self.html += html_timeline.format('dmesg', self.height) 2935 # Function: createTimeScale 2484 # Function: createTimeScale 2936 # Description: 2485 # Description: 2937 # Create the timescale for a t 2486 # Create the timescale for a timeline block 2938 # Arguments: 2487 # Arguments: 2939 # m0: start time (mode begin) 2488 # m0: start time (mode begin) 2940 # mMax: end time (mode end) 2489 # mMax: end time (mode end) 2941 # tTotal: total timeline time 2490 # tTotal: total timeline time 2942 # mode: suspend or resume 2491 # mode: suspend or resume 2943 # Output: 2492 # Output: 2944 # The html code needed to disp 2493 # The html code needed to display the time scale 2945 def createTimeScale(self, m0, mMax, t 2494 def createTimeScale(self, m0, mMax, tTotal, mode): 2946 timescale = '<div class="t" s 2495 timescale = '<div class="t" style="right:{0}%">{1}</div>\n' 2947 rline = '<div class="t" style 2496 rline = '<div class="t" style="left:0;border-left:1px solid black;border-right:0;">{0}</div>\n' 2948 output = '<div class="timesca 2497 output = '<div class="timescale">\n' 2949 # set scale for timeline 2498 # set scale for timeline 2950 mTotal = mMax - m0 2499 mTotal = mMax - m0 2951 tS = 0.1 2500 tS = 0.1 2952 if(tTotal <= 0): 2501 if(tTotal <= 0): 2953 return output+'</div> 2502 return output+'</div>\n' 2954 if(tTotal > 4): 2503 if(tTotal > 4): 2955 tS = 1 2504 tS = 1 2956 divTotal = int(mTotal/tS) + 1 2505 divTotal = int(mTotal/tS) + 1 2957 divEdge = (mTotal - tS*(divTo 2506 divEdge = (mTotal - tS*(divTotal-1))*100/mTotal 2958 for i in range(divTotal): 2507 for i in range(divTotal): 2959 htmlline = '' 2508 htmlline = '' 2960 if(mode == 'suspend') 2509 if(mode == 'suspend'): 2961 pos = '%0.3f' 2510 pos = '%0.3f' % (100 - ((float(i)*tS*100)/mTotal) - divEdge) 2962 val = '%0.fms 2511 val = '%0.fms' % (float(i-divTotal+1)*tS*1000) 2963 if(i == divTo 2512 if(i == divTotal - 1): 2964 val = 2513 val = mode 2965 htmlline = ti 2514 htmlline = timescale.format(pos, val) 2966 else: 2515 else: 2967 pos = '%0.3f' 2516 pos = '%0.3f' % (100 - ((float(i)*tS*100)/mTotal)) 2968 val = '%0.fms 2517 val = '%0.fms' % (float(i)*tS*1000) 2969 htmlline = ti 2518 htmlline = timescale.format(pos, val) 2970 if(i == 0): 2519 if(i == 0): 2971 htmll 2520 htmlline = rline.format(mode) 2972 output += htmlline 2521 output += htmlline 2973 self.html += output+'</div>\n 2522 self.html += output+'</div>\n' 2974 2523 2975 # Class: TestProps 2524 # Class: TestProps 2976 # Description: 2525 # Description: 2977 # A list of values describing the prop 2526 # A list of values describing the properties of these test runs 2978 class TestProps: 2527 class TestProps: 2979 stampfmt = r'# [a-z]*-(?P<m>[0-9]{2}) !! 2528 stampfmt = '# [a-z]*-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\ 2980 r'(?P<H>[0-9] !! 2529 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\ 2981 r' (?P<host>. !! 2530 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$' 2982 wififmt = r'^# wifi *(?P<d>\S*) *( !! 2531 batteryfmt = '^# battery (?P<a1>\w*) (?P<c1>\d*) (?P<a2>\w*) (?P<c2>\d*)' 2983 tstatfmt = r'^# turbostat (?P<t>\S* !! 2532 wififmt = '^# wifi (?P<w>.*)' 2984 testerrfmt = r'^# enter_sleep_error ( !! 2533 tstatfmt = '^# turbostat (?P<t>\S*)' 2985 sysinfofmt = r'^# sysinfo .*' !! 2534 mcelogfmt = '^# mcelog (?P<m>\S*)' 2986 cmdlinefmt = r'^# command \| (?P<cmd> !! 2535 testerrfmt = '^# enter_sleep_error (?P<e>.*)' 2987 kparamsfmt = r'^# kparams \| (?P<kp>. !! 2536 sysinfofmt = '^# sysinfo .*' 2988 devpropfmt = r'# Device Properties: . !! 2537 cmdlinefmt = '^# command \| (?P<cmd>.*)' 2989 pinfofmt = r'# platform-(?P<val>[a- !! 2538 kparamsfmt = '^# kparams \| (?P<kp>.*)' 2990 tracertypefmt = r'# tracer: (?P<t>.*) !! 2539 devpropfmt = '# Device Properties: .*' 2991 firmwarefmt = r'# fwsuspend (?P<s>[0- !! 2540 tracertypefmt = '# tracer: (?P<t>.*)' 2992 procexecfmt = r'ps - (?P<ps>.*)$' !! 2541 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$' 2993 procmultifmt = r'@(?P<n>[0-9]*)\|(?P< !! 2542 procexecfmt = 'ps - (?P<ps>.*)$' 2994 ftrace_line_fmt_fg = \ 2543 ftrace_line_fmt_fg = \ 2995 r'^ *(?P<time>[0-9\.]*) *\| * !! 2544 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\ 2996 r' *(?P<proc>.*)-(?P<pid>[0-9 !! 2545 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\ 2997 r'[ +!#\*@$]*(?P<dur>[0-9\.]* !! 2546 '[ +!#\*@$]*(?P<dur>[0-9\.]*) .*\| (?P<msg>.*)' 2998 ftrace_line_fmt_nop = \ 2547 ftrace_line_fmt_nop = \ 2999 r' *(?P<proc>.*)-(?P<pid>[0-9 !! 2548 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\[(?P<cpu>[0-9]*)\] *'+\ 3000 r'(?P<flags>\S*) *(?P<time>[0 !! 2549 '(?P<flags>.{4}) *(?P<time>[0-9\.]*): *'+\ 3001 r'(?P<msg>.*)' !! 2550 '(?P<msg>.*)' 3002 machinesuspend = r'machine_suspend\[. << 3003 multiproclist = dict() << 3004 multiproctime = 0.0 << 3005 multiproccnt = 0 << 3006 def __init__(self): 2551 def __init__(self): 3007 self.stamp = '' 2552 self.stamp = '' 3008 self.sysinfo = '' 2553 self.sysinfo = '' 3009 self.cmdline = '' 2554 self.cmdline = '' >> 2555 self.kparams = '' 3010 self.testerror = [] 2556 self.testerror = [] >> 2557 self.mcelog = [] 3011 self.turbostat = [] 2558 self.turbostat = [] >> 2559 self.battery = [] 3012 self.wifi = [] 2560 self.wifi = [] 3013 self.fwdata = [] 2561 self.fwdata = [] 3014 self.ftrace_line_fmt = self.f 2562 self.ftrace_line_fmt = self.ftrace_line_fmt_nop 3015 self.cgformat = False 2563 self.cgformat = False 3016 self.data = 0 2564 self.data = 0 3017 self.ktemp = dict() 2565 self.ktemp = dict() 3018 def setTracerType(self, tracer): 2566 def setTracerType(self, tracer): 3019 if(tracer == 'function_graph' 2567 if(tracer == 'function_graph'): 3020 self.cgformat = True 2568 self.cgformat = True 3021 self.ftrace_line_fmt 2569 self.ftrace_line_fmt = self.ftrace_line_fmt_fg 3022 elif(tracer == 'nop'): 2570 elif(tracer == 'nop'): 3023 self.ftrace_line_fmt 2571 self.ftrace_line_fmt = self.ftrace_line_fmt_nop 3024 else: 2572 else: 3025 doError('Invalid trac 2573 doError('Invalid tracer format: [%s]' % tracer) 3026 def stampInfo(self, line, sv): !! 2574 def decode(self, data): >> 2575 try: >> 2576 out = base64.b64decode(data).decode('zlib') >> 2577 except: >> 2578 out = data >> 2579 return out >> 2580 def stampInfo(self, line): 3027 if re.match(self.stampfmt, li 2581 if re.match(self.stampfmt, line): 3028 self.stamp = line 2582 self.stamp = line 3029 return True 2583 return True 3030 elif re.match(self.sysinfofmt 2584 elif re.match(self.sysinfofmt, line): 3031 self.sysinfo = line 2585 self.sysinfo = line 3032 return True 2586 return True >> 2587 elif re.match(self.kparamsfmt, line): >> 2588 self.kparams = line >> 2589 return True >> 2590 elif re.match(self.cmdlinefmt, line): >> 2591 self.cmdline = line >> 2592 return True >> 2593 elif re.match(self.mcelogfmt, line): >> 2594 self.mcelog.append(line) >> 2595 return True 3033 elif re.match(self.tstatfmt, 2596 elif re.match(self.tstatfmt, line): 3034 self.turbostat.append 2597 self.turbostat.append(line) 3035 return True 2598 return True >> 2599 elif re.match(self.batteryfmt, line): >> 2600 self.battery.append(line) >> 2601 return True 3036 elif re.match(self.wififmt, l 2602 elif re.match(self.wififmt, line): 3037 self.wifi.append(line 2603 self.wifi.append(line) 3038 return True 2604 return True 3039 elif re.match(self.testerrfmt 2605 elif re.match(self.testerrfmt, line): 3040 self.testerror.append 2606 self.testerror.append(line) 3041 return True 2607 return True 3042 elif re.match(self.firmwarefm 2608 elif re.match(self.firmwarefmt, line): 3043 self.fwdata.append(li 2609 self.fwdata.append(line) 3044 return True 2610 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 2611 return False 3060 def parseStamp(self, data, sv): 2612 def parseStamp(self, data, sv): 3061 # global test data 2613 # global test data 3062 m = re.match(self.stampfmt, s 2614 m = re.match(self.stampfmt, self.stamp) 3063 if not self.stamp or not m: << 3064 doError('data does no << 3065 data.stamp = {'time': '', 'ho 2615 data.stamp = {'time': '', 'host': '', 'mode': ''} 3066 dt = datetime(int(m.group('y' 2616 dt = datetime(int(m.group('y'))+2000, int(m.group('m')), 3067 int(m.group('d')), in 2617 int(m.group('d')), int(m.group('H')), int(m.group('M')), 3068 int(m.group('S'))) 2618 int(m.group('S'))) 3069 data.stamp['time'] = dt.strft 2619 data.stamp['time'] = dt.strftime('%B %d %Y, %I:%M:%S %p') 3070 data.stamp['host'] = m.group( 2620 data.stamp['host'] = m.group('host') 3071 data.stamp['mode'] = m.group( 2621 data.stamp['mode'] = m.group('mode') 3072 data.stamp['kernel'] = m.grou 2622 data.stamp['kernel'] = m.group('kernel') 3073 if re.match(self.sysinfofmt, 2623 if re.match(self.sysinfofmt, self.sysinfo): 3074 for f in self.sysinfo 2624 for f in self.sysinfo.split('|'): 3075 if '#' in f: 2625 if '#' in f: 3076 conti 2626 continue 3077 tmp = f.strip 2627 tmp = f.strip().split(':', 1) 3078 key = tmp[0] 2628 key = tmp[0] 3079 val = tmp[1] 2629 val = tmp[1] 3080 data.stamp[ke 2630 data.stamp[key] = val 3081 sv.hostname = data.stamp['hos 2631 sv.hostname = data.stamp['host'] 3082 sv.suspendmode = data.stamp[' 2632 sv.suspendmode = data.stamp['mode'] 3083 if sv.suspendmode == 'freeze' << 3084 self.machinesuspend = << 3085 else: << 3086 self.machinesuspend = << 3087 if sv.suspendmode == 'command 2633 if sv.suspendmode == 'command' and sv.ftracefile != '': 3088 modes = ['on', 'freez 2634 modes = ['on', 'freeze', 'standby', 'mem', 'disk'] 3089 fp = sv.openlog(sv.ft !! 2635 fp = sysvals.openlog(sv.ftracefile, 'r') 3090 for line in fp: 2636 for line in fp: 3091 m = re.match( !! 2637 m = re.match('.* machine_suspend\[(?P<mode>.*)\]', line) 3092 if m and m.gr 2638 if m and m.group('mode') in ['1', '2', '3', '4']: 3093 sv.su 2639 sv.suspendmode = modes[int(m.group('mode'))] 3094 data. 2640 data.stamp['mode'] = sv.suspendmode 3095 break 2641 break 3096 fp.close() 2642 fp.close() 3097 sv.cmdline = self.cmdline !! 2643 m = re.match(self.cmdlinefmt, self.cmdline) >> 2644 if m: >> 2645 sv.cmdline = m.group('cmd') >> 2646 if self.kparams: >> 2647 m = re.match(self.kparamsfmt, self.kparams) >> 2648 if m: >> 2649 sv.kparams = m.group('kp') 3098 if not sv.stamp: 2650 if not sv.stamp: 3099 sv.stamp = data.stamp 2651 sv.stamp = data.stamp 3100 # firmware data 2652 # firmware data 3101 if sv.suspendmode == 'mem' an 2653 if sv.suspendmode == 'mem' and len(self.fwdata) > data.testnumber: 3102 m = re.match(self.fir 2654 m = re.match(self.firmwarefmt, self.fwdata[data.testnumber]) 3103 if m: 2655 if m: 3104 data.fwSuspen 2656 data.fwSuspend, data.fwResume = int(m.group('s')), int(m.group('r')) 3105 if(data.fwSus 2657 if(data.fwSuspend > 0 or data.fwResume > 0): 3106 data. 2658 data.fwValid = True >> 2659 # mcelog data >> 2660 if len(self.mcelog) > data.testnumber: >> 2661 m = re.match(self.mcelogfmt, self.mcelog[data.testnumber]) >> 2662 if m: >> 2663 data.mcelog = self.decode(m.group('m')) 3107 # turbostat data 2664 # turbostat data 3108 if len(self.turbostat) > data 2665 if len(self.turbostat) > data.testnumber: 3109 m = re.match(self.tst 2666 m = re.match(self.tstatfmt, self.turbostat[data.testnumber]) 3110 if m: 2667 if m: 3111 data.turbosta 2668 data.turbostat = m.group('t') >> 2669 # battery data >> 2670 if len(self.battery) > data.testnumber: >> 2671 m = re.match(self.batteryfmt, self.battery[data.testnumber]) >> 2672 if m: >> 2673 data.battery = m.groups() 3112 # wifi data 2674 # wifi data 3113 if len(self.wifi) > data.test 2675 if len(self.wifi) > data.testnumber: 3114 m = re.match(self.wif 2676 m = re.match(self.wififmt, self.wifi[data.testnumber]) 3115 if m: 2677 if m: 3116 data.wifi = { !! 2678 data.wifi = m.group('w') 3117 'time << 3118 data.stamp['w << 3119 # sleep mode enter errors 2679 # sleep mode enter errors 3120 if len(self.testerror) > data 2680 if len(self.testerror) > data.testnumber: 3121 m = re.match(self.tes 2681 m = re.match(self.testerrfmt, self.testerror[data.testnumber]) 3122 if m: 2682 if m: 3123 data.enterfai 2683 data.enterfail = m.group('e') 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 2684 3165 # Class: TestRun 2685 # Class: TestRun 3166 # Description: 2686 # Description: 3167 # A container for a suspend/resume tes 2687 # A container for a suspend/resume test run. This is necessary as 3168 # there could be more than one, and th 2688 # there could be more than one, and they need to be separate. 3169 class TestRun: 2689 class TestRun: 3170 def __init__(self, dataobj): 2690 def __init__(self, dataobj): 3171 self.data = dataobj 2691 self.data = dataobj 3172 self.ftemp = dict() 2692 self.ftemp = dict() 3173 self.ttemp = dict() 2693 self.ttemp = dict() 3174 2694 3175 class ProcessMonitor: 2695 class ProcessMonitor: 3176 maxchars = 512 << 3177 def __init__(self): 2696 def __init__(self): 3178 self.proclist = dict() 2697 self.proclist = dict() 3179 self.running = False 2698 self.running = False 3180 def procstat(self): 2699 def procstat(self): 3181 c = ['cat /proc/[1-9]*/stat 2 2700 c = ['cat /proc/[1-9]*/stat 2>/dev/null'] 3182 process = Popen(c, shell=True 2701 process = Popen(c, shell=True, stdout=PIPE) 3183 running = dict() 2702 running = dict() 3184 for line in process.stdout: 2703 for line in process.stdout: 3185 data = ascii(line).sp !! 2704 data = line.split() 3186 pid = data[0] 2705 pid = data[0] 3187 name = re.sub('[()]', 2706 name = re.sub('[()]', '', data[1]) 3188 user = int(data[13]) 2707 user = int(data[13]) 3189 kern = int(data[14]) 2708 kern = int(data[14]) 3190 kjiff = ujiff = 0 2709 kjiff = ujiff = 0 3191 if pid not in self.pr 2710 if pid not in self.proclist: 3192 self.proclist 2711 self.proclist[pid] = {'name' : name, 'user' : user, 'kern' : kern} 3193 else: 2712 else: 3194 val = self.pr 2713 val = self.proclist[pid] 3195 ujiff = user 2714 ujiff = user - val['user'] 3196 kjiff = kern 2715 kjiff = kern - val['kern'] 3197 val['user'] = 2716 val['user'] = user 3198 val['kern'] = 2717 val['kern'] = kern 3199 if ujiff > 0 or kjiff 2718 if ujiff > 0 or kjiff > 0: 3200 running[pid] 2719 running[pid] = ujiff + kjiff 3201 process.wait() 2720 process.wait() 3202 out = [''] !! 2721 out = '' 3203 for pid in running: 2722 for pid in running: 3204 jiffies = running[pid 2723 jiffies = running[pid] 3205 val = self.proclist[p 2724 val = self.proclist[pid] 3206 if len(out[-1]) > sel !! 2725 if out: 3207 out.append('' !! 2726 out += ',' 3208 elif len(out[-1]) > 0 !! 2727 out += '%s-%s %d' % (val['name'], pid, jiffies) 3209 out[-1] += ', !! 2728 return 'ps - '+out 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): 2729 def processMonitor(self, tid): 3217 while self.running: 2730 while self.running: 3218 self.procstat() !! 2731 out = self.procstat() >> 2732 if out: >> 2733 sysvals.fsetVal(out, 'trace_marker') 3219 def start(self): 2734 def start(self): 3220 self.thread = Thread(target=s 2735 self.thread = Thread(target=self.processMonitor, args=(0,)) 3221 self.running = True 2736 self.running = True 3222 self.thread.start() 2737 self.thread.start() 3223 def stop(self): 2738 def stop(self): 3224 self.running = False 2739 self.running = False 3225 2740 3226 # ----------------- FUNCTIONS --------------- 2741 # ----------------- FUNCTIONS -------------------- 3227 2742 3228 # Function: doesTraceLogHaveTraceEvents 2743 # Function: doesTraceLogHaveTraceEvents 3229 # Description: 2744 # Description: 3230 # Quickly determine if the ftrace log 2745 # Quickly determine if the ftrace log has all of the trace events, 3231 # markers, and/or kprobes required for 2746 # markers, and/or kprobes required for primary parsing. 3232 def doesTraceLogHaveTraceEvents(): 2747 def doesTraceLogHaveTraceEvents(): 3233 kpcheck = ['_cal: (', '_ret: ('] 2748 kpcheck = ['_cal: (', '_ret: ('] 3234 techeck = ['suspend_resume', 'device_ !! 2749 techeck = ['suspend_resume', 'device_pm_callback'] 3235 tmcheck = ['SUSPEND START', 'RESUME C 2750 tmcheck = ['SUSPEND START', 'RESUME COMPLETE'] 3236 sysvals.usekprobes = False 2751 sysvals.usekprobes = False 3237 fp = sysvals.openlog(sysvals.ftracefi 2752 fp = sysvals.openlog(sysvals.ftracefile, 'r') 3238 for line in fp: 2753 for line in fp: 3239 # check for kprobes 2754 # check for kprobes 3240 if not sysvals.usekprobes: 2755 if not sysvals.usekprobes: 3241 for i in kpcheck: 2756 for i in kpcheck: 3242 if i in line: 2757 if i in line: 3243 sysva 2758 sysvals.usekprobes = True 3244 # check for all necessary tra 2759 # check for all necessary trace events 3245 check = techeck[:] 2760 check = techeck[:] 3246 for i in techeck: 2761 for i in techeck: 3247 if i in line: 2762 if i in line: 3248 check.remove( 2763 check.remove(i) 3249 techeck = check 2764 techeck = check 3250 # check for all necessary tra 2765 # check for all necessary trace markers 3251 check = tmcheck[:] 2766 check = tmcheck[:] 3252 for i in tmcheck: 2767 for i in tmcheck: 3253 if i in line: 2768 if i in line: 3254 check.remove( 2769 check.remove(i) 3255 tmcheck = check 2770 tmcheck = check 3256 fp.close() 2771 fp.close() 3257 sysvals.usetraceevents = True if len( !! 2772 sysvals.usetraceevents = True if len(techeck) < 2 else False 3258 sysvals.usetracemarkers = True if len 2773 sysvals.usetracemarkers = True if len(tmcheck) == 0 else False 3259 2774 3260 # Function: appendIncompleteTraceLog 2775 # Function: appendIncompleteTraceLog 3261 # Description: 2776 # Description: >> 2777 # [deprecated for kernel 3.15 or newer] 3262 # Adds callgraph data which lacks trac 2778 # Adds callgraph data which lacks trace event data. This is only 3263 # for timelines generated from 3.15 or 2779 # for timelines generated from 3.15 or older 3264 # Arguments: 2780 # Arguments: 3265 # testruns: the array of Data objects 2781 # testruns: the array of Data objects obtained from parseKernelLog 3266 def appendIncompleteTraceLog(testruns): 2782 def appendIncompleteTraceLog(testruns): 3267 # create TestRun vessels for ftrace p 2783 # create TestRun vessels for ftrace parsing 3268 testcnt = len(testruns) 2784 testcnt = len(testruns) 3269 testidx = 0 2785 testidx = 0 3270 testrun = [] 2786 testrun = [] 3271 for data in testruns: 2787 for data in testruns: 3272 testrun.append(TestRun(data)) 2788 testrun.append(TestRun(data)) 3273 2789 3274 # extract the callgraph and traceeven 2790 # extract the callgraph and traceevent data 3275 sysvals.vprint('Analyzing the ftrace 2791 sysvals.vprint('Analyzing the ftrace data (%s)...' % \ 3276 os.path.basename(sysvals.ftra 2792 os.path.basename(sysvals.ftracefile)) 3277 tp = TestProps() 2793 tp = TestProps() 3278 tf = sysvals.openlog(sysvals.ftracefi 2794 tf = sysvals.openlog(sysvals.ftracefile, 'r') 3279 data = 0 2795 data = 0 3280 for line in tf: 2796 for line in tf: 3281 # remove any latent carriage 2797 # remove any latent carriage returns 3282 line = line.replace('\r\n', ' 2798 line = line.replace('\r\n', '') 3283 if tp.stampInfo(line, sysvals !! 2799 if tp.stampInfo(line): >> 2800 continue >> 2801 # determine the trace data type (required for further parsing) >> 2802 m = re.match(tp.tracertypefmt, line) >> 2803 if(m): >> 2804 tp.setTracerType(m.group('t')) >> 2805 continue >> 2806 # device properties line >> 2807 if(re.match(tp.devpropfmt, line)): >> 2808 devProps(line) 3284 continue 2809 continue 3285 # parse only valid lines, if 2810 # parse only valid lines, if this is not one move on 3286 m = re.match(tp.ftrace_line_f 2811 m = re.match(tp.ftrace_line_fmt, line) 3287 if(not m): 2812 if(not m): 3288 continue 2813 continue 3289 # gather the basic message da 2814 # gather the basic message data from the line 3290 m_time = m.group('time') 2815 m_time = m.group('time') 3291 m_pid = m.group('pid') 2816 m_pid = m.group('pid') 3292 m_msg = m.group('msg') 2817 m_msg = m.group('msg') 3293 if(tp.cgformat): 2818 if(tp.cgformat): 3294 m_param3 = m.group('d 2819 m_param3 = m.group('dur') 3295 else: 2820 else: 3296 m_param3 = 'traceeven 2821 m_param3 = 'traceevent' 3297 if(m_time and m_pid and m_msg 2822 if(m_time and m_pid and m_msg): 3298 t = FTraceLine(m_time 2823 t = FTraceLine(m_time, m_msg, m_param3) 3299 pid = int(m_pid) 2824 pid = int(m_pid) 3300 else: 2825 else: 3301 continue 2826 continue 3302 # the line should be a call, 2827 # the line should be a call, return, or event 3303 if(not t.fcall and not t.fret 2828 if(not t.fcall and not t.freturn and not t.fevent): 3304 continue 2829 continue 3305 # look for the suspend start 2830 # look for the suspend start marker 3306 if(t.startMarker()): 2831 if(t.startMarker()): 3307 data = testrun[testid 2832 data = testrun[testidx].data 3308 tp.parseStamp(data, s 2833 tp.parseStamp(data, sysvals) 3309 data.setStart(t.time, !! 2834 data.setStart(t.time) 3310 continue 2835 continue 3311 if(not data): 2836 if(not data): 3312 continue 2837 continue 3313 # find the end of resume 2838 # find the end of resume 3314 if(t.endMarker()): 2839 if(t.endMarker()): 3315 data.setEnd(t.time, t !! 2840 data.setEnd(t.time) 3316 testidx += 1 2841 testidx += 1 3317 if(testidx >= testcnt 2842 if(testidx >= testcnt): 3318 break 2843 break 3319 continue 2844 continue 3320 # trace event processing 2845 # trace event processing 3321 if(t.fevent): 2846 if(t.fevent): 3322 continue 2847 continue 3323 # call/return processing 2848 # call/return processing 3324 elif sysvals.usecallgraph: 2849 elif sysvals.usecallgraph: 3325 # create a callgraph 2850 # create a callgraph object for the data 3326 if(pid not in testrun 2851 if(pid not in testrun[testidx].ftemp): 3327 testrun[testi 2852 testrun[testidx].ftemp[pid] = [] 3328 testrun[testi 2853 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals)) 3329 # when the call is fi 2854 # when the call is finished, see which device matches it 3330 cg = testrun[testidx] 2855 cg = testrun[testidx].ftemp[pid][-1] 3331 res = cg.addLine(t) 2856 res = cg.addLine(t) 3332 if(res != 0): 2857 if(res != 0): 3333 testrun[testi 2858 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals)) 3334 if(res == -1): 2859 if(res == -1): 3335 testrun[testi 2860 testrun[testidx].ftemp[pid][-1].addLine(t) 3336 tf.close() 2861 tf.close() 3337 2862 3338 for test in testrun: 2863 for test in testrun: 3339 # add the callgraph data to t 2864 # add the callgraph data to the device hierarchy 3340 for pid in test.ftemp: 2865 for pid in test.ftemp: 3341 for cg in test.ftemp[ 2866 for cg in test.ftemp[pid]: 3342 if len(cg.lis 2867 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0): 3343 conti 2868 continue 3344 if(not cg.pos 2869 if(not cg.postProcess()): 3345 id = 2870 id = 'task %s cpu %s' % (pid, m.group('cpu')) 3346 sysva 2871 sysvals.vprint('Sanity check failed for '+\ 3347 2872 id+', ignoring this callback') 3348 conti 2873 continue 3349 callstart = c 2874 callstart = cg.start 3350 callend = cg. 2875 callend = cg.end 3351 for p in test 2876 for p in test.data.sortedPhases(): 3352 if(te 2877 if(test.data.dmesg[p]['start'] <= callstart and 3353 2878 callstart <= test.data.dmesg[p]['end']): 3354 2879 list = test.data.dmesg[p]['list'] 3355 2880 for devname in list: 3356 2881 dev = list[devname] 3357 2882 if(pid == dev['pid'] and 3358 2883 callstart <= dev['start'] and 3359 2884 callend >= dev['end']): 3360 2885 dev['ftrace'] = cg 3361 2886 break 3362 2887 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 2888 # Function: parseTraceLog 3419 # Description: 2889 # Description: 3420 # Analyze an ftrace log output file ge 2890 # Analyze an ftrace log output file generated from this app during 3421 # the execution phase. Used when the f 2891 # the execution phase. Used when the ftrace log is the primary data source 3422 # and includes the suspend_resume and 2892 # and includes the suspend_resume and device_pm_callback trace events 3423 # The ftrace filename is taken from sy 2893 # The ftrace filename is taken from sysvals 3424 # Output: 2894 # Output: 3425 # An array of Data objects 2895 # An array of Data objects 3426 def parseTraceLog(live=False): 2896 def parseTraceLog(live=False): 3427 sysvals.vprint('Analyzing the ftrace 2897 sysvals.vprint('Analyzing the ftrace data (%s)...' % \ 3428 os.path.basename(sysvals.ftra 2898 os.path.basename(sysvals.ftracefile)) 3429 if(os.path.exists(sysvals.ftracefile) 2899 if(os.path.exists(sysvals.ftracefile) == False): 3430 doError('%s does not exist' % 2900 doError('%s does not exist' % sysvals.ftracefile) 3431 if not live: 2901 if not live: 3432 sysvals.setupAllKprobes() 2902 sysvals.setupAllKprobes() 3433 ksuscalls = ['ksys_sync', 'pm_prepare !! 2903 ksuscalls = ['pm_prepare_console'] 3434 krescalls = ['pm_restore_console'] 2904 krescalls = ['pm_restore_console'] 3435 tracewatch = ['irq_wakeup'] !! 2905 tracewatch = [] 3436 if sysvals.usekprobes: 2906 if sysvals.usekprobes: 3437 tracewatch += ['sync_filesyst 2907 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend', 3438 'syscore_resume', 're 2908 'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON', 3439 'CPU_OFF', 'acpi_susp !! 2909 'CPU_OFF', 'timekeeping_freeze', 'acpi_suspend'] 3440 2910 3441 # extract the callgraph and traceeven 2911 # extract the callgraph and traceevent data 3442 s2idle_enter = hwsus = False !! 2912 tp = TestProps() 3443 testruns, testdata = [], [] !! 2913 testruns = [] 3444 testrun, data, limbo = 0, 0, True !! 2914 testdata = [] >> 2915 testrun = 0 >> 2916 data = 0 >> 2917 tf = sysvals.openlog(sysvals.ftracefile, 'r') 3445 phase = 'suspend_prepare' 2918 phase = 'suspend_prepare' 3446 tp, tf = loadTraceLog() !! 2919 for line in tf: 3447 for m_time, m_proc, m_pid, m_msg, m_p !! 2920 # remove any latent carriage returns >> 2921 line = line.replace('\r\n', '') >> 2922 if tp.stampInfo(line): >> 2923 continue >> 2924 # tracer type line: determine the trace data type >> 2925 m = re.match(tp.tracertypefmt, line) >> 2926 if(m): >> 2927 tp.setTracerType(m.group('t')) >> 2928 continue >> 2929 # device properties line >> 2930 if(re.match(tp.devpropfmt, line)): >> 2931 devProps(line) >> 2932 continue >> 2933 # ignore all other commented lines >> 2934 if line[0] == '#': >> 2935 continue >> 2936 # ftrace line: parse only valid lines >> 2937 m = re.match(tp.ftrace_line_fmt, line) >> 2938 if(not m): >> 2939 continue 3448 # gather the basic message da 2940 # gather the basic message data from the line >> 2941 m_time = m.group('time') >> 2942 m_proc = m.group('proc') >> 2943 m_pid = m.group('pid') >> 2944 m_msg = m.group('msg') >> 2945 if(tp.cgformat): >> 2946 m_param3 = m.group('dur') >> 2947 else: >> 2948 m_param3 = 'traceevent' 3449 if(m_time and m_pid and m_msg 2949 if(m_time and m_pid and m_msg): 3450 t = FTraceLine(m_time 2950 t = FTraceLine(m_time, m_msg, m_param3) 3451 pid = int(m_pid) 2951 pid = int(m_pid) 3452 else: 2952 else: 3453 continue 2953 continue 3454 # the line should be a call, 2954 # the line should be a call, return, or event 3455 if(not t.fcall and not t.fret 2955 if(not t.fcall and not t.freturn and not t.fevent): 3456 continue 2956 continue 3457 # find the start of suspend 2957 # find the start of suspend 3458 if(t.startMarker()): 2958 if(t.startMarker()): 3459 data, limbo = Data(le !! 2959 data = Data(len(testdata)) 3460 testdata.append(data) 2960 testdata.append(data) 3461 testrun = TestRun(dat 2961 testrun = TestRun(data) 3462 testruns.append(testr 2962 testruns.append(testrun) 3463 tp.parseStamp(data, s 2963 tp.parseStamp(data, sysvals) 3464 data.setStart(t.time, !! 2964 data.setStart(t.time) 3465 data.first_suspend_pr 2965 data.first_suspend_prepare = True 3466 phase = data.setPhase 2966 phase = data.setPhase('suspend_prepare', t.time, True) 3467 continue 2967 continue 3468 if(not data or limbo): !! 2968 if(not data): 3469 continue 2969 continue 3470 # process cpu exec line 2970 # process cpu exec line 3471 if t.type == 'tracing_mark_wr 2971 if t.type == 'tracing_mark_write': 3472 if t.name == 'CMD COM << 3473 data.tKernRes << 3474 m = re.match(tp.proce 2972 m = re.match(tp.procexecfmt, t.name) 3475 if(m): 2973 if(m): 3476 parts, msg = !! 2974 proclist = dict() 3477 m = re.match( !! 2975 for ps in m.group('ps').split(','): 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 = 2976 val = ps.split() 3490 if no !! 2977 if not val: 3491 2978 continue 3492 name 2979 name = val[0].replace('--', '-') 3493 procl 2980 proclist[name] = int(val[1]) 3494 if parts == 1 !! 2981 data.pstl[t.time] = proclist 3495 data. << 3496 elif parts == << 3497 data. << 3498 tp.mu << 3499 continue 2982 continue 3500 # find the end of resume 2983 # find the end of resume 3501 if(t.endMarker()): 2984 if(t.endMarker()): 3502 if data.tKernRes == 0 !! 2985 data.handleEndMarker(t.time) 3503 data.tKernRes << 3504 data.handleEndMarker( << 3505 if(not sysvals.usetra 2986 if(not sysvals.usetracemarkers): 3506 # no trace ma 2987 # no trace markers? then quit and be sure to finish recording 3507 # the event w 2988 # the event we used to trigger resume end 3508 if('thaw_proc 2989 if('thaw_processes' in testrun.ttemp and len(testrun.ttemp['thaw_processes']) > 0): 3509 # if 2990 # if an entry exists, assume this is its end 3510 testr 2991 testrun.ttemp['thaw_processes'][-1]['end'] = t.time 3511 limbo = True !! 2992 break 3512 continue 2993 continue 3513 # trace event processing 2994 # trace event processing 3514 if(t.fevent): 2995 if(t.fevent): 3515 if(t.type == 'suspend 2996 if(t.type == 'suspend_resume'): 3516 # suspend_res 2997 # suspend_resume trace events have two types, begin and end 3517 if(re.match(r !! 2998 if(re.match('(?P<name>.*) begin$', t.name)): 3518 isbeg 2999 isbegin = True 3519 elif(re.match !! 3000 elif(re.match('(?P<name>.*) end$', t.name)): 3520 isbeg 3001 isbegin = False 3521 else: 3002 else: 3522 conti 3003 continue 3523 if '[' in t.n !! 3004 m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name) 3524 m = r !! 3005 if(m): >> 3006 val = m.group('val') >> 3007 if val == '0': >> 3008 name = m.group('name') >> 3009 else: >> 3010 name = m.group('name')+'['+val+']' 3525 else: 3011 else: 3526 m = r !! 3012 m = re.match('(?P<name>.*) .*', t.name) 3527 name = m.grou !! 3013 name = m.group('name') 3528 # ignore thes 3014 # ignore these events 3529 if(name.split 3015 if(name.split('[')[0] in tracewatch): 3530 conti 3016 continue 3531 # -- phase ch 3017 # -- phase changes -- 3532 # start of ke 3018 # start of kernel suspend 3533 if(re.match(r !! 3019 if(re.match('suspend_enter\[.*', t.name)): 3534 if(is !! 3020 if(isbegin): 3535 3021 data.tKernSus = t.time 3536 conti 3022 continue 3537 # suspend_pre 3023 # suspend_prepare start 3538 elif(re.match !! 3024 elif(re.match('dpm_prepare\[.*', t.name)): 3539 if is 3025 if isbegin and data.first_suspend_prepare: 3540 3026 data.first_suspend_prepare = False 3541 3027 if data.tKernSus == 0: 3542 3028 data.tKernSus = t.time 3543 3029 continue 3544 phase 3030 phase = data.setPhase('suspend_prepare', t.time, isbegin) 3545 conti 3031 continue 3546 # suspend sta 3032 # suspend start 3547 elif(re.match !! 3033 elif(re.match('dpm_suspend\[.*', t.name)): 3548 phase 3034 phase = data.setPhase('suspend', t.time, isbegin) 3549 conti 3035 continue 3550 # suspend_lat 3036 # suspend_late start 3551 elif(re.match !! 3037 elif(re.match('dpm_suspend_late\[.*', t.name)): 3552 phase 3038 phase = data.setPhase('suspend_late', t.time, isbegin) 3553 conti 3039 continue 3554 # suspend_noi 3040 # suspend_noirq start 3555 elif(re.match !! 3041 elif(re.match('dpm_suspend_noirq\[.*', t.name)): 3556 phase 3042 phase = data.setPhase('suspend_noirq', t.time, isbegin) 3557 conti 3043 continue 3558 # suspend_mac 3044 # suspend_machine/resume_machine 3559 elif(re.match !! 3045 elif(re.match('machine_suspend\[.*', t.name)): 3560 lp = << 3561 if(is 3046 if(isbegin): 3562 !! 3047 lp = data.lastPhase() 3563 << 3564 << 3565 << 3566 << 3567 << 3568 << 3569 << 3570 << 3571 << 3572 << 3573 << 3574 << 3575 3048 phase = data.setPhase('suspend_machine', data.dmesg[lp]['end'], True) 3576 3049 data.setPhase(phase, t.time, False) 3577 3050 if data.tSuspended == 0: 3578 3051 data.tSuspended = t.time 3579 else: 3052 else: 3580 << 3581 << 3582 << 3583 3053 phase = data.setPhase('resume_machine', t.time, True) 3584 3054 if(sysvals.suspendmode in ['mem', 'disk']): 3585 3055 susp = phase.replace('resume', 'suspend') 3586 3056 if susp in data.dmesg: 3587 3057 data.dmesg[susp]['end'] = t.time 3588 3058 data.tSuspended = t.time 3589 3059 data.tResumed = t.time 3590 conti 3060 continue 3591 # resume_noir 3061 # resume_noirq start 3592 elif(re.match !! 3062 elif(re.match('dpm_resume_noirq\[.*', t.name)): 3593 phase 3063 phase = data.setPhase('resume_noirq', t.time, isbegin) 3594 conti 3064 continue 3595 # resume_earl 3065 # resume_early start 3596 elif(re.match !! 3066 elif(re.match('dpm_resume_early\[.*', t.name)): 3597 phase 3067 phase = data.setPhase('resume_early', t.time, isbegin) 3598 conti 3068 continue 3599 # resume star 3069 # resume start 3600 elif(re.match !! 3070 elif(re.match('dpm_resume\[.*', t.name)): 3601 phase 3071 phase = data.setPhase('resume', t.time, isbegin) 3602 conti 3072 continue 3603 # resume comp 3073 # resume complete start 3604 elif(re.match !! 3074 elif(re.match('dpm_complete\[.*', t.name)): 3605 phase 3075 phase = data.setPhase('resume_complete', t.time, isbegin) 3606 conti 3076 continue 3607 # skip trace 3077 # skip trace events inside devices calls 3608 if(not data.i 3078 if(not data.isTraceEventOutsideDeviceCalls(pid, t.time)): 3609 conti 3079 continue 3610 # global even 3080 # global events (outside device calls) are graphed 3611 if(name not i 3081 if(name not in testrun.ttemp): 3612 testr 3082 testrun.ttemp[name] = [] 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): 3083 if(isbegin): 3627 # cre 3084 # create a new list entry 3628 testr 3085 testrun.ttemp[name].append(\ 3629 3086 {'begin': t.time, 'end': t.time, 'pid': pid}) 3630 else: 3087 else: 3631 if(le 3088 if(len(testrun.ttemp[name]) > 0): 3632 3089 # if an entry exists, assume this is its end 3633 3090 testrun.ttemp[name][-1]['end'] = t.time 3634 # device callback sta 3091 # device callback start 3635 elif(t.type == 'devic 3092 elif(t.type == 'device_pm_callback_start'): 3636 if phase not 3093 if phase not in data.dmesg: 3637 conti 3094 continue 3638 m = re.match( !! 3095 m = re.match('(?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*',\ 3639 t.nam 3096 t.name); 3640 if(not m): 3097 if(not m): 3641 conti 3098 continue 3642 drv = m.group 3099 drv = m.group('drv') 3643 n = m.group(' 3100 n = m.group('d') 3644 p = m.group(' 3101 p = m.group('p') 3645 if(n and p): 3102 if(n and p): 3646 data. 3103 data.newAction(phase, n, pid, p, t.time, -1, drv) 3647 if pi 3104 if pid not in data.devpids: 3648 3105 data.devpids.append(pid) 3649 # device callback fin 3106 # device callback finish 3650 elif(t.type == 'devic 3107 elif(t.type == 'device_pm_callback_end'): 3651 if phase not 3108 if phase not in data.dmesg: 3652 conti 3109 continue 3653 m = re.match( !! 3110 m = re.match('(?P<drv>.*) (?P<d>.*), err.*', t.name); 3654 if(not m): 3111 if(not m): 3655 conti 3112 continue 3656 n = m.group(' 3113 n = m.group('d') 3657 dev = data.fi !! 3114 list = data.dmesg[phase]['list'] 3658 if dev: !! 3115 if(n in list): >> 3116 dev = list[n] 3659 dev[' 3117 dev['length'] = t.time - dev['start'] 3660 dev[' 3118 dev['end'] = t.time 3661 # kprobe event processing 3119 # kprobe event processing 3662 elif(t.fkprobe): 3120 elif(t.fkprobe): 3663 kprobename = t.type 3121 kprobename = t.type 3664 kprobedata = t.name 3122 kprobedata = t.name 3665 key = (kprobename, pi 3123 key = (kprobename, pid) 3666 # displayname is gene 3124 # displayname is generated from kprobe data 3667 displayname = '' 3125 displayname = '' 3668 if(t.fcall): 3126 if(t.fcall): 3669 displayname = 3127 displayname = sysvals.kprobeDisplayName(kprobename, kprobedata) 3670 if not displa 3128 if not displayname: 3671 conti 3129 continue 3672 if(key not in 3130 if(key not in tp.ktemp): 3673 tp.kt 3131 tp.ktemp[key] = [] 3674 tp.ktemp[key] 3132 tp.ktemp[key].append({ 3675 'pid' 3133 'pid': pid, 3676 'begi 3134 'begin': t.time, 3677 'end' 3135 'end': -1, 3678 'name 3136 'name': displayname, 3679 'cdat 3137 'cdata': kprobedata, 3680 'proc 3138 'proc': m_proc, 3681 }) 3139 }) 3682 # start of ke 3140 # start of kernel resume 3683 if(data.tKern !! 3141 if(phase == 'suspend_prepare' and kprobename in ksuscalls): 3684 and k << 3685 data. 3142 data.tKernSus = t.time 3686 elif(t.freturn): 3143 elif(t.freturn): 3687 if(key not in 3144 if(key not in tp.ktemp) or len(tp.ktemp[key]) < 1: 3688 conti 3145 continue 3689 e = next((x f 3146 e = next((x for x in reversed(tp.ktemp[key]) if x['end'] < 0), 0) 3690 if not e: 3147 if not e: 3691 conti 3148 continue 3692 if (t.time - << 3693 tp.kt << 3694 conti << 3695 e['end'] = t. 3149 e['end'] = t.time 3696 e['rdata'] = 3150 e['rdata'] = kprobedata 3697 # end of kern 3151 # end of kernel resume 3698 if(phase != ' 3152 if(phase != 'suspend_prepare' and kprobename in krescalls): 3699 if ph 3153 if phase in data.dmesg: 3700 3154 data.dmesg[phase]['end'] = t.time 3701 data. 3155 data.tKernRes = t.time 3702 3156 3703 # callgraph processing 3157 # callgraph processing 3704 elif sysvals.usecallgraph: 3158 elif sysvals.usecallgraph: 3705 # create a callgraph 3159 # create a callgraph object for the data 3706 key = (m_proc, pid) 3160 key = (m_proc, pid) 3707 if(key not in testrun 3161 if(key not in testrun.ftemp): 3708 testrun.ftemp 3162 testrun.ftemp[key] = [] 3709 testrun.ftemp 3163 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals)) 3710 # when the call is fi 3164 # when the call is finished, see which device matches it 3711 cg = testrun.ftemp[ke 3165 cg = testrun.ftemp[key][-1] 3712 res = cg.addLine(t) 3166 res = cg.addLine(t) 3713 if(res != 0): 3167 if(res != 0): 3714 testrun.ftemp 3168 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals)) 3715 if(res == -1): 3169 if(res == -1): 3716 testrun.ftemp 3170 testrun.ftemp[key][-1].addLine(t) >> 3171 tf.close() 3717 if len(testdata) < 1: 3172 if len(testdata) < 1: 3718 sysvals.vprint('WARNING: ftra 3173 sysvals.vprint('WARNING: ftrace start marker is missing') 3719 if data and not data.devicegroups: 3174 if data and not data.devicegroups: 3720 sysvals.vprint('WARNING: ftra 3175 sysvals.vprint('WARNING: ftrace end marker is missing') 3721 data.handleEndMarker(t.time, !! 3176 data.handleEndMarker(t.time) 3722 3177 3723 if sysvals.suspendmode == 'command': 3178 if sysvals.suspendmode == 'command': 3724 for test in testruns: 3179 for test in testruns: 3725 for p in test.data.so 3180 for p in test.data.sortedPhases(): 3726 if p == 'susp 3181 if p == 'suspend_prepare': 3727 test. 3182 test.data.dmesg[p]['start'] = test.data.start 3728 test. 3183 test.data.dmesg[p]['end'] = test.data.end 3729 else: 3184 else: 3730 test. 3185 test.data.dmesg[p]['start'] = test.data.end 3731 test. 3186 test.data.dmesg[p]['end'] = test.data.end 3732 test.data.tSuspended 3187 test.data.tSuspended = test.data.end 3733 test.data.tResumed = 3188 test.data.tResumed = test.data.end 3734 test.data.fwValid = F 3189 test.data.fwValid = False 3735 3190 3736 # dev source and procmon events can b 3191 # dev source and procmon events can be unreadable with mixed phase height 3737 if sysvals.usedevsrc or sysvals.usepr 3192 if sysvals.usedevsrc or sysvals.useprocmon: 3738 sysvals.mixedphaseheight = Fa 3193 sysvals.mixedphaseheight = False 3739 3194 3740 # expand phase boundaries so there ar 3195 # expand phase boundaries so there are no gaps 3741 for data in testdata: 3196 for data in testdata: 3742 lp = data.sortedPhases()[0] 3197 lp = data.sortedPhases()[0] 3743 for p in data.sortedPhases(): 3198 for p in data.sortedPhases(): 3744 if(p != lp and not (' 3199 if(p != lp and not ('machine' in p and 'machine' in lp)): 3745 data.dmesg[lp 3200 data.dmesg[lp]['end'] = data.dmesg[p]['start'] 3746 lp = p 3201 lp = p 3747 3202 3748 for i in range(len(testruns)): 3203 for i in range(len(testruns)): 3749 test = testruns[i] 3204 test = testruns[i] 3750 data = test.data 3205 data = test.data 3751 # find the total time range f 3206 # find the total time range for this test (begin, end) 3752 tlb, tle = data.start, data.e 3207 tlb, tle = data.start, data.end 3753 if i < len(testruns) - 1: 3208 if i < len(testruns) - 1: 3754 tle = testruns[i+1].d 3209 tle = testruns[i+1].data.start 3755 # add the process usage data 3210 # add the process usage data to the timeline 3756 if sysvals.useprocmon: 3211 if sysvals.useprocmon: 3757 data.createProcessUsa 3212 data.createProcessUsageEvents() 3758 # add the traceevent data to 3213 # add the traceevent data to the device hierarchy 3759 if(sysvals.usetraceevents): 3214 if(sysvals.usetraceevents): 3760 # add actual trace fu 3215 # add actual trace funcs 3761 for name in sorted(te !! 3216 for name in test.ttemp: 3762 for event in 3217 for event in test.ttemp[name]: 3763 if ev !! 3218 data.newActionGlobal(name, event['begin'], event['end'], event['pid']) 3764 << 3765 title << 3766 if na << 3767 << 3768 data. << 3769 # add the kprobe base 3219 # add the kprobe based virtual tracefuncs as actual devices 3770 for key in sorted(tp. !! 3220 for key in tp.ktemp: 3771 name, pid = k 3221 name, pid = key 3772 if name not i 3222 if name not in sysvals.tracefuncs: 3773 conti 3223 continue 3774 if pid not in 3224 if pid not in data.devpids: 3775 data. 3225 data.devpids.append(pid) 3776 for e in tp.k 3226 for e in tp.ktemp[key]: 3777 kb, k 3227 kb, ke = e['begin'], e['end'] 3778 if ke 3228 if ke - kb < 0.000001 or tlb > kb or tle <= kb: 3779 3229 continue 3780 color 3230 color = sysvals.kprobeColor(name) 3781 data. 3231 data.newActionGlobal(e['name'], kb, ke, pid, color) 3782 # add config base kpr 3232 # add config base kprobes and dev kprobes 3783 if sysvals.usedevsrc: 3233 if sysvals.usedevsrc: 3784 for key in so !! 3234 for key in tp.ktemp: 3785 name, 3235 name, pid = key 3786 if na 3236 if name in sysvals.tracefuncs or name not in sysvals.dev_tracefuncs: 3787 3237 continue 3788 for e 3238 for e in tp.ktemp[key]: 3789 3239 kb, ke = e['begin'], e['end'] 3790 3240 if ke - kb < 0.000001 or tlb > kb or tle <= kb: 3791 3241 continue 3792 3242 data.addDeviceFunctionCall(e['name'], name, e['proc'], pid, kb, 3793 3243 ke, e['cdata'], e['rdata']) 3794 if sysvals.usecallgraph: 3244 if sysvals.usecallgraph: 3795 # add the callgraph d 3245 # add the callgraph data to the device hierarchy 3796 sortlist = dict() 3246 sortlist = dict() 3797 for key in sorted(tes !! 3247 for key in test.ftemp: 3798 proc, pid = k 3248 proc, pid = key 3799 for cg in tes 3249 for cg in test.ftemp[key]: 3800 if le 3250 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0): 3801 3251 continue 3802 if(no 3252 if(not cg.postProcess()): 3803 3253 id = 'task %s' % (pid) 3804 3254 sysvals.vprint('Sanity check failed for '+\ 3805 3255 id+', ignoring this callback') 3806 3256 continue 3807 # mat 3257 # match cg data to devices 3808 devna 3258 devname = '' 3809 if sy 3259 if sysvals.suspendmode != 'command': 3810 3260 devname = cg.deviceMatch(pid, data) 3811 if no 3261 if not devname: 3812 3262 sortkey = '%f%f%d' % (cg.start, cg.end, pid) 3813 3263 sortlist[sortkey] = cg 3814 elif 3264 elif len(cg.list) > 1000000 and cg.name != sysvals.ftopfunc: 3815 3265 sysvals.vprint('WARNING: the callgraph for %s is massive (%d lines)' %\ 3816 3266 (devname, len(cg.list))) 3817 # create blocks for o 3267 # create blocks for orphan cg data 3818 for sortkey in sorted 3268 for sortkey in sorted(sortlist): 3819 cg = sortlist 3269 cg = sortlist[sortkey] 3820 name = cg.nam 3270 name = cg.name 3821 if sysvals.is 3271 if sysvals.isCallgraphFunc(name): 3822 sysva 3272 sysvals.vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name)) 3823 cg.ne 3273 cg.newActionFromFunction(data) 3824 if sysvals.suspendmode == 'command': 3274 if sysvals.suspendmode == 'command': 3825 return (testdata, '') 3275 return (testdata, '') 3826 3276 3827 # fill in any missing phases 3277 # fill in any missing phases 3828 error = [] 3278 error = [] 3829 for data in testdata: 3279 for data in testdata: 3830 tn = '' if len(testdata) == 1 3280 tn = '' if len(testdata) == 1 else ('%d' % (data.testnumber + 1)) 3831 terr = '' 3281 terr = '' 3832 phasedef = data.phasedef 3282 phasedef = data.phasedef 3833 lp = 'suspend_prepare' 3283 lp = 'suspend_prepare' 3834 for p in sorted(phasedef, key 3284 for p in sorted(phasedef, key=lambda k:phasedef[k]['order']): 3835 if p not in data.dmes 3285 if p not in data.dmesg: 3836 if not terr: 3286 if not terr: 3837 ph = !! 3287 pprint('TEST%s FAILED: %s failed in %s phase' % (tn, sysvals.suspendmode, lp)) 3838 if p !! 3288 terr = '%s%s failed in %s phase' % (sysvals.suspendmode, tn, lp) 3839 << 3840 << 3841 << 3842 << 3843 else: << 3844 << 3845 pprin << 3846 error 3289 error.append(terr) 3847 if da 3290 if data.tSuspended == 0: 3848 3291 data.tSuspended = data.dmesg[lp]['end'] 3849 if da 3292 if data.tResumed == 0: 3850 3293 data.tResumed = data.dmesg[lp]['end'] 3851 data. 3294 data.fwValid = False 3852 sysvals.vprin 3295 sysvals.vprint('WARNING: phase "%s" is missing!' % p) 3853 lp = p 3296 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 3297 if not terr and data.enterfail: 3859 pprint('test%s FAILED 3298 pprint('test%s FAILED: enter %s failed with %s' % (tn, sysvals.suspendmode, data.enterfail)) 3860 terr = 'test%s failed 3299 terr = 'test%s failed to enter %s mode' % (tn, sysvals.suspendmode) 3861 error.append(terr) 3300 error.append(terr) 3862 if data.tSuspended == 0: 3301 if data.tSuspended == 0: 3863 data.tSuspended = dat 3302 data.tSuspended = data.tKernRes 3864 if data.tResumed == 0: 3303 if data.tResumed == 0: 3865 data.tResumed = data. 3304 data.tResumed = data.tSuspended 3866 3305 3867 if(len(sysvals.devicefilter) 3306 if(len(sysvals.devicefilter) > 0): 3868 data.deviceFilter(sys 3307 data.deviceFilter(sysvals.devicefilter) 3869 data.fixupInitcallsThatDidntR 3308 data.fixupInitcallsThatDidntReturn() 3870 if sysvals.usedevsrc: 3309 if sysvals.usedevsrc: 3871 data.optimizeDevSrc() 3310 data.optimizeDevSrc() 3872 3311 3873 # x2: merge any overlapping devices b 3312 # x2: merge any overlapping devices between test runs 3874 if sysvals.usedevsrc and len(testdata 3313 if sysvals.usedevsrc and len(testdata) > 1: 3875 tc = len(testdata) 3314 tc = len(testdata) 3876 for i in range(tc - 1): 3315 for i in range(tc - 1): 3877 devlist = testdata[i] 3316 devlist = testdata[i].overflowDevices() 3878 for j in range(i + 1, 3317 for j in range(i + 1, tc): 3879 testdata[j].m 3318 testdata[j].mergeOverlapDevices(devlist) 3880 testdata[0].stitchTouchingThr 3319 testdata[0].stitchTouchingThreads(testdata[1:]) 3881 return (testdata, ', '.join(error)) 3320 return (testdata, ', '.join(error)) 3882 3321 3883 # Function: loadKernelLog 3322 # Function: loadKernelLog 3884 # Description: 3323 # Description: >> 3324 # [deprecated for kernel 3.15.0 or newer] 3885 # load the dmesg file into memory and 3325 # load the dmesg file into memory and fix up any ordering issues >> 3326 # The dmesg filename is taken from sysvals 3886 # Output: 3327 # Output: 3887 # An array of empty Data objects with 3328 # An array of empty Data objects with only their dmesgtext attributes set 3888 def loadKernelLog(): 3329 def loadKernelLog(): 3889 sysvals.vprint('Analyzing the dmesg d 3330 sysvals.vprint('Analyzing the dmesg data (%s)...' % \ 3890 os.path.basename(sysvals.dmes 3331 os.path.basename(sysvals.dmesgfile)) 3891 if(os.path.exists(sysvals.dmesgfile) 3332 if(os.path.exists(sysvals.dmesgfile) == False): 3892 doError('%s does not exist' % 3333 doError('%s does not exist' % sysvals.dmesgfile) 3893 3334 3894 # there can be multiple test runs in 3335 # there can be multiple test runs in a single file 3895 tp = TestProps() 3336 tp = TestProps() 3896 tp.stamp = datetime.now().strftime('# 3337 tp.stamp = datetime.now().strftime('# suspend-%m%d%y-%H%M%S localhost mem unknown') 3897 testruns = [] 3338 testruns = [] 3898 data = 0 3339 data = 0 3899 lf = sysvals.openlog(sysvals.dmesgfil 3340 lf = sysvals.openlog(sysvals.dmesgfile, 'r') 3900 for line in lf: 3341 for line in lf: 3901 line = line.replace('\r\n', ' 3342 line = line.replace('\r\n', '') 3902 idx = line.find('[') 3343 idx = line.find('[') 3903 if idx > 1: 3344 if idx > 1: 3904 line = line[idx:] 3345 line = line[idx:] 3905 if tp.stampInfo(line, sysvals !! 3346 if tp.stampInfo(line): 3906 continue 3347 continue 3907 m = re.match(r'[ \t]*(\[ *)(? !! 3348 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 3908 if(not m): 3349 if(not m): 3909 continue 3350 continue 3910 msg = m.group("msg") 3351 msg = m.group("msg") 3911 if re.match(r'PM: Syncing fil !! 3352 if(re.match('PM: Syncing filesystems.*', msg)): 3912 re.match(r'PM: suspen << 3913 if(data): 3353 if(data): 3914 testruns.appe 3354 testruns.append(data) 3915 data = Data(len(testr 3355 data = Data(len(testruns)) 3916 tp.parseStamp(data, s 3356 tp.parseStamp(data, sysvals) 3917 if(not data): 3357 if(not data): 3918 continue 3358 continue 3919 m = re.match(r'.* *(?P<k>[0-9 !! 3359 m = re.match('.* *(?P<k>[0-9]\.[0-9]{2}\.[0-9]-.*) .*', msg) 3920 if(m): 3360 if(m): 3921 sysvals.stamp['kernel 3361 sysvals.stamp['kernel'] = m.group('k') 3922 m = re.match(r'PM: Preparing !! 3362 m = re.match('PM: Preparing system for (?P<m>.*) sleep', msg) 3923 if not m: !! 3363 if(m): 3924 m = re.match(r'PM: Pr << 3925 if m: << 3926 sysvals.stamp['mode'] 3364 sysvals.stamp['mode'] = sysvals.suspendmode = m.group('m') 3927 data.dmesgtext.append(line) 3365 data.dmesgtext.append(line) 3928 lf.close() 3366 lf.close() 3929 3367 3930 if sysvals.suspendmode == 's2idle': << 3931 sysvals.suspendmode = 'freeze << 3932 elif sysvals.suspendmode == 'deep': << 3933 sysvals.suspendmode = 'mem' << 3934 if data: 3368 if data: 3935 testruns.append(data) 3369 testruns.append(data) 3936 if len(testruns) < 1: 3370 if len(testruns) < 1: 3937 doError('dmesg log has no sus 3371 doError('dmesg log has no suspend/resume data: %s' \ 3938 % sysvals.dmesgfile) 3372 % sysvals.dmesgfile) 3939 3373 3940 # fix lines with same timestamp/funct 3374 # fix lines with same timestamp/function with the call and return swapped 3941 for data in testruns: 3375 for data in testruns: 3942 last = '' 3376 last = '' 3943 for line in data.dmesgtext: 3377 for line in data.dmesgtext: 3944 ct, cf, n, p = data.i !! 3378 mc = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) calling '+\ 3945 rt, rf, l = data.init !! 3379 '(?P<f>.*)\+ @ .*, parent: .*', line) 3946 if ct and rt and ct = !! 3380 mr = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) call '+\ >> 3381 '(?P<f>.*)\+ returned .* after (?P<dt>.*) usecs', last) >> 3382 if(mc and mr and (mc.group('t') == mr.group('t')) and >> 3383 (mc.group('f') == mr.group('f'))): 3947 i = data.dmes 3384 i = data.dmesgtext.index(last) 3948 j = data.dmes 3385 j = data.dmesgtext.index(line) 3949 data.dmesgtex 3386 data.dmesgtext[i] = line 3950 data.dmesgtex 3387 data.dmesgtext[j] = last 3951 last = line 3388 last = line 3952 return testruns 3389 return testruns 3953 3390 3954 # Function: parseKernelLog 3391 # Function: parseKernelLog 3955 # Description: 3392 # Description: >> 3393 # [deprecated for kernel 3.15.0 or newer] 3956 # Analyse a dmesg log output file gene 3394 # Analyse a dmesg log output file generated from this app during 3957 # the execution phase. Create a set of 3395 # the execution phase. Create a set of device structures in memory 3958 # for subsequent formatting in the htm 3396 # for subsequent formatting in the html output file 3959 # This call is only for legacy support 3397 # This call is only for legacy support on kernels where the ftrace 3960 # data lacks the suspend_resume or dev 3398 # data lacks the suspend_resume or device_pm_callbacks trace events. 3961 # Arguments: 3399 # Arguments: 3962 # data: an empty Data object (with dme 3400 # data: an empty Data object (with dmesgtext) obtained from loadKernelLog 3963 # Output: 3401 # Output: 3964 # The filled Data object 3402 # The filled Data object 3965 def parseKernelLog(data): 3403 def parseKernelLog(data): 3966 phase = 'suspend_runtime' 3404 phase = 'suspend_runtime' 3967 3405 3968 if(data.fwValid): 3406 if(data.fwValid): 3969 sysvals.vprint('Firmware Susp 3407 sysvals.vprint('Firmware Suspend = %u ns, Firmware Resume = %u ns' % \ 3970 (data.fwSuspend, data 3408 (data.fwSuspend, data.fwResume)) 3971 3409 3972 # dmesg phase match table 3410 # dmesg phase match table 3973 dm = { 3411 dm = { 3974 'suspend_prepare': ['PM: Sync !! 3412 'suspend_prepare': ['PM: Syncing filesystems.*'], 3975 'suspend': ['PM: Ente !! 3413 'suspend': ['PM: Entering [a-z]* sleep.*', 'Suspending console.*'], 3976 'PM: Susp !! 3414 'suspend_late': ['PM: suspend of devices complete after.*'], 3977 'suspend_late': ['PM: susp !! 3415 'suspend_noirq': ['PM: late suspend of devices complete after.*'], 3978 !! 3416 'suspend_machine': ['PM: noirq suspend of devices complete after.*'], 3979 'suspend_noirq': ['PM: late !! 3417 'resume_machine': ['ACPI: Low-level resume complete.*'], 3980 !! 3418 'resume_noirq': ['ACPI: Waking up from system sleep state.*'], 3981 'suspend_machine': ['PM: susp !! 3419 'resume_early': ['PM: noirq resume of devices complete after.*'], 3982 !! 3420 'resume': ['PM: early resume of devices complete after.*'], 3983 !! 3421 'resume_complete': ['PM: resume of devices complete after.*'], 3984 'resume_machine': ['[PM: ]*T !! 3422 'post_resume': ['.*Restarting tasks \.\.\..*'], 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 } 3423 } >> 3424 if(sysvals.suspendmode == 'standby'): >> 3425 dm['resume_machine'] = ['PM: Restoring platform NVS memory'] >> 3426 elif(sysvals.suspendmode == 'disk'): >> 3427 dm['suspend_late'] = ['PM: freeze of devices complete after.*'] >> 3428 dm['suspend_noirq'] = ['PM: late freeze of devices complete after.*'] >> 3429 dm['suspend_machine'] = ['PM: noirq freeze of devices complete after.*'] >> 3430 dm['resume_machine'] = ['PM: Restoring platform NVS memory'] >> 3431 dm['resume_early'] = ['PM: noirq restore of devices complete after.*'] >> 3432 dm['resume'] = ['PM: early restore of devices complete after.*'] >> 3433 dm['resume_complete'] = ['PM: restore of devices complete after.*'] >> 3434 elif(sysvals.suspendmode == 'freeze'): >> 3435 dm['resume_machine'] = ['ACPI: resume from mwait'] 3998 3436 3999 # action table (expected events that 3437 # action table (expected events that occur and show up in dmesg) 4000 at = { 3438 at = { 4001 'sync_filesystems': { 3439 'sync_filesystems': { 4002 'smsg': '.*[Ff]+ilesy !! 3440 'smsg': 'PM: Syncing filesystems.*', 4003 'emsg': 'PM: Preparin !! 3441 'emsg': 'PM: Preparing system for mem sleep.*' }, 4004 'freeze_user_processes': { 3442 'freeze_user_processes': { 4005 'smsg': 'Freezing use !! 3443 'smsg': 'Freezing user space processes .*', 4006 'emsg': 'Freezing rem 3444 'emsg': 'Freezing remaining freezable tasks.*' }, 4007 'freeze_tasks': { 3445 'freeze_tasks': { 4008 'smsg': 'Freezing rem 3446 'smsg': 'Freezing remaining freezable tasks.*', 4009 'emsg': 'PM: Suspendi !! 3447 'emsg': 'PM: Entering (?P<mode>[a-z,A-Z]*) sleep.*' }, 4010 'ACPI prepare': { 3448 'ACPI prepare': { 4011 'smsg': 'ACPI: Prepar 3449 'smsg': 'ACPI: Preparing to enter system sleep state.*', 4012 'emsg': 'PM: Saving p 3450 'emsg': 'PM: Saving platform NVS memory.*' }, 4013 'PM vns': { 3451 'PM vns': { 4014 'smsg': 'PM: Saving p 3452 'smsg': 'PM: Saving platform NVS memory.*', 4015 'emsg': 'Disabling no 3453 'emsg': 'Disabling non-boot CPUs .*' }, 4016 } 3454 } 4017 3455 4018 t0 = -1.0 3456 t0 = -1.0 4019 cpu_start = -1.0 3457 cpu_start = -1.0 4020 prevktime = -1.0 3458 prevktime = -1.0 4021 actions = dict() 3459 actions = dict() 4022 for line in data.dmesgtext: 3460 for line in data.dmesgtext: 4023 # parse each dmesg line into 3461 # parse each dmesg line into the time and message 4024 m = re.match(r'[ \t]*(\[ *)(? !! 3462 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 4025 if(m): 3463 if(m): 4026 val = m.group('ktime' 3464 val = m.group('ktime') 4027 try: 3465 try: 4028 ktime = float 3466 ktime = float(val) 4029 except: 3467 except: 4030 continue 3468 continue 4031 msg = m.group('msg') 3469 msg = m.group('msg') 4032 # initialize data sta 3470 # initialize data start to first line time 4033 if t0 < 0: 3471 if t0 < 0: 4034 data.setStart 3472 data.setStart(ktime) 4035 t0 = ktime 3473 t0 = ktime 4036 else: 3474 else: 4037 continue 3475 continue 4038 3476 4039 # check for a phase change li 3477 # check for a phase change line 4040 phasechange = False 3478 phasechange = False 4041 for p in dm: 3479 for p in dm: 4042 for s in dm[p]: 3480 for s in dm[p]: 4043 if(re.match(s 3481 if(re.match(s, msg)): 4044 phase 3482 phasechange, phase = True, p 4045 dm[p] << 4046 break 3483 break 4047 3484 4048 # hack for determining resume 3485 # hack for determining resume_machine end for freeze 4049 if(not sysvals.usetraceevents 3486 if(not sysvals.usetraceevents and sysvals.suspendmode == 'freeze' \ 4050 and phase == 'resume_ 3487 and phase == 'resume_machine' and \ 4051 data.initcall_debug_c !! 3488 re.match('calling (?P<f>.*)\+ @ .*, parent: .*', msg)): 4052 data.setPhase(phase, 3489 data.setPhase(phase, ktime, False) 4053 phase = 'resume_noirq 3490 phase = 'resume_noirq' 4054 data.setPhase(phase, 3491 data.setPhase(phase, ktime, True) 4055 3492 4056 if phasechange: 3493 if phasechange: 4057 if phase == 'suspend_ 3494 if phase == 'suspend_prepare': 4058 data.setPhase 3495 data.setPhase(phase, ktime, True) 4059 data.setStart 3496 data.setStart(ktime) 4060 data.tKernSus 3497 data.tKernSus = ktime 4061 elif phase == 'suspen 3498 elif phase == 'suspend': 4062 lp = data.las 3499 lp = data.lastPhase() 4063 if lp: 3500 if lp: 4064 data. 3501 data.setPhase(lp, ktime, False) 4065 data.setPhase 3502 data.setPhase(phase, ktime, True) 4066 elif phase == 'suspen 3503 elif phase == 'suspend_late': 4067 lp = data.las 3504 lp = data.lastPhase() 4068 if lp: 3505 if lp: 4069 data. 3506 data.setPhase(lp, ktime, False) 4070 data.setPhase 3507 data.setPhase(phase, ktime, True) 4071 elif phase == 'suspen 3508 elif phase == 'suspend_noirq': 4072 lp = data.las 3509 lp = data.lastPhase() 4073 if lp: 3510 if lp: 4074 data. 3511 data.setPhase(lp, ktime, False) 4075 data.setPhase 3512 data.setPhase(phase, ktime, True) 4076 elif phase == 'suspen 3513 elif phase == 'suspend_machine': 4077 lp = data.las 3514 lp = data.lastPhase() 4078 if lp: 3515 if lp: 4079 data. 3516 data.setPhase(lp, ktime, False) 4080 data.setPhase 3517 data.setPhase(phase, ktime, True) 4081 elif phase == 'resume 3518 elif phase == 'resume_machine': 4082 lp = data.las 3519 lp = data.lastPhase() 4083 if(sysvals.su 3520 if(sysvals.suspendmode in ['freeze', 'standby']): 4084 data. 3521 data.tSuspended = prevktime 4085 if lp 3522 if lp: 4086 3523 data.setPhase(lp, prevktime, False) 4087 else: 3524 else: 4088 data. 3525 data.tSuspended = ktime 4089 if lp 3526 if lp: 4090 3527 data.setPhase(lp, prevktime, False) 4091 data.tResumed 3528 data.tResumed = ktime 4092 data.setPhase 3529 data.setPhase(phase, ktime, True) 4093 elif phase == 'resume 3530 elif phase == 'resume_noirq': 4094 lp = data.las 3531 lp = data.lastPhase() 4095 if lp: 3532 if lp: 4096 data. 3533 data.setPhase(lp, ktime, False) 4097 data.setPhase 3534 data.setPhase(phase, ktime, True) 4098 elif phase == 'resume 3535 elif phase == 'resume_early': 4099 lp = data.las 3536 lp = data.lastPhase() 4100 if lp: 3537 if lp: 4101 data. 3538 data.setPhase(lp, ktime, False) 4102 data.setPhase 3539 data.setPhase(phase, ktime, True) 4103 elif phase == 'resume 3540 elif phase == 'resume': 4104 lp = data.las 3541 lp = data.lastPhase() 4105 if lp: 3542 if lp: 4106 data. 3543 data.setPhase(lp, ktime, False) 4107 data.setPhase 3544 data.setPhase(phase, ktime, True) 4108 elif phase == 'resume 3545 elif phase == 'resume_complete': 4109 lp = data.las 3546 lp = data.lastPhase() 4110 if lp: 3547 if lp: 4111 data. 3548 data.setPhase(lp, ktime, False) 4112 data.setPhase 3549 data.setPhase(phase, ktime, True) 4113 elif phase == 'post_r 3550 elif phase == 'post_resume': 4114 lp = data.las 3551 lp = data.lastPhase() 4115 if lp: 3552 if lp: 4116 data. 3553 data.setPhase(lp, ktime, False) 4117 data.setEnd(k 3554 data.setEnd(ktime) 4118 data.tKernRes 3555 data.tKernRes = ktime 4119 break 3556 break 4120 3557 4121 # -- device callbacks -- 3558 # -- device callbacks -- 4122 if(phase in data.sortedPhases 3559 if(phase in data.sortedPhases()): 4123 # device init call 3560 # device init call 4124 t, f, n, p = data.ini !! 3561 if(re.match('calling (?P<f>.*)\+ @ .*, parent: .*', msg)): 4125 if t and f and n and !! 3562 sm = re.match('calling (?P<f>.*)\+ @ '+\ 4126 data.newActio !! 3563 '(?P<n>.*), parent: (?P<p>.*)', msg); 4127 else: !! 3564 f = sm.group('f') 4128 # device init !! 3565 n = sm.group('n') 4129 t, f, l = dat !! 3566 p = sm.group('p') 4130 if t and f an !! 3567 if(f and n and p): 4131 list !! 3568 data.newAction(phase, f, int(n), p, ktime, -1, '') 4132 if(f !! 3569 # device init return 4133 !! 3570 elif(re.match('call (?P<f>.*)\+ returned .* after '+\ 4134 !! 3571 '(?P<t>.*) usecs', msg)): 4135 !! 3572 sm = re.match('call (?P<f>.*)\+ returned .* after '+\ >> 3573 '(?P<t>.*) usecs(?P<a>.*)', msg); >> 3574 f = sm.group('f') >> 3575 t = sm.group('t') >> 3576 list = data.dmesg[phase]['list'] >> 3577 if(f in list): >> 3578 dev = list[f] >> 3579 dev['length'] = int(t) >> 3580 dev['end'] = ktime 4136 3581 4137 # if trace events are not ava 3582 # if trace events are not available, these are better than nothing 4138 if(not sysvals.usetraceevents 3583 if(not sysvals.usetraceevents): 4139 # look for known acti 3584 # look for known actions 4140 for a in sorted(at): !! 3585 for a in at: 4141 if(re.match(a 3586 if(re.match(at[a]['smsg'], msg)): 4142 if(a 3587 if(a not in actions): 4143 !! 3588 actions[a] = [] >> 3589 actions[a].append({'begin': ktime, 'end': ktime}) 4144 if(re.match(a 3590 if(re.match(at[a]['emsg'], msg)): 4145 if(a !! 3591 if(a in actions): 4146 3592 actions[a][-1]['end'] = ktime 4147 # now look for CPU on 3593 # now look for CPU on/off events 4148 if(re.match(r'Disabli !! 3594 if(re.match('Disabling non-boot CPUs .*', msg)): 4149 # start of fi 3595 # start of first cpu suspend 4150 cpu_start = k 3596 cpu_start = ktime 4151 elif(re.match(r'Enabl !! 3597 elif(re.match('Enabling non-boot CPUs .*', msg)): 4152 # start of fi 3598 # start of first cpu resume 4153 cpu_start = k 3599 cpu_start = ktime 4154 elif(re.match(r'smpbo !! 3600 elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)): 4155 or re.match(r << 4156 # end of a cp 3601 # end of a cpu suspend, start of the next 4157 m = re.match( !! 3602 m = re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg) 4158 if(not m): << 4159 m = r << 4160 cpu = 'CPU'+m 3603 cpu = 'CPU'+m.group('cpu') 4161 if(cpu not in 3604 if(cpu not in actions): 4162 actio 3605 actions[cpu] = [] 4163 actions[cpu]. 3606 actions[cpu].append({'begin': cpu_start, 'end': ktime}) 4164 cpu_start = k 3607 cpu_start = ktime 4165 elif(re.match(r'CPU(? !! 3608 elif(re.match('CPU(?P<cpu>[0-9]*) is up', msg)): 4166 # end of a cp 3609 # end of a cpu resume, start of the next 4167 m = re.match( !! 3610 m = re.match('CPU(?P<cpu>[0-9]*) is up', msg) 4168 cpu = 'CPU'+m 3611 cpu = 'CPU'+m.group('cpu') 4169 if(cpu not in 3612 if(cpu not in actions): 4170 actio 3613 actions[cpu] = [] 4171 actions[cpu]. 3614 actions[cpu].append({'begin': cpu_start, 'end': ktime}) 4172 cpu_start = k 3615 cpu_start = ktime 4173 prevktime = ktime 3616 prevktime = ktime 4174 data.initDevicegroups() 3617 data.initDevicegroups() 4175 3618 4176 # fill in any missing phases 3619 # fill in any missing phases 4177 phasedef = data.phasedef 3620 phasedef = data.phasedef 4178 terr, lp = '', 'suspend_prepare' 3621 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 3622 for p in sorted(phasedef, key=lambda k:phasedef[k]['order']): 4182 if p not in data.dmesg: 3623 if p not in data.dmesg: 4183 if not terr: 3624 if not terr: 4184 pprint('TEST 3625 pprint('TEST FAILED: %s failed in %s phase' % (sysvals.suspendmode, lp)) 4185 terr = '%s fa 3626 terr = '%s failed in %s phase' % (sysvals.suspendmode, lp) 4186 if data.tSusp 3627 if data.tSuspended == 0: 4187 data. 3628 data.tSuspended = data.dmesg[lp]['end'] 4188 if data.tResu 3629 if data.tResumed == 0: 4189 data. 3630 data.tResumed = data.dmesg[lp]['end'] 4190 sysvals.vprint('WARNI 3631 sysvals.vprint('WARNING: phase "%s" is missing!' % p) 4191 lp = p 3632 lp = p 4192 lp = data.sortedPhases()[0] 3633 lp = data.sortedPhases()[0] 4193 for p in data.sortedPhases(): 3634 for p in data.sortedPhases(): 4194 if(p != lp and not ('machine' 3635 if(p != lp and not ('machine' in p and 'machine' in lp)): 4195 data.dmesg[lp]['end'] 3636 data.dmesg[lp]['end'] = data.dmesg[p]['start'] 4196 lp = p 3637 lp = p 4197 if data.tSuspended == 0: 3638 if data.tSuspended == 0: 4198 data.tSuspended = data.tKernR 3639 data.tSuspended = data.tKernRes 4199 if data.tResumed == 0: 3640 if data.tResumed == 0: 4200 data.tResumed = data.tSuspend 3641 data.tResumed = data.tSuspended 4201 3642 4202 # fill in any actions we've found 3643 # fill in any actions we've found 4203 for name in sorted(actions): !! 3644 for name in actions: 4204 for event in actions[name]: 3645 for event in actions[name]: 4205 data.newActionGlobal( 3646 data.newActionGlobal(name, event['begin'], event['end']) 4206 3647 4207 if(len(sysvals.devicefilter) > 0): 3648 if(len(sysvals.devicefilter) > 0): 4208 data.deviceFilter(sysvals.dev 3649 data.deviceFilter(sysvals.devicefilter) 4209 data.fixupInitcallsThatDidntReturn() 3650 data.fixupInitcallsThatDidntReturn() 4210 return True 3651 return True 4211 3652 4212 def callgraphHTML(sv, hf, num, cg, title, col 3653 def callgraphHTML(sv, hf, num, cg, title, color, devid): 4213 html_func_top = '<article id="{0}" cl 3654 html_func_top = '<article id="{0}" class="atop" style="background:{1}">\n<input type="checkbox" class="pf" id="f{2}" checked/><label for="f{2}">{3} {4}</label>\n' 4214 html_func_start = '<article>\n<input 3655 html_func_start = '<article>\n<input type="checkbox" class="pf" id="f{0}" checked/><label for="f{0}">{1} {2}</label>\n' 4215 html_func_end = '</article>\n' 3656 html_func_end = '</article>\n' 4216 html_func_leaf = '<article>{0} {1}</a 3657 html_func_leaf = '<article>{0} {1}</article>\n' 4217 3658 4218 cgid = devid 3659 cgid = devid 4219 if cg.id: 3660 if cg.id: 4220 cgid += cg.id 3661 cgid += cg.id 4221 cglen = (cg.end - cg.start) * 1000 3662 cglen = (cg.end - cg.start) * 1000 4222 if cglen < sv.mincglen: 3663 if cglen < sv.mincglen: 4223 return num 3664 return num 4224 3665 4225 fmt = '<r>(%.3f ms @ '+sv.timeformat+' 3666 fmt = '<r>(%.3f ms @ '+sv.timeformat+' to '+sv.timeformat+')</r>' 4226 flen = fmt % (cglen, cg.start, cg.end 3667 flen = fmt % (cglen, cg.start, cg.end) 4227 hf.write(html_func_top.format(cgid, c 3668 hf.write(html_func_top.format(cgid, color, num, title, flen)) 4228 num += 1 3669 num += 1 4229 for line in cg.list: 3670 for line in cg.list: 4230 if(line.length < 0.000000001) 3671 if(line.length < 0.000000001): 4231 flen = '' 3672 flen = '' 4232 else: 3673 else: 4233 fmt = '<n>(%.3f ms @ ' 3674 fmt = '<n>(%.3f ms @ '+sv.timeformat+')</n>' 4234 flen = fmt % (line.le 3675 flen = fmt % (line.length*1000, line.time) 4235 if line.isLeaf(): 3676 if line.isLeaf(): 4236 if line.length * 1000 << 4237 continue << 4238 hf.write(html_func_le 3677 hf.write(html_func_leaf.format(line.name, flen)) 4239 elif line.freturn: 3678 elif line.freturn: 4240 hf.write(html_func_en 3679 hf.write(html_func_end) 4241 else: 3680 else: 4242 hf.write(html_func_st 3681 hf.write(html_func_start.format(num, line.name, flen)) 4243 num += 1 3682 num += 1 4244 hf.write(html_func_end) 3683 hf.write(html_func_end) 4245 return num 3684 return num 4246 3685 4247 def addCallgraphs(sv, hf, data): 3686 def addCallgraphs(sv, hf, data): 4248 hf.write('<section id="callgraphs" cl 3687 hf.write('<section id="callgraphs" class="callgraph">\n') 4249 # write out the ftrace data converted 3688 # write out the ftrace data converted to html 4250 num = 0 3689 num = 0 4251 for p in data.sortedPhases(): 3690 for p in data.sortedPhases(): 4252 if sv.cgphase and p != sv.cgp 3691 if sv.cgphase and p != sv.cgphase: 4253 continue 3692 continue 4254 list = data.dmesg[p]['list'] 3693 list = data.dmesg[p]['list'] 4255 for d in data.sortedDevices(p !! 3694 for devname in data.sortedDevices(p): 4256 if len(sv.cgfilter) > !! 3695 if len(sv.cgfilter) > 0 and devname not in sv.cgfilter: 4257 continue 3696 continue 4258 dev = list[d] !! 3697 dev = list[devname] 4259 color = 'white' 3698 color = 'white' 4260 if 'color' in data.dm 3699 if 'color' in data.dmesg[p]: 4261 color = data. 3700 color = data.dmesg[p]['color'] 4262 if 'color' in dev: 3701 if 'color' in dev: 4263 color = dev[' 3702 color = dev['color'] 4264 name = d if '[' not i !! 3703 name = devname 4265 if(d in sv.devprops): !! 3704 if(devname in sv.devprops): 4266 name = sv.dev !! 3705 name = sv.devprops[devname].altName(devname) 4267 if 'drv' in dev and d << 4268 name += ' {%s << 4269 if sv.suspendmode in 3706 if sv.suspendmode in suspendmodename: 4270 name += ' '+p 3707 name += ' '+p 4271 if('ftrace' in dev): 3708 if('ftrace' in dev): 4272 cg = dev['ftr 3709 cg = dev['ftrace'] 4273 if cg.name == 3710 if cg.name == sv.ftopfunc: 4274 name 3711 name = 'top level suspend/resume call' 4275 num = callgra 3712 num = callgraphHTML(sv, hf, num, cg, 4276 name, 3713 name, color, dev['id']) 4277 if('ftraces' in dev): 3714 if('ftraces' in dev): 4278 for cg in dev 3715 for cg in dev['ftraces']: 4279 num = 3716 num = callgraphHTML(sv, hf, num, cg, 4280 3717 name+' → '+cg.name, color, dev['id']) 4281 hf.write('\n\n </section>\n') 3718 hf.write('\n\n </section>\n') 4282 3719 4283 def summaryCSS(title, center=True): 3720 def summaryCSS(title, center=True): 4284 tdcenter = 'text-align:center;' if ce 3721 tdcenter = 'text-align:center;' if center else '' 4285 out = '<!DOCTYPE html>\n<html>\n<head 3722 out = '<!DOCTYPE html>\n<html>\n<head>\n\ 4286 <meta http-equiv="content-type" conte 3723 <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\ 4287 <title>'+title+'</title>\n\ 3724 <title>'+title+'</title>\n\ 4288 <style type=\'text/css\'>\n\ 3725 <style type=\'text/css\'>\n\ 4289 .stamp {width: 100%;text-alig 3726 .stamp {width: 100%;text-align:center;background:#888;line-height:30px;color:white;font: 25px Arial;}\n\ 4290 table {width:100%;border-coll 3727 table {width:100%;border-collapse: collapse;border:1px solid;}\n\ 4291 th {border: 1px solid black;b 3728 th {border: 1px solid black;background:#222;color:white;}\n\ 4292 td {font: 14px "Times New Rom 3729 td {font: 14px "Times New Roman";'+tdcenter+'}\n\ 4293 tr.head td {border: 1px solid 3730 tr.head td {border: 1px solid black;background:#aaa;}\n\ 4294 tr.alt {background-color:#ddd 3731 tr.alt {background-color:#ddd;}\n\ 4295 tr.notice {color:red;}\n\ 3732 tr.notice {color:red;}\n\ 4296 .minval {background-color:#BB 3733 .minval {background-color:#BBFFBB;}\n\ 4297 .medval {background-color:#BB 3734 .medval {background-color:#BBBBFF;}\n\ 4298 .maxval {background-color:#FF 3735 .maxval {background-color:#FFBBBB;}\n\ 4299 .head a {color:#000;text-deco 3736 .head a {color:#000;text-decoration: none;}\n\ 4300 </style>\n</head>\n<body>\n' 3737 </style>\n</head>\n<body>\n' 4301 return out 3738 return out 4302 3739 4303 # Function: createHTMLSummarySimple 3740 # Function: createHTMLSummarySimple 4304 # Description: 3741 # Description: 4305 # Create summary html file for a serie 3742 # Create summary html file for a series of tests 4306 # Arguments: 3743 # Arguments: 4307 # testruns: array of Data objects from 3744 # testruns: array of Data objects from parseTraceLog 4308 def createHTMLSummarySimple(testruns, htmlfil 3745 def createHTMLSummarySimple(testruns, htmlfile, title): 4309 # write the html header first (html h 3746 # write the html header first (html head, css code, up to body start) 4310 html = summaryCSS('Summary - SleepGra 3747 html = summaryCSS('Summary - SleepGraph') 4311 3748 4312 # extract the test data into list 3749 # extract the test data into list 4313 list = dict() 3750 list = dict() 4314 tAvg, tMin, tMax, tMed = [0.0, 0.0], 3751 tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [dict(), dict()] 4315 iMin, iMed, iMax = [0, 0], [0, 0], [0 3752 iMin, iMed, iMax = [0, 0], [0, 0], [0, 0] 4316 num = 0 3753 num = 0 4317 useturbo = usewifi = False !! 3754 useturbo = False 4318 lastmode = '' 3755 lastmode = '' 4319 cnt = dict() 3756 cnt = dict() 4320 for data in sorted(testruns, key=lamb 3757 for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])): 4321 mode = data['mode'] 3758 mode = data['mode'] 4322 if mode not in list: 3759 if mode not in list: 4323 list[mode] = {'data': 3760 list[mode] = {'data': [], 'avg': [0,0], 'min': [0,0], 'max': [0,0], 'med': [0,0]} 4324 if lastmode and lastmode != m 3761 if lastmode and lastmode != mode and num > 0: 4325 for i in range(2): 3762 for i in range(2): 4326 s = sorted(tM 3763 s = sorted(tMed[i]) 4327 list[lastmode !! 3764 list[lastmode]['med'][i] = s[int(len(s)/2)] 4328 iMed[i] = tMe 3765 iMed[i] = tMed[i][list[lastmode]['med'][i]] 4329 list[lastmode]['avg'] 3766 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num] 4330 list[lastmode]['min'] 3767 list[lastmode]['min'] = tMin 4331 list[lastmode]['max'] 3768 list[lastmode]['max'] = tMax 4332 list[lastmode]['idx'] 3769 list[lastmode]['idx'] = (iMin, iMed, iMax) 4333 tAvg, tMin, tMax, tMe 3770 tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [dict(), dict()] 4334 iMin, iMed, iMax = [0 3771 iMin, iMed, iMax = [0, 0], [0, 0], [0, 0] 4335 num = 0 3772 num = 0 4336 pkgpc10 = syslpi = wifi = '' !! 3773 pkgpc10 = syslpi = '' 4337 if 'pkgpc10' in data and 'sys 3774 if 'pkgpc10' in data and 'syslpi' in data: 4338 pkgpc10, syslpi, uset !! 3775 pkgpc10 = data['pkgpc10'] 4339 if 'wifi' in data: !! 3776 syslpi = data['syslpi'] 4340 wifi, usewifi = data[ !! 3777 useturbo = True 4341 res = data['result'] 3778 res = data['result'] 4342 tVal = [float(data['suspend'] 3779 tVal = [float(data['suspend']), float(data['resume'])] 4343 list[mode]['data'].append([da 3780 list[mode]['data'].append([data['host'], data['kernel'], 4344 data['time'], tVal[0] 3781 data['time'], tVal[0], tVal[1], data['url'], res, 4345 data['issues'], data[ 3782 data['issues'], data['sus_worst'], data['sus_worsttime'], 4346 data['res_worst'], da !! 3783 data['res_worst'], data['res_worsttime'], pkgpc10, syslpi]) 4347 (data['fullmode'] if << 4348 idx = len(list[mode]['data']) 3784 idx = len(list[mode]['data']) - 1 4349 if res.startswith('fail in'): 3785 if res.startswith('fail in'): 4350 res = 'fail' 3786 res = 'fail' 4351 if res not in cnt: 3787 if res not in cnt: 4352 cnt[res] = 1 3788 cnt[res] = 1 4353 else: 3789 else: 4354 cnt[res] += 1 3790 cnt[res] += 1 4355 if res == 'pass': 3791 if res == 'pass': 4356 for i in range(2): 3792 for i in range(2): 4357 tMed[i][tVal[ 3793 tMed[i][tVal[i]] = idx 4358 tAvg[i] += tV 3794 tAvg[i] += tVal[i] 4359 if tMin[i] == 3795 if tMin[i] == 0 or tVal[i] < tMin[i]: 4360 iMin[ 3796 iMin[i] = idx 4361 tMin[ 3797 tMin[i] = tVal[i] 4362 if tMax[i] == 3798 if tMax[i] == 0 or tVal[i] > tMax[i]: 4363 iMax[ 3799 iMax[i] = idx 4364 tMax[ 3800 tMax[i] = tVal[i] 4365 num += 1 3801 num += 1 4366 lastmode = mode 3802 lastmode = mode 4367 if lastmode and num > 0: 3803 if lastmode and num > 0: 4368 for i in range(2): 3804 for i in range(2): 4369 s = sorted(tMed[i]) 3805 s = sorted(tMed[i]) 4370 list[lastmode]['med'] !! 3806 list[lastmode]['med'][i] = s[int(len(s)/2)] 4371 iMed[i] = tMed[i][lis 3807 iMed[i] = tMed[i][list[lastmode]['med'][i]] 4372 list[lastmode]['avg'] = [tAvg 3808 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num] 4373 list[lastmode]['min'] = tMin 3809 list[lastmode]['min'] = tMin 4374 list[lastmode]['max'] = tMax 3810 list[lastmode]['max'] = tMax 4375 list[lastmode]['idx'] = (iMin 3811 list[lastmode]['idx'] = (iMin, iMed, iMax) 4376 3812 4377 # group test header 3813 # group test header 4378 desc = [] 3814 desc = [] 4379 for ilk in sorted(cnt, reverse=True): 3815 for ilk in sorted(cnt, reverse=True): 4380 if cnt[ilk] > 0: 3816 if cnt[ilk] > 0: 4381 desc.append('%d %s' % 3817 desc.append('%d %s' % (cnt[ilk], ilk)) 4382 html += '<div class="stamp">%s (%d te 3818 html += '<div class="stamp">%s (%d tests: %s)</div>\n' % (title, len(testruns), ', '.join(desc)) 4383 th = '\t<th>{0}</th>\n' 3819 th = '\t<th>{0}</th>\n' 4384 td = '\t<td>{0}</td>\n' 3820 td = '\t<td>{0}</td>\n' 4385 tdh = '\t<td{1}>{0}</td>\n' 3821 tdh = '\t<td{1}>{0}</td>\n' 4386 tdlink = '\t<td><a href="{0}">html</a 3822 tdlink = '\t<td><a href="{0}">html</a></td>\n' 4387 cols = 12 !! 3823 colspan = '14' if useturbo else '12' 4388 if useturbo: << 4389 cols += 2 << 4390 if usewifi: << 4391 cols += 1 << 4392 colspan = '%d' % cols << 4393 3824 4394 # table header 3825 # table header 4395 html += '<table>\n<tr>\n' + th.format 3826 html += '<table>\n<tr>\n' + th.format('#') +\ 4396 th.format('Mode') + th.format 3827 th.format('Mode') + th.format('Host') + th.format('Kernel') +\ 4397 th.format('Test Time') + th.f 3828 th.format('Test Time') + th.format('Result') + th.format('Issues') +\ 4398 th.format('Suspend') + th.for 3829 th.format('Suspend') + th.format('Resume') +\ 4399 th.format('Worst Suspend Devi 3830 th.format('Worst Suspend Device') + th.format('SD Time') +\ 4400 th.format('Worst Resume Devic 3831 th.format('Worst Resume Device') + th.format('RD Time') 4401 if useturbo: 3832 if useturbo: 4402 html += th.format('PkgPC10') 3833 html += th.format('PkgPC10') + th.format('SysLPI') 4403 if usewifi: << 4404 html += th.format('Wifi') << 4405 html += th.format('Detail')+'</tr>\n' 3834 html += th.format('Detail')+'</tr>\n' 4406 # export list into html 3835 # export list into html 4407 head = '<tr class="head"><td>{0}</td> 3836 head = '<tr class="head"><td>{0}</td><td>{1}</td>'+\ 4408 '<td colspan='+colspan+' clas 3837 '<td colspan='+colspan+' class="sus">Suspend Avg={2} '+\ 4409 '<span class=minval><a href=" 3838 '<span class=minval><a href="#s{10}min">Min={3}</a></span> '+\ 4410 '<span class=medval><a href=" 3839 '<span class=medval><a href="#s{10}med">Med={4}</a></span> '+\ 4411 '<span class=maxval><a href=" 3840 '<span class=maxval><a href="#s{10}max">Max={5}</a></span> '+\ 4412 'Resume Avg={6} '+\ 3841 'Resume Avg={6} '+\ 4413 '<span class=minval><a href=" 3842 '<span class=minval><a href="#r{10}min">Min={7}</a></span> '+\ 4414 '<span class=medval><a href=" 3843 '<span class=medval><a href="#r{10}med">Med={8}</a></span> '+\ 4415 '<span class=maxval><a href=" 3844 '<span class=maxval><a href="#r{10}max">Max={9}</a></span></td>'+\ 4416 '</tr>\n' 3845 '</tr>\n' 4417 headnone = '<tr class="head"><td>{0}< 3846 headnone = '<tr class="head"><td>{0}</td><td>{1}</td><td colspan='+\ 4418 colspan+'></td></tr>\n' 3847 colspan+'></td></tr>\n' 4419 for mode in sorted(list): !! 3848 for mode in list: 4420 # header line for each suspen 3849 # header line for each suspend mode 4421 num = 0 3850 num = 0 4422 tAvg, tMin, tMax, tMed = list 3851 tAvg, tMin, tMax, tMed = list[mode]['avg'], list[mode]['min'],\ 4423 list[mode]['max'], li 3852 list[mode]['max'], list[mode]['med'] 4424 count = len(list[mode]['data' 3853 count = len(list[mode]['data']) 4425 if 'idx' in list[mode]: 3854 if 'idx' in list[mode]: 4426 iMin, iMed, iMax = li 3855 iMin, iMed, iMax = list[mode]['idx'] 4427 html += head.format(' 3856 html += head.format('%d' % count, mode.upper(), 4428 '%.3f' % tAvg 3857 '%.3f' % tAvg[0], '%.3f' % tMin[0], '%.3f' % tMed[0], '%.3f' % tMax[0], 4429 '%.3f' % tAvg 3858 '%.3f' % tAvg[1], '%.3f' % tMin[1], '%.3f' % tMed[1], '%.3f' % tMax[1], 4430 mode.lower() 3859 mode.lower() 4431 ) 3860 ) 4432 else: 3861 else: 4433 iMin = iMed = iMax = 3862 iMin = iMed = iMax = [-1, -1, -1] 4434 html += headnone.form 3863 html += headnone.format('%d' % count, mode.upper()) 4435 for d in list[mode]['data']: 3864 for d in list[mode]['data']: 4436 # row classes - alter 3865 # row classes - alternate row color 4437 rcls = ['alt'] if num 3866 rcls = ['alt'] if num % 2 == 1 else [] 4438 if d[6] != 'pass': 3867 if d[6] != 'pass': 4439 rcls.append(' 3868 rcls.append('notice') 4440 html += '<tr class="' 3869 html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n' 4441 # figure out if the l 3870 # figure out if the line has sus or res highlighted 4442 idx = list[mode]['dat 3871 idx = list[mode]['data'].index(d) 4443 tHigh = ['', ''] 3872 tHigh = ['', ''] 4444 for i in range(2): 3873 for i in range(2): 4445 tag = 's%s' % 3874 tag = 's%s' % mode if i == 0 else 'r%s' % mode 4446 if idx == iMi 3875 if idx == iMin[i]: 4447 tHigh 3876 tHigh[i] = ' id="%smin" class=minval title="Minimum"' % tag 4448 elif idx == i 3877 elif idx == iMax[i]: 4449 tHigh 3878 tHigh[i] = ' id="%smax" class=maxval title="Maximum"' % tag 4450 elif idx == i 3879 elif idx == iMed[i]: 4451 tHigh 3880 tHigh[i] = ' id="%smed" class=medval title="Median"' % tag 4452 html += td.format("%d 3881 html += td.format("%d" % (list[mode]['data'].index(d) + 1)) # row 4453 html += td.format(d[1 !! 3882 html += td.format(mode) # mode 4454 html += td.format(d[0 3883 html += td.format(d[0]) # host 4455 html += td.format(d[1 3884 html += td.format(d[1]) # kernel 4456 html += td.format(d[2 3885 html += td.format(d[2]) # time 4457 html += td.format(d[6 3886 html += td.format(d[6]) # result 4458 html += td.format(d[7 3887 html += td.format(d[7]) # issues 4459 html += tdh.format('% 3888 html += tdh.format('%.3f ms' % d[3], tHigh[0]) if d[3] else td.format('') # suspend 4460 html += tdh.format('% 3889 html += tdh.format('%.3f ms' % d[4], tHigh[1]) if d[4] else td.format('') # resume 4461 html += td.format(d[8 3890 html += td.format(d[8]) # sus_worst 4462 html += td.format('%. 3891 html += td.format('%.3f ms' % d[9]) if d[9] else td.format('') # sus_worst time 4463 html += td.format(d[1 3892 html += td.format(d[10]) # res_worst 4464 html += td.format('%. 3893 html += td.format('%.3f ms' % d[11]) if d[11] else td.format('') # res_worst time 4465 if useturbo: 3894 if useturbo: 4466 html += td.fo 3895 html += td.format(d[12]) # pkg_pc10 4467 html += td.fo 3896 html += td.format(d[13]) # syslpi 4468 if usewifi: << 4469 html += td.fo << 4470 html += tdlink.format 3897 html += tdlink.format(d[5]) if d[5] else td.format('') # url 4471 html += '</tr>\n' 3898 html += '</tr>\n' 4472 num += 1 3899 num += 1 4473 3900 4474 # flush the data to file 3901 # flush the data to file 4475 hf = open(htmlfile, 'w') 3902 hf = open(htmlfile, 'w') 4476 hf.write(html+'</table>\n</body>\n</h 3903 hf.write(html+'</table>\n</body>\n</html>\n') 4477 hf.close() 3904 hf.close() 4478 3905 4479 def createHTMLDeviceSummary(testruns, htmlfil 3906 def createHTMLDeviceSummary(testruns, htmlfile, title): 4480 html = summaryCSS('Device Summary - S 3907 html = summaryCSS('Device Summary - SleepGraph', False) 4481 3908 4482 # create global device list from all 3909 # create global device list from all tests 4483 devall = dict() 3910 devall = dict() 4484 for data in testruns: 3911 for data in testruns: 4485 host, url, devlist = data['ho 3912 host, url, devlist = data['host'], data['url'], data['devlist'] 4486 for type in devlist: 3913 for type in devlist: 4487 if type not in devall 3914 if type not in devall: 4488 devall[type] 3915 devall[type] = dict() 4489 mdevlist, devlist = d 3916 mdevlist, devlist = devall[type], data['devlist'][type] 4490 for name in devlist: 3917 for name in devlist: 4491 length = devl 3918 length = devlist[name] 4492 if name not i 3919 if name not in mdevlist: 4493 mdevl 3920 mdevlist[name] = {'name': name, 'host': host, 4494 3921 'worst': length, 'total': length, 'count': 1, 4495 3922 'url': url} 4496 else: 3923 else: 4497 if le 3924 if length > mdevlist[name]['worst']: 4498 3925 mdevlist[name]['worst'] = length 4499 3926 mdevlist[name]['url'] = url 4500 3927 mdevlist[name]['host'] = host 4501 mdevl 3928 mdevlist[name]['total'] += length 4502 mdevl 3929 mdevlist[name]['count'] += 1 4503 3930 4504 # generate the html 3931 # generate the html 4505 th = '\t<th>{0}</th>\n' 3932 th = '\t<th>{0}</th>\n' 4506 td = '\t<td align=center>{0}</td>\n' 3933 td = '\t<td align=center>{0}</td>\n' 4507 tdr = '\t<td align=right>{0}</td>\n' 3934 tdr = '\t<td align=right>{0}</td>\n' 4508 tdlink = '\t<td align=center><a href= 3935 tdlink = '\t<td align=center><a href="{0}">html</a></td>\n' 4509 limit = 1 3936 limit = 1 4510 for type in sorted(devall, reverse=Tr 3937 for type in sorted(devall, reverse=True): 4511 num = 0 3938 num = 0 4512 devlist = devall[type] 3939 devlist = devall[type] 4513 # table header 3940 # table header 4514 html += '<div class="stamp">% 3941 html += '<div class="stamp">%s (%s devices > %d ms)</div><table>\n' % \ 4515 (title, type.upper(), 3942 (title, type.upper(), limit) 4516 html += '<tr>\n' + '<th align 3943 html += '<tr>\n' + '<th align=right>Device Name</th>' +\ 4517 th.format('Average Ti 3944 th.format('Average Time') + th.format('Count') +\ 4518 th.format('Worst Time 3945 th.format('Worst Time') + th.format('Host (worst time)') +\ 4519 th.format('Link (wors 3946 th.format('Link (worst time)') + '</tr>\n' 4520 for name in sorted(devlist, k !! 3947 for name in sorted(devlist, key=lambda k:devlist[k]['worst'], reverse=True): 4521 devlist[k]['total'], << 4522 data = devall[type][n 3948 data = devall[type][name] 4523 data['average'] = dat 3949 data['average'] = data['total'] / data['count'] 4524 if data['average'] < 3950 if data['average'] < limit: 4525 continue 3951 continue 4526 # row classes - alter 3952 # row classes - alternate row color 4527 rcls = ['alt'] if num 3953 rcls = ['alt'] if num % 2 == 1 else [] 4528 html += '<tr class="' 3954 html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n' 4529 html += tdr.format(da 3955 html += tdr.format(data['name']) # name 4530 html += td.format('%. 3956 html += td.format('%.3f ms' % data['average']) # average 4531 html += td.format(dat 3957 html += td.format(data['count']) # count 4532 html += td.format('%. 3958 html += td.format('%.3f ms' % data['worst']) # worst 4533 html += td.format(dat 3959 html += td.format(data['host']) # host 4534 html += tdlink.format 3960 html += tdlink.format(data['url']) # url 4535 html += '</tr>\n' 3961 html += '</tr>\n' 4536 num += 1 3962 num += 1 4537 html += '</table>\n' 3963 html += '</table>\n' 4538 3964 4539 # flush the data to file 3965 # flush the data to file 4540 hf = open(htmlfile, 'w') 3966 hf = open(htmlfile, 'w') 4541 hf.write(html+'</body>\n</html>\n') 3967 hf.write(html+'</body>\n</html>\n') 4542 hf.close() 3968 hf.close() 4543 return devall 3969 return devall 4544 3970 4545 def createHTMLIssuesSummary(testruns, issues, 3971 def createHTMLIssuesSummary(testruns, issues, htmlfile, title, extra=''): 4546 multihost = len([e for e in issues if 3972 multihost = len([e for e in issues if len(e['urls']) > 1]) > 0 4547 html = summaryCSS('Issues Summary - S 3973 html = summaryCSS('Issues Summary - SleepGraph', False) 4548 total = len(testruns) 3974 total = len(testruns) 4549 3975 4550 # generate the html 3976 # generate the html 4551 th = '\t<th>{0}</th>\n' 3977 th = '\t<th>{0}</th>\n' 4552 td = '\t<td align={0}>{1}</td>\n' 3978 td = '\t<td align={0}>{1}</td>\n' 4553 tdlink = '<a href="{1}">{0}</a>' 3979 tdlink = '<a href="{1}">{0}</a>' 4554 subtitle = '%d issues' % len(issues) 3980 subtitle = '%d issues' % len(issues) if len(issues) > 0 else 'no issues' 4555 html += '<div class="stamp">%s (%s)</ 3981 html += '<div class="stamp">%s (%s)</div><table>\n' % (title, subtitle) 4556 html += '<tr>\n' + th.format('Issue') 3982 html += '<tr>\n' + th.format('Issue') + th.format('Count') 4557 if multihost: 3983 if multihost: 4558 html += th.format('Hosts') 3984 html += th.format('Hosts') 4559 html += th.format('Tests') + th.forma 3985 html += th.format('Tests') + th.format('Fail Rate') +\ 4560 th.format('First Instance') + 3986 th.format('First Instance') + '</tr>\n' 4561 3987 4562 num = 0 3988 num = 0 4563 for e in sorted(issues, key=lambda v: 3989 for e in sorted(issues, key=lambda v:v['count'], reverse=True): 4564 testtotal = 0 3990 testtotal = 0 4565 links = [] 3991 links = [] 4566 for host in sorted(e['urls']) 3992 for host in sorted(e['urls']): 4567 links.append(tdlink.f 3993 links.append(tdlink.format(host, e['urls'][host][0])) 4568 testtotal += len(e['u 3994 testtotal += len(e['urls'][host]) 4569 rate = '%d/%d (%.2f%%)' % (te 3995 rate = '%d/%d (%.2f%%)' % (testtotal, total, 100*float(testtotal)/float(total)) 4570 # row classes - alternate row 3996 # row classes - alternate row color 4571 rcls = ['alt'] if num % 2 == 3997 rcls = ['alt'] if num % 2 == 1 else [] 4572 html += '<tr class="'+(' '.jo 3998 html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n' 4573 html += td.format('left', e[' 3999 html += td.format('left', e['line']) # issue 4574 html += td.format('center', e 4000 html += td.format('center', e['count']) # count 4575 if multihost: 4001 if multihost: 4576 html += td.format('ce 4002 html += td.format('center', len(e['urls'])) # hosts 4577 html += td.format('center', t 4003 html += td.format('center', testtotal) # test count 4578 html += td.format('center', r 4004 html += td.format('center', rate) # test rate 4579 html += td.format('center now 4005 html += td.format('center nowrap', '<br>'.join(links)) # links 4580 html += '</tr>\n' 4006 html += '</tr>\n' 4581 num += 1 4007 num += 1 4582 4008 4583 # flush the data to file 4009 # flush the data to file 4584 hf = open(htmlfile, 'w') 4010 hf = open(htmlfile, 'w') 4585 hf.write(html+'</table>\n'+extra+'</b 4011 hf.write(html+'</table>\n'+extra+'</body>\n</html>\n') 4586 hf.close() 4012 hf.close() 4587 return issues 4013 return issues 4588 4014 4589 def ordinal(value): 4015 def ordinal(value): 4590 suffix = 'th' 4016 suffix = 'th' 4591 if value < 10 or value > 19: 4017 if value < 10 or value > 19: 4592 if value % 10 == 1: 4018 if value % 10 == 1: 4593 suffix = 'st' 4019 suffix = 'st' 4594 elif value % 10 == 2: 4020 elif value % 10 == 2: 4595 suffix = 'nd' 4021 suffix = 'nd' 4596 elif value % 10 == 3: 4022 elif value % 10 == 3: 4597 suffix = 'rd' 4023 suffix = 'rd' 4598 return '%d%s' % (value, suffix) 4024 return '%d%s' % (value, suffix) 4599 4025 4600 # Function: createHTML 4026 # Function: createHTML 4601 # Description: 4027 # Description: 4602 # Create the output html file from the 4028 # Create the output html file from the resident test data 4603 # Arguments: 4029 # Arguments: 4604 # testruns: array of Data objects from 4030 # testruns: array of Data objects from parseKernelLog or parseTraceLog 4605 # Output: 4031 # Output: 4606 # True if the html file was created, f 4032 # True if the html file was created, false if it failed 4607 def createHTML(testruns, testfail): 4033 def createHTML(testruns, testfail): 4608 if len(testruns) < 1: 4034 if len(testruns) < 1: 4609 pprint('ERROR: Not enough tes 4035 pprint('ERROR: Not enough test data to build a timeline') 4610 return 4036 return 4611 4037 4612 kerror = False 4038 kerror = False 4613 for data in testruns: 4039 for data in testruns: 4614 if data.kerror: 4040 if data.kerror: 4615 kerror = True 4041 kerror = True 4616 if(sysvals.suspendmode in ['f 4042 if(sysvals.suspendmode in ['freeze', 'standby']): 4617 data.trimFreezeTime(t 4043 data.trimFreezeTime(testruns[-1].tSuspended) 4618 else: << 4619 data.getMemTime() << 4620 4044 4621 # html function templates 4045 # html function templates 4622 html_error = '<div id="{1}" title="ke 4046 html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">{2}→</div>\n' 4623 html_traceevent = '<div title="{0}" c 4047 html_traceevent = '<div title="{0}" class="traceevent{6}" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;{7}">{5}</div>\n' 4624 html_cpuexec = '<div class="jiffie" s 4048 html_cpuexec = '<div class="jiffie" style="left:{0}%;top:{1}px;height:{2}px;width:{3}%;background:{4};"></div>\n' 4625 html_timetotal = '<table class="time1 4049 html_timetotal = '<table class="time1">\n<tr>'\ 4626 '<td class="green" title="{3} 4050 '<td class="green" title="{3}">{2} Suspend Time: <b>{0} ms</b></td>'\ 4627 '<td class="yellow" title="{4 4051 '<td class="yellow" title="{4}">{2} Resume Time: <b>{1} ms</b></td>'\ 4628 '</tr>\n</table>\n' 4052 '</tr>\n</table>\n' 4629 html_timetotal2 = '<table class="time 4053 html_timetotal2 = '<table class="time1">\n<tr>'\ 4630 '<td class="green" title="{4} 4054 '<td class="green" title="{4}">{3} Suspend Time: <b>{0} ms</b></td>'\ 4631 '<td class="gray" title="time 4055 '<td class="gray" title="time spent in low-power mode with clock running">'+sysvals.suspendmode+' time: <b>{1} ms</b></td>'\ 4632 '<td class="yellow" title="{5 4056 '<td class="yellow" title="{5}">{3} Resume Time: <b>{2} ms</b></td>'\ 4633 '</tr>\n</table>\n' 4057 '</tr>\n</table>\n' 4634 html_timetotal3 = '<table class="time 4058 html_timetotal3 = '<table class="time1">\n<tr>'\ 4635 '<td class="green">Execution 4059 '<td class="green">Execution Time: <b>{0} ms</b></td>'\ 4636 '<td class="yellow">Command: 4060 '<td class="yellow">Command: <b>{1}</b></td>'\ 4637 '</tr>\n</table>\n' 4061 '</tr>\n</table>\n' >> 4062 html_timegroups = '<table class="time2">\n<tr>'\ >> 4063 '<td class="green" title="time from kernel enter_state({5}) to firmware mode [kernel time only]">{4}Kernel Suspend: {0} ms</td>'\ >> 4064 '<td class="purple">{4}Firmware Suspend: {1} ms</td>'\ >> 4065 '<td class="purple">{4}Firmware Resume: {2} ms</td>'\ >> 4066 '<td class="yellow" title="time from firmware mode to return from kernel enter_state({5}) [kernel time only]">{4}Kernel Resume: {3} ms</td>'\ >> 4067 '</tr>\n</table>\n' 4638 html_fail = '<table class="testfail"> 4068 html_fail = '<table class="testfail"><tr><td>{0}</td></tr></table>\n' 4639 html_kdesc = '<td class="{3}" title=" << 4640 html_fwdesc = '<td class="{3}" title= << 4641 html_wifdesc = '<td class="yellow" ti << 4642 4069 4643 # html format variables 4070 # html format variables 4644 scaleH = 20 4071 scaleH = 20 4645 if kerror: 4072 if kerror: 4646 scaleH = 40 4073 scaleH = 40 4647 4074 4648 # device timeline 4075 # device timeline 4649 devtl = Timeline(30, scaleH) 4076 devtl = Timeline(30, scaleH) 4650 4077 4651 # write the test title and general in 4078 # write the test title and general info header 4652 devtl.createHeader(sysvals, testruns[ 4079 devtl.createHeader(sysvals, testruns[0].stamp) 4653 4080 4654 # Generate the header for this timeli 4081 # Generate the header for this timeline 4655 for data in testruns: 4082 for data in testruns: 4656 tTotal = data.end - data.star 4083 tTotal = data.end - data.start >> 4084 sktime, rktime = data.getTimeValues() 4657 if(tTotal == 0): 4085 if(tTotal == 0): 4658 doError('No timeline 4086 doError('No timeline data') >> 4087 if(len(data.tLow) > 0): >> 4088 low_time = '|'.join(data.tLow) 4659 if sysvals.suspendmode == 'co 4089 if sysvals.suspendmode == 'command': 4660 run_time = '%.0f' % ( !! 4090 run_time = '%.0f'%((data.end-data.start)*1000) 4661 if sysvals.testcomman 4091 if sysvals.testcommand: 4662 testdesc = sy 4092 testdesc = sysvals.testcommand 4663 else: 4093 else: 4664 testdesc = 'u 4094 testdesc = 'unknown' 4665 if(len(testruns) > 1) 4095 if(len(testruns) > 1): 4666 testdesc = or 4096 testdesc = ordinal(data.testnumber+1)+' '+testdesc 4667 thtml = html_timetota 4097 thtml = html_timetotal3.format(run_time, testdesc) 4668 devtl.html += thtml 4098 devtl.html += thtml 4669 continue !! 4099 elif data.fwValid: 4670 # typical full suspend/resume !! 4100 suspend_time = '%.0f'%(sktime + (data.fwSuspend/1000000.0)) 4671 stot, rtot = sktime, rktime = !! 4101 resume_time = '%.0f'%(rktime + (data.fwResume/1000000.0)) 4672 ssrc, rsrc, testdesc, testdes !! 4102 testdesc1 = 'Total' 4673 if data.fwValid: !! 4103 testdesc2 = '' 4674 stot += (data.fwSuspe !! 4104 stitle = 'time from kernel enter_state(%s) to low-power mode [kernel & firmware time]' % sysvals.suspendmode 4675 rtot += (data.fwResum !! 4105 rtitle = 'time from low-power mode to return from kernel enter_state(%s) [firmware & kernel time]' % sysvals.suspendmode 4676 ssrc.append('firmware !! 4106 if(len(testruns) > 1): 4677 rsrc.append('firmware !! 4107 testdesc1 = testdesc2 = ordinal(data.testnumber+1) 4678 testdesc = 'Total' !! 4108 testdesc2 += ' ' 4679 if 'time' in data.wifi and da !! 4109 if(len(data.tLow) == 0): 4680 rtot += data.end - da !! 4110 thtml = html_timetotal.format(suspend_time, \ 4681 rsrc.append('wifi') !! 4111 resume_time, testdesc1, stitle, rtitle) 4682 testdesc = 'Total' !! 4112 else: 4683 suspend_time, resume_time = ' !! 4113 thtml = html_timetotal2.format(suspend_time, low_time, \ 4684 stitle = 'time from kernel su !! 4114 resume_time, testdesc1, stitle, rtitle) 4685 (sysvals.suspendmode, !! 4115 devtl.html += thtml 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 4116 sftime = '%.3f'%(data.fwSuspend / 1000000.0) 4706 rftime = '%.3f'%(data 4117 rftime = '%.3f'%(data.fwResume / 1000000.0) 4707 thtml += html_fwdesc. !! 4118 devtl.html += html_timegroups.format('%.3f'%sktime, \ 4708 thtml += html_fwdesc. !! 4119 sftime, rftime, '%.3f'%rktime, testdesc2, sysvals.suspendmode) 4709 thtml += html_kdesc.format(te !! 4120 else: 4710 if 'time' in data.wifi: !! 4121 suspend_time = '%.3f' % sktime 4711 if data.wifi['stat'] !! 4122 resume_time = '%.3f' % rktime 4712 wtime = '%.0f !! 4123 testdesc = 'Kernel' >> 4124 stitle = 'time from kernel enter_state(%s) to firmware mode [kernel time only]' % sysvals.suspendmode >> 4125 rtitle = 'time from firmware mode to return from kernel enter_state(%s) [kernel time only]' % sysvals.suspendmode >> 4126 if(len(testruns) > 1): >> 4127 testdesc = ordinal(data.testnumber+1)+' '+testdesc >> 4128 if(len(data.tLow) == 0): >> 4129 thtml = html_timetotal.format(suspend_time, \ >> 4130 resume_time, testdesc, stitle, rtitle) 4713 else: 4131 else: 4714 wtime = 'TIME !! 4132 thtml = html_timetotal2.format(suspend_time, low_time, \ 4715 thtml += html_wifdesc !! 4133 resume_time, testdesc, stitle, rtitle) 4716 thtml += '</tr>\n</table>\n' !! 4134 devtl.html += thtml 4717 devtl.html += thtml !! 4135 4718 if testfail: 4136 if testfail: 4719 devtl.html += html_fail.forma 4137 devtl.html += html_fail.format(testfail) 4720 4138 4721 # time scale for potentially multiple 4139 # time scale for potentially multiple datasets 4722 t0 = testruns[0].start 4140 t0 = testruns[0].start 4723 tMax = testruns[-1].end 4141 tMax = testruns[-1].end 4724 tTotal = tMax - t0 4142 tTotal = tMax - t0 4725 4143 4726 # determine the maximum number of row 4144 # determine the maximum number of rows we need to draw 4727 fulllist = [] 4145 fulllist = [] 4728 threadlist = [] 4146 threadlist = [] 4729 pscnt = 0 4147 pscnt = 0 4730 devcnt = 0 4148 devcnt = 0 4731 for data in testruns: 4149 for data in testruns: 4732 data.selectTimelineDevices('% 4150 data.selectTimelineDevices('%f', tTotal, sysvals.mindevlen) 4733 for group in data.devicegroup 4151 for group in data.devicegroups: 4734 devlist = [] 4152 devlist = [] 4735 for phase in group: 4153 for phase in group: 4736 for devname i !! 4154 for devname in data.tdevlist[phase]: 4737 d = D 4155 d = DevItem(data.testnumber, phase, data.dmesg[phase]['list'][devname]) 4738 devli 4156 devlist.append(d) 4739 if d. 4157 if d.isa('kth'): 4740 4158 threadlist.append(d) 4741 else: 4159 else: 4742 4160 if d.isa('ps'): 4743 4161 pscnt += 1 4744 4162 else: 4745 4163 devcnt += 1 4746 4164 fulllist.append(d) 4747 if sysvals.mixedphase 4165 if sysvals.mixedphaseheight: 4748 devtl.getPhas 4166 devtl.getPhaseRows(devlist) 4749 if not sysvals.mixedphaseheight: 4167 if not sysvals.mixedphaseheight: 4750 if len(threadlist) > 0 and le 4168 if len(threadlist) > 0 and len(fulllist) > 0: 4751 if pscnt > 0 and devc 4169 if pscnt > 0 and devcnt > 0: 4752 msg = 'user p 4170 msg = 'user processes & device pm callbacks' 4753 elif pscnt > 0: 4171 elif pscnt > 0: 4754 msg = 'user p 4172 msg = 'user processes' 4755 else: 4173 else: 4756 msg = 'device 4174 msg = 'device pm callbacks' 4757 d = testruns[0].addHo 4175 d = testruns[0].addHorizontalDivider(msg, testruns[-1].end) 4758 fulllist.insert(0, d) 4176 fulllist.insert(0, d) 4759 devtl.getPhaseRows(fulllist) 4177 devtl.getPhaseRows(fulllist) 4760 if len(threadlist) > 0: 4178 if len(threadlist) > 0: 4761 d = testruns[0].addHo 4179 d = testruns[0].addHorizontalDivider('asynchronous kernel threads', testruns[-1].end) 4762 threadlist.insert(0, 4180 threadlist.insert(0, d) 4763 devtl.getPhaseRows(th 4181 devtl.getPhaseRows(threadlist, devtl.rows) 4764 devtl.calcTotalRows() 4182 devtl.calcTotalRows() 4765 4183 4766 # draw the full timeline 4184 # draw the full timeline 4767 devtl.createZoomBox(sysvals.suspendmo 4185 devtl.createZoomBox(sysvals.suspendmode, len(testruns)) 4768 for data in testruns: 4186 for data in testruns: 4769 # draw each test run and bloc 4187 # draw each test run and block chronologically 4770 phases = {'suspend':[],'resum 4188 phases = {'suspend':[],'resume':[]} 4771 for phase in data.sortedPhase 4189 for phase in data.sortedPhases(): 4772 if data.dmesg[phase][ 4190 if data.dmesg[phase]['start'] >= data.tSuspended: 4773 phases['resum 4191 phases['resume'].append(phase) 4774 else: 4192 else: 4775 phases['suspe 4193 phases['suspend'].append(phase) 4776 # now draw the actual timelin 4194 # now draw the actual timeline blocks 4777 for dir in phases: 4195 for dir in phases: 4778 # draw suspend and re 4196 # draw suspend and resume blocks separately 4779 bname = '%s%d' % (dir 4197 bname = '%s%d' % (dir[0], data.testnumber) 4780 if dir == 'suspend': 4198 if dir == 'suspend': 4781 m0 = data.sta 4199 m0 = data.start 4782 mMax = data.t 4200 mMax = data.tSuspended 4783 left = '%f' % 4201 left = '%f' % (((m0-t0)*100.0)/tTotal) 4784 else: 4202 else: 4785 m0 = data.tSu 4203 m0 = data.tSuspended 4786 mMax = data.e 4204 mMax = data.end 4787 # in an x2 ru 4205 # in an x2 run, remove any gap between blocks 4788 if len(testru 4206 if len(testruns) > 1 and data.testnumber == 0: 4789 mMax 4207 mMax = testruns[1].start 4790 left = '%f' % 4208 left = '%f' % ((((m0-t0)*100.0)+sysvals.srgap/2)/tTotal) 4791 mTotal = mMax - m0 4209 mTotal = mMax - m0 4792 # if a timeline block 4210 # if a timeline block is 0 length, skip altogether 4793 if mTotal == 0: 4211 if mTotal == 0: 4794 continue 4212 continue 4795 width = '%f' % (((mTo 4213 width = '%f' % (((mTotal*100.0)-sysvals.srgap/2)/tTotal) 4796 devtl.html += devtl.h 4214 devtl.html += devtl.html_tblock.format(bname, left, width, devtl.scaleH) 4797 for b in phases[dir]: 4215 for b in phases[dir]: 4798 # draw the ph 4216 # draw the phase color background 4799 phase = data. 4217 phase = data.dmesg[b] 4800 length = phas 4218 length = phase['end']-phase['start'] 4801 left = '%f' % 4219 left = '%f' % (((phase['start']-m0)*100.0)/mTotal) 4802 width = '%f' 4220 width = '%f' % ((length*100.0)/mTotal) 4803 devtl.html += 4221 devtl.html += devtl.html_phase.format(left, width, \ 4804 '%.3f 4222 '%.3f'%devtl.scaleH, '%.3f'%devtl.bodyH, \ 4805 data. 4223 data.dmesg[b]['color'], '') 4806 for e in data.errorin 4224 for e in data.errorinfo[dir]: 4807 # draw red li 4225 # draw red lines for any kernel errors found 4808 type, t, idx1 4226 type, t, idx1, idx2 = e 4809 id = '%d_%d' 4227 id = '%d_%d' % (idx1, idx2) 4810 right = '%f' 4228 right = '%f' % (((mMax-t)*100.0)/mTotal) 4811 devtl.html += 4229 devtl.html += html_error.format(right, id, type) 4812 for b in phases[dir]: 4230 for b in phases[dir]: 4813 # draw the de 4231 # draw the devices for this phase 4814 phaselist = d 4232 phaselist = data.dmesg[b]['list'] 4815 for d in sort !! 4233 for d in data.tdevlist[b]: 4816 dname !! 4234 name = d 4817 name, !! 4235 drv = '' 4818 drv = !! 4236 dev = phaselist[d] >> 4237 xtraclass = '' >> 4238 xtrainfo = '' >> 4239 xtrastyle = '' 4819 if 'h 4240 if 'htmlclass' in dev: 4820 4241 xtraclass = dev['htmlclass'] 4821 if 'c 4242 if 'color' in dev: 4822 4243 xtrastyle = 'background:%s;' % dev['color'] 4823 if(d 4244 if(d in sysvals.devprops): 4824 4245 name = sysvals.devprops[d].altName(d) 4825 4246 xtraclass = sysvals.devprops[d].xtraClass() 4826 4247 xtrainfo = sysvals.devprops[d].xtraInfo() 4827 elif 4248 elif xtraclass == ' kth': 4828 4249 xtrainfo = ' kernel_thread' 4829 if('d 4250 if('drv' in dev and dev['drv']): 4830 4251 drv = ' {%s}' % dev['drv'] 4831 rowhe 4252 rowheight = devtl.phaseRowHeight(data.testnumber, b, dev['row']) 4832 rowto 4253 rowtop = devtl.phaseRowTop(data.testnumber, b, dev['row']) 4833 top = 4254 top = '%.3f' % (rowtop + devtl.scaleH) 4834 left 4255 left = '%f' % (((dev['start']-m0)*100)/mTotal) 4835 width 4256 width = '%f' % (((dev['end']-dev['start'])*100)/mTotal) 4836 lengt 4257 length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000) 4837 title 4258 title = name+drv+xtrainfo+length 4838 if sy 4259 if sysvals.suspendmode == 'command': 4839 4260 title += sysvals.testcommand 4840 elif 4261 elif xtraclass == ' ps': 4841 4262 if 'suspend' in b: 4842 4263 title += 'pre_suspend_process' 4843 4264 else: 4844 4265 title += 'post_resume_process' 4845 else: 4266 else: 4846 4267 title += b 4847 devtl 4268 devtl.html += devtl.html_device.format(dev['id'], \ 4848 4269 title, left, top, '%.3f'%rowheight, width, \ 4849 !! 4270 d+drv, xtraclass, xtrastyle) 4850 if('c 4271 if('cpuexec' in dev): 4851 4272 for t in sorted(dev['cpuexec']): 4852 4273 start, end = t >> 4274 j = float(dev['cpuexec'][t]) / 5 >> 4275 if j > 1.0: >> 4276 j = 1.0 4853 4277 height = '%.3f' % (rowheight/3) 4854 4278 top = '%.3f' % (rowtop + devtl.scaleH + 2*rowheight/3) 4855 4279 left = '%f' % (((start-m0)*100)/mTotal) 4856 4280 width = '%f' % ((end-start)*100/mTotal) 4857 !! 4281 color = 'rgba(255, 0, 0, %f)' % j 4858 4282 devtl.html += \ 4859 4283 html_cpuexec.format(left, top, height, width, color) 4860 if('s 4284 if('src' not in dev): 4861 4285 continue 4862 # dra 4286 # draw any trace events for this device 4863 for e 4287 for e in dev['src']: 4864 << 4865 << 4866 4288 height = '%.3f' % devtl.rowH 4867 4289 top = '%.3f' % (rowtop + devtl.scaleH + (e.row*devtl.rowH)) 4868 4290 left = '%f' % (((e.time-m0)*100)/mTotal) 4869 4291 width = '%f' % (e.length*100/mTotal) 4870 4292 xtrastyle = '' 4871 4293 if e.color: 4872 4294 xtrastyle = 'background:%s;' % e.color 4873 4295 devtl.html += \ 4874 4296 html_traceevent.format(e.title(), \ 4875 4297 left, top, height, width, e.text(), '', xtrastyle) 4876 # draw the time scale 4298 # draw the time scale, try to make the number of labels readable 4877 devtl.createTimeScale 4299 devtl.createTimeScale(m0, mMax, tTotal, dir) 4878 devtl.html += '</div> 4300 devtl.html += '</div>\n' 4879 4301 4880 # timeline is finished 4302 # timeline is finished 4881 devtl.html += '</div>\n</div>\n' 4303 devtl.html += '</div>\n</div>\n' 4882 4304 4883 # draw a legend which describes the p 4305 # draw a legend which describes the phases by color 4884 if sysvals.suspendmode != 'command': 4306 if sysvals.suspendmode != 'command': 4885 phasedef = testruns[-1].phase 4307 phasedef = testruns[-1].phasedef 4886 devtl.html += '<div class="le 4308 devtl.html += '<div class="legend">\n' 4887 pdelta = 100.0/len(phasedef.k 4309 pdelta = 100.0/len(phasedef.keys()) 4888 pmargin = pdelta / 4.0 4310 pmargin = pdelta / 4.0 4889 for phase in sorted(phasedef, 4311 for phase in sorted(phasedef, key=lambda k:phasedef[k]['order']): 4890 id, p = '', phasedef[ 4312 id, p = '', phasedef[phase] 4891 for word in phase.spl 4313 for word in phase.split('_'): 4892 id += word[0] 4314 id += word[0] 4893 order = '%.2f' % ((p[ 4315 order = '%.2f' % ((p['order'] * pdelta) + pmargin) 4894 name = phase.replace( 4316 name = phase.replace('_', ' ') 4895 devtl.html += devtl.h 4317 devtl.html += devtl.html_legend.format(order, p['color'], name, id) 4896 devtl.html += '</div>\n' 4318 devtl.html += '</div>\n' 4897 4319 4898 hf = open(sysvals.htmlfile, 'w') 4320 hf = open(sysvals.htmlfile, 'w') 4899 addCSS(hf, sysvals, len(testruns), ke 4321 addCSS(hf, sysvals, len(testruns), kerror) 4900 4322 4901 # write the device timeline 4323 # write the device timeline 4902 hf.write(devtl.html) 4324 hf.write(devtl.html) 4903 hf.write('<div id="devicedetailtitle" 4325 hf.write('<div id="devicedetailtitle"></div>\n') 4904 hf.write('<div id="devicedetail" styl 4326 hf.write('<div id="devicedetail" style="display:none;">\n') 4905 # draw the colored boxes for the devi 4327 # draw the colored boxes for the device detail section 4906 for data in testruns: 4328 for data in testruns: 4907 hf.write('<div id="devicedeta 4329 hf.write('<div id="devicedetail%d">\n' % data.testnumber) 4908 pscolor = 'linear-gradient(to 4330 pscolor = 'linear-gradient(to top left, #ccc, #eee)' 4909 hf.write(devtl.html_phaselet. 4331 hf.write(devtl.html_phaselet.format('pre_suspend_process', \ 4910 '0', '0', pscolor)) 4332 '0', '0', pscolor)) 4911 for b in data.sortedPhases(): 4333 for b in data.sortedPhases(): 4912 phase = data.dmesg[b] 4334 phase = data.dmesg[b] 4913 length = phase['end'] 4335 length = phase['end']-phase['start'] 4914 left = '%.3f' % (((ph 4336 left = '%.3f' % (((phase['start']-t0)*100.0)/tTotal) 4915 width = '%.3f' % ((le 4337 width = '%.3f' % ((length*100.0)/tTotal) 4916 hf.write(devtl.html_p 4338 hf.write(devtl.html_phaselet.format(b, left, width, \ 4917 data.dmesg[b] 4339 data.dmesg[b]['color'])) 4918 hf.write(devtl.html_phaselet. 4340 hf.write(devtl.html_phaselet.format('post_resume_process', \ 4919 '0', '0', pscolor)) 4341 '0', '0', pscolor)) 4920 if sysvals.suspendmode == 'co 4342 if sysvals.suspendmode == 'command': 4921 hf.write(devtl.html_p 4343 hf.write(devtl.html_phaselet.format('cmdexec', '0', '0', pscolor)) 4922 hf.write('</div>\n') 4344 hf.write('</div>\n') 4923 hf.write('</div>\n') 4345 hf.write('</div>\n') 4924 4346 4925 # write the ftrace data (callgraph) 4347 # write the ftrace data (callgraph) 4926 if sysvals.cgtest >= 0 and len(testru 4348 if sysvals.cgtest >= 0 and len(testruns) > sysvals.cgtest: 4927 data = testruns[sysvals.cgtes 4349 data = testruns[sysvals.cgtest] 4928 else: 4350 else: 4929 data = testruns[-1] 4351 data = testruns[-1] 4930 if sysvals.usecallgraph: 4352 if sysvals.usecallgraph: 4931 addCallgraphs(sysvals, hf, da 4353 addCallgraphs(sysvals, hf, data) 4932 4354 4933 # add the test log as a hidden div 4355 # add the test log as a hidden div 4934 if sysvals.testlog and sysvals.logmsg 4356 if sysvals.testlog and sysvals.logmsg: 4935 hf.write('<div id="testlog" s 4357 hf.write('<div id="testlog" style="display:none;">\n'+sysvals.logmsg+'</div>\n') 4936 # add the dmesg log as a hidden div 4358 # add the dmesg log as a hidden div 4937 if sysvals.dmesglog and sysvals.dmesg 4359 if sysvals.dmesglog and sysvals.dmesgfile: 4938 hf.write('<div id="dmesglog" 4360 hf.write('<div id="dmesglog" style="display:none;">\n') 4939 lf = sysvals.openlog(sysvals. 4361 lf = sysvals.openlog(sysvals.dmesgfile, 'r') 4940 for line in lf: 4362 for line in lf: 4941 line = line.replace(' 4363 line = line.replace('<', '<').replace('>', '>') 4942 hf.write(line) 4364 hf.write(line) 4943 lf.close() 4365 lf.close() 4944 hf.write('</div>\n') 4366 hf.write('</div>\n') 4945 # add the ftrace log as a hidden div 4367 # add the ftrace log as a hidden div 4946 if sysvals.ftracelog and sysvals.ftra 4368 if sysvals.ftracelog and sysvals.ftracefile: 4947 hf.write('<div id="ftracelog" 4369 hf.write('<div id="ftracelog" style="display:none;">\n') 4948 lf = sysvals.openlog(sysvals. 4370 lf = sysvals.openlog(sysvals.ftracefile, 'r') 4949 for line in lf: 4371 for line in lf: 4950 hf.write(line) 4372 hf.write(line) 4951 lf.close() 4373 lf.close() 4952 hf.write('</div>\n') 4374 hf.write('</div>\n') 4953 4375 4954 # write the footer and close 4376 # write the footer and close 4955 addScriptCode(hf, testruns) 4377 addScriptCode(hf, testruns) 4956 hf.write('</body>\n</html>\n') 4378 hf.write('</body>\n</html>\n') 4957 hf.close() 4379 hf.close() 4958 return True 4380 return True 4959 4381 4960 def addCSS(hf, sv, testcount=1, kerror=False, 4382 def addCSS(hf, sv, testcount=1, kerror=False, extra=''): 4961 kernel = sv.stamp['kernel'] 4383 kernel = sv.stamp['kernel'] 4962 host = sv.hostname[0].upper()+sv.host 4384 host = sv.hostname[0].upper()+sv.hostname[1:] 4963 mode = sv.suspendmode 4385 mode = sv.suspendmode 4964 if sv.suspendmode in suspendmodename: 4386 if sv.suspendmode in suspendmodename: 4965 mode = suspendmodename[sv.sus 4387 mode = suspendmodename[sv.suspendmode] 4966 title = host+' '+mode+' '+kernel 4388 title = host+' '+mode+' '+kernel 4967 4389 4968 # various format changes by flags 4390 # various format changes by flags 4969 cgchk = 'checked' 4391 cgchk = 'checked' 4970 cgnchk = 'not(:checked)' 4392 cgnchk = 'not(:checked)' 4971 if sv.cgexp: 4393 if sv.cgexp: 4972 cgchk = 'not(:checked)' 4394 cgchk = 'not(:checked)' 4973 cgnchk = 'checked' 4395 cgnchk = 'checked' 4974 4396 4975 hoverZ = 'z-index:8;' 4397 hoverZ = 'z-index:8;' 4976 if sv.usedevsrc: 4398 if sv.usedevsrc: 4977 hoverZ = '' 4399 hoverZ = '' 4978 4400 4979 devlistpos = 'absolute' 4401 devlistpos = 'absolute' 4980 if testcount > 1: 4402 if testcount > 1: 4981 devlistpos = 'relative' 4403 devlistpos = 'relative' 4982 4404 4983 scaleTH = 20 4405 scaleTH = 20 4984 if kerror: 4406 if kerror: 4985 scaleTH = 60 4407 scaleTH = 60 4986 4408 4987 # write the html header first (html h 4409 # write the html header first (html head, css code, up to body start) 4988 html_header = '<!DOCTYPE html>\n<html 4410 html_header = '<!DOCTYPE html>\n<html>\n<head>\n\ 4989 <meta http-equiv="content-type" conte 4411 <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\ 4990 <title>'+title+'</title>\n\ 4412 <title>'+title+'</title>\n\ 4991 <style type=\'text/css\'>\n\ 4413 <style type=\'text/css\'>\n\ 4992 body {overflow-y:scroll;}\n\ 4414 body {overflow-y:scroll;}\n\ 4993 .stamp {width:100%;text-align 4415 .stamp {width:100%;text-align:center;background:gray;line-height:30px;color:white;font:25px Arial;}\n\ 4994 .stamp.sysinfo {font:10px Ari 4416 .stamp.sysinfo {font:10px Arial;}\n\ 4995 .callgraph {margin-top:30px;b 4417 .callgraph {margin-top:30px;box-shadow:5px 5px 20px black;}\n\ 4996 .callgraph article * {padding 4418 .callgraph article * {padding-left:28px;}\n\ 4997 h1 {color:black;font:bold 30p 4419 h1 {color:black;font:bold 30px Times;}\n\ 4998 t0 {color:black;font:bold 30p 4420 t0 {color:black;font:bold 30px Times;}\n\ 4999 t1 {color:black;font:30px Tim 4421 t1 {color:black;font:30px Times;}\n\ 5000 t2 {color:black;font:25px Tim 4422 t2 {color:black;font:25px Times;}\n\ 5001 t3 {color:black;font:20px Tim 4423 t3 {color:black;font:20px Times;white-space:nowrap;}\n\ 5002 t4 {color:black;font:bold 30p 4424 t4 {color:black;font:bold 30px Times;line-height:60px;white-space:nowrap;}\n\ 5003 cS {font:bold 13px Times;}\n\ 4425 cS {font:bold 13px Times;}\n\ 5004 table {width:100%;}\n\ 4426 table {width:100%;}\n\ 5005 .gray {background:rgba(80,80, 4427 .gray {background:rgba(80,80,80,0.1);}\n\ 5006 .green {background:rgba(204,2 4428 .green {background:rgba(204,255,204,0.4);}\n\ 5007 .purple {background:rgba(128, 4429 .purple {background:rgba(128,0,128,0.2);}\n\ 5008 .yellow {background:rgba(255, 4430 .yellow {background:rgba(255,255,204,0.4);}\n\ 5009 .blue {background:rgba(169,20 4431 .blue {background:rgba(169,208,245,0.4);}\n\ 5010 .time1 {font:22px Arial;borde 4432 .time1 {font:22px Arial;border:1px solid;}\n\ 5011 .time2 {font:15px Arial;borde 4433 .time2 {font:15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\ 5012 .testfail {font:bold 22px Ari 4434 .testfail {font:bold 22px Arial;color:red;border:1px dashed;}\n\ 5013 td {text-align:center;}\n\ 4435 td {text-align:center;}\n\ 5014 r {color:#500000;font:15px Ta 4436 r {color:#500000;font:15px Tahoma;}\n\ 5015 n {color:#505050;font:15px Ta 4437 n {color:#505050;font:15px Tahoma;}\n\ 5016 .tdhl {color:red;}\n\ 4438 .tdhl {color:red;}\n\ 5017 .hide {display:none;}\n\ 4439 .hide {display:none;}\n\ 5018 .pf {display:none;}\n\ 4440 .pf {display:none;}\n\ 5019 .pf:'+cgchk+' + label {backgr 4441 .pf:'+cgchk+' + label {background:url(\'data:image/svg+xml;utf,<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" version="1.1"><circle cx="9" cy="9" r="8" stroke="black" stroke-width="1" fill="white"/><rect x="4" y="8" width="10" height="2" style="fill:black;stroke-width:0"/><rect x="8" y="4" width="2" height="10" style="fill:black;stroke-width:0"/></svg>\') no-repeat left center;}\n\ 5020 .pf:'+cgnchk+' ~ label {backg 4442 .pf:'+cgnchk+' ~ label {background:url(\'data:image/svg+xml;utf,<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" version="1.1"><circle cx="9" cy="9" r="8" stroke="black" stroke-width="1" fill="white"/><rect x="4" y="8" width="10" height="2" style="fill:black;stroke-width:0"/></svg>\') no-repeat left center;}\n\ 5021 .pf:'+cgchk+' ~ *:not(:nth-ch 4443 .pf:'+cgchk+' ~ *:not(:nth-child(2)) {display:none;}\n\ 5022 .zoombox {position:relative;w 4444 .zoombox {position:relative;width:100%;overflow-x:scroll;-webkit-user-select:none;-moz-user-select:none;user-select:none;}\n\ 5023 .timeline {position:relative; 4445 .timeline {position:relative;font-size:14px;cursor:pointer;width:100%; overflow:hidden;background:linear-gradient(#cccccc, white);}\n\ 5024 .thread {position:absolute;he 4446 .thread {position:absolute;height:0%;overflow:hidden;z-index:7;line-height:30px;font-size:14px;border:1px solid;text-align:center;white-space:nowrap;}\n\ 5025 .thread.ps {border-radius:3px 4447 .thread.ps {border-radius:3px;background:linear-gradient(to top, #ccc, #eee);}\n\ 5026 .thread:hover {background:whi 4448 .thread:hover {background:white;border:1px solid red;'+hoverZ+'}\n\ 5027 .thread.sec,.thread.sec:hover 4449 .thread.sec,.thread.sec:hover {background:black;border:0;color:white;line-height:15px;font-size:10px;}\n\ 5028 .hover {background:white;bord 4450 .hover {background:white;border:1px solid red;'+hoverZ+'}\n\ 5029 .hover.sync {background:white 4451 .hover.sync {background:white;}\n\ 5030 .hover.bg,.hover.kth,.hover.s 4452 .hover.bg,.hover.kth,.hover.sync,.hover.ps {background:white;}\n\ 5031 .jiffie {position:absolute;po 4453 .jiffie {position:absolute;pointer-events: none;z-index:8;}\n\ 5032 .traceevent {position:absolut 4454 .traceevent {position:absolute;font-size:10px;z-index:7;overflow:hidden;color:black;text-align:center;white-space:nowrap;border-radius:5px;border:1px solid black;background:linear-gradient(to bottom right,#CCC,#969696);}\n\ 5033 .traceevent:hover {color:whit 4455 .traceevent:hover {color:white;font-weight:bold;border:1px solid white;}\n\ 5034 .phase {position:absolute;ove 4456 .phase {position:absolute;overflow:hidden;border:0px;text-align:center;}\n\ 5035 .phaselet {float:left;overflo 4457 .phaselet {float:left;overflow:hidden;border:0px;text-align:center;min-height:100px;font-size:24px;}\n\ 5036 .t {position:absolute;line-he 4458 .t {position:absolute;line-height:'+('%d'%scaleTH)+'px;pointer-events:none;top:0;height:100%;border-right:1px solid black;z-index:6;}\n\ 5037 .err {position:absolute;top:0 4459 .err {position:absolute;top:0%;height:100%;border-right:3px solid red;color:red;font:bold 14px Times;line-height:18px;}\n\ 5038 .legend {position:relative; w 4460 .legend {position:relative; width:100%; height:40px; text-align:center;margin-bottom:20px}\n\ 5039 .legend .square {position:abs 4461 .legend .square {position:absolute;cursor:pointer;top:10px; width:0px;height:20px;border:1px solid;padding-left:20px;}\n\ 5040 button {height:40px;width:200 4462 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\ 5041 .btnfmt {position:relative;fl 4463 .btnfmt {position:relative;float:right;height:25px;width:auto;margin-top:3px;margin-bottom:0;font-size:10px;text-align:center;}\n\ 5042 .devlist {position:'+devlistp 4464 .devlist {position:'+devlistpos+';width:190px;}\n\ 5043 a:link {color:white;text-deco 4465 a:link {color:white;text-decoration:none;}\n\ 5044 a:visited {color:white;}\n\ 4466 a:visited {color:white;}\n\ 5045 a:hover {color:white;}\n\ 4467 a:hover {color:white;}\n\ 5046 a:active {color:white;}\n\ 4468 a:active {color:white;}\n\ 5047 .version {position:relative;f 4469 .version {position:relative;float:left;color:white;font-size:10px;line-height:30px;margin-left:10px;}\n\ 5048 #devicedetail {min-height:100 4470 #devicedetail {min-height:100px;box-shadow:5px 5px 20px black;}\n\ 5049 .tblock {position:absolute;he 4471 .tblock {position:absolute;height:100%;background:#ddd;}\n\ 5050 .tback {position:absolute;wid 4472 .tback {position:absolute;width:100%;background:linear-gradient(#ccc, #ddd);}\n\ 5051 .bg {z-index:1;}\n\ 4473 .bg {z-index:1;}\n\ 5052 '+extra+'\ 4474 '+extra+'\ 5053 </style>\n</head>\n<body>\n' 4475 </style>\n</head>\n<body>\n' 5054 hf.write(html_header) 4476 hf.write(html_header) 5055 4477 5056 # Function: addScriptCode 4478 # Function: addScriptCode 5057 # Description: 4479 # Description: 5058 # Adds the javascript code to the outp 4480 # Adds the javascript code to the output html 5059 # Arguments: 4481 # Arguments: 5060 # hf: the open html file pointer 4482 # hf: the open html file pointer 5061 # testruns: array of Data objects from 4483 # testruns: array of Data objects from parseKernelLog or parseTraceLog 5062 def addScriptCode(hf, testruns): 4484 def addScriptCode(hf, testruns): 5063 t0 = testruns[0].start * 1000 4485 t0 = testruns[0].start * 1000 5064 tMax = testruns[-1].end * 1000 4486 tMax = testruns[-1].end * 1000 5065 hf.write('<script type="text/javascri << 5066 # create an array in javascript memor 4487 # create an array in javascript memory with the device details 5067 detail = ' var devtable = [];\n' 4488 detail = ' var devtable = [];\n' 5068 for data in testruns: 4489 for data in testruns: 5069 topo = data.deviceTopology() 4490 topo = data.deviceTopology() 5070 detail += ' devtable[%d] 4491 detail += ' devtable[%d] = "%s";\n' % (data.testnumber, topo) 5071 detail += ' var bounds = [%f,%f]; 4492 detail += ' var bounds = [%f,%f];\n' % (t0, tMax) 5072 # add the code which will manipulate 4493 # add the code which will manipulate the data in the browser 5073 hf.write(detail); !! 4494 script_code = \ 5074 script_code = r""" var resolutio !! 4495 '<script type="text/javascript">\n'+detail+\ 5075 var dragval = [0, 0]; !! 4496 ' var resolution = -1;\n'\ 5076 function redrawTimescale(t0, tMax, tS !! 4497 ' var dragval = [0, 0];\n'\ 5077 var rline = '<div class="t" s !! 4498 ' function redrawTimescale(t0, tMax, tS) {\n'\ 5078 var tTotal = tMax - t0; !! 4499 ' var rline = \'<div class="t" style="left:0;border-left:1px solid black;border-right:0;">\';\n'\ 5079 var list = document.getElemen !! 4500 ' var tTotal = tMax - t0;\n'\ 5080 for (var i = 0; i < list.leng !! 4501 ' var list = document.getElementsByClassName("tblock");\n'\ 5081 var timescale = list[ !! 4502 ' for (var i = 0; i < list.length; i++) {\n'\ 5082 var m0 = t0 + (tTotal !! 4503 ' var timescale = list[i].getElementsByClassName("timescale")[0];\n'\ 5083 var mTotal = tTotal*p !! 4504 ' var m0 = t0 + (tTotal*parseFloat(list[i].style.left)/100);\n'\ 5084 var mMax = m0 + mTota !! 4505 ' var mTotal = tTotal*parseFloat(list[i].style.width)/100;\n'\ 5085 var html = ""; !! 4506 ' var mMax = m0 + mTotal;\n'\ 5086 var divTotal = Math.f !! 4507 ' var html = "";\n'\ 5087 if(divTotal > 1000) c !! 4508 ' var divTotal = Math.floor(mTotal/tS) + 1;\n'\ 5088 var divEdge = (mTotal !! 4509 ' if(divTotal > 1000) continue;\n'\ 5089 var pos = 0.0, val = !! 4510 ' var divEdge = (mTotal - tS*(divTotal-1))*100/mTotal;\n'\ 5090 for (var j = 0; j < d !! 4511 ' var pos = 0.0, val = 0.0;\n'\ 5091 var htmlline !! 4512 ' for (var j = 0; j < divTotal; j++) {\n'\ 5092 var mode = li !! 4513 ' var htmlline = "";\n'\ 5093 if(mode == "s !! 4514 ' var mode = list[i].id[5];\n'\ 5094 pos = !! 4515 ' if(mode == "s") {\n'\ 5095 val = !! 4516 ' pos = 100 - (((j)*tS*100)/mTotal) - divEdge;\n'\ 5096 if(j !! 4517 ' val = (j-divTotal+1)*tS;\n'\ 5097 !! 4518 ' if(j == divTotal - 1)\n'\ 5098 else !! 4519 ' htmlline = \'<div class="t" style="right:\'+pos+\'%"><cS>S→</cS></div>\';\n'\ 5099 !! 4520 ' else\n'\ 5100 } else { !! 4521 ' htmlline = \'<div class="t" style="right:\'+pos+\'%">\'+val+\'ms</div>\';\n'\ 5101 pos = !! 4522 ' } else {\n'\ 5102 val = !! 4523 ' pos = 100 - (((j)*tS*100)/mTotal);\n'\ 5103 htmll !! 4524 ' val = (j)*tS;\n'\ 5104 if(j !! 4525 ' htmlline = \'<div class="t" style="right:\'+pos+\'%">\'+val+\'ms</div>\';\n'\ 5105 !! 4526 ' if(j == 0)\n'\ 5106 !! 4527 ' if(mode == "r")\n'\ 5107 !! 4528 ' htmlline = rline+"<cS>←R</cS></div>";\n'\ 5108 !! 4529 ' else\n'\ 5109 } !! 4530 ' htmlline = rline+"<cS>0ms</div>";\n'\ 5110 html += htmll !! 4531 ' }\n'\ 5111 } !! 4532 ' html += htmlline;\n'\ 5112 timescale.innerHTML = !! 4533 ' }\n'\ 5113 } !! 4534 ' timescale.innerHTML = html;\n'\ 5114 } !! 4535 ' }\n'\ 5115 function zoomTimeline() { !! 4536 ' }\n'\ 5116 var dmesg = document.getEleme !! 4537 ' function zoomTimeline() {\n'\ 5117 var zoombox = document.getEle !! 4538 ' var dmesg = document.getElementById("dmesg");\n'\ 5118 var left = zoombox.scrollLeft !! 4539 ' var zoombox = document.getElementById("dmesgzoombox");\n'\ 5119 var val = parseFloat(dmesg.st !! 4540 ' var left = zoombox.scrollLeft;\n'\ 5120 var newval = 100; !! 4541 ' var val = parseFloat(dmesg.style.width);\n'\ 5121 var sh = window.outerWidth / !! 4542 ' var newval = 100;\n'\ 5122 if(this.id == "zoomin") { !! 4543 ' var sh = window.outerWidth / 2;\n'\ 5123 newval = val * 1.2; !! 4544 ' if(this.id == "zoomin") {\n'\ 5124 if(newval > 910034) n !! 4545 ' newval = val * 1.2;\n'\ 5125 dmesg.style.width = n !! 4546 ' if(newval > 910034) newval = 910034;\n'\ 5126 zoombox.scrollLeft = !! 4547 ' dmesg.style.width = newval+"%";\n'\ 5127 } else if (this.id == "zoomou !! 4548 ' zoombox.scrollLeft = ((left + sh) * newval / val) - sh;\n'\ 5128 newval = val / 1.2; !! 4549 ' } else if (this.id == "zoomout") {\n'\ 5129 if(newval < 100) newv !! 4550 ' newval = val / 1.2;\n'\ 5130 dmesg.style.width = n !! 4551 ' if(newval < 100) newval = 100;\n'\ 5131 zoombox.scrollLeft = !! 4552 ' dmesg.style.width = newval+"%";\n'\ 5132 } else { !! 4553 ' zoombox.scrollLeft = ((left + sh) * newval / val) - sh;\n'\ 5133 zoombox.scrollLeft = !! 4554 ' } else {\n'\ 5134 dmesg.style.width = " !! 4555 ' zoombox.scrollLeft = 0;\n'\ 5135 } !! 4556 ' dmesg.style.width = "100%";\n'\ 5136 var tS = [10000, 5000, 2000, !! 4557 ' }\n'\ 5137 var t0 = bounds[0]; !! 4558 ' var tS = [10000, 5000, 2000, 1000, 500, 200, 100, 50, 20, 10, 5, 2, 1];\n'\ 5138 var tMax = bounds[1]; !! 4559 ' var t0 = bounds[0];\n'\ 5139 var tTotal = tMax - t0; !! 4560 ' var tMax = bounds[1];\n'\ 5140 var wTotal = tTotal * 100.0 / !! 4561 ' var tTotal = tMax - t0;\n'\ 5141 var idx = 7*window.innerWidth !! 4562 ' var wTotal = tTotal * 100.0 / newval;\n'\ 5142 for(var i = 0; (i < tS.length !! 4563 ' var idx = 7*window.innerWidth/1100;\n'\ 5143 if(i >= tS.length) i = tS.len !! 4564 ' for(var i = 0; (i < tS.length)&&((wTotal / tS[i]) < idx); i++);\n'\ 5144 if(tS[i] == resolution) retur !! 4565 ' if(i >= tS.length) i = tS.length - 1;\n'\ 5145 resolution = tS[i]; !! 4566 ' if(tS[i] == resolution) return;\n'\ 5146 redrawTimescale(t0, tMax, tS[ !! 4567 ' resolution = tS[i];\n'\ 5147 } !! 4568 ' redrawTimescale(t0, tMax, tS[i]);\n'\ 5148 function deviceName(title) { !! 4569 ' }\n'\ 5149 var name = title.slice(0, tit !! 4570 ' function deviceName(title) {\n'\ 5150 return name; !! 4571 ' var name = title.slice(0, title.indexOf(" ("));\n'\ 5151 } !! 4572 ' return name;\n'\ 5152 function deviceHover() { !! 4573 ' }\n'\ 5153 var name = deviceName(this.ti !! 4574 ' function deviceHover() {\n'\ 5154 var dmesg = document.getEleme !! 4575 ' var name = deviceName(this.title);\n'\ 5155 var dev = dmesg.getElementsBy !! 4576 ' var dmesg = document.getElementById("dmesg");\n'\ 5156 var cpu = -1; !! 4577 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 5157 if(name.match("CPU_ON\[[0-9]* !! 4578 ' var cpu = -1;\n'\ 5158 cpu = parseInt(name.s !! 4579 ' if(name.match("CPU_ON\[[0-9]*\]"))\n'\ 5159 else if(name.match("CPU_OFF\[ !! 4580 ' cpu = parseInt(name.slice(7));\n'\ 5160 cpu = parseInt(name.s !! 4581 ' else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\ 5161 for (var i = 0; i < dev.lengt !! 4582 ' cpu = parseInt(name.slice(8));\n'\ 5162 dname = deviceName(de !! 4583 ' for (var i = 0; i < dev.length; i++) {\n'\ 5163 var cname = dev[i].cl !! 4584 ' dname = deviceName(dev[i].title);\n'\ 5164 if((cpu >= 0 && dname !! 4585 ' var cname = dev[i].className.slice(dev[i].className.indexOf("thread"));\n'\ 5165 (name == dnam !! 4586 ' if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\ 5166 { !! 4587 ' (name == dname))\n'\ 5167 dev[i].classN !! 4588 ' {\n'\ 5168 } else { !! 4589 ' dev[i].className = "hover "+cname;\n'\ 5169 dev[i].classN !! 4590 ' } else {\n'\ 5170 } !! 4591 ' dev[i].className = cname;\n'\ 5171 } !! 4592 ' }\n'\ 5172 } !! 4593 ' }\n'\ 5173 function deviceUnhover() { !! 4594 ' }\n'\ 5174 var dmesg = document.getEleme !! 4595 ' function deviceUnhover() {\n'\ 5175 var dev = dmesg.getElementsBy !! 4596 ' var dmesg = document.getElementById("dmesg");\n'\ 5176 for (var i = 0; i < dev.lengt !! 4597 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 5177 dev[i].className = de !! 4598 ' for (var i = 0; i < dev.length; i++) {\n'\ 5178 } !! 4599 ' dev[i].className = dev[i].className.slice(dev[i].className.indexOf("thread"));\n'\ 5179 } !! 4600 ' }\n'\ 5180 function deviceTitle(title, total, cp !! 4601 ' }\n'\ 5181 var prefix = "Total"; !! 4602 ' function deviceTitle(title, total, cpu) {\n'\ 5182 if(total.length > 3) { !! 4603 ' var prefix = "Total";\n'\ 5183 prefix = "Average"; !! 4604 ' if(total.length > 3) {\n'\ 5184 total[1] = (total[1]+ !! 4605 ' prefix = "Average";\n'\ 5185 total[2] = (total[2]+ !! 4606 ' total[1] = (total[1]+total[3])/2;\n'\ 5186 } !! 4607 ' total[2] = (total[2]+total[4])/2;\n'\ 5187 var devtitle = document.getEl !! 4608 ' }\n'\ 5188 var name = deviceName(title); !! 4609 ' var devtitle = document.getElementById("devicedetailtitle");\n'\ 5189 if(cpu >= 0) name = "CPU"+cpu !! 4610 ' var name = deviceName(title);\n'\ 5190 var driver = ""; !! 4611 ' if(cpu >= 0) name = "CPU"+cpu;\n'\ 5191 var tS = "<t2>(</t2>"; !! 4612 ' var driver = "";\n'\ 5192 var tR = "<t2>)</t2>"; !! 4613 ' var tS = "<t2>(</t2>";\n'\ 5193 if(total[1] > 0) !! 4614 ' var tR = "<t2>)</t2>";\n'\ 5194 tS = "<t2>("+prefix+" !! 4615 ' if(total[1] > 0)\n'\ 5195 if(total[2] > 0) !! 4616 ' tS = "<t2>("+prefix+" Suspend:</t2><t0> "+total[1].toFixed(3)+" ms</t0> ";\n'\ 5196 tR = " <t2>"+prefix+" !! 4617 ' if(total[2] > 0)\n'\ 5197 var s = title.indexOf("{"); !! 4618 ' tR = " <t2>"+prefix+" Resume:</t2><t0> "+total[2].toFixed(3)+" ms<t2>)</t2></t0>";\n'\ 5198 var e = title.indexOf("}"); !! 4619 ' var s = title.indexOf("{");\n'\ 5199 if((s >= 0) && (e >= 0)) !! 4620 ' var e = title.indexOf("}");\n'\ 5200 driver = title.slice(< !! 4621 ' if((s >= 0) && (e >= 0))\n'\ 5201 if(total[1] > 0 && total[2] > !! 4622 ' driver = title.slice(s+1, e) + " <t1>@</t1> ";\n'\ 5202 devtitle.innerHTML = !! 4623 ' if(total[1] > 0 && total[2] > 0)\n'\ 5203 else !! 4624 ' devtitle.innerHTML = "<t0>"+driver+name+"</t0> "+tS+tR;\n'\ 5204 devtitle.innerHTML = !! 4625 ' else\n'\ 5205 return name; !! 4626 ' devtitle.innerHTML = "<t0>"+title+"</t0>";\n'\ 5206 } !! 4627 ' return name;\n'\ 5207 function deviceDetail() { !! 4628 ' }\n'\ 5208 var devinfo = document.getEle !! 4629 ' function deviceDetail() {\n'\ 5209 devinfo.style.display = "bloc !! 4630 ' var devinfo = document.getElementById("devicedetail");\n'\ 5210 var name = deviceName(this.ti !! 4631 ' devinfo.style.display = "block";\n'\ 5211 var cpu = -1; !! 4632 ' var name = deviceName(this.title);\n'\ 5212 if(name.match("CPU_ON\[[0-9]* !! 4633 ' var cpu = -1;\n'\ 5213 cpu = parseInt(name.s !! 4634 ' if(name.match("CPU_ON\[[0-9]*\]"))\n'\ 5214 else if(name.match("CPU_OFF\[ !! 4635 ' cpu = parseInt(name.slice(7));\n'\ 5215 cpu = parseInt(name.s !! 4636 ' else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\ 5216 var dmesg = document.getEleme !! 4637 ' cpu = parseInt(name.slice(8));\n'\ 5217 var dev = dmesg.getElementsBy !! 4638 ' var dmesg = document.getElementById("dmesg");\n'\ 5218 var idlist = []; !! 4639 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 5219 var pdata = [[]]; !! 4640 ' var idlist = [];\n'\ 5220 if(document.getElementById("d !! 4641 ' var pdata = [[]];\n'\ 5221 pdata = [[], []]; !! 4642 ' if(document.getElementById("devicedetail1"))\n'\ 5222 var pd = pdata[0]; !! 4643 ' pdata = [[], []];\n'\ 5223 var total = [0.0, 0.0, 0.0]; !! 4644 ' var pd = pdata[0];\n'\ 5224 for (var i = 0; i < dev.lengt !! 4645 ' var total = [0.0, 0.0, 0.0];\n'\ 5225 dname = deviceName(de !! 4646 ' for (var i = 0; i < dev.length; i++) {\n'\ 5226 if((cpu >= 0 && dname !! 4647 ' dname = deviceName(dev[i].title);\n'\ 5227 (name == dnam !! 4648 ' if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\ 5228 { !! 4649 ' (name == dname))\n'\ 5229 idlist[idlist !! 4650 ' {\n'\ 5230 var tidx = 1; !! 4651 ' idlist[idlist.length] = dev[i].id;\n'\ 5231 if(dev[i].id[ !! 4652 ' var tidx = 1;\n'\ 5232 pd = !! 4653 ' if(dev[i].id[0] == "a") {\n'\ 5233 } else { !! 4654 ' pd = pdata[0];\n'\ 5234 if(pd !! 4655 ' } else {\n'\ 5235 if(to !! 4656 ' if(pdata.length == 1) pdata[1] = [];\n'\ 5236 pd = !! 4657 ' if(total.length == 3) total[3]=total[4]=0.0;\n'\ 5237 tidx !! 4658 ' pd = pdata[1];\n'\ 5238 } !! 4659 ' tidx = 3;\n'\ 5239 var info = de !! 4660 ' }\n'\ 5240 var pname = i !! 4661 ' var info = dev[i].title.split(" ");\n'\ 5241 pd[pname] = p !! 4662 ' var pname = info[info.length-1];\n'\ 5242 total[0] += p !! 4663 ' pd[pname] = parseFloat(info[info.length-3].slice(1));\n'\ 5243 if(pname.inde !! 4664 ' total[0] += pd[pname];\n'\ 5244 total !! 4665 ' if(pname.indexOf("suspend") >= 0)\n'\ 5245 else !! 4666 ' total[tidx] += pd[pname];\n'\ 5246 total !! 4667 ' else\n'\ 5247 } !! 4668 ' total[tidx+1] += pd[pname];\n'\ 5248 } !! 4669 ' }\n'\ 5249 var devname = deviceTitle(thi !! 4670 ' }\n'\ 5250 var left = 0.0; !! 4671 ' var devname = deviceTitle(this.title, total, cpu);\n'\ 5251 for (var t = 0; t < pdata.len !! 4672 ' var left = 0.0;\n'\ 5252 pd = pdata[t]; !! 4673 ' for (var t = 0; t < pdata.length; t++) {\n'\ 5253 devinfo = document.ge !! 4674 ' pd = pdata[t];\n'\ 5254 var phases = devinfo. !! 4675 ' devinfo = document.getElementById("devicedetail"+t);\n'\ 5255 for (var i = 0; i < p !! 4676 ' var phases = devinfo.getElementsByClassName("phaselet");\n'\ 5256 if(phases[i]. !! 4677 ' for (var i = 0; i < phases.length; i++) {\n'\ 5257 var w !! 4678 ' if(phases[i].id in pd) {\n'\ 5258 var f !! 4679 ' var w = 100.0*pd[phases[i].id]/total[0];\n'\ 5259 if(w !! 4680 ' var fs = 32;\n'\ 5260 var f !! 4681 ' if(w < 8) fs = 4*w | 0;\n'\ 5261 phase !! 4682 ' var fs2 = fs*3/4;\n'\ 5262 phase !! 4683 ' phases[i].style.width = w+"%";\n'\ 5263 phase !! 4684 ' phases[i].style.left = left+"%";\n'\ 5264 left !! 4685 ' phases[i].title = phases[i].id+" "+pd[phases[i].id]+" ms";\n'\ 5265 var t !! 4686 ' left += w;\n'\ 5266 var p !! 4687 ' var time = "<t4 style=\\"font-size:"+fs+"px\\">"+pd[phases[i].id]+" ms<br></t4>";\n'\ 5267 phase !! 4688 ' var pname = "<t3 style=\\"font-size:"+fs2+"px\\">"+phases[i].id.replace(new RegExp("_", "g"), " ")+"</t3>";\n'\ 5268 } else { !! 4689 ' phases[i].innerHTML = time+pname;\n'\ 5269 phase !! 4690 ' } else {\n'\ 5270 phase !! 4691 ' phases[i].style.width = "0%";\n'\ 5271 } !! 4692 ' phases[i].style.left = left+"%";\n'\ 5272 } !! 4693 ' }\n'\ 5273 } !! 4694 ' }\n'\ 5274 if(typeof devstats !== 'undef !! 4695 ' }\n'\ 5275 callDetail(this.id, t !! 4696 ' if(typeof devstats !== \'undefined\')\n'\ 5276 var cglist = document.getElem !! 4697 ' callDetail(this.id, this.title);\n'\ 5277 if(!cglist) return; !! 4698 ' var cglist = document.getElementById("callgraphs");\n'\ 5278 var cg = cglist.getElementsBy !! 4699 ' if(!cglist) return;\n'\ 5279 if(cg.length < 10) return; !! 4700 ' var cg = cglist.getElementsByClassName("atop");\n'\ 5280 for (var i = 0; i < cg.length !! 4701 ' if(cg.length < 10) return;\n'\ 5281 cgid = cg[i].id.split !! 4702 ' for (var i = 0; i < cg.length; i++) {\n'\ 5282 if(idlist.indexOf(cgi !! 4703 ' cgid = cg[i].id.split("x")[0]\n'\ 5283 cg[i].style.d !! 4704 ' if(idlist.indexOf(cgid) >= 0) {\n'\ 5284 } else { !! 4705 ' cg[i].style.display = "block";\n'\ 5285 cg[i].style.d !! 4706 ' } else {\n'\ 5286 } !! 4707 ' cg[i].style.display = "none";\n'\ 5287 } !! 4708 ' }\n'\ 5288 } !! 4709 ' }\n'\ 5289 function callDetail(devid, devtitle) !! 4710 ' }\n'\ 5290 if(!(devid in devstats) || de !! 4711 ' function callDetail(devid, devtitle) {\n'\ 5291 return; !! 4712 ' if(!(devid in devstats) || devstats[devid].length < 1)\n'\ 5292 var list = devstats[devid]; !! 4713 ' return;\n'\ 5293 var tmp = devtitle.split(" ") !! 4714 ' var list = devstats[devid];\n'\ 5294 var name = tmp[0], phase = tm !! 4715 ' var tmp = devtitle.split(" ");\n'\ 5295 var dd = document.getElementB !! 4716 ' var name = tmp[0], phase = tmp[tmp.length-1];\n'\ 5296 var total = parseFloat(tmp[1] !! 4717 ' var dd = document.getElementById(phase);\n'\ 5297 var mlist = []; !! 4718 ' var total = parseFloat(tmp[1].slice(1));\n'\ 5298 var maxlen = 0; !! 4719 ' var mlist = [];\n'\ 5299 var info = [] !! 4720 ' var maxlen = 0;\n'\ 5300 for(var i in list) { !! 4721 ' var info = []\n'\ 5301 if(list[i][0] == "@") !! 4722 ' for(var i in list) {\n'\ 5302 info = list[i !! 4723 ' if(list[i][0] == "@") {\n'\ 5303 continue; !! 4724 ' info = list[i].split("|");\n'\ 5304 } !! 4725 ' continue;\n'\ 5305 var tmp = list[i].spl !! 4726 ' }\n'\ 5306 var t = parseFloat(tm !! 4727 ' var tmp = list[i].split("|");\n'\ 5307 var p = (t*100.0/tota !! 4728 ' var t = parseFloat(tmp[0]), f = tmp[1], c = parseInt(tmp[2]);\n'\ 5308 mlist[mlist.length] = !! 4729 ' var p = (t*100.0/total).toFixed(2);\n'\ 5309 if(f.length > maxlen) !! 4730 ' mlist[mlist.length] = [f, c, t.toFixed(2), p+"%"];\n'\ 5310 maxlen = f.le !! 4731 ' if(f.length > maxlen)\n'\ 5311 } !! 4732 ' maxlen = f.length;\n'\ 5312 var pad = 5; !! 4733 ' }\n'\ 5313 if(mlist.length == 0) pad = 3 !! 4734 ' var pad = 5;\n'\ 5314 var html = '<div style="paddi !! 4735 ' if(mlist.length == 0) pad = 30;\n'\ 5315 if(info.length > 2) !! 4736 ' var html = \'<div style="padding-top:\'+pad+\'px"><t3> <b>\'+name+\':</b>\';\n'\ 5316 html += " start=<b>"+ !! 4737 ' if(info.length > 2)\n'\ 5317 if(info.length > 3) !! 4738 ' html += " start=<b>"+info[1]+"</b>, end=<b>"+info[2]+"</b>";\n'\ 5318 html += ", length<i>( !! 4739 ' if(info.length > 3)\n'\ 5319 if(info.length > 4) !! 4740 ' html += ", length<i>(w/o overhead)</i>=<b>"+info[3]+" ms</b>";\n'\ 5320 html += ", return=<b> !! 4741 ' if(info.length > 4)\n'\ 5321 html += "</t3></div>"; !! 4742 ' html += ", return=<b>"+info[4]+"</b>";\n'\ 5322 if(mlist.length > 0) { !! 4743 ' html += "</t3></div>";\n'\ 5323 html += '<table class !! 4744 ' if(mlist.length > 0) {\n'\ 5324 for(var i in mlist) !! 4745 ' html += \'<table class=fstat style="padding-top:\'+(maxlen*5)+\'px;"><tr><th>Function</th>\';\n'\ 5325 html += "<td !! 4746 ' for(var i in mlist)\n'\ 5326 html += "</tr><tr><th !! 4747 ' html += "<td class=vt>"+mlist[i][0]+"</td>";\n'\ 5327 for(var i in mlist) !! 4748 ' html += "</tr><tr><th>Calls</th>";\n'\ 5328 html += "<td> !! 4749 ' for(var i in mlist)\n'\ 5329 html += "</tr><tr><th !! 4750 ' html += "<td>"+mlist[i][1]+"</td>";\n'\ 5330 for(var i in mlist) !! 4751 ' html += "</tr><tr><th>Time(ms)</th>";\n'\ 5331 html += "<td> !! 4752 ' for(var i in mlist)\n'\ 5332 html += "</tr><tr><th !! 4753 ' html += "<td>"+mlist[i][2]+"</td>";\n'\ 5333 for(var i in mlist) !! 4754 ' html += "</tr><tr><th>Percent</th>";\n'\ 5334 html += "<td> !! 4755 ' for(var i in mlist)\n'\ 5335 html += "</tr></table !! 4756 ' html += "<td>"+mlist[i][3]+"</td>";\n'\ 5336 } !! 4757 ' html += "</tr></table>";\n'\ 5337 dd.innerHTML = html; !! 4758 ' }\n'\ 5338 var height = (maxlen*5)+100; !! 4759 ' dd.innerHTML = html;\n'\ 5339 dd.style.height = height+"px" !! 4760 ' var height = (maxlen*5)+100;\n'\ 5340 document.getElementById("devi !! 4761 ' dd.style.height = height+"px";\n'\ 5341 } !! 4762 ' document.getElementById("devicedetail").style.height = height+"px";\n'\ 5342 function callSelect() { !! 4763 ' }\n'\ 5343 var cglist = document.getElem !! 4764 ' function callSelect() {\n'\ 5344 if(!cglist) return; !! 4765 ' var cglist = document.getElementById("callgraphs");\n'\ 5345 var cg = cglist.getElementsBy !! 4766 ' if(!cglist) return;\n'\ 5346 for (var i = 0; i < cg.length !! 4767 ' var cg = cglist.getElementsByClassName("atop");\n'\ 5347 if(this.id == cg[i].i !! 4768 ' for (var i = 0; i < cg.length; i++) {\n'\ 5348 cg[i].style.d !! 4769 ' if(this.id == cg[i].id) {\n'\ 5349 } else { !! 4770 ' cg[i].style.display = "block";\n'\ 5350 cg[i].style.d !! 4771 ' } else {\n'\ 5351 } !! 4772 ' cg[i].style.display = "none";\n'\ 5352 } !! 4773 ' }\n'\ 5353 } !! 4774 ' }\n'\ 5354 function devListWindow(e) { !! 4775 ' }\n'\ 5355 var win = window.open(); !! 4776 ' function devListWindow(e) {\n'\ 5356 var html = "<title>"+e.target !! 4777 ' var win = window.open();\n'\ 5357 "<style type=\"text/c !! 4778 ' var html = "<title>"+e.target.innerHTML+"</title>"+\n'\ 5358 " ul {list-style-ty !! 4779 ' "<style type=\\"text/css\\">"+\n'\ 5359 "</style>" !! 4780 ' " ul {list-style-type:circle;padding-left:10px;margin-left:10px;}"+\n'\ 5360 var dt = devtable[0]; !! 4781 ' "</style>"\n'\ 5361 if(e.target.id != "devlist1") !! 4782 ' var dt = devtable[0];\n'\ 5362 dt = devtable[1]; !! 4783 ' if(e.target.id != "devlist1")\n'\ 5363 win.document.write(html+dt); !! 4784 ' dt = devtable[1];\n'\ 5364 } !! 4785 ' win.document.write(html+dt);\n'\ 5365 function errWindow() { !! 4786 ' }\n'\ 5366 var range = this.id.split("_" !! 4787 ' function errWindow() {\n'\ 5367 var idx1 = parseInt(range[0]) !! 4788 ' var range = this.id.split("_");\n'\ 5368 var idx2 = parseInt(range[1]) !! 4789 ' var idx1 = parseInt(range[0]);\n'\ 5369 var win = window.open(); !! 4790 ' var idx2 = parseInt(range[1]);\n'\ 5370 var log = document.getElement !! 4791 ' var win = window.open();\n'\ 5371 var title = "<title>dmesg log !! 4792 ' var log = document.getElementById("dmesglog");\n'\ 5372 var text = log.innerHTML.spli !! 4793 ' var title = "<title>dmesg log</title>";\n'\ 5373 var html = ""; !! 4794 ' var text = log.innerHTML.split("\\n");\n'\ 5374 for(var i = 0; i < text.lengt !! 4795 ' var html = "";\n'\ 5375 if(i == idx1) { !! 4796 ' for(var i = 0; i < text.length; i++) {\n'\ 5376 html += "<e i !! 4797 ' if(i == idx1) {\n'\ 5377 } else if(i > idx1 && !! 4798 ' html += "<e id=target>"+text[i]+"</e>\\n";\n'\ 5378 html += "<e>" !! 4799 ' } else if(i > idx1 && i <= idx2) {\n'\ 5379 } else { !! 4800 ' html += "<e>"+text[i]+"</e>\\n";\n'\ 5380 html += text[ !! 4801 ' } else {\n'\ 5381 } !! 4802 ' html += text[i]+"\\n";\n'\ 5382 } !! 4803 ' }\n'\ 5383 win.document.write("<style>e{ !! 4804 ' }\n'\ 5384 win.location.hash = "#target" !! 4805 ' win.document.write("<style>e{color:red}</style>"+title+"<pre>"+html+"</pre>");\n'\ 5385 win.document.close(); !! 4806 ' win.location.hash = "#target";\n'\ 5386 } !! 4807 ' win.document.close();\n'\ 5387 function logWindow(e) { !! 4808 ' }\n'\ 5388 var name = e.target.id.slice( !! 4809 ' function logWindow(e) {\n'\ 5389 var win = window.open(); !! 4810 ' var name = e.target.id.slice(4);\n'\ 5390 var log = document.getElement !! 4811 ' var win = window.open();\n'\ 5391 var title = "<title>"+documen !! 4812 ' var log = document.getElementById(name+"log");\n'\ 5392 win.document.write(title+"<pr !! 4813 ' var title = "<title>"+document.title.split(" ")[0]+" "+name+" log</title>";\n'\ 5393 win.document.close(); !! 4814 ' win.document.write(title+"<pre>"+log.innerHTML+"</pre>");\n'\ 5394 } !! 4815 ' win.document.close();\n'\ 5395 function onMouseDown(e) { !! 4816 ' }\n'\ 5396 dragval[0] = e.clientX; !! 4817 ' function onMouseDown(e) {\n'\ 5397 dragval[1] = document.getElem !! 4818 ' dragval[0] = e.clientX;\n'\ 5398 document.onmousemove = onMous !! 4819 ' dragval[1] = document.getElementById("dmesgzoombox").scrollLeft;\n'\ 5399 } !! 4820 ' document.onmousemove = onMouseMove;\n'\ 5400 function onMouseMove(e) { !! 4821 ' }\n'\ 5401 var zoombox = document.getEle !! 4822 ' function onMouseMove(e) {\n'\ 5402 zoombox.scrollLeft = dragval[ !! 4823 ' var zoombox = document.getElementById("dmesgzoombox");\n'\ 5403 } !! 4824 ' zoombox.scrollLeft = dragval[1] + dragval[0] - e.clientX;\n'\ 5404 function onMouseUp(e) { !! 4825 ' }\n'\ 5405 document.onmousemove = null; !! 4826 ' function onMouseUp(e) {\n'\ 5406 } !! 4827 ' document.onmousemove = null;\n'\ 5407 function onKeyPress(e) { !! 4828 ' }\n'\ 5408 var c = e.charCode; !! 4829 ' function onKeyPress(e) {\n'\ 5409 if(c != 42 && c != 43 && c != !! 4830 ' var c = e.charCode;\n'\ 5410 var click = document.createEv !! 4831 ' if(c != 42 && c != 43 && c != 45) return;\n'\ 5411 click.initEvent("click", true !! 4832 ' var click = document.createEvent("Events");\n'\ 5412 if(c == 43) !! 4833 ' click.initEvent("click", true, false);\n'\ 5413 document.getElementBy !! 4834 ' if(c == 43) \n'\ 5414 else if(c == 45) !! 4835 ' document.getElementById("zoomin").dispatchEvent(click);\n'\ 5415 document.getElementBy !! 4836 ' else if(c == 45)\n'\ 5416 else if(c == 42) !! 4837 ' document.getElementById("zoomout").dispatchEvent(click);\n'\ 5417 document.getElementBy !! 4838 ' else if(c == 42)\n'\ 5418 } !! 4839 ' document.getElementById("zoomdef").dispatchEvent(click);\n'\ 5419 window.addEventListener("resize", fun !! 4840 ' }\n'\ 5420 window.addEventListener("load", funct !! 4841 ' window.addEventListener("resize", function () {zoomTimeline();});\n'\ 5421 var dmesg = document.getEleme !! 4842 ' window.addEventListener("load", function () {\n'\ 5422 dmesg.style.width = "100%" !! 4843 ' var dmesg = document.getElementById("dmesg");\n'\ 5423 dmesg.onmousedown = onMouseDo !! 4844 ' dmesg.style.width = "100%"\n'\ 5424 document.onmouseup = onMouseU !! 4845 ' dmesg.onmousedown = onMouseDown;\n'\ 5425 document.onkeypress = onKeyPr !! 4846 ' document.onmouseup = onMouseUp;\n'\ 5426 document.getElementById("zoom !! 4847 ' document.onkeypress = onKeyPress;\n'\ 5427 document.getElementById("zoom !! 4848 ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\ 5428 document.getElementById("zoom !! 4849 ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\ 5429 var list = document.getElemen !! 4850 ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\ 5430 for (var i = 0; i < list.leng !! 4851 ' var list = document.getElementsByClassName("err");\n'\ 5431 list[i].onclick = err !! 4852 ' for (var i = 0; i < list.length; i++)\n'\ 5432 var list = document.getElemen !! 4853 ' list[i].onclick = errWindow;\n'\ 5433 for (var i = 0; i < list.leng !! 4854 ' var list = document.getElementsByClassName("logbtn");\n'\ 5434 list[i].onclick = log !! 4855 ' for (var i = 0; i < list.length; i++)\n'\ 5435 list = document.getElementsBy !! 4856 ' list[i].onclick = logWindow;\n'\ 5436 for (var i = 0; i < list.leng !! 4857 ' list = document.getElementsByClassName("devlist");\n'\ 5437 list[i].onclick = dev !! 4858 ' for (var i = 0; i < list.length; i++)\n'\ 5438 var dev = dmesg.getElementsBy !! 4859 ' list[i].onclick = devListWindow;\n'\ 5439 for (var i = 0; i < dev.lengt !! 4860 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 5440 dev[i].onclick = devi !! 4861 ' for (var i = 0; i < dev.length; i++) {\n'\ 5441 dev[i].onmouseover = !! 4862 ' dev[i].onclick = deviceDetail;\n'\ 5442 dev[i].onmouseout = d !! 4863 ' dev[i].onmouseover = deviceHover;\n'\ 5443 } !! 4864 ' dev[i].onmouseout = deviceUnhover;\n'\ 5444 var dev = dmesg.getElementsBy !! 4865 ' }\n'\ 5445 for (var i = 0; i < dev.lengt !! 4866 ' var dev = dmesg.getElementsByClassName("srccall");\n'\ 5446 dev[i].onclick = call !! 4867 ' for (var i = 0; i < dev.length; i++)\n'\ 5447 zoomTimeline(); !! 4868 ' dev[i].onclick = callSelect;\n'\ 5448 }); !! 4869 ' zoomTimeline();\n'\ 5449 </script> """ !! 4870 ' });\n'\ >> 4871 '</script>\n' 5450 hf.write(script_code); 4872 hf.write(script_code); 5451 4873 >> 4874 def setRuntimeSuspend(before=True): >> 4875 global sysvals >> 4876 sv = sysvals >> 4877 if sv.rs == 0: >> 4878 return >> 4879 if before: >> 4880 # runtime suspend disable or enable >> 4881 if sv.rs > 0: >> 4882 sv.rstgt, sv.rsval, sv.rsdir = 'on', 'auto', 'enabled' >> 4883 else: >> 4884 sv.rstgt, sv.rsval, sv.rsdir = 'auto', 'on', 'disabled' >> 4885 pprint('CONFIGURING RUNTIME SUSPEND...') >> 4886 sv.rslist = deviceInfo(sv.rstgt) >> 4887 for i in sv.rslist: >> 4888 sv.setVal(sv.rsval, i) >> 4889 pprint('runtime suspend %s on all devices (%d changed)' % (sv.rsdir, len(sv.rslist))) >> 4890 pprint('waiting 5 seconds...') >> 4891 time.sleep(5) >> 4892 else: >> 4893 # runtime suspend re-enable or re-disable >> 4894 for i in sv.rslist: >> 4895 sv.setVal(sv.rstgt, i) >> 4896 pprint('runtime suspend settings restored on %d devices' % len(sv.rslist)) >> 4897 5452 # Function: executeSuspend 4898 # Function: executeSuspend 5453 # Description: 4899 # Description: 5454 # Execute system suspend through the s 4900 # Execute system suspend through the sysfs interface, then copy the output 5455 # dmesg and ftrace files to the test o 4901 # dmesg and ftrace files to the test output directory. 5456 def executeSuspend(quiet=False): !! 4902 def executeSuspend(): 5457 sv, tp, pm = sysvals, sysvals.tpath, !! 4903 pm = ProcessMonitor() 5458 if sv.wifi: !! 4904 tp = sysvals.tpath 5459 wifi = sv.checkWifi() !! 4905 wifi = sysvals.checkWifi() 5460 sv.dlog('wifi check, connecte << 5461 testdata = [] 4906 testdata = [] >> 4907 battery = True if getBattery() else False 5462 # run these commands to prepare the s 4908 # run these commands to prepare the system for suspend 5463 if sv.display: !! 4909 if sysvals.display: 5464 if not quiet: !! 4910 pprint('SET DISPLAY TO %s' % sysvals.display.upper()) 5465 pprint('SET DISPLAY T !! 4911 displayControl(sysvals.display) 5466 ret = sv.displayControl(sv.di << 5467 sv.dlog('xset display %s, ret << 5468 time.sleep(1) 4912 time.sleep(1) 5469 if sv.sync: !! 4913 if sysvals.sync: 5470 if not quiet: !! 4914 pprint('SYNCING FILESYSTEMS') 5471 pprint('SYNCING FILES << 5472 sv.dlog('syncing filesystems' << 5473 call('sync', shell=True) 4915 call('sync', shell=True) 5474 sv.dlog('read dmesg') !! 4916 # mark the start point in the kernel ring buffer just as we start 5475 sv.initdmesg() !! 4917 sysvals.initdmesg() 5476 sv.dlog('cmdinfo before') !! 4918 # start ftrace 5477 sv.cmdinfo(True) !! 4919 if(sysvals.usecallgraph or sysvals.usetraceevents): 5478 sv.start(pm) !! 4920 pprint('START TRACING') >> 4921 sysvals.fsetVal('1', 'tracing_on') >> 4922 if sysvals.useprocmon: >> 4923 pm.start() 5479 # execute however many s/r runs reque 4924 # execute however many s/r runs requested 5480 for count in range(1,sv.execcount+1): !! 4925 for count in range(1,sysvals.execcount+1): 5481 # x2delay in between test run 4926 # x2delay in between test runs 5482 if(count > 1 and sv.x2delay > !! 4927 if(count > 1 and sysvals.x2delay > 0): 5483 sv.fsetVal('WAIT %d' !! 4928 sysvals.fsetVal('WAIT %d' % sysvals.x2delay, 'trace_marker') 5484 time.sleep(sv.x2delay !! 4929 time.sleep(sysvals.x2delay/1000.0) 5485 sv.fsetVal('WAIT END' !! 4930 sysvals.fsetVal('WAIT END', 'trace_marker') 5486 # start message 4931 # start message 5487 if sv.testcommand != '': !! 4932 if sysvals.testcommand != '': 5488 pprint('COMMAND START 4933 pprint('COMMAND START') 5489 else: 4934 else: 5490 if(sv.rtcwake): !! 4935 if(sysvals.rtcwake): 5491 pprint('SUSPE 4936 pprint('SUSPEND START') 5492 else: 4937 else: 5493 pprint('SUSPE 4938 pprint('SUSPEND START (press a key to resume)') >> 4939 sysvals.mcelog(True) >> 4940 bat1 = getBattery() if battery else False 5494 # set rtcwake 4941 # set rtcwake 5495 if(sv.rtcwake): !! 4942 if(sysvals.rtcwake): 5496 if not quiet: !! 4943 pprint('will issue an rtcwake in %d seconds' % sysvals.rtcwaketime) 5497 pprint('will !! 4944 sysvals.rtcWakeAlarmOn() 5498 sv.dlog('enable RTC w << 5499 sv.rtcWakeAlarmOn() << 5500 # start of suspend trace mark 4945 # start of suspend trace marker 5501 sv.fsetVal(datetime.now().str !! 4946 if(sysvals.usecallgraph or sysvals.usetraceevents): >> 4947 sysvals.fsetVal('SUSPEND START', 'trace_marker') 5502 # predelay delay 4948 # predelay delay 5503 if(count == 1 and sv.predelay !! 4949 if(count == 1 and sysvals.predelay > 0): 5504 sv.fsetVal('WAIT %d' !! 4950 sysvals.fsetVal('WAIT %d' % sysvals.predelay, 'trace_marker') 5505 time.sleep(sv.predela !! 4951 time.sleep(sysvals.predelay/1000.0) 5506 sv.fsetVal('WAIT END' !! 4952 sysvals.fsetVal('WAIT END', 'trace_marker') 5507 # initiate suspend or command 4953 # initiate suspend or command 5508 sv.dlog('system executing a s << 5509 tdata = {'error': ''} 4954 tdata = {'error': ''} 5510 if sv.testcommand != '': !! 4955 if sysvals.testcommand != '': 5511 res = call(sv.testcom !! 4956 res = call(sysvals.testcommand+' 2>&1', shell=True); 5512 if res != 0: 4957 if res != 0: 5513 tdata['error' 4958 tdata['error'] = 'cmd returned %d' % res 5514 else: 4959 else: 5515 s0ixready = sv.s0ixSu !! 4960 mode = sysvals.suspendmode 5516 mode = sv.suspendmode !! 4961 if sysvals.memmode and os.path.exists(sysvals.mempowerfile): 5517 if sv.memmode and os. << 5518 mode = 'mem' 4962 mode = 'mem' 5519 sv.testVal(sv !! 4963 pf = open(sysvals.mempowerfile, 'w') 5520 if sv.diskmode and os !! 4964 pf.write(sysvals.memmode) >> 4965 pf.close() >> 4966 if sysvals.diskmode and os.path.exists(sysvals.diskpowerfile): 5521 mode = 'disk' 4967 mode = 'disk' 5522 sv.testVal(sv !! 4968 pf = open(sysvals.diskpowerfile, 'w') 5523 if sv.acpidebug: !! 4969 pf.write(sysvals.diskmode) 5524 sv.testVal(sv !! 4970 pf.close() 5525 if ((mode == 'freeze' !! 4971 if mode == 'freeze' and sysvals.haveTurbostat(): 5526 and sv.haveTu << 5527 # execution w 4972 # execution will pause here 5528 retval, turbo !! 4973 turbo = sysvals.turbostat() 5529 if retval != !! 4974 if '|' in turbo: 5530 tdata << 5531 if turbo: << 5532 tdata 4975 tdata['turbo'] = turbo >> 4976 else: >> 4977 tdata['error'] = turbo 5533 else: 4978 else: 5534 pf = open(sv. !! 4979 if sysvals.haveTurbostat(): >> 4980 sysvals.vprint('WARNING: ignoring turbostat in mode "%s"' % mode) >> 4981 pf = open(sysvals.powerfile, 'w') 5535 pf.write(mode 4982 pf.write(mode) 5536 # execution w 4983 # execution will pause here 5537 try: 4984 try: 5538 pf.fl << 5539 pf.cl 4985 pf.close() 5540 except Except 4986 except Exception as e: 5541 tdata 4987 tdata['error'] = str(e) 5542 sv.fsetVal('CMD COMPLETE', 't !! 4988 if(sysvals.rtcwake): 5543 sv.dlog('system returned') !! 4989 sysvals.rtcWakeAlarmOff() 5544 # reset everything << 5545 sv.testVal('restoreall') << 5546 if(sv.rtcwake): << 5547 sv.dlog('disable RTC << 5548 sv.rtcWakeAlarmOff() << 5549 # postdelay delay 4990 # postdelay delay 5550 if(count == sv.execcount and !! 4991 if(count == sysvals.execcount and sysvals.postdelay > 0): 5551 sv.fsetVal('WAIT %d' !! 4992 sysvals.fsetVal('WAIT %d' % sysvals.postdelay, 'trace_marker') 5552 time.sleep(sv.postdel !! 4993 time.sleep(sysvals.postdelay/1000.0) 5553 sv.fsetVal('WAIT END' !! 4994 sysvals.fsetVal('WAIT END', 'trace_marker') 5554 # return from suspend 4995 # return from suspend 5555 pprint('RESUME COMPLETE') 4996 pprint('RESUME COMPLETE') 5556 if(count < sv.execcount): !! 4997 if(sysvals.usecallgraph or sysvals.usetraceevents): 5557 sv.fsetVal(datetime.n !! 4998 sysvals.fsetVal('RESUME COMPLETE', 'trace_marker') 5558 elif(not sv.wifitrace): !! 4999 if(sysvals.suspendmode == 'mem' or sysvals.suspendmode == 'command'): 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 5000 tdata['fw'] = getFPDT(False) >> 5001 mcelog = sysvals.mcelog() >> 5002 if mcelog: >> 5003 tdata['mcelog'] = mcelog >> 5004 bat2 = getBattery() if battery else False >> 5005 if battery and bat1 and bat2: >> 5006 tdata['bat'] = (bat1, bat2) >> 5007 if 'device' in wifi and 'ip' in wifi: >> 5008 tdata['wifi'] = (wifi, sysvals.checkWifi()) 5573 testdata.append(tdata) 5009 testdata.append(tdata) 5574 sv.dlog('cmdinfo after') !! 5010 # stop ftrace 5575 cmdafter = sv.cmdinfo(False) !! 5011 if(sysvals.usecallgraph or sysvals.usetraceevents): >> 5012 if sysvals.useprocmon: >> 5013 pm.stop() >> 5014 sysvals.fsetVal('0', 'tracing_on') 5576 # grab a copy of the dmesg output 5015 # grab a copy of the dmesg output 5577 if not quiet: !! 5016 pprint('CAPTURING DMESG') 5578 pprint('CAPTURING DMESG') !! 5017 sysvals.getdmesg(testdata) 5579 sv.getdmesg(testdata) << 5580 # grab a copy of the ftrace output 5018 # grab a copy of the ftrace output 5581 if sv.useftrace: !! 5019 if(sysvals.usecallgraph or sysvals.usetraceevents): 5582 if not quiet: !! 5020 pprint('CAPTURING TRACE') 5583 pprint('CAPTURING TRA !! 5021 op = sysvals.writeDatafileHeader(sysvals.ftracefile, testdata) 5584 op = sv.writeDatafileHeader(s !! 5022 fp = open(tp+'trace', 'r') 5585 fp = open(tp+'trace', 'rb') !! 5023 for line in fp: 5586 op.write(ascii(fp.read())) !! 5024 op.write(line) 5587 op.close() 5025 op.close() 5588 sv.fsetVal('', 'trace') !! 5026 sysvals.fsetVal('', 'trace') 5589 sv.platforminfo(cmdafter) !! 5027 devProps() >> 5028 return testdata 5590 5029 5591 def readFile(file): 5030 def readFile(file): 5592 if os.path.islink(file): 5031 if os.path.islink(file): 5593 return os.readlink(file).spli 5032 return os.readlink(file).split('/')[-1] 5594 else: 5033 else: 5595 return sysvals.getVal(file).s 5034 return sysvals.getVal(file).strip() 5596 5035 5597 # Function: ms2nice 5036 # Function: ms2nice 5598 # Description: 5037 # Description: 5599 # Print out a very concise time string 5038 # Print out a very concise time string in minutes and seconds 5600 # Output: 5039 # Output: 5601 # The time string, e.g. "1901m16s" 5040 # The time string, e.g. "1901m16s" 5602 def ms2nice(val): 5041 def ms2nice(val): 5603 val = int(val) 5042 val = int(val) 5604 h = val // 3600000 !! 5043 h = val / 3600000 5605 m = (val // 60000) % 60 !! 5044 m = (val / 60000) % 60 5606 s = (val // 1000) % 60 !! 5045 s = (val / 1000) % 60 5607 if h > 0: 5046 if h > 0: 5608 return '%d:%02d:%02d' % (h, m 5047 return '%d:%02d:%02d' % (h, m, s) 5609 if m > 0: 5048 if m > 0: 5610 return '%02d:%02d' % (m, s) 5049 return '%02d:%02d' % (m, s) 5611 return '%ds' % s 5050 return '%ds' % s 5612 5051 5613 def yesno(val): 5052 def yesno(val): 5614 list = {'enabled':'A', 'disabled':'S' 5053 list = {'enabled':'A', 'disabled':'S', 'auto':'E', 'on':'D', 5615 'active':'A', 'suspended':'S' 5054 'active':'A', 'suspended':'S', 'suspending':'S'} 5616 if val not in list: 5055 if val not in list: 5617 return ' ' 5056 return ' ' 5618 return list[val] 5057 return list[val] 5619 5058 5620 # Function: deviceInfo 5059 # Function: deviceInfo 5621 # Description: 5060 # Description: 5622 # Detect all the USB hosts and devices 5061 # Detect all the USB hosts and devices currently connected and add 5623 # a list of USB device names to sysval 5062 # a list of USB device names to sysvals for better timeline readability 5624 def deviceInfo(output=''): 5063 def deviceInfo(output=''): 5625 if not output: 5064 if not output: 5626 pprint('LEGEND\n'\ 5065 pprint('LEGEND\n'\ 5627 '---------------------------- 5066 '---------------------------------------------------------------------------------------------\n'\ 5628 ' A = async/sync PM queue (A 5067 ' A = async/sync PM queue (A/S) C = runtime active children\n'\ 5629 ' R = runtime suspend enable 5068 ' R = runtime suspend enabled/disabled (E/D) rACTIVE = runtime active (min/sec)\n'\ 5630 ' S = runtime status active/ 5069 ' S = runtime status active/suspended (A/S) rSUSPEND = runtime suspend (min/sec)\n'\ 5631 ' U = runtime usage count\n' 5070 ' U = runtime usage count\n'\ 5632 '---------------------------- 5071 '---------------------------------------------------------------------------------------------\n'\ 5633 'DEVICE N 5072 'DEVICE NAME A R S U C rACTIVE rSUSPEND\n'\ 5634 '---------------------------- 5073 '---------------------------------------------------------------------------------------------') 5635 5074 5636 res = [] 5075 res = [] 5637 tgtval = 'runtime_status' 5076 tgtval = 'runtime_status' 5638 lines = dict() 5077 lines = dict() 5639 for dirname, dirnames, filenames in o 5078 for dirname, dirnames, filenames in os.walk('/sys/devices'): 5640 if(not re.match(r'.*/power', !! 5079 if(not re.match('.*/power', dirname) or 5641 'control' not in file 5080 'control' not in filenames or 5642 tgtval not in filenam 5081 tgtval not in filenames): 5643 continue 5082 continue 5644 name = '' 5083 name = '' 5645 dirname = dirname[:-6] 5084 dirname = dirname[:-6] 5646 device = dirname.split('/')[- 5085 device = dirname.split('/')[-1] 5647 power = dict() 5086 power = dict() 5648 power[tgtval] = readFile('%s/ 5087 power[tgtval] = readFile('%s/power/%s' % (dirname, tgtval)) 5649 # only list devices which sup 5088 # only list devices which support runtime suspend 5650 if power[tgtval] not in ['act 5089 if power[tgtval] not in ['active', 'suspended', 'suspending']: 5651 continue 5090 continue 5652 for i in ['product', 'driver' 5091 for i in ['product', 'driver', 'subsystem']: 5653 file = '%s/%s' % (dir 5092 file = '%s/%s' % (dirname, i) 5654 if os.path.exists(fil 5093 if os.path.exists(file): 5655 name = readFi 5094 name = readFile(file) 5656 break 5095 break 5657 for i in ['async', 'control', 5096 for i in ['async', 'control', 'runtime_status', 'runtime_usage', 5658 'runtime_active_kids' 5097 'runtime_active_kids', 'runtime_active_time', 5659 'runtime_suspended_ti 5098 'runtime_suspended_time']: 5660 if i in filenames: 5099 if i in filenames: 5661 power[i] = re 5100 power[i] = readFile('%s/power/%s' % (dirname, i)) 5662 if output: 5101 if output: 5663 if power['control'] = 5102 if power['control'] == output: 5664 res.append('% 5103 res.append('%s/power/control' % dirname) 5665 continue 5104 continue 5666 lines[dirname] = '%-26s %-26s 5105 lines[dirname] = '%-26s %-26s %1s %1s %1s %1s %1s %10s %10s' % \ 5667 (device[:26], name[:2 5106 (device[:26], name[:26], 5668 yesno(power['async']) 5107 yesno(power['async']), \ 5669 yesno(power['control' 5108 yesno(power['control']), \ 5670 yesno(power['runtime_ 5109 yesno(power['runtime_status']), \ 5671 power['runtime_usage' 5110 power['runtime_usage'], \ 5672 power['runtime_active 5111 power['runtime_active_kids'], \ 5673 ms2nice(power['runtim 5112 ms2nice(power['runtime_active_time']), \ 5674 ms2nice(power['runtim 5113 ms2nice(power['runtime_suspended_time'])) 5675 for i in sorted(lines): 5114 for i in sorted(lines): 5676 print(lines[i]) 5115 print(lines[i]) 5677 return res 5116 return res 5678 5117 >> 5118 # Function: devProps >> 5119 # Description: >> 5120 # Retrieve a list of properties for all devices in the trace log >> 5121 def devProps(data=0): >> 5122 props = dict() >> 5123 >> 5124 if data: >> 5125 idx = data.index(': ') + 2 >> 5126 if idx >= len(data): >> 5127 return >> 5128 devlist = data[idx:].split(';') >> 5129 for dev in devlist: >> 5130 f = dev.split(',') >> 5131 if len(f) < 3: >> 5132 continue >> 5133 dev = f[0] >> 5134 props[dev] = DevProps() >> 5135 props[dev].altname = f[1] >> 5136 if int(f[2]): >> 5137 props[dev].async = True >> 5138 else: >> 5139 props[dev].async = False >> 5140 sysvals.devprops = props >> 5141 if sysvals.suspendmode == 'command' and 'testcommandstring' in props: >> 5142 sysvals.testcommand = props['testcommandstring'].altname >> 5143 return >> 5144 >> 5145 if(os.path.exists(sysvals.ftracefile) == False): >> 5146 doError('%s does not exist' % sysvals.ftracefile) >> 5147 >> 5148 # first get the list of devices we need properties for >> 5149 msghead = 'Additional data added by AnalyzeSuspend' >> 5150 alreadystamped = False >> 5151 tp = TestProps() >> 5152 tf = sysvals.openlog(sysvals.ftracefile, 'r') >> 5153 for line in tf: >> 5154 if msghead in line: >> 5155 alreadystamped = True >> 5156 continue >> 5157 # determine the trace data type (required for further parsing) >> 5158 m = re.match(tp.tracertypefmt, line) >> 5159 if(m): >> 5160 tp.setTracerType(m.group('t')) >> 5161 continue >> 5162 # parse only valid lines, if this is not one move on >> 5163 m = re.match(tp.ftrace_line_fmt, line) >> 5164 if(not m or 'device_pm_callback_start' not in line): >> 5165 continue >> 5166 m = re.match('.*: (?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*', m.group('msg')); >> 5167 if(not m): >> 5168 continue >> 5169 dev = m.group('d') >> 5170 if dev not in props: >> 5171 props[dev] = DevProps() >> 5172 tf.close() >> 5173 >> 5174 if not alreadystamped and sysvals.suspendmode == 'command': >> 5175 out = '#\n# '+msghead+'\n# Device Properties: ' >> 5176 out += 'testcommandstring,%s,0;' % (sysvals.testcommand) >> 5177 with sysvals.openlog(sysvals.ftracefile, 'a') as fp: >> 5178 fp.write(out+'\n') >> 5179 sysvals.devprops = props >> 5180 return >> 5181 >> 5182 # now get the syspath for each of our target devices >> 5183 for dirname, dirnames, filenames in os.walk('/sys/devices'): >> 5184 if(re.match('.*/power', dirname) and 'async' in filenames): >> 5185 dev = dirname.split('/')[-2] >> 5186 if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)): >> 5187 props[dev].syspath = dirname[:-6] >> 5188 >> 5189 # now fill in the properties for our target devices >> 5190 for dev in props: >> 5191 dirname = props[dev].syspath >> 5192 if not dirname or not os.path.exists(dirname): >> 5193 continue >> 5194 with open(dirname+'/power/async') as fp: >> 5195 text = fp.read() >> 5196 props[dev].async = False >> 5197 if 'enabled' in text: >> 5198 props[dev].async = True >> 5199 fields = os.listdir(dirname) >> 5200 if 'product' in fields: >> 5201 with open(dirname+'/product') as fp: >> 5202 props[dev].altname = fp.read() >> 5203 elif 'name' in fields: >> 5204 with open(dirname+'/name') as fp: >> 5205 props[dev].altname = fp.read() >> 5206 elif 'model' in fields: >> 5207 with open(dirname+'/model') as fp: >> 5208 props[dev].altname = fp.read() >> 5209 elif 'description' in fields: >> 5210 with open(dirname+'/description') as fp: >> 5211 props[dev].altname = fp.read() >> 5212 elif 'id' in fields: >> 5213 with open(dirname+'/id') as fp: >> 5214 props[dev].altname = fp.read() >> 5215 elif 'idVendor' in fields and 'idProduct' in fields: >> 5216 idv, idp = '', '' >> 5217 with open(dirname+'/idVendor') as fp: >> 5218 idv = fp.read().strip() >> 5219 with open(dirname+'/idProduct') as fp: >> 5220 idp = fp.read().strip() >> 5221 props[dev].altname = '%s:%s' % (idv, idp) >> 5222 >> 5223 if props[dev].altname: >> 5224 out = props[dev].altname.strip().replace('\n', ' ') >> 5225 out = out.replace(',', ' ') >> 5226 out = out.replace(';', ' ') >> 5227 props[dev].altname = out >> 5228 >> 5229 # and now write the data to the ftrace file >> 5230 if not alreadystamped: >> 5231 out = '#\n# '+msghead+'\n# Device Properties: ' >> 5232 for dev in sorted(props): >> 5233 out += props[dev].out(dev) >> 5234 with sysvals.openlog(sysvals.ftracefile, 'a') as fp: >> 5235 fp.write(out+'\n') >> 5236 >> 5237 sysvals.devprops = props >> 5238 5679 # Function: getModes 5239 # Function: getModes 5680 # Description: 5240 # Description: 5681 # Determine the supported power modes 5241 # Determine the supported power modes on this system 5682 # Output: 5242 # Output: 5683 # A string list of the available modes 5243 # A string list of the available modes 5684 def getModes(): 5244 def getModes(): 5685 modes = [] 5245 modes = [] 5686 if(os.path.exists(sysvals.powerfile)) 5246 if(os.path.exists(sysvals.powerfile)): 5687 fp = open(sysvals.powerfile, 5247 fp = open(sysvals.powerfile, 'r') 5688 modes = fp.read().split() 5248 modes = fp.read().split() 5689 fp.close() 5249 fp.close() 5690 if(os.path.exists(sysvals.mempowerfil 5250 if(os.path.exists(sysvals.mempowerfile)): 5691 deep = False 5251 deep = False 5692 fp = open(sysvals.mempowerfil 5252 fp = open(sysvals.mempowerfile, 'r') 5693 for m in fp.read().split(): 5253 for m in fp.read().split(): 5694 memmode = m.strip('[] 5254 memmode = m.strip('[]') 5695 if memmode == 'deep': 5255 if memmode == 'deep': 5696 deep = True 5256 deep = True 5697 else: 5257 else: 5698 modes.append( 5258 modes.append('mem-%s' % memmode) 5699 fp.close() 5259 fp.close() 5700 if 'mem' in modes and not dee 5260 if 'mem' in modes and not deep: 5701 modes.remove('mem') 5261 modes.remove('mem') 5702 if('disk' in modes and os.path.exists 5262 if('disk' in modes and os.path.exists(sysvals.diskpowerfile)): 5703 fp = open(sysvals.diskpowerfi 5263 fp = open(sysvals.diskpowerfile, 'r') 5704 for m in fp.read().split(): 5264 for m in fp.read().split(): 5705 modes.append('disk-%s 5265 modes.append('disk-%s' % m.strip('[]')) 5706 fp.close() 5266 fp.close() 5707 return modes 5267 return modes 5708 5268 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 5269 # Function: dmidecode 5744 # Description: 5270 # Description: 5745 # Read the bios tables and pull out sy 5271 # Read the bios tables and pull out system info 5746 # Arguments: 5272 # Arguments: 5747 # mempath: /dev/mem or custom mem path 5273 # mempath: /dev/mem or custom mem path 5748 # fatal: True to exit on error, False 5274 # fatal: True to exit on error, False to return empty dict 5749 # Output: 5275 # Output: 5750 # A dict object with all available key 5276 # A dict object with all available key/values 5751 def dmidecode(mempath, fatal=False): 5277 def dmidecode(mempath, fatal=False): 5752 out = dict() 5278 out = dict() 5753 if(not (os.path.exists(mempath) and o << 5754 return dmidecode_backup(out, << 5755 5279 5756 # the list of values to retrieve, wit 5280 # the list of values to retrieve, with hardcoded (type, idx) 5757 info = { 5281 info = { 5758 'bios-vendor': (0, 4), 5282 'bios-vendor': (0, 4), 5759 'bios-version': (0, 5), 5283 'bios-version': (0, 5), 5760 'bios-release-date': (0, 8), 5284 'bios-release-date': (0, 8), 5761 'system-manufacturer': (1, 4) 5285 'system-manufacturer': (1, 4), 5762 'system-product-name': (1, 5) 5286 'system-product-name': (1, 5), 5763 'system-version': (1, 6), 5287 'system-version': (1, 6), 5764 'system-serial-number': (1, 7 5288 'system-serial-number': (1, 7), 5765 'baseboard-manufacturer': (2, 5289 'baseboard-manufacturer': (2, 4), 5766 'baseboard-product-name': (2, 5290 'baseboard-product-name': (2, 5), 5767 'baseboard-version': (2, 6), 5291 'baseboard-version': (2, 6), 5768 'baseboard-serial-number': (2 5292 'baseboard-serial-number': (2, 7), 5769 'chassis-manufacturer': (3, 4 5293 'chassis-manufacturer': (3, 4), >> 5294 'chassis-type': (3, 5), 5770 'chassis-version': (3, 6), 5295 'chassis-version': (3, 6), 5771 'chassis-serial-number': (3, 5296 'chassis-serial-number': (3, 7), 5772 'processor-manufacturer': (4, 5297 'processor-manufacturer': (4, 7), 5773 'processor-version': (4, 16), 5298 'processor-version': (4, 16), 5774 } 5299 } >> 5300 if(not os.path.exists(mempath)): >> 5301 if(fatal): >> 5302 doError('file does not exist: %s' % mempath) >> 5303 return out >> 5304 if(not os.access(mempath, os.R_OK)): >> 5305 if(fatal): >> 5306 doError('file is not readable: %s' % mempath) >> 5307 return out 5775 5308 5776 # by default use legacy scan, but try 5309 # by default use legacy scan, but try to use EFI first 5777 memaddr, memsize = 0xf0000, 0x10000 !! 5310 memaddr = 0xf0000 >> 5311 memsize = 0x10000 5778 for ep in ['/sys/firmware/efi/systab' 5312 for ep in ['/sys/firmware/efi/systab', '/proc/efi/systab']: 5779 if not os.path.exists(ep) or 5313 if not os.path.exists(ep) or not os.access(ep, os.R_OK): 5780 continue 5314 continue 5781 fp = open(ep, 'r') 5315 fp = open(ep, 'r') 5782 buf = fp.read() 5316 buf = fp.read() 5783 fp.close() 5317 fp.close() 5784 i = buf.find('SMBIOS=') 5318 i = buf.find('SMBIOS=') 5785 if i >= 0: 5319 if i >= 0: 5786 try: 5320 try: 5787 memaddr = int 5321 memaddr = int(buf[i+7:], 16) 5788 memsize = 0x2 5322 memsize = 0x20 5789 except: 5323 except: 5790 continue 5324 continue 5791 5325 5792 # read in the memory for scanning 5326 # read in the memory for scanning 5793 try: 5327 try: 5794 fp = open(mempath, 'rb') 5328 fp = open(mempath, 'rb') 5795 fp.seek(memaddr) 5329 fp.seek(memaddr) 5796 buf = fp.read(memsize) 5330 buf = fp.read(memsize) 5797 except: 5331 except: 5798 return dmidecode_backup(out, !! 5332 if(fatal): >> 5333 doError('DMI table is unreachable, sorry') >> 5334 else: >> 5335 pprint('WARNING: /dev/mem is not readable, ignoring DMI data') >> 5336 return out 5799 fp.close() 5337 fp.close() 5800 5338 5801 # search for either an SM table or DM 5339 # search for either an SM table or DMI table 5802 i = base = length = num = 0 5340 i = base = length = num = 0 5803 while(i < memsize): 5341 while(i < memsize): 5804 if buf[i:i+4] == b'_SM_' and !! 5342 if buf[i:i+4] == '_SM_' and i < memsize - 16: 5805 length = struct.unpac 5343 length = struct.unpack('H', buf[i+22:i+24])[0] 5806 base, num = struct.un 5344 base, num = struct.unpack('IH', buf[i+24:i+30]) 5807 break 5345 break 5808 elif buf[i:i+5] == b'_DMI_': !! 5346 elif buf[i:i+5] == '_DMI_': 5809 length = struct.unpac 5347 length = struct.unpack('H', buf[i+6:i+8])[0] 5810 base, num = struct.un 5348 base, num = struct.unpack('IH', buf[i+8:i+14]) 5811 break 5349 break 5812 i += 16 5350 i += 16 5813 if base == 0 and length == 0 and num 5351 if base == 0 and length == 0 and num == 0: 5814 return dmidecode_backup(out, !! 5352 if(fatal): >> 5353 doError('Neither SMBIOS nor DMI were found') >> 5354 else: >> 5355 return out 5815 5356 5816 # read in the SM or DMI table 5357 # read in the SM or DMI table 5817 try: 5358 try: 5818 fp = open(mempath, 'rb') 5359 fp = open(mempath, 'rb') 5819 fp.seek(base) 5360 fp.seek(base) 5820 buf = fp.read(length) 5361 buf = fp.read(length) 5821 except: 5362 except: 5822 return dmidecode_backup(out, !! 5363 if(fatal): >> 5364 doError('DMI table is unreachable, sorry') >> 5365 else: >> 5366 pprint('WARNING: /dev/mem is not readable, ignoring DMI data') >> 5367 return out 5823 fp.close() 5368 fp.close() 5824 5369 5825 # scan the table for the values we wa 5370 # scan the table for the values we want 5826 count = i = 0 5371 count = i = 0 5827 while(count < num and i <= len(buf) - 5372 while(count < num and i <= len(buf) - 4): 5828 type, size, handle = struct.u 5373 type, size, handle = struct.unpack('BBH', buf[i:i+4]) 5829 n = i + size 5374 n = i + size 5830 while n < len(buf) - 1: 5375 while n < len(buf) - 1: 5831 if 0 == struct.unpack 5376 if 0 == struct.unpack('H', buf[n:n+2])[0]: 5832 break 5377 break 5833 n += 1 5378 n += 1 5834 data = buf[i+size:n+2].split( !! 5379 data = buf[i+size:n+2].split('\0') 5835 for name in info: 5380 for name in info: 5836 itype, idxadr = info[ 5381 itype, idxadr = info[name] 5837 if itype == type: 5382 if itype == type: 5838 idx = struct. !! 5383 idx = struct.unpack('B', buf[i+idxadr])[0] 5839 if idx > 0 an 5384 if idx > 0 and idx < len(data) - 1: 5840 s = d !! 5385 s = data[idx-1].strip() 5841 if s. !! 5386 if s and s.lower() != 'to be filled by o.e.m.': 5842 !! 5387 out[name] = data[idx-1] 5843 i = n + 2 5388 i = n + 2 5844 count += 1 5389 count += 1 5845 return out 5390 return out 5846 5391 >> 5392 def getBattery(): >> 5393 p, charge, bat = '/sys/class/power_supply', 0, {} >> 5394 if not os.path.exists(p): >> 5395 return False >> 5396 for d in os.listdir(p): >> 5397 type = sysvals.getVal(os.path.join(p, d, 'type')).strip().lower() >> 5398 if type != 'battery': >> 5399 continue >> 5400 for v in ['status', 'energy_now', 'capacity_now']: >> 5401 bat[v] = sysvals.getVal(os.path.join(p, d, v)).strip().lower() >> 5402 break >> 5403 if 'status' not in bat: >> 5404 return False >> 5405 ac = False if 'discharging' in bat['status'] else True >> 5406 for v in ['energy_now', 'capacity_now']: >> 5407 if v in bat and bat[v]: >> 5408 charge = int(bat[v]) >> 5409 return (ac, charge) >> 5410 >> 5411 def displayControl(cmd): >> 5412 xset, ret = 'xset -d :0.0 {0}', 0 >> 5413 if sysvals.sudouser: >> 5414 xset = 'sudo -u %s %s' % (sysvals.sudouser, xset) >> 5415 if cmd == 'init': >> 5416 ret = call(xset.format('dpms 0 0 0'), shell=True) >> 5417 if not ret: >> 5418 ret = call(xset.format('s off'), shell=True) >> 5419 elif cmd == 'reset': >> 5420 ret = call(xset.format('s reset'), shell=True) >> 5421 elif cmd in ['on', 'off', 'standby', 'suspend']: >> 5422 b4 = displayControl('stat') >> 5423 ret = call(xset.format('dpms force %s' % cmd), shell=True) >> 5424 if not ret: >> 5425 curr = displayControl('stat') >> 5426 sysvals.vprint('Display Switched: %s -> %s' % (b4, curr)) >> 5427 if curr != cmd: >> 5428 sysvals.vprint('WARNING: Display failed to change to %s' % cmd) >> 5429 if ret: >> 5430 sysvals.vprint('WARNING: Display failed to change to %s with xset' % cmd) >> 5431 return ret >> 5432 elif cmd == 'stat': >> 5433 fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout >> 5434 ret = 'unknown' >> 5435 for line in fp: >> 5436 m = re.match('[\s]*Monitor is (?P<m>.*)', line) >> 5437 if(m and len(m.group('m')) >= 2): >> 5438 out = m.group('m').lower() >> 5439 ret = out[3:] if out[0:2] == 'in' else out >> 5440 break >> 5441 fp.close() >> 5442 return ret >> 5443 5847 # Function: getFPDT 5444 # Function: getFPDT 5848 # Description: 5445 # Description: 5849 # Read the acpi bios tables and pull o 5446 # Read the acpi bios tables and pull out FPDT, the firmware data 5850 # Arguments: 5447 # Arguments: 5851 # output: True to output the info to s 5448 # output: True to output the info to stdout, False otherwise 5852 def getFPDT(output): 5449 def getFPDT(output): 5853 rectype = {} 5450 rectype = {} 5854 rectype[0] = 'Firmware Basic Boot Per 5451 rectype[0] = 'Firmware Basic Boot Performance Record' 5855 rectype[1] = 'S3 Performance Table Re 5452 rectype[1] = 'S3 Performance Table Record' 5856 prectype = {} 5453 prectype = {} 5857 prectype[0] = 'Basic S3 Resume Perfor 5454 prectype[0] = 'Basic S3 Resume Performance Record' 5858 prectype[1] = 'Basic S3 Suspend Perfo 5455 prectype[1] = 'Basic S3 Suspend Performance Record' 5859 5456 5860 sysvals.rootCheck(True) 5457 sysvals.rootCheck(True) 5861 if(not os.path.exists(sysvals.fpdtpat 5458 if(not os.path.exists(sysvals.fpdtpath)): 5862 if(output): 5459 if(output): 5863 doError('file does no 5460 doError('file does not exist: %s' % sysvals.fpdtpath) 5864 return False 5461 return False 5865 if(not os.access(sysvals.fpdtpath, os 5462 if(not os.access(sysvals.fpdtpath, os.R_OK)): 5866 if(output): 5463 if(output): 5867 doError('file is not 5464 doError('file is not readable: %s' % sysvals.fpdtpath) 5868 return False 5465 return False 5869 if(not os.path.exists(sysvals.mempath 5466 if(not os.path.exists(sysvals.mempath)): 5870 if(output): 5467 if(output): 5871 doError('file does no 5468 doError('file does not exist: %s' % sysvals.mempath) 5872 return False 5469 return False 5873 if(not os.access(sysvals.mempath, os. 5470 if(not os.access(sysvals.mempath, os.R_OK)): 5874 if(output): 5471 if(output): 5875 doError('file is not 5472 doError('file is not readable: %s' % sysvals.mempath) 5876 return False 5473 return False 5877 5474 5878 fp = open(sysvals.fpdtpath, 'rb') 5475 fp = open(sysvals.fpdtpath, 'rb') 5879 buf = fp.read() 5476 buf = fp.read() 5880 fp.close() 5477 fp.close() 5881 5478 5882 if(len(buf) < 36): 5479 if(len(buf) < 36): 5883 if(output): 5480 if(output): 5884 doError('Invalid FPDT 5481 doError('Invalid FPDT table data, should '+\ 5885 'be at least 5482 'be at least 36 bytes') 5886 return False 5483 return False 5887 5484 5888 table = struct.unpack('4sIBB6s8sI4sI' 5485 table = struct.unpack('4sIBB6s8sI4sI', buf[0:36]) 5889 if(output): 5486 if(output): 5890 pprint('\n'\ 5487 pprint('\n'\ 5891 'Firmware Performance Data Ta 5488 'Firmware Performance Data Table (%s)\n'\ 5892 ' Signature 5489 ' Signature : %s\n'\ 5893 ' Table Length 5490 ' Table Length : %u\n'\ 5894 ' Revision 5491 ' Revision : %u\n'\ 5895 ' Checksum 5492 ' Checksum : 0x%x\n'\ 5896 ' OEM ID 5493 ' OEM ID : %s\n'\ 5897 ' OEM Table ID 5494 ' OEM Table ID : %s\n'\ 5898 ' OEM Revision 5495 ' OEM Revision : %u\n'\ 5899 ' Creator ID 5496 ' Creator ID : %s\n'\ 5900 ' Creator Revision 5497 ' Creator Revision : 0x%x\n'\ 5901 '' % (ascii(table[0]), ascii( !! 5498 '' % (table[0], table[0], table[1], table[2], table[3], 5902 table[3], ascii(table !! 5499 table[4], table[5], table[6], table[7], table[8])) 5903 ascii(table[7]), tabl << 5904 5500 5905 if(table[0] != b'FPDT'): !! 5501 if(table[0] != 'FPDT'): 5906 if(output): 5502 if(output): 5907 doError('Invalid FPDT 5503 doError('Invalid FPDT table') 5908 return False 5504 return False 5909 if(len(buf) <= 36): 5505 if(len(buf) <= 36): 5910 return False 5506 return False 5911 i = 0 5507 i = 0 5912 fwData = [0, 0] 5508 fwData = [0, 0] 5913 records = buf[36:] 5509 records = buf[36:] 5914 try: 5510 try: 5915 fp = open(sysvals.mempath, 'r 5511 fp = open(sysvals.mempath, 'rb') 5916 except: 5512 except: 5917 pprint('WARNING: /dev/mem is 5513 pprint('WARNING: /dev/mem is not readable, ignoring the FPDT data') 5918 return False 5514 return False 5919 while(i < len(records)): 5515 while(i < len(records)): 5920 header = struct.unpack('HBB', 5516 header = struct.unpack('HBB', records[i:i+4]) 5921 if(header[0] not in rectype): 5517 if(header[0] not in rectype): 5922 i += header[1] 5518 i += header[1] 5923 continue 5519 continue 5924 if(header[1] != 16): 5520 if(header[1] != 16): 5925 i += header[1] 5521 i += header[1] 5926 continue 5522 continue 5927 addr = struct.unpack('Q', rec 5523 addr = struct.unpack('Q', records[i+8:i+16])[0] 5928 try: 5524 try: 5929 fp.seek(addr) 5525 fp.seek(addr) 5930 first = fp.read(8) 5526 first = fp.read(8) 5931 except: 5527 except: 5932 if(output): 5528 if(output): 5933 pprint('Bad a 5529 pprint('Bad address 0x%x in %s' % (addr, sysvals.mempath)) 5934 return [0, 0] 5530 return [0, 0] 5935 rechead = struct.unpack('4sI' 5531 rechead = struct.unpack('4sI', first) 5936 recdata = fp.read(rechead[1]- 5532 recdata = fp.read(rechead[1]-8) 5937 if(rechead[0] == b'FBPT'): !! 5533 if(rechead[0] == 'FBPT'): 5938 record = struct.unpac !! 5534 record = struct.unpack('HBBIQQQQQ', recdata) 5939 if(output): 5535 if(output): 5940 pprint('%s (% 5536 pprint('%s (%s)\n'\ 5941 ' 5537 ' Reset END : %u ns\n'\ 5942 ' OS Loader 5538 ' OS Loader LoadImage Start : %u ns\n'\ 5943 ' OS Loader S 5539 ' OS Loader StartImage Start : %u ns\n'\ 5944 ' ExitBoo 5540 ' ExitBootServices Entry : %u ns\n'\ 5945 ' ExitBo 5541 ' ExitBootServices Exit : %u ns'\ 5946 '' % (rectype !! 5542 '' % (rectype[header[0]], rechead[0], record[4], record[5], 5947 recor 5543 record[6], record[7], record[8])) 5948 elif(rechead[0] == b'S3PT'): !! 5544 elif(rechead[0] == 'S3PT'): 5949 if(output): 5545 if(output): 5950 pprint('%s (% !! 5546 pprint('%s (%s)' % (rectype[header[0]], rechead[0])) 5951 j = 0 5547 j = 0 5952 while(j < len(recdata 5548 while(j < len(recdata)): 5953 prechead = st 5549 prechead = struct.unpack('HBB', recdata[j:j+4]) 5954 if(prechead[0 5550 if(prechead[0] not in prectype): 5955 conti 5551 continue 5956 if(prechead[0 5552 if(prechead[0] == 0): 5957 recor 5553 record = struct.unpack('IIQQ', recdata[j:j+prechead[1]]) 5958 fwDat 5554 fwData[1] = record[2] 5959 if(ou 5555 if(output): 5960 5556 pprint(' %s\n'\ 5961 5557 ' Resume Count : %u\n'\ 5962 5558 ' FullResume : %u ns\n'\ 5963 5559 ' AverageResume : %u ns'\ 5964 5560 '' % (prectype[prechead[0]], record[1], 5965 5561 record[2], record[3])) 5966 elif(prechead 5562 elif(prechead[0] == 1): 5967 recor 5563 record = struct.unpack('QQ', recdata[j+4:j+prechead[1]]) 5968 fwDat 5564 fwData[0] = record[1] - record[0] 5969 if(ou 5565 if(output): 5970 5566 pprint(' %s\n'\ 5971 5567 ' SuspendStart : %u ns\n'\ 5972 5568 ' SuspendEnd : %u ns\n'\ 5973 5569 ' SuspendTime : %u ns'\ 5974 5570 '' % (prectype[prechead[0]], record[0], 5975 5571 record[1], fwData[0])) 5976 5572 5977 j += prechead 5573 j += prechead[1] 5978 if(output): 5574 if(output): 5979 pprint('') 5575 pprint('') 5980 i += header[1] 5576 i += header[1] 5981 fp.close() 5577 fp.close() 5982 return fwData 5578 return fwData 5983 5579 5984 # Function: statusCheck 5580 # Function: statusCheck 5985 # Description: 5581 # Description: 5986 # Verify that the requested command an 5582 # Verify that the requested command and options will work, and 5987 # print the results to the terminal 5583 # print the results to the terminal 5988 # Output: 5584 # Output: 5989 # True if the test will work, False if 5585 # True if the test will work, False if not 5990 def statusCheck(probecheck=False): 5586 def statusCheck(probecheck=False): 5991 status = '' 5587 status = '' 5992 5588 5993 pprint('Checking this system (%s)...' 5589 pprint('Checking this system (%s)...' % platform.node()) 5994 5590 5995 # check we have root access 5591 # check we have root access 5996 res = sysvals.colorText('NO (No featu 5592 res = sysvals.colorText('NO (No features of this tool will work!)') 5997 if(sysvals.rootCheck(False)): 5593 if(sysvals.rootCheck(False)): 5998 res = 'YES' 5594 res = 'YES' 5999 pprint(' have root access: %s' % r 5595 pprint(' have root access: %s' % res) 6000 if(res != 'YES'): 5596 if(res != 'YES'): 6001 pprint(' Try running this 5597 pprint(' Try running this script with sudo') 6002 return 'missing root access' 5598 return 'missing root access' 6003 5599 6004 # check sysfs is mounted 5600 # check sysfs is mounted 6005 res = sysvals.colorText('NO (No featu 5601 res = sysvals.colorText('NO (No features of this tool will work!)') 6006 if(os.path.exists(sysvals.powerfile)) 5602 if(os.path.exists(sysvals.powerfile)): 6007 res = 'YES' 5603 res = 'YES' 6008 pprint(' is sysfs mounted: %s' % r 5604 pprint(' is sysfs mounted: %s' % res) 6009 if(res != 'YES'): 5605 if(res != 'YES'): 6010 return 'sysfs is missing' 5606 return 'sysfs is missing' 6011 5607 6012 # check target mode is a valid mode 5608 # check target mode is a valid mode 6013 if sysvals.suspendmode != 'command': 5609 if sysvals.suspendmode != 'command': 6014 res = sysvals.colorText('NO') 5610 res = sysvals.colorText('NO') 6015 modes = getModes() 5611 modes = getModes() 6016 if(sysvals.suspendmode in mod 5612 if(sysvals.suspendmode in modes): 6017 res = 'YES' 5613 res = 'YES' 6018 else: 5614 else: 6019 status = '%s mode is 5615 status = '%s mode is not supported' % sysvals.suspendmode 6020 pprint(' is "%s" a valid p 5616 pprint(' is "%s" a valid power mode: %s' % (sysvals.suspendmode, res)) 6021 if(res == 'NO'): 5617 if(res == 'NO'): 6022 pprint(' valid p 5618 pprint(' valid power modes are: %s' % modes) 6023 pprint(' please 5619 pprint(' please choose one with -m') 6024 5620 6025 # check if ftrace is available 5621 # check if ftrace is available 6026 if sysvals.useftrace: !! 5622 res = sysvals.colorText('NO') 6027 res = sysvals.colorText('NO') !! 5623 ftgood = sysvals.verifyFtrace() 6028 sysvals.useftrace = sysvals.v !! 5624 if(ftgood): 6029 efmt = '"{0}" uses ftrace, an !! 5625 res = 'YES' 6030 if sysvals.useftrace: !! 5626 elif(sysvals.usecallgraph): 6031 res = 'YES' !! 5627 status = 'ftrace is not properly supported' 6032 elif sysvals.usecallgraph: !! 5628 pprint(' is ftrace supported: %s' % res) 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 5629 6040 # check if kprobes are available 5630 # check if kprobes are available 6041 if sysvals.usekprobes: 5631 if sysvals.usekprobes: 6042 res = sysvals.colorText('NO') 5632 res = sysvals.colorText('NO') 6043 sysvals.usekprobes = sysvals. 5633 sysvals.usekprobes = sysvals.verifyKprobes() 6044 if(sysvals.usekprobes): 5634 if(sysvals.usekprobes): 6045 res = 'YES' 5635 res = 'YES' 6046 else: 5636 else: 6047 sysvals.usedevsrc = F 5637 sysvals.usedevsrc = False 6048 pprint(' are kprobes suppo 5638 pprint(' are kprobes supported: %s' % res) 6049 5639 6050 # what data source are we using 5640 # what data source are we using 6051 res = 'DMESG (very limited, ftrace is !! 5641 res = 'DMESG' 6052 if sysvals.useftrace: !! 5642 if(ftgood): 6053 sysvals.usetraceevents = True 5643 sysvals.usetraceevents = True 6054 for e in sysvals.traceevents: 5644 for e in sysvals.traceevents: 6055 if not os.path.exists 5645 if not os.path.exists(sysvals.epath+e): 6056 sysvals.usetr 5646 sysvals.usetraceevents = False 6057 if(sysvals.usetraceevents): 5647 if(sysvals.usetraceevents): 6058 res = 'FTRACE (all tr 5648 res = 'FTRACE (all trace events found)' 6059 pprint(' timeline data source: %s' 5649 pprint(' timeline data source: %s' % res) 6060 5650 6061 # check if rtcwake 5651 # check if rtcwake 6062 res = sysvals.colorText('NO') 5652 res = sysvals.colorText('NO') 6063 if(sysvals.rtcpath != ''): 5653 if(sysvals.rtcpath != ''): 6064 res = 'YES' 5654 res = 'YES' 6065 elif(sysvals.rtcwake): 5655 elif(sysvals.rtcwake): 6066 status = 'rtcwake is not prop 5656 status = 'rtcwake is not properly supported' 6067 pprint(' is rtcwake supported: %s' 5657 pprint(' is rtcwake supported: %s' % res) 6068 5658 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: 5659 if not probecheck: 6081 return status 5660 return status 6082 5661 6083 # verify kprobes 5662 # verify kprobes 6084 if sysvals.usekprobes: 5663 if sysvals.usekprobes: 6085 for name in sysvals.tracefunc 5664 for name in sysvals.tracefuncs: 6086 sysvals.defaultKprobe 5665 sysvals.defaultKprobe(name, sysvals.tracefuncs[name]) 6087 if sysvals.usedevsrc: 5666 if sysvals.usedevsrc: 6088 for name in sysvals.d 5667 for name in sysvals.dev_tracefuncs: 6089 sysvals.defau 5668 sysvals.defaultKprobe(name, sysvals.dev_tracefuncs[name]) 6090 sysvals.addKprobes(True) 5669 sysvals.addKprobes(True) 6091 5670 6092 return status 5671 return status 6093 5672 6094 # Function: doError 5673 # Function: doError 6095 # Description: 5674 # Description: 6096 # generic error function for catastrph 5675 # generic error function for catastrphic failures 6097 # Arguments: 5676 # Arguments: 6098 # msg: the error message to print 5677 # msg: the error message to print 6099 # help: True if printHelp should be ca 5678 # help: True if printHelp should be called after, False otherwise 6100 def doError(msg, help=False): 5679 def doError(msg, help=False): 6101 if(help == True): 5680 if(help == True): 6102 printHelp() 5681 printHelp() 6103 pprint('ERROR: %s\n' % msg) 5682 pprint('ERROR: %s\n' % msg) 6104 sysvals.outputResult({'error':msg}) 5683 sysvals.outputResult({'error':msg}) 6105 sys.exit(1) 5684 sys.exit(1) 6106 5685 6107 # Function: getArgInt 5686 # Function: getArgInt 6108 # Description: 5687 # Description: 6109 # pull out an integer argument from th 5688 # pull out an integer argument from the command line with checks 6110 def getArgInt(name, args, min, max, main=True 5689 def getArgInt(name, args, min, max, main=True): 6111 if main: 5690 if main: 6112 try: 5691 try: 6113 arg = next(args) !! 5692 arg = args.next() 6114 except: 5693 except: 6115 doError(name+': no ar 5694 doError(name+': no argument supplied', True) 6116 else: 5695 else: 6117 arg = args 5696 arg = args 6118 try: 5697 try: 6119 val = int(arg) 5698 val = int(arg) 6120 except: 5699 except: 6121 doError(name+': non-integer v 5700 doError(name+': non-integer value given', True) 6122 if(val < min or val > max): 5701 if(val < min or val > max): 6123 doError(name+': value should 5702 doError(name+': value should be between %d and %d' % (min, max), True) 6124 return val 5703 return val 6125 5704 6126 # Function: getArgFloat 5705 # Function: getArgFloat 6127 # Description: 5706 # Description: 6128 # pull out a float argument from the c 5707 # pull out a float argument from the command line with checks 6129 def getArgFloat(name, args, min, max, main=Tr 5708 def getArgFloat(name, args, min, max, main=True): 6130 if main: 5709 if main: 6131 try: 5710 try: 6132 arg = next(args) !! 5711 arg = args.next() 6133 except: 5712 except: 6134 doError(name+': no ar 5713 doError(name+': no argument supplied', True) 6135 else: 5714 else: 6136 arg = args 5715 arg = args 6137 try: 5716 try: 6138 val = float(arg) 5717 val = float(arg) 6139 except: 5718 except: 6140 doError(name+': non-numerical 5719 doError(name+': non-numerical value given', True) 6141 if(val < min or val > max): 5720 if(val < min or val > max): 6142 doError(name+': value should 5721 doError(name+': value should be between %f and %f' % (min, max), True) 6143 return val 5722 return val 6144 5723 6145 def processData(live=False, quiet=False): !! 5724 def processData(live=False): 6146 if not quiet: !! 5725 pprint('PROCESSING DATA') 6147 pprint('PROCESSING: %s' % sys << 6148 sysvals.vprint('usetraceevents=%s, us 5726 sysvals.vprint('usetraceevents=%s, usetracemarkers=%s, usekprobes=%s' % \ 6149 (sysvals.usetraceevents, sysv 5727 (sysvals.usetraceevents, sysvals.usetracemarkers, sysvals.usekprobes)) 6150 error = '' 5728 error = '' 6151 if(sysvals.usetraceevents): 5729 if(sysvals.usetraceevents): 6152 testruns, error = parseTraceL 5730 testruns, error = parseTraceLog(live) 6153 if sysvals.dmesgfile: 5731 if sysvals.dmesgfile: 6154 for data in testruns: 5732 for data in testruns: 6155 data.extractE 5733 data.extractErrorInfo() 6156 else: 5734 else: 6157 testruns = loadKernelLog() 5735 testruns = loadKernelLog() 6158 for data in testruns: 5736 for data in testruns: 6159 parseKernelLog(data) 5737 parseKernelLog(data) 6160 if(sysvals.ftracefile and (sy 5738 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)): 6161 appendIncompleteTrace 5739 appendIncompleteTraceLog(testruns) 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:') 5740 sysvals.vprint('System Info:') 6168 for key in sorted(sysvals.stamp): 5741 for key in sorted(sysvals.stamp): 6169 if key in shown: !! 5742 sysvals.vprint(' %-8s : %s' % (key.upper(), sysvals.stamp[key])) 6170 sysvals.vprint(' % !! 5743 if sysvals.kparams: >> 5744 sysvals.vprint('Kparams:\n %s' % sysvals.kparams) 6171 sysvals.vprint('Command:\n %s' % s 5745 sysvals.vprint('Command:\n %s' % sysvals.cmdline) 6172 for data in testruns: 5746 for data in testruns: >> 5747 if data.mcelog: >> 5748 sysvals.vprint('MCELOG Data:') >> 5749 for line in data.mcelog.split('\n'): >> 5750 sysvals.vprint(' %s' % line) 6173 if data.turbostat: 5751 if data.turbostat: 6174 idx, s = 0, 'Turbosta 5752 idx, s = 0, 'Turbostat:\n ' 6175 for val in data.turbo 5753 for val in data.turbostat.split('|'): 6176 idx += len(va 5754 idx += len(val) + 1 6177 if idx >= 80: 5755 if idx >= 80: 6178 idx = 5756 idx = 0 6179 s += 5757 s += '\n ' 6180 s += val + ' 5758 s += val + ' ' 6181 sysvals.vprint(s) 5759 sysvals.vprint(s) >> 5760 if data.battery: >> 5761 a1, c1, a2, c2 = data.battery >> 5762 s = 'Battery:\n Before - AC: %s, Charge: %d\n After - AC: %s, Charge: %d' % \ >> 5763 (a1, int(c1), a2, int(c2)) >> 5764 sysvals.vprint(s) >> 5765 if data.wifi: >> 5766 w = data.wifi.replace('|', ' ').split(',') >> 5767 s = 'Wifi:\n Before %s\n After %s' % \ >> 5768 (w[0], w[1]) >> 5769 sysvals.vprint(s) 6182 data.printDetails() 5770 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: 5771 if sysvals.cgdump: 6190 for data in testruns: 5772 for data in testruns: 6191 data.debugPrint() 5773 data.debugPrint() 6192 sys.exit(0) 5774 sys.exit(0) 6193 if len(testruns) < 1: 5775 if len(testruns) < 1: 6194 pprint('ERROR: Not enough tes 5776 pprint('ERROR: Not enough test data to build a timeline') 6195 return (testruns, {'error': ' 5777 return (testruns, {'error': 'timeline generation failed'}) 6196 sysvals.vprint('Creating the html tim 5778 sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile) 6197 createHTML(testruns, error) 5779 createHTML(testruns, error) 6198 if not quiet: !! 5780 pprint('DONE') 6199 pprint('DONE: %s' % sys << 6200 data = testruns[0] 5781 data = testruns[0] 6201 stamp = data.stamp 5782 stamp = data.stamp 6202 stamp['suspend'], stamp['resume'] = d 5783 stamp['suspend'], stamp['resume'] = data.getTimeValues() 6203 if data.fwValid: 5784 if data.fwValid: 6204 stamp['fwsuspend'], stamp['fw 5785 stamp['fwsuspend'], stamp['fwresume'] = data.fwSuspend, data.fwResume 6205 if error: 5786 if error: 6206 stamp['error'] = error 5787 stamp['error'] = error 6207 return (testruns, stamp) 5788 return (testruns, stamp) 6208 5789 6209 # Function: rerunTest 5790 # Function: rerunTest 6210 # Description: 5791 # Description: 6211 # generate an output from an existing 5792 # generate an output from an existing set of ftrace/dmesg logs 6212 def rerunTest(htmlfile=''): 5793 def rerunTest(htmlfile=''): 6213 if sysvals.ftracefile: 5794 if sysvals.ftracefile: 6214 doesTraceLogHaveTraceEvents() 5795 doesTraceLogHaveTraceEvents() 6215 if not sysvals.dmesgfile and not sysv 5796 if not sysvals.dmesgfile and not sysvals.usetraceevents: 6216 doError('recreating this html 5797 doError('recreating this html output requires a dmesg file') 6217 if htmlfile: 5798 if htmlfile: 6218 sysvals.htmlfile = htmlfile 5799 sysvals.htmlfile = htmlfile 6219 else: 5800 else: 6220 sysvals.setOutputFile() 5801 sysvals.setOutputFile() 6221 if os.path.exists(sysvals.htmlfile): 5802 if os.path.exists(sysvals.htmlfile): 6222 if not os.path.isfile(sysvals 5803 if not os.path.isfile(sysvals.htmlfile): 6223 doError('a directory 5804 doError('a directory already exists with this name: %s' % sysvals.htmlfile) 6224 elif not os.access(sysvals.ht 5805 elif not os.access(sysvals.htmlfile, os.W_OK): 6225 doError('missing perm 5806 doError('missing permission to write to %s' % sysvals.htmlfile) 6226 testruns, stamp = processData() !! 5807 testruns, stamp = processData(False) 6227 sysvals.resetlog() !! 5808 sysvals.logmsg = '' 6228 return stamp 5809 return stamp 6229 5810 6230 # Function: runTest 5811 # Function: runTest 6231 # Description: 5812 # Description: 6232 # execute a suspend/resume, gather the 5813 # execute a suspend/resume, gather the logs, and generate the output 6233 def runTest(n=0, quiet=False): !! 5814 def runTest(n=0): 6234 # prepare for the test 5815 # prepare for the test >> 5816 sysvals.initFtrace() 6235 sysvals.initTestOutput('suspend') 5817 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 5818 6251 # execute the test 5819 # execute the test 6252 executeSuspend(quiet) !! 5820 testdata = executeSuspend() 6253 sysvals.cleanupFtrace() 5821 sysvals.cleanupFtrace() 6254 if sysvals.skiphtml: 5822 if sysvals.skiphtml: 6255 sysvals.outputResult({}, n) << 6256 sysvals.sudoUserchown(sysvals 5823 sysvals.sudoUserchown(sysvals.testdir) 6257 return 5824 return 6258 testruns, stamp = processData(True, q !! 5825 if not testdata[0]['error']: 6259 for data in testruns: !! 5826 testruns, stamp = processData(True) 6260 del data !! 5827 for data in testruns: >> 5828 del data >> 5829 else: >> 5830 stamp = testdata[0] >> 5831 6261 sysvals.sudoUserchown(sysvals.testdir 5832 sysvals.sudoUserchown(sysvals.testdir) 6262 sysvals.outputResult(stamp, n) 5833 sysvals.outputResult(stamp, n) 6263 if 'error' in stamp: 5834 if 'error' in stamp: 6264 return 2 5835 return 2 6265 return 0 5836 return 0 6266 5837 6267 def find_in_html(html, start, end, firstonly= 5838 def find_in_html(html, start, end, firstonly=True): 6268 cnt, out, list = len(html), [], [] !! 5839 n, out = 0, [] 6269 if firstonly: !! 5840 while n < len(html): 6270 m = re.search(start, html) !! 5841 m = re.search(start, html[n:]) 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: 5842 if not m: 6280 break 5843 break 6281 e = s + m.start() !! 5844 i = m.end() 6282 str = html[s:e] !! 5845 m = re.search(end, html[n+i:]) >> 5846 if not m: >> 5847 break >> 5848 j = m.start() >> 5849 str = html[n+i:n+i+j] 6283 if end == 'ms': 5850 if end == 'ms': 6284 num = re.search(r'[-+ 5851 num = re.search(r'[-+]?\d*\.\d+|\d+', str) 6285 str = num.group() if 5852 str = num.group() if num else 'NaN' 6286 if firstonly: 5853 if firstonly: 6287 return str 5854 return str 6288 out.append(str) 5855 out.append(str) >> 5856 n += i+j 6289 if firstonly: 5857 if firstonly: 6290 return '' 5858 return '' 6291 return out 5859 return out 6292 5860 6293 def data_from_html(file, outpath, issues, ful 5861 def data_from_html(file, outpath, issues, fulldetail=False): 6294 try: !! 5862 html = open(file, 'r').read() 6295 html = open(file, 'r').read() << 6296 except: << 6297 html = ascii(open(file, 'rb') << 6298 sysvals.htmlfile = os.path.relpath(fi 5863 sysvals.htmlfile = os.path.relpath(file, outpath) 6299 # extract general info 5864 # extract general info 6300 suspend = find_in_html(html, 'Kernel 5865 suspend = find_in_html(html, 'Kernel Suspend', 'ms') 6301 resume = find_in_html(html, 'Kernel R 5866 resume = find_in_html(html, 'Kernel Resume', 'ms') 6302 sysinfo = find_in_html(html, '<div cl 5867 sysinfo = find_in_html(html, '<div class="stamp sysinfo">', '</div>') 6303 line = find_in_html(html, '<div class 5868 line = find_in_html(html, '<div class="stamp">', '</div>') 6304 stmp = line.split() 5869 stmp = line.split() 6305 if not suspend or not resume or len(s 5870 if not suspend or not resume or len(stmp) != 8: 6306 return False 5871 return False 6307 try: 5872 try: 6308 dt = datetime.strptime(' '.jo 5873 dt = datetime.strptime(' '.join(stmp[3:]), '%B %d %Y, %I:%M:%S %p') 6309 except: 5874 except: 6310 return False 5875 return False 6311 sysvals.hostname = stmp[0] 5876 sysvals.hostname = stmp[0] 6312 tstr = dt.strftime('%Y/%m/%d %H:%M:%S 5877 tstr = dt.strftime('%Y/%m/%d %H:%M:%S') 6313 error = find_in_html(html, '<table cl 5878 error = find_in_html(html, '<table class="testfail"><tr><td>', '</td>') 6314 if error: 5879 if error: 6315 m = re.match(r'[a-z0-9]* fail !! 5880 m = re.match('[a-z]* failed in (?P<p>[a-z0-9_]*) phase', error) 6316 if m: 5881 if m: 6317 result = 'fail in %s' 5882 result = 'fail in %s' % m.group('p') 6318 else: 5883 else: 6319 result = 'fail' 5884 result = 'fail' 6320 else: 5885 else: 6321 result = 'pass' 5886 result = 'pass' 6322 # extract error info 5887 # extract error info 6323 tp, ilist = False, [] !! 5888 ilist = [] 6324 extra = dict() 5889 extra = dict() 6325 log = find_in_html(html, '<div id="dm 5890 log = find_in_html(html, '<div id="dmesglog" style="display:none;">', 6326 '</div>').strip() 5891 '</div>').strip() 6327 if log: 5892 if log: 6328 d = Data(0) 5893 d = Data(0) 6329 d.end = 999999999 5894 d.end = 999999999 6330 d.dmesgtext = log.split('\n') 5895 d.dmesgtext = log.split('\n') 6331 tp = d.extractErrorInfo() !! 5896 msglist = d.extractErrorInfo() 6332 if len(issues) < 100: !! 5897 for msg in msglist: 6333 for msg in tp.msglist !! 5898 sysvals.errorSummary(issues, msg) 6334 sysvals.error << 6335 if stmp[2] == 'freeze': 5899 if stmp[2] == 'freeze': 6336 extra = d.turbostatIn 5900 extra = d.turbostatInfo() 6337 elist = dict() 5901 elist = dict() 6338 for dir in d.errorinfo: 5902 for dir in d.errorinfo: 6339 for err in d.errorinf 5903 for err in d.errorinfo[dir]: 6340 if err[0] not 5904 if err[0] not in elist: 6341 elist 5905 elist[err[0]] = 0 6342 elist[err[0]] 5906 elist[err[0]] += 1 6343 for i in elist: 5907 for i in elist: 6344 ilist.append('%sx%d' 5908 ilist.append('%sx%d' % (i, elist[i]) if elist[i] > 1 else i) 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 5909 low = find_in_html(html, 'freeze time: <b>', ' ms</b>') 6357 for lowstr in ['waking', '+']: !! 5910 if low and '|' in low: 6358 if not low: !! 5911 issue = 'FREEZEx%d' % len(low.split('|')) 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 5912 match = [i for i in issues if i['match'] == issue] 6368 if len(match) > 0: 5913 if len(match) > 0: 6369 match[0]['count'] += 5914 match[0]['count'] += 1 6370 if sysvals.hostname n 5915 if sysvals.hostname not in match[0]['urls']: 6371 match[0]['url 5916 match[0]['urls'][sysvals.hostname] = [sysvals.htmlfile] 6372 elif sysvals.htmlfile 5917 elif sysvals.htmlfile not in match[0]['urls'][sysvals.hostname]: 6373 match[0]['url 5918 match[0]['urls'][sysvals.hostname].append(sysvals.htmlfile) 6374 else: 5919 else: 6375 issues.append({ 5920 issues.append({ 6376 'match': issu 5921 'match': issue, 'count': 1, 'line': issue, 6377 'urls': {sysv 5922 'urls': {sysvals.hostname: [sysvals.htmlfile]}, 6378 }) 5923 }) 6379 ilist.append(issue) 5924 ilist.append(issue) 6380 # extract device info 5925 # extract device info 6381 devices = dict() 5926 devices = dict() 6382 for line in html.split('\n'): 5927 for line in html.split('\n'): 6383 m = re.match(r' *<div id=\"[a !! 5928 m = re.match(' *<div id=\"[a,0-9]*\" *title=\"(?P<title>.*)\" class=\"thread.*', line) 6384 if not m or 'thread kth' in l 5929 if not m or 'thread kth' in line or 'thread sec' in line: 6385 continue 5930 continue 6386 m = re.match(r'(?P<n>.*) \((? !! 5931 m = re.match('(?P<n>.*) \((?P<t>[0-9,\.]*) ms\) (?P<p>.*)', m.group('title')) 6387 if not m: 5932 if not m: 6388 continue 5933 continue 6389 name, time, phase = m.group(' 5934 name, time, phase = m.group('n'), m.group('t'), m.group('p') 6390 if name == 'async_synchronize << 6391 continue << 6392 if ' async' in name or ' sync 5935 if ' async' in name or ' sync' in name: 6393 name = ' '.join(name. 5936 name = ' '.join(name.split(' ')[:-1]) 6394 if phase.startswith('suspend' 5937 if phase.startswith('suspend'): 6395 d = 'suspend' 5938 d = 'suspend' 6396 elif phase.startswith('resume 5939 elif phase.startswith('resume'): 6397 d = 'resume' 5940 d = 'resume' 6398 else: 5941 else: 6399 continue 5942 continue 6400 if d not in devices: 5943 if d not in devices: 6401 devices[d] = dict() 5944 devices[d] = dict() 6402 if name not in devices[d]: 5945 if name not in devices[d]: 6403 devices[d][name] = 0. 5946 devices[d][name] = 0.0 6404 devices[d][name] += float(tim 5947 devices[d][name] += float(time) 6405 # create worst device info 5948 # create worst device info 6406 worst = dict() 5949 worst = dict() 6407 for d in ['suspend', 'resume']: 5950 for d in ['suspend', 'resume']: 6408 worst[d] = {'name':'', 'time' 5951 worst[d] = {'name':'', 'time': 0.0} 6409 dev = devices[d] if d in devi 5952 dev = devices[d] if d in devices else 0 6410 if dev and len(dev.keys()) > 5953 if dev and len(dev.keys()) > 0: 6411 n = sorted(dev, key=l !! 5954 n = sorted(dev, key=dev.get, reverse=True)[0] 6412 worst[d]['name'], wor 5955 worst[d]['name'], worst[d]['time'] = n, dev[n] 6413 data = { 5956 data = { 6414 'mode': stmp[2], 5957 'mode': stmp[2], 6415 'host': stmp[0], 5958 'host': stmp[0], 6416 'kernel': stmp[1], 5959 'kernel': stmp[1], 6417 'sysinfo': sysinfo, 5960 'sysinfo': sysinfo, 6418 'time': tstr, 5961 'time': tstr, 6419 'result': result, 5962 'result': result, 6420 'issues': ' '.join(ilist), 5963 'issues': ' '.join(ilist), 6421 'suspend': suspend, 5964 'suspend': suspend, 6422 'resume': resume, 5965 'resume': resume, 6423 'devlist': devices, 5966 'devlist': devices, 6424 'sus_worst': worst['suspend'] 5967 'sus_worst': worst['suspend']['name'], 6425 'sus_worsttime': worst['suspe 5968 'sus_worsttime': worst['suspend']['time'], 6426 'res_worst': worst['resume'][ 5969 'res_worst': worst['resume']['name'], 6427 'res_worsttime': worst['resum 5970 'res_worsttime': worst['resume']['time'], 6428 'url': sysvals.htmlfile, 5971 'url': sysvals.htmlfile, 6429 } 5972 } 6430 for key in extra: 5973 for key in extra: 6431 data[key] = extra[key] 5974 data[key] = extra[key] 6432 if fulldetail: 5975 if fulldetail: 6433 data['funclist'] = find_in_ht 5976 data['funclist'] = find_in_html(html, '<div title="', '" class="traceevent"', False) 6434 if tp: << 6435 for arg in ['-multi ', '-info << 6436 if arg in tp.cmdline: << 6437 data['target' << 6438 break << 6439 return data 5977 return data 6440 5978 6441 def genHtml(subdir, force=False): !! 5979 def genHtml(subdir): 6442 for dirname, dirnames, filenames in o 5980 for dirname, dirnames, filenames in os.walk(subdir): 6443 sysvals.dmesgfile = sysvals.f 5981 sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = '' 6444 for filename in filenames: 5982 for filename in filenames: 6445 file = os.path.join(d !! 5983 if(re.match('.*_dmesg.txt', filename)): 6446 if sysvals.usable(fil !! 5984 sysvals.dmesgfile = os.path.join(dirname, filename) 6447 if(re.match(r !! 5985 elif(re.match('.*_ftrace.txt', filename)): 6448 sysva !! 5986 sysvals.ftracefile = os.path.join(dirname, filename) 6449 elif(re.match << 6450 sysva << 6451 sysvals.setOutputFile() 5987 sysvals.setOutputFile() 6452 if (sysvals.dmesgfile or sysv !! 5988 if sysvals.ftracefile and sysvals.htmlfile and \ 6453 (force or not sysvals !! 5989 not os.path.exists(sysvals.htmlfile): 6454 pprint('FTRACE: %s' % 5990 pprint('FTRACE: %s' % sysvals.ftracefile) 6455 if sysvals.dmesgfile: 5991 if sysvals.dmesgfile: 6456 pprint('DMESG 5992 pprint('DMESG : %s' % sysvals.dmesgfile) 6457 rerunTest() 5993 rerunTest() 6458 5994 6459 # Function: runSummary 5995 # Function: runSummary 6460 # Description: 5996 # Description: 6461 # create a summary of tests in a sub-d 5997 # create a summary of tests in a sub-directory 6462 def runSummary(subdir, local=True, genhtml=Fa 5998 def runSummary(subdir, local=True, genhtml=False): 6463 inpath = os.path.abspath(subdir) 5999 inpath = os.path.abspath(subdir) 6464 outpath = os.path.abspath('.') if loc 6000 outpath = os.path.abspath('.') if local else inpath 6465 pprint('Generating a summary of folde 6001 pprint('Generating a summary of folder:\n %s' % inpath) 6466 if genhtml: 6002 if genhtml: 6467 genHtml(subdir) 6003 genHtml(subdir) 6468 target, issues, testruns = '', [], [] !! 6004 issues = [] >> 6005 testruns = [] 6469 desc = {'host':[],'mode':[],'kernel': 6006 desc = {'host':[],'mode':[],'kernel':[]} 6470 for dirname, dirnames, filenames in o 6007 for dirname, dirnames, filenames in os.walk(subdir): 6471 for filename in filenames: 6008 for filename in filenames: 6472 if(not re.match(r'.*. !! 6009 if(not re.match('.*.html', filename)): 6473 continue 6010 continue 6474 data = data_from_html 6011 data = data_from_html(os.path.join(dirname, filename), outpath, issues) 6475 if(not data): 6012 if(not data): 6476 continue 6013 continue 6477 if 'target' in data: << 6478 target = data << 6479 testruns.append(data) 6014 testruns.append(data) 6480 for key in desc: 6015 for key in desc: 6481 if data[key] 6016 if data[key] not in desc[key]: 6482 desc[ 6017 desc[key].append(data[key]) 6483 pprint('Summary files:') 6018 pprint('Summary files:') 6484 if len(desc['host']) == len(desc['mod 6019 if len(desc['host']) == len(desc['mode']) == len(desc['kernel']) == 1: 6485 title = '%s %s %s' % (desc['h 6020 title = '%s %s %s' % (desc['host'][0], desc['kernel'][0], desc['mode'][0]) 6486 if target: << 6487 title += ' %s' % targ << 6488 else: 6021 else: 6489 title = inpath 6022 title = inpath 6490 createHTMLSummarySimple(testruns, os. 6023 createHTMLSummarySimple(testruns, os.path.join(outpath, 'summary.html'), title) 6491 pprint(' summary.html - tab 6024 pprint(' summary.html - tabular list of test data found') 6492 createHTMLDeviceSummary(testruns, os. 6025 createHTMLDeviceSummary(testruns, os.path.join(outpath, 'summary-devices.html'), title) 6493 pprint(' summary-devices.html - ker 6026 pprint(' summary-devices.html - kernel device list sorted by total execution time') 6494 createHTMLIssuesSummary(testruns, iss 6027 createHTMLIssuesSummary(testruns, issues, os.path.join(outpath, 'summary-issues.html'), title) 6495 pprint(' summary-issues.html - ker 6028 pprint(' summary-issues.html - kernel issues found sorted by frequency') 6496 6029 6497 # Function: checkArgBool 6030 # Function: checkArgBool 6498 # Description: 6031 # Description: 6499 # check if a boolean string value is t 6032 # check if a boolean string value is true or false 6500 def checkArgBool(name, value): 6033 def checkArgBool(name, value): 6501 if value in switchvalues: 6034 if value in switchvalues: 6502 if value in switchoff: 6035 if value in switchoff: 6503 return False 6036 return False 6504 return True 6037 return True 6505 doError('invalid boolean --> (%s: %s) 6038 doError('invalid boolean --> (%s: %s), use "true/false" or "1/0"' % (name, value), True) 6506 return False 6039 return False 6507 6040 6508 # Function: configFromFile 6041 # Function: configFromFile 6509 # Description: 6042 # Description: 6510 # Configure the script via the info in 6043 # Configure the script via the info in a config file 6511 def configFromFile(file): 6044 def configFromFile(file): 6512 Config = configparser.ConfigParser() !! 6045 Config = ConfigParser.ConfigParser() 6513 6046 6514 Config.read(file) 6047 Config.read(file) 6515 sections = Config.sections() 6048 sections = Config.sections() 6516 overridekprobes = False 6049 overridekprobes = False 6517 overridedevkprobes = False 6050 overridedevkprobes = False 6518 if 'Settings' in sections: 6051 if 'Settings' in sections: 6519 for opt in Config.options('Se 6052 for opt in Config.options('Settings'): 6520 value = Config.get('S 6053 value = Config.get('Settings', opt).lower() 6521 option = opt.lower() 6054 option = opt.lower() 6522 if(option == 'verbose 6055 if(option == 'verbose'): 6523 sysvals.verbo 6056 sysvals.verbose = checkArgBool(option, value) 6524 elif(option == 'addlo 6057 elif(option == 'addlogs'): 6525 sysvals.dmesg 6058 sysvals.dmesglog = sysvals.ftracelog = checkArgBool(option, value) 6526 elif(option == 'dev') 6059 elif(option == 'dev'): 6527 sysvals.usede 6060 sysvals.usedevsrc = checkArgBool(option, value) 6528 elif(option == 'proc' 6061 elif(option == 'proc'): 6529 sysvals.usepr 6062 sysvals.useprocmon = checkArgBool(option, value) 6530 elif(option == 'x2'): 6063 elif(option == 'x2'): 6531 if checkArgBo 6064 if checkArgBool(option, value): 6532 sysva 6065 sysvals.execcount = 2 6533 elif(option == 'callg 6066 elif(option == 'callgraph'): 6534 sysvals.useca 6067 sysvals.usecallgraph = checkArgBool(option, value) 6535 elif(option == 'overr 6068 elif(option == 'override-timeline-functions'): 6536 overridekprob 6069 overridekprobes = checkArgBool(option, value) 6537 elif(option == 'overr 6070 elif(option == 'override-dev-timeline-functions'): 6538 overridedevkp 6071 overridedevkprobes = checkArgBool(option, value) 6539 elif(option == 'skiph 6072 elif(option == 'skiphtml'): 6540 sysvals.skiph 6073 sysvals.skiphtml = checkArgBool(option, value) 6541 elif(option == 'sync' 6074 elif(option == 'sync'): 6542 sysvals.sync 6075 sysvals.sync = checkArgBool(option, value) 6543 elif(option == 'rs' o 6076 elif(option == 'rs' or option == 'runtimesuspend'): 6544 if value in s 6077 if value in switchvalues: 6545 if va 6078 if value in switchoff: 6546 6079 sysvals.rs = -1 6547 else: 6080 else: 6548 6081 sysvals.rs = 1 6549 else: 6082 else: 6550 doErr 6083 doError('invalid value --> (%s: %s), use "enable/disable"' % (option, value), True) 6551 elif(option == 'displ 6084 elif(option == 'display'): 6552 disopt = ['on 6085 disopt = ['on', 'off', 'standby', 'suspend'] 6553 if value not 6086 if value not in disopt: 6554 doErr 6087 doError('invalid value --> (%s: %s), use %s' % (option, value, disopt), True) 6555 sysvals.displ 6088 sysvals.display = value 6556 elif(option == 'gzip' 6089 elif(option == 'gzip'): 6557 sysvals.gzip 6090 sysvals.gzip = checkArgBool(option, value) 6558 elif(option == 'cgfil 6091 elif(option == 'cgfilter'): 6559 sysvals.setCa 6092 sysvals.setCallgraphFilter(value) 6560 elif(option == 'cgski 6093 elif(option == 'cgskip'): 6561 if value in s 6094 if value in switchoff: 6562 sysva 6095 sysvals.cgskip = '' 6563 else: 6096 else: 6564 sysva 6097 sysvals.cgskip = sysvals.configFile(val) 6565 if(no 6098 if(not sysvals.cgskip): 6566 6099 doError('%s does not exist' % sysvals.cgskip) 6567 elif(option == 'cgtes 6100 elif(option == 'cgtest'): 6568 sysvals.cgtes 6101 sysvals.cgtest = getArgInt('cgtest', value, 0, 1, False) 6569 elif(option == 'cgpha 6102 elif(option == 'cgphase'): 6570 d = Data(0) 6103 d = Data(0) 6571 if value not !! 6104 if value not in d.sortedPhases(): 6572 doErr 6105 doError('invalid phase --> (%s: %s), valid phases are %s'\ 6573 !! 6106 % (option, value, d.sortedPhases()), True) 6574 sysvals.cgpha 6107 sysvals.cgphase = value 6575 elif(option == 'fadd' 6108 elif(option == 'fadd'): 6576 file = sysval 6109 file = sysvals.configFile(value) 6577 if(not file): 6110 if(not file): 6578 doErr 6111 doError('%s does not exist' % value) 6579 sysvals.addFt 6112 sysvals.addFtraceFilterFunctions(file) 6580 elif(option == 'resul 6113 elif(option == 'result'): 6581 sysvals.resul 6114 sysvals.result = value 6582 elif(option == 'multi 6115 elif(option == 'multi'): 6583 nums = value. 6116 nums = value.split() 6584 if len(nums) 6117 if len(nums) != 2: 6585 doErr 6118 doError('multi requires 2 integers (exec_count and delay)', True) 6586 sysvals.multi !! 6119 sysvals.multitest['run'] = True >> 6120 sysvals.multitest['count'] = getArgInt('multi: n d (exec count)', nums[0], 2, 1000000, False) >> 6121 sysvals.multitest['delay'] = getArgInt('multi: n d (delay between tests)', nums[1], 0, 3600, False) 6587 elif(option == 'devic 6122 elif(option == 'devicefilter'): 6588 sysvals.setDe 6123 sysvals.setDeviceFilter(value) 6589 elif(option == 'expan 6124 elif(option == 'expandcg'): 6590 sysvals.cgexp 6125 sysvals.cgexp = checkArgBool(option, value) 6591 elif(option == 'srgap 6126 elif(option == 'srgap'): 6592 if checkArgBo 6127 if checkArgBool(option, value): 6593 sysva 6128 sysvals.srgap = 5 6594 elif(option == 'mode' 6129 elif(option == 'mode'): 6595 sysvals.suspe 6130 sysvals.suspendmode = value 6596 elif(option == 'comma 6131 elif(option == 'command' or option == 'cmd'): 6597 sysvals.testc 6132 sysvals.testcommand = value 6598 elif(option == 'x2del 6133 elif(option == 'x2delay'): 6599 sysvals.x2del 6134 sysvals.x2delay = getArgInt('x2delay', value, 0, 60000, False) 6600 elif(option == 'prede 6135 elif(option == 'predelay'): 6601 sysvals.prede 6136 sysvals.predelay = getArgInt('predelay', value, 0, 60000, False) 6602 elif(option == 'postd 6137 elif(option == 'postdelay'): 6603 sysvals.postd 6138 sysvals.postdelay = getArgInt('postdelay', value, 0, 60000, False) 6604 elif(option == 'maxde 6139 elif(option == 'maxdepth'): 6605 sysvals.max_g 6140 sysvals.max_graph_depth = getArgInt('maxdepth', value, 0, 1000, False) 6606 elif(option == 'rtcwa 6141 elif(option == 'rtcwake'): 6607 if value in s 6142 if value in switchoff: 6608 sysva 6143 sysvals.rtcwake = False 6609 else: 6144 else: 6610 sysva 6145 sysvals.rtcwake = True 6611 sysva 6146 sysvals.rtcwaketime = getArgInt('rtcwake', value, 0, 3600, False) 6612 elif(option == 'timep 6147 elif(option == 'timeprec'): 6613 sysvals.setPr 6148 sysvals.setPrecision(getArgInt('timeprec', value, 0, 6, False)) 6614 elif(option == 'minde 6149 elif(option == 'mindev'): 6615 sysvals.minde 6150 sysvals.mindevlen = getArgFloat('mindev', value, 0.0, 10000.0, False) 6616 elif(option == 'calll 6151 elif(option == 'callloop-maxgap'): 6617 sysvals.calll 6152 sysvals.callloopmaxgap = getArgFloat('callloop-maxgap', value, 0.0, 1.0, False) 6618 elif(option == 'calll 6153 elif(option == 'callloop-maxlen'): 6619 sysvals.calll 6154 sysvals.callloopmaxgap = getArgFloat('callloop-maxlen', value, 0.0, 1.0, False) 6620 elif(option == 'mincg 6155 elif(option == 'mincg'): 6621 sysvals.mincg 6156 sysvals.mincglen = getArgFloat('mincg', value, 0.0, 10000.0, False) 6622 elif(option == 'bufsi 6157 elif(option == 'bufsize'): 6623 sysvals.bufsi 6158 sysvals.bufsize = getArgInt('bufsize', value, 1, 1024*1024*8, False) 6624 elif(option == 'outpu 6159 elif(option == 'output-dir'): 6625 sysvals.outdi 6160 sysvals.outdir = sysvals.setOutputFolder(value) 6626 6161 6627 if sysvals.suspendmode == 'command' a 6162 if sysvals.suspendmode == 'command' and not sysvals.testcommand: 6628 doError('No command supplied 6163 doError('No command supplied for mode "command"') 6629 6164 6630 # compatibility errors 6165 # compatibility errors 6631 if sysvals.usedevsrc and sysvals.usec 6166 if sysvals.usedevsrc and sysvals.usecallgraph: 6632 doError('-dev is not compatib 6167 doError('-dev is not compatible with -f') 6633 if sysvals.usecallgraph and sysvals.u 6168 if sysvals.usecallgraph and sysvals.useprocmon: 6634 doError('-proc is not compati 6169 doError('-proc is not compatible with -f') 6635 6170 6636 if overridekprobes: 6171 if overridekprobes: 6637 sysvals.tracefuncs = dict() 6172 sysvals.tracefuncs = dict() 6638 if overridedevkprobes: 6173 if overridedevkprobes: 6639 sysvals.dev_tracefuncs = dict 6174 sysvals.dev_tracefuncs = dict() 6640 6175 6641 kprobes = dict() 6176 kprobes = dict() 6642 kprobesec = 'dev_timeline_functions_' 6177 kprobesec = 'dev_timeline_functions_'+platform.machine() 6643 if kprobesec in sections: 6178 if kprobesec in sections: 6644 for name in Config.options(kp 6179 for name in Config.options(kprobesec): 6645 text = Config.get(kpr 6180 text = Config.get(kprobesec, name) 6646 kprobes[name] = (text 6181 kprobes[name] = (text, True) 6647 kprobesec = 'timeline_functions_'+pla 6182 kprobesec = 'timeline_functions_'+platform.machine() 6648 if kprobesec in sections: 6183 if kprobesec in sections: 6649 for name in Config.options(kp 6184 for name in Config.options(kprobesec): 6650 if name in kprobes: 6185 if name in kprobes: 6651 doError('Dupl 6186 doError('Duplicate timeline function found "%s"' % (name)) 6652 text = Config.get(kpr 6187 text = Config.get(kprobesec, name) 6653 kprobes[name] = (text 6188 kprobes[name] = (text, False) 6654 6189 6655 for name in kprobes: 6190 for name in kprobes: 6656 function = name 6191 function = name 6657 format = name 6192 format = name 6658 color = '' 6193 color = '' 6659 args = dict() 6194 args = dict() 6660 text, dev = kprobes[name] 6195 text, dev = kprobes[name] 6661 data = text.split() 6196 data = text.split() 6662 i = 0 6197 i = 0 6663 for val in data: 6198 for val in data: 6664 # bracketted strings 6199 # bracketted strings are special formatting, read them separately 6665 if val[0] == '[' and 6200 if val[0] == '[' and val[-1] == ']': 6666 for prop in v 6201 for prop in val[1:-1].split(','): 6667 p = p 6202 p = prop.split('=') 6668 if p[ 6203 if p[0] == 'color': 6669 6204 try: 6670 6205 color = int(p[1], 16) 6671 6206 color = '#'+p[1] 6672 6207 except: 6673 6208 color = p[1] 6674 continue 6209 continue 6675 # first real arg shou 6210 # first real arg should be the format string 6676 if i == 0: 6211 if i == 0: 6677 format = val 6212 format = val 6678 # all other args are 6213 # all other args are actual function args 6679 else: 6214 else: 6680 d = val.split 6215 d = val.split('=') 6681 args[d[0]] = 6216 args[d[0]] = d[1] 6682 i += 1 6217 i += 1 6683 if not function or not format 6218 if not function or not format: 6684 doError('Invalid kpro 6219 doError('Invalid kprobe: %s' % name) 6685 for arg in re.findall('{(?P<n 6220 for arg in re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', format): 6686 if arg not in args: 6221 if arg not in args: 6687 doError('Kpro 6222 doError('Kprobe "%s" is missing argument "%s"' % (name, arg)) 6688 if (dev and name in sysvals.d 6223 if (dev and name in sysvals.dev_tracefuncs) or (not dev and name in sysvals.tracefuncs): 6689 doError('Duplicate ti 6224 doError('Duplicate timeline function found "%s"' % (name)) 6690 6225 6691 kp = { 6226 kp = { 6692 'name': name, 6227 'name': name, 6693 'func': function, 6228 'func': function, 6694 'format': format, 6229 'format': format, 6695 sysvals.archargs: arg 6230 sysvals.archargs: args 6696 } 6231 } 6697 if color: 6232 if color: 6698 kp['color'] = color 6233 kp['color'] = color 6699 if dev: 6234 if dev: 6700 sysvals.dev_tracefunc 6235 sysvals.dev_tracefuncs[name] = kp 6701 else: 6236 else: 6702 sysvals.tracefuncs[na 6237 sysvals.tracefuncs[name] = kp 6703 6238 6704 # Function: printHelp 6239 # Function: printHelp 6705 # Description: 6240 # Description: 6706 # print out the help text 6241 # print out the help text 6707 def printHelp(): 6242 def printHelp(): 6708 pprint('\n%s v%s\n'\ 6243 pprint('\n%s v%s\n'\ 6709 'Usage: sudo sleepgraph <options> <co 6244 'Usage: sudo sleepgraph <options> <commands>\n'\ 6710 '\n'\ 6245 '\n'\ 6711 'Description:\n'\ 6246 'Description:\n'\ 6712 ' This tool is designed to assist ke 6247 ' This tool is designed to assist kernel and OS developers in optimizing\n'\ 6713 ' their linux stack\'s suspend/resum 6248 ' their linux stack\'s suspend/resume time. Using a kernel image built\n'\ 6714 ' with a few extra options enabled, 6249 ' with a few extra options enabled, the tool will execute a suspend and\n'\ 6715 ' capture dmesg and ftrace data unti 6250 ' capture dmesg and ftrace data until resume is complete. This data is\n'\ 6716 ' transformed into a device timeline 6251 ' transformed into a device timeline and an optional callgraph to give\n'\ 6717 ' a detailed view of which devices/s 6252 ' a detailed view of which devices/subsystems are taking the most\n'\ 6718 ' time in suspend/resume.\n'\ 6253 ' time in suspend/resume.\n'\ 6719 '\n'\ 6254 '\n'\ 6720 ' If no specific command is given, t 6255 ' If no specific command is given, the default behavior is to initiate\n'\ 6721 ' a suspend/resume and capture the d 6256 ' a suspend/resume and capture the dmesg/ftrace output as an html timeline.\n'\ 6722 '\n'\ 6257 '\n'\ 6723 ' Generates output files in subdirec 6258 ' Generates output files in subdirectory: suspend-yymmdd-HHMMSS\n'\ 6724 ' HTML output: < 6259 ' HTML output: <hostname>_<mode>.html\n'\ 6725 ' raw dmesg output: < 6260 ' raw dmesg output: <hostname>_<mode>_dmesg.txt\n'\ 6726 ' raw ftrace output: < 6261 ' raw ftrace output: <hostname>_<mode>_ftrace.txt\n'\ 6727 '\n'\ 6262 '\n'\ 6728 'Options:\n'\ 6263 'Options:\n'\ 6729 ' -h Print this help text 6264 ' -h Print this help text\n'\ 6730 ' -v Print the current to 6265 ' -v Print the current tool version\n'\ 6731 ' -config fn Pull arguments and c 6266 ' -config fn Pull arguments and config options from file fn\n'\ 6732 ' -verbose Print extra informat 6267 ' -verbose Print extra information during execution and analysis\n'\ 6733 ' -m mode Mode to initiate for 6268 ' -m mode Mode to initiate for suspend (default: %s)\n'\ 6734 ' -o name Overrides the output 6269 ' -o name Overrides the output subdirectory name when running a new test\n'\ 6735 ' default: suspend-{da 6270 ' default: suspend-{date}-{time}\n'\ 6736 ' -rtcwake t Wakeup t seconds aft 6271 ' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)\n'\ 6737 ' -addlogs Add the dmesg and ft 6272 ' -addlogs Add the dmesg and ftrace logs to the html output\n'\ 6738 ' -noturbostat Dont use turbostat i !! 6273 ' -turbostat Use turbostat to execute the command in freeze mode (default: disabled)\n'\ 6739 ' -srgap Add a visible gap in 6274 ' -srgap Add a visible gap in the timeline between sus/res (default: disabled)\n'\ 6740 ' -skiphtml Run the test and cap 6275 ' -skiphtml Run the test and capture the trace logs, but skip the timeline (default: disabled)\n'\ 6741 ' -result fn Export a results tab 6276 ' -result fn Export a results table to a text file for parsing.\n'\ 6742 ' -wifi If a wifi connection << 6743 ' -wifitrace Trace kernel executi << 6744 ' -netfix Use netfix to reset << 6745 ' [testprep]\n'\ 6277 ' [testprep]\n'\ 6746 ' -sync Sync the filesystems 6278 ' -sync Sync the filesystems before starting the test\n'\ 6747 ' -rs on/off Enable/disable runti 6279 ' -rs on/off Enable/disable runtime suspend for all devices, restore all after test\n'\ 6748 ' -display m Change the display m 6280 ' -display m Change the display mode to m for the test (on/off/standby/suspend)\n'\ 6749 ' [advanced]\n'\ 6281 ' [advanced]\n'\ 6750 ' -gzip Gzip the trace and d 6282 ' -gzip Gzip the trace and dmesg logs to save space\n'\ 6751 ' -cmd {s} Run the timeline ove 6283 ' -cmd {s} Run the timeline over a custom command, e.g. "sync -d"\n'\ 6752 ' -proc Add usermode process 6284 ' -proc Add usermode process info into the timeline (default: disabled)\n'\ 6753 ' -dev Add kernel function 6285 ' -dev Add kernel function calls and threads to the timeline (default: disabled)\n'\ 6754 ' -x2 Run two suspend/resu 6286 ' -x2 Run two suspend/resumes back to back (default: disabled)\n'\ 6755 ' -x2delay t Include t ms delay b 6287 ' -x2delay t Include t ms delay between multiple test runs (default: 0 ms)\n'\ 6756 ' -predelay t Include t ms delay b 6288 ' -predelay t Include t ms delay before 1st suspend (default: 0 ms)\n'\ 6757 ' -postdelay t Include t ms delay a 6289 ' -postdelay t Include t ms delay after last resume (default: 0 ms)\n'\ 6758 ' -mindev ms Discard all device b 6290 ' -mindev ms Discard all device blocks shorter than ms milliseconds (e.g. 0.001 for us)\n'\ 6759 ' -multi n d Execute <n> consecut !! 6291 ' -multi n d Execute <n> consecutive tests at <d> seconds intervals. The outputs will\n'\ 6760 ' by a "d", "h", or "m !! 6292 ' be created in a new subdirectory with a summary page.\n'\ 6761 ' The outputs will be << 6762 ' -maxfail n Abort a -multi run a << 6763 ' [debug]\n'\ 6293 ' [debug]\n'\ 6764 ' -f Use ftrace to create 6294 ' -f Use ftrace to create device callgraphs (default: disabled)\n'\ 6765 ' -ftop Use ftrace on the to 6295 ' -ftop Use ftrace on the top level call: "%s" (default: disabled)\n'\ 6766 ' -maxdepth N limit the callgraph 6296 ' -maxdepth N limit the callgraph data to N call levels (default: 0=all)\n'\ 6767 ' -expandcg pre-expand the callg 6297 ' -expandcg pre-expand the callgraph data in the html output (default: disabled)\n'\ 6768 ' -fadd file Add functions to be 6298 ' -fadd file Add functions to be graphed in the timeline from a list in a text file\n'\ 6769 ' -filter "d1,d2,..." Filter out al 6299 ' -filter "d1,d2,..." Filter out all but this comma-delimited list of device names\n'\ 6770 ' -mincg ms Discard all callgrap 6300 ' -mincg ms Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)\n'\ 6771 ' -cgphase P Only show callgraph 6301 ' -cgphase P Only show callgraph data for phase P (e.g. suspend_late)\n'\ 6772 ' -cgtest N Only show callgraph 6302 ' -cgtest N Only show callgraph data for test N (e.g. 0 or 1 in an x2 run)\n'\ 6773 ' -timeprec N Number of significan 6303 ' -timeprec N Number of significant digits in timestamps (0:S, [3:ms], 6:us)\n'\ 6774 ' -cgfilter S Filter the callgraph 6304 ' -cgfilter S Filter the callgraph output in the timeline\n'\ 6775 ' -cgskip file Callgraph functions 6305 ' -cgskip file Callgraph functions to skip, off to disable (default: cgskip.txt)\n'\ 6776 ' -bufsize N Set trace buffer siz 6306 ' -bufsize N Set trace buffer size to N kilo-bytes (default: all of free memory)\n'\ 6777 ' -devdump Print out all the ra 6307 ' -devdump Print out all the raw device data for each phase\n'\ 6778 ' -cgdump Print out all the ra 6308 ' -cgdump Print out all the raw callgraph data\n'\ 6779 '\n'\ 6309 '\n'\ 6780 'Other commands:\n'\ 6310 'Other commands:\n'\ 6781 ' -modes List available suspe 6311 ' -modes List available suspend modes\n'\ 6782 ' -status Test to see if the s 6312 ' -status Test to see if the system is enabled to run this tool\n'\ 6783 ' -fpdt Print out the conten 6313 ' -fpdt Print out the contents of the ACPI Firmware Performance Data Table\n'\ 6784 ' -wificheck Print out wifi conne !! 6314 ' -battery Print out battery info (if available)\n'\ >> 6315 ' -wifi Print out wifi connection info (if wireless-tools and device exists)\n'\ 6785 ' -x<mode> Test xset by togglin 6316 ' -x<mode> Test xset by toggling the given mode (on/off/standby/suspend)\n'\ 6786 ' -sysinfo Print out system inf 6317 ' -sysinfo Print out system info extracted from BIOS\n'\ 6787 ' -devinfo Print out the pm set 6318 ' -devinfo Print out the pm settings of all devices which support runtime suspend\n'\ 6788 ' -cmdinfo Print out all the pl << 6789 ' -flist Print the list of fu 6319 ' -flist Print the list of functions currently being captured in ftrace\n'\ 6790 ' -flistall Print all functions 6320 ' -flistall Print all functions capable of being captured in ftrace\n'\ 6791 ' -summary dir Create a summary of 6321 ' -summary dir Create a summary of tests in this dir [-genhtml builds missing html]\n'\ 6792 ' [redo]\n'\ 6322 ' [redo]\n'\ 6793 ' -ftrace ftracefile Create HTML o 6323 ' -ftrace ftracefile Create HTML output using ftrace input (used with -dmesg)\n'\ 6794 ' -dmesg dmesgfile Create HTML o 6324 ' -dmesg dmesgfile Create HTML output using dmesg (used with -ftrace)\n'\ 6795 '' % (sysvals.title, sysvals.version, 6325 '' % (sysvals.title, sysvals.version, sysvals.suspendmode, sysvals.ftopfunc)) 6796 return True 6326 return True 6797 6327 6798 # ----------------- MAIN -------------------- 6328 # ----------------- MAIN -------------------- 6799 # exec start (skipped if script is loaded as 6329 # exec start (skipped if script is loaded as library) 6800 if __name__ == '__main__': 6330 if __name__ == '__main__': 6801 genhtml = False 6331 genhtml = False 6802 cmd = '' 6332 cmd = '' 6803 simplecmds = ['-sysinfo', '-modes', ' 6333 simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', 6804 '-devinfo', '-status', '-xon' !! 6334 '-devinfo', '-status', '-battery', '-xon', '-xoff', '-xstandby', 6805 '-xinit', '-xreset', '-xstat' !! 6335 '-xsuspend', '-xinit', '-xreset', '-xstat', '-wifi'] 6806 if '-f' in sys.argv: 6336 if '-f' in sys.argv: 6807 sysvals.cgskip = sysvals.conf 6337 sysvals.cgskip = sysvals.configFile('cgskip.txt') 6808 # loop through the command line argum 6338 # loop through the command line arguments 6809 args = iter(sys.argv[1:]) 6339 args = iter(sys.argv[1:]) 6810 for arg in args: 6340 for arg in args: 6811 if(arg == '-m'): 6341 if(arg == '-m'): 6812 try: 6342 try: 6813 val = next(ar !! 6343 val = args.next() 6814 except: 6344 except: 6815 doError('No m 6345 doError('No mode supplied', True) 6816 if val == 'command' a 6346 if val == 'command' and not sysvals.testcommand: 6817 doError('No c 6347 doError('No command supplied for mode "command"', True) 6818 sysvals.suspendmode = 6348 sysvals.suspendmode = val 6819 elif(arg in simplecmds): 6349 elif(arg in simplecmds): 6820 cmd = arg[1:] 6350 cmd = arg[1:] 6821 elif(arg == '-h'): 6351 elif(arg == '-h'): 6822 printHelp() 6352 printHelp() 6823 sys.exit(0) 6353 sys.exit(0) 6824 elif(arg == '-v'): 6354 elif(arg == '-v'): 6825 pprint("Version %s" % 6355 pprint("Version %s" % sysvals.version) 6826 sys.exit(0) 6356 sys.exit(0) 6827 elif(arg == '-debugtiming'): << 6828 debugtiming = True << 6829 elif(arg == '-x2'): 6357 elif(arg == '-x2'): 6830 sysvals.execcount = 2 6358 sysvals.execcount = 2 6831 elif(arg == '-x2delay'): 6359 elif(arg == '-x2delay'): 6832 sysvals.x2delay = get 6360 sysvals.x2delay = getArgInt('-x2delay', args, 0, 60000) 6833 elif(arg == '-predelay'): 6361 elif(arg == '-predelay'): 6834 sysvals.predelay = ge 6362 sysvals.predelay = getArgInt('-predelay', args, 0, 60000) 6835 elif(arg == '-postdelay'): 6363 elif(arg == '-postdelay'): 6836 sysvals.postdelay = g 6364 sysvals.postdelay = getArgInt('-postdelay', args, 0, 60000) 6837 elif(arg == '-f'): 6365 elif(arg == '-f'): 6838 sysvals.usecallgraph 6366 sysvals.usecallgraph = True 6839 elif(arg == '-ftop'): 6367 elif(arg == '-ftop'): 6840 sysvals.usecallgraph 6368 sysvals.usecallgraph = True 6841 sysvals.ftop = True 6369 sysvals.ftop = True 6842 sysvals.usekprobes = 6370 sysvals.usekprobes = False 6843 elif(arg == '-skiphtml'): 6371 elif(arg == '-skiphtml'): 6844 sysvals.skiphtml = Tr 6372 sysvals.skiphtml = True 6845 elif(arg == '-cgdump'): 6373 elif(arg == '-cgdump'): 6846 sysvals.cgdump = True 6374 sysvals.cgdump = True 6847 elif(arg == '-devdump'): 6375 elif(arg == '-devdump'): 6848 sysvals.devdump = Tru 6376 sysvals.devdump = True 6849 elif(arg == '-genhtml'): 6377 elif(arg == '-genhtml'): 6850 genhtml = True 6378 genhtml = True 6851 elif(arg == '-addlogs'): 6379 elif(arg == '-addlogs'): 6852 sysvals.dmesglog = sy 6380 sysvals.dmesglog = sysvals.ftracelog = True 6853 elif(arg == '-nologs'): 6381 elif(arg == '-nologs'): 6854 sysvals.dmesglog = sy 6382 sysvals.dmesglog = sysvals.ftracelog = False 6855 elif(arg == '-addlogdmesg'): 6383 elif(arg == '-addlogdmesg'): 6856 sysvals.dmesglog = Tr 6384 sysvals.dmesglog = True 6857 elif(arg == '-addlogftrace'): 6385 elif(arg == '-addlogftrace'): 6858 sysvals.ftracelog = T 6386 sysvals.ftracelog = True 6859 elif(arg == '-noturbostat'): !! 6387 elif(arg == '-turbostat'): 6860 sysvals.tstat = False !! 6388 sysvals.tstat = True >> 6389 if not sysvals.haveTurbostat(): >> 6390 doError('Turbostat command not found') 6861 elif(arg == '-verbose'): 6391 elif(arg == '-verbose'): 6862 sysvals.verbose = Tru 6392 sysvals.verbose = True 6863 elif(arg == '-proc'): 6393 elif(arg == '-proc'): 6864 sysvals.useprocmon = 6394 sysvals.useprocmon = True 6865 elif(arg == '-dev'): 6395 elif(arg == '-dev'): 6866 sysvals.usedevsrc = T 6396 sysvals.usedevsrc = True 6867 elif(arg == '-sync'): 6397 elif(arg == '-sync'): 6868 sysvals.sync = True 6398 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'): 6399 elif(arg == '-gzip'): 6876 sysvals.gzip = True 6400 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'): 6401 elif(arg == '-rs'): 6888 try: 6402 try: 6889 val = next(ar !! 6403 val = args.next() 6890 except: 6404 except: 6891 doError('-rs 6405 doError('-rs requires "enable" or "disable"', True) 6892 if val.lower() in swi 6406 if val.lower() in switchvalues: 6893 if val.lower( 6407 if val.lower() in switchoff: 6894 sysva 6408 sysvals.rs = -1 6895 else: 6409 else: 6896 sysva 6410 sysvals.rs = 1 6897 else: 6411 else: 6898 doError('inva 6412 doError('invalid option: %s, use "enable/disable" or "on/off"' % val, True) 6899 elif(arg == '-display'): 6413 elif(arg == '-display'): 6900 try: 6414 try: 6901 val = next(ar !! 6415 val = args.next() 6902 except: 6416 except: 6903 doError('-dis 6417 doError('-display requires an mode value', True) 6904 disopt = ['on', 'off' 6418 disopt = ['on', 'off', 'standby', 'suspend'] 6905 if val.lower() not in 6419 if val.lower() not in disopt: 6906 doError('vali 6420 doError('valid display mode values are %s' % disopt, True) 6907 sysvals.display = val 6421 sysvals.display = val.lower() 6908 elif(arg == '-maxdepth'): 6422 elif(arg == '-maxdepth'): 6909 sysvals.max_graph_dep 6423 sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000) 6910 elif(arg == '-rtcwake'): 6424 elif(arg == '-rtcwake'): 6911 try: 6425 try: 6912 val = next(ar !! 6426 val = args.next() 6913 except: 6427 except: 6914 doError('No r 6428 doError('No rtcwake time supplied', True) 6915 if val.lower() in swi 6429 if val.lower() in switchoff: 6916 sysvals.rtcwa 6430 sysvals.rtcwake = False 6917 else: 6431 else: 6918 sysvals.rtcwa 6432 sysvals.rtcwake = True 6919 sysvals.rtcwa 6433 sysvals.rtcwaketime = getArgInt('-rtcwake', val, 0, 3600, False) 6920 elif(arg == '-timeprec'): 6434 elif(arg == '-timeprec'): 6921 sysvals.setPrecision( 6435 sysvals.setPrecision(getArgInt('-timeprec', args, 0, 6)) 6922 elif(arg == '-mindev'): 6436 elif(arg == '-mindev'): 6923 sysvals.mindevlen = g 6437 sysvals.mindevlen = getArgFloat('-mindev', args, 0.0, 10000.0) 6924 elif(arg == '-mincg'): 6438 elif(arg == '-mincg'): 6925 sysvals.mincglen = ge 6439 sysvals.mincglen = getArgFloat('-mincg', args, 0.0, 10000.0) 6926 elif(arg == '-bufsize'): 6440 elif(arg == '-bufsize'): 6927 sysvals.bufsize = get 6441 sysvals.bufsize = getArgInt('-bufsize', args, 1, 1024*1024*8) 6928 elif(arg == '-cgtest'): 6442 elif(arg == '-cgtest'): 6929 sysvals.cgtest = getA 6443 sysvals.cgtest = getArgInt('-cgtest', args, 0, 1) 6930 elif(arg == '-cgphase'): 6444 elif(arg == '-cgphase'): 6931 try: 6445 try: 6932 val = next(ar !! 6446 val = args.next() 6933 except: 6447 except: 6934 doError('No p 6448 doError('No phase name supplied', True) 6935 d = Data(0) 6449 d = Data(0) 6936 if val not in d.phase 6450 if val not in d.phasedef: 6937 doError('inva 6451 doError('invalid phase --> (%s: %s), valid phases are %s'\ 6938 % (ar 6452 % (arg, val, d.phasedef.keys()), True) 6939 sysvals.cgphase = val 6453 sysvals.cgphase = val 6940 elif(arg == '-cgfilter'): 6454 elif(arg == '-cgfilter'): 6941 try: 6455 try: 6942 val = next(ar !! 6456 val = args.next() 6943 except: 6457 except: 6944 doError('No c 6458 doError('No callgraph functions supplied', True) 6945 sysvals.setCallgraphF 6459 sysvals.setCallgraphFilter(val) 6946 elif(arg == '-skipkprobe'): 6460 elif(arg == '-skipkprobe'): 6947 try: 6461 try: 6948 val = next(ar !! 6462 val = args.next() 6949 except: 6463 except: 6950 doError('No k 6464 doError('No kprobe functions supplied', True) 6951 sysvals.skipKprobes(v 6465 sysvals.skipKprobes(val) 6952 elif(arg == '-cgskip'): 6466 elif(arg == '-cgskip'): 6953 try: 6467 try: 6954 val = next(ar !! 6468 val = args.next() 6955 except: 6469 except: 6956 doError('No f 6470 doError('No file supplied', True) 6957 if val.lower() in swi 6471 if val.lower() in switchoff: 6958 sysvals.cgski 6472 sysvals.cgskip = '' 6959 else: 6473 else: 6960 sysvals.cgski 6474 sysvals.cgskip = sysvals.configFile(val) 6961 if(not sysval 6475 if(not sysvals.cgskip): 6962 doErr 6476 doError('%s does not exist' % sysvals.cgskip) 6963 elif(arg == '-callloop-maxgap 6477 elif(arg == '-callloop-maxgap'): 6964 sysvals.callloopmaxga 6478 sysvals.callloopmaxgap = getArgFloat('-callloop-maxgap', args, 0.0, 1.0) 6965 elif(arg == '-callloop-maxlen 6479 elif(arg == '-callloop-maxlen'): 6966 sysvals.callloopmaxle 6480 sysvals.callloopmaxlen = getArgFloat('-callloop-maxlen', args, 0.0, 1.0) 6967 elif(arg == '-cmd'): 6481 elif(arg == '-cmd'): 6968 try: 6482 try: 6969 val = next(ar !! 6483 val = args.next() 6970 except: 6484 except: 6971 doError('No c 6485 doError('No command string supplied', True) 6972 sysvals.testcommand = 6486 sysvals.testcommand = val 6973 sysvals.suspendmode = 6487 sysvals.suspendmode = 'command' 6974 elif(arg == '-expandcg'): 6488 elif(arg == '-expandcg'): 6975 sysvals.cgexp = True 6489 sysvals.cgexp = True 6976 elif(arg == '-srgap'): 6490 elif(arg == '-srgap'): 6977 sysvals.srgap = 5 6491 sysvals.srgap = 5 6978 elif(arg == '-maxfail'): << 6979 sysvals.maxfail = get << 6980 elif(arg == '-multi'): 6492 elif(arg == '-multi'): 6981 try: !! 6493 sysvals.multitest['run'] = True 6982 c, d = next(a !! 6494 sysvals.multitest['count'] = getArgInt('-multi n d (exec count)', args, 2, 1000000) 6983 except: !! 6495 sysvals.multitest['delay'] = getArgInt('-multi n d (delay between tests)', args, 0, 3600) 6984 doError('-mul << 6985 sysvals.multiinit(c, << 6986 elif(arg == '-o'): 6496 elif(arg == '-o'): 6987 try: 6497 try: 6988 val = next(ar !! 6498 val = args.next() 6989 except: 6499 except: 6990 doError('No s 6500 doError('No subdirectory name supplied', True) 6991 sysvals.outdir = sysv 6501 sysvals.outdir = sysvals.setOutputFolder(val) 6992 elif(arg == '-config'): 6502 elif(arg == '-config'): 6993 try: 6503 try: 6994 val = next(ar !! 6504 val = args.next() 6995 except: 6505 except: 6996 doError('No t 6506 doError('No text file supplied', True) 6997 file = sysvals.config 6507 file = sysvals.configFile(val) 6998 if(not file): 6508 if(not file): 6999 doError('%s d 6509 doError('%s does not exist' % val) 7000 configFromFile(file) 6510 configFromFile(file) 7001 elif(arg == '-fadd'): 6511 elif(arg == '-fadd'): 7002 try: 6512 try: 7003 val = next(ar !! 6513 val = args.next() 7004 except: 6514 except: 7005 doError('No t 6515 doError('No text file supplied', True) 7006 file = sysvals.config 6516 file = sysvals.configFile(val) 7007 if(not file): 6517 if(not file): 7008 doError('%s d 6518 doError('%s does not exist' % val) 7009 sysvals.addFtraceFilt 6519 sysvals.addFtraceFilterFunctions(file) 7010 elif(arg == '-dmesg'): 6520 elif(arg == '-dmesg'): 7011 try: 6521 try: 7012 val = next(ar !! 6522 val = args.next() 7013 except: 6523 except: 7014 doError('No d 6524 doError('No dmesg file supplied', True) 7015 sysvals.notestrun = T 6525 sysvals.notestrun = True 7016 sysvals.dmesgfile = v 6526 sysvals.dmesgfile = val 7017 if(os.path.exists(sys 6527 if(os.path.exists(sysvals.dmesgfile) == False): 7018 doError('%s d 6528 doError('%s does not exist' % sysvals.dmesgfile) 7019 elif(arg == '-ftrace'): 6529 elif(arg == '-ftrace'): 7020 try: 6530 try: 7021 val = next(ar !! 6531 val = args.next() 7022 except: 6532 except: 7023 doError('No f 6533 doError('No ftrace file supplied', True) 7024 sysvals.notestrun = T 6534 sysvals.notestrun = True 7025 sysvals.ftracefile = 6535 sysvals.ftracefile = val 7026 if(os.path.exists(sys 6536 if(os.path.exists(sysvals.ftracefile) == False): 7027 doError('%s d 6537 doError('%s does not exist' % sysvals.ftracefile) 7028 elif(arg == '-summary'): 6538 elif(arg == '-summary'): 7029 try: 6539 try: 7030 val = next(ar !! 6540 val = args.next() 7031 except: 6541 except: 7032 doError('No d 6542 doError('No directory supplied', True) 7033 cmd = 'summary' 6543 cmd = 'summary' 7034 sysvals.outdir = val 6544 sysvals.outdir = val 7035 sysvals.notestrun = T 6545 sysvals.notestrun = True 7036 if(os.path.isdir(val) 6546 if(os.path.isdir(val) == False): 7037 doError('%s i 6547 doError('%s is not accesible' % val) 7038 elif(arg == '-filter'): 6548 elif(arg == '-filter'): 7039 try: 6549 try: 7040 val = next(ar !! 6550 val = args.next() 7041 except: 6551 except: 7042 doError('No d 6552 doError('No devnames supplied', True) 7043 sysvals.setDeviceFilt 6553 sysvals.setDeviceFilter(val) 7044 elif(arg == '-result'): 6554 elif(arg == '-result'): 7045 try: 6555 try: 7046 val = next(ar !! 6556 val = args.next() 7047 except: 6557 except: 7048 doError('No r 6558 doError('No result file supplied', True) 7049 sysvals.result = val 6559 sysvals.result = val 7050 sysvals.signalHandler 6560 sysvals.signalHandlerInit() 7051 else: 6561 else: 7052 doError('Invalid argu 6562 doError('Invalid argument: '+arg, True) 7053 6563 7054 # compatibility errors 6564 # compatibility errors 7055 if(sysvals.usecallgraph and sysvals.u 6565 if(sysvals.usecallgraph and sysvals.usedevsrc): 7056 doError('-dev is not compatib 6566 doError('-dev is not compatible with -f') 7057 if(sysvals.usecallgraph and sysvals.u 6567 if(sysvals.usecallgraph and sysvals.useprocmon): 7058 doError('-proc is not compati 6568 doError('-proc is not compatible with -f') 7059 6569 7060 if sysvals.usecallgraph and sysvals.c 6570 if sysvals.usecallgraph and sysvals.cgskip: 7061 sysvals.vprint('Using cgskip 6571 sysvals.vprint('Using cgskip file: %s' % sysvals.cgskip) 7062 sysvals.setCallgraphBlacklist 6572 sysvals.setCallgraphBlacklist(sysvals.cgskip) 7063 6573 7064 # callgraph size cannot exceed device 6574 # callgraph size cannot exceed device size 7065 if sysvals.mincglen < sysvals.mindevl 6575 if sysvals.mincglen < sysvals.mindevlen: 7066 sysvals.mincglen = sysvals.mi 6576 sysvals.mincglen = sysvals.mindevlen 7067 6577 7068 # remove existing buffers before calc 6578 # remove existing buffers before calculating memory 7069 if(sysvals.usecallgraph or sysvals.us 6579 if(sysvals.usecallgraph or sysvals.usedevsrc): 7070 sysvals.fsetVal('16', 'buffer 6580 sysvals.fsetVal('16', 'buffer_size_kb') 7071 sysvals.cpuInfo() 6581 sysvals.cpuInfo() 7072 6582 7073 # just run a utility command and exit 6583 # just run a utility command and exit 7074 if(cmd != ''): 6584 if(cmd != ''): 7075 ret = 0 6585 ret = 0 7076 if(cmd == 'status'): 6586 if(cmd == 'status'): 7077 if not statusCheck(Tr 6587 if not statusCheck(True): 7078 ret = 1 6588 ret = 1 7079 elif(cmd == 'fpdt'): 6589 elif(cmd == 'fpdt'): 7080 if not getFPDT(True): 6590 if not getFPDT(True): 7081 ret = 1 6591 ret = 1 >> 6592 elif(cmd == 'battery'): >> 6593 out = getBattery() >> 6594 if out: >> 6595 pprint('AC Connect : %s\nBattery Charge: %d' % out) >> 6596 else: >> 6597 pprint('no battery found') >> 6598 ret = 1 7082 elif(cmd == 'sysinfo'): 6599 elif(cmd == 'sysinfo'): 7083 sysvals.printSystemIn 6600 sysvals.printSystemInfo(True) 7084 elif(cmd == 'devinfo'): 6601 elif(cmd == 'devinfo'): 7085 deviceInfo() 6602 deviceInfo() 7086 elif(cmd == 'modes'): 6603 elif(cmd == 'modes'): 7087 pprint(getModes()) 6604 pprint(getModes()) 7088 elif(cmd == 'flist'): 6605 elif(cmd == 'flist'): 7089 sysvals.getFtraceFilt 6606 sysvals.getFtraceFilterFunctions(True) 7090 elif(cmd == 'flistall'): 6607 elif(cmd == 'flistall'): 7091 sysvals.getFtraceFilt 6608 sysvals.getFtraceFilterFunctions(False) 7092 elif(cmd == 'summary'): 6609 elif(cmd == 'summary'): 7093 runSummary(sysvals.ou 6610 runSummary(sysvals.outdir, True, genhtml) 7094 elif(cmd in ['xon', 'xoff', ' 6611 elif(cmd in ['xon', 'xoff', 'xstandby', 'xsuspend', 'xinit', 'xreset']): 7095 sysvals.verbose = Tru 6612 sysvals.verbose = True 7096 ret = sysvals.display !! 6613 ret = displayControl(cmd[1:]) 7097 elif(cmd == 'xstat'): 6614 elif(cmd == 'xstat'): 7098 pprint('Display Statu !! 6615 pprint('Display Status: %s' % displayControl('stat').upper()) 7099 elif(cmd == 'wificheck'): !! 6616 elif(cmd == 'wifi'): 7100 dev = sysvals.checkWi !! 6617 out = sysvals.checkWifi() 7101 if dev: !! 6618 if 'device' not in out: 7102 print('%s is !! 6619 pprint('WIFI interface not found') 7103 else: 6620 else: 7104 print('No wif !! 6621 for key in sorted(out): 7105 elif(cmd == 'cmdinfo'): !! 6622 pprint('%6s: %s' % (key.upper(), out[key])) 7106 for out in sysvals.cm << 7107 print('[%s - << 7108 sys.exit(ret) 6623 sys.exit(ret) 7109 6624 7110 # if instructed, re-analyze existing 6625 # if instructed, re-analyze existing data files 7111 if(sysvals.notestrun): 6626 if(sysvals.notestrun): 7112 stamp = rerunTest(sysvals.out 6627 stamp = rerunTest(sysvals.outdir) 7113 sysvals.outputResult(stamp) 6628 sysvals.outputResult(stamp) 7114 sys.exit(0) 6629 sys.exit(0) 7115 6630 7116 # verify that we can run a test 6631 # verify that we can run a test 7117 error = statusCheck() 6632 error = statusCheck() 7118 if(error): 6633 if(error): 7119 doError(error) 6634 doError(error) 7120 6635 7121 # extract mem/disk extra modes and co 6636 # extract mem/disk extra modes and convert 7122 mode = sysvals.suspendmode 6637 mode = sysvals.suspendmode 7123 if mode.startswith('mem'): 6638 if mode.startswith('mem'): 7124 memmode = mode.split('-', 1)[ 6639 memmode = mode.split('-', 1)[-1] if '-' in mode else 'deep' 7125 if memmode == 'shallow': 6640 if memmode == 'shallow': 7126 mode = 'standby' 6641 mode = 'standby' 7127 elif memmode == 's2idle': 6642 elif memmode == 's2idle': 7128 mode = 'freeze' 6643 mode = 'freeze' 7129 else: 6644 else: 7130 mode = 'mem' 6645 mode = 'mem' 7131 sysvals.memmode = memmode 6646 sysvals.memmode = memmode 7132 sysvals.suspendmode = mode 6647 sysvals.suspendmode = mode 7133 if mode.startswith('disk-'): 6648 if mode.startswith('disk-'): 7134 sysvals.diskmode = mode.split 6649 sysvals.diskmode = mode.split('-', 1)[-1] 7135 sysvals.suspendmode = 'disk' 6650 sysvals.suspendmode = 'disk' >> 6651 7136 sysvals.systemInfo(dmidecode(sysvals. 6652 sysvals.systemInfo(dmidecode(sysvals.mempath)) 7137 6653 7138 failcnt, ret = 0, 0 !! 6654 setRuntimeSuspend(True) >> 6655 if sysvals.display: >> 6656 displayControl('init') >> 6657 ret = 0 7139 if sysvals.multitest['run']: 6658 if sysvals.multitest['run']: 7140 # run multiple tests in a sep 6659 # run multiple tests in a separate subdirectory 7141 if not sysvals.outdir: 6660 if not sysvals.outdir: 7142 if 'time' in sysvals. !! 6661 s = 'suspend-x%d' % sysvals.multitest['count'] 7143 s = '-%dm' % !! 6662 sysvals.outdir = datetime.now().strftime(s+'-%y%m%d-%H%M%S') 7144 else: << 7145 s = '-x%d' % << 7146 sysvals.outdir = date << 7147 if not os.path.isdir(sysvals. 6663 if not os.path.isdir(sysvals.outdir): 7148 os.makedirs(sysvals.o 6664 os.makedirs(sysvals.outdir) 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 6665 for i in range(sysvals.multitest['count']): 7154 sysvals.multistat(Tru !! 6666 if(i != 0): 7155 if i != 0 and sysvals << 7156 pprint('Waiti 6667 pprint('Waiting %d seconds...' % (sysvals.multitest['delay'])) 7157 time.sleep(sy 6668 time.sleep(sysvals.multitest['delay']) >> 6669 pprint('TEST (%d/%d) START' % (i+1, sysvals.multitest['count'])) 7158 fmt = 'suspend-%y%m%d 6670 fmt = 'suspend-%y%m%d-%H%M%S' 7159 sysvals.testdir = os. 6671 sysvals.testdir = os.path.join(sysvals.outdir, datetime.now().strftime(fmt)) 7160 ret = runTest(i+1, no !! 6672 ret = runTest(i+1) 7161 failcnt = 0 if not re !! 6673 pprint('TEST (%d/%d) COMPLETE' % (i+1, sysvals.multitest['count'])) 7162 if sysvals.maxfail > !! 6674 sysvals.logmsg = '' 7163 pprint('Maxim << 7164 break << 7165 sysvals.resetlog() << 7166 sysvals.multistat(Fal << 7167 if 'time' in sysvals. << 7168 break << 7169 if not sysvals.skiphtml: 6675 if not sysvals.skiphtml: 7170 runSummary(sysvals.ou 6676 runSummary(sysvals.outdir, False, False) 7171 sysvals.sudoUserchown(sysvals 6677 sysvals.sudoUserchown(sysvals.outdir) 7172 else: 6678 else: 7173 if sysvals.outdir: 6679 if sysvals.outdir: 7174 sysvals.testdir = sys 6680 sysvals.testdir = sysvals.outdir 7175 # run the test in the current 6681 # run the test in the current directory 7176 ret = runTest() 6682 ret = runTest() 7177 << 7178 # reset to default values after testi << 7179 if sysvals.display: 6683 if sysvals.display: 7180 sysvals.displayControl('reset !! 6684 displayControl('reset') 7181 if sysvals.rs != 0: !! 6685 setRuntimeSuspend(False) 7182 sysvals.setRuntimeSuspend(Fal << 7183 sys.exit(ret) 6686 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.