~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/power/pm-graph/sleepgraph.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/power/pm-graph/sleepgraph.py (Version linux-6.12-rc7) and /tools/power/pm-graph/sleepgraph.py (Version linux-6.0.19)


  1 #!/usr/bin/env python3                              1 #!/usr/bin/env python3
  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      7 # This program is free software; you can redistribute it and/or modify it
  8 # under the terms and conditions of the GNU Ge      8 # under the terms and conditions of the GNU General Public License,
  9 # version 2, as published by the Free Software      9 # version 2, as published by the Free Software Foundation.
 10 #                                                  10 #
 11 # This program is distributed in the hope it w     11 # This program is distributed in the hope it will be useful, but WITHOUT
 12 # ANY WARRANTY; without even the implied warra     12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13 # FITNESS FOR A PARTICULAR PURPOSE.  See the G     13 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 14 # more details.                                    14 # more details.
 15 #                                                  15 #
 16 # Authors:                                         16 # Authors:
 17 #        Todd Brandt <todd.e.brandt@linux.intel     17 #        Todd Brandt <todd.e.brandt@linux.intel.com>
 18 #                                                  18 #
 19 # Links:                                           19 # Links:
 20 #        Home Page                                 20 #        Home Page
 21 #          https://01.org/pm-graph                 21 #          https://01.org/pm-graph
 22 #        Source repo                               22 #        Source repo
 23 #          git@github.com:intel/pm-graph           23 #          git@github.com:intel/pm-graph
 24 #                                                  24 #
 25 # Description:                                     25 # Description:
 26 #        This tool is designed to assist kerne     26 #        This tool is designed to assist kernel and OS developers in optimizing
 27 #        their linux stack's suspend/resume ti     27 #        their linux stack's suspend/resume time. Using a kernel image built
 28 #        with a few extra options enabled, the     28 #        with a few extra options enabled, the tool will execute a suspend and
 29 #        will capture dmesg and ftrace data un     29 #        will capture dmesg and ftrace data until resume is complete. This data
 30 #        is transformed into a device timeline     30 #        is transformed into a device timeline and a callgraph to give a quick
 31 #        and detailed view of which devices an     31 #        and detailed view of which devices and callbacks are taking the most
 32 #        time in suspend/resume. The output is     32 #        time in suspend/resume. The output is a single html file which can be
 33 #        viewed in firefox or chrome.              33 #        viewed in firefox or chrome.
 34 #                                                  34 #
 35 #        The following kernel build options ar     35 #        The following kernel build options are required:
 36 #                CONFIG_DEVMEM=y                   36 #                CONFIG_DEVMEM=y
 37 #                CONFIG_PM_DEBUG=y                 37 #                CONFIG_PM_DEBUG=y
 38 #                CONFIG_PM_SLEEP_DEBUG=y           38 #                CONFIG_PM_SLEEP_DEBUG=y
 39 #                CONFIG_FTRACE=y                   39 #                CONFIG_FTRACE=y
 40 #                CONFIG_FUNCTION_TRACER=y          40 #                CONFIG_FUNCTION_TRACER=y
 41 #                CONFIG_FUNCTION_GRAPH_TRACER=     41 #                CONFIG_FUNCTION_GRAPH_TRACER=y
 42 #                CONFIG_KPROBES=y                  42 #                CONFIG_KPROBES=y
 43 #                CONFIG_KPROBES_ON_FTRACE=y        43 #                CONFIG_KPROBES_ON_FTRACE=y
 44 #                                                  44 #
 45 #        For kernel versions older than 3.15:      45 #        For kernel versions older than 3.15:
 46 #        The following additional kernel param     46 #        The following additional kernel parameters are required:
 47 #                (e.g. in file /etc/default/gr     47 #                (e.g. in file /etc/default/grub)
 48 #                GRUB_CMDLINE_LINUX_DEFAULT=".     48 #                GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=16M ..."
 49 #                                                  49 #
 50                                                    50 
 51 # ----------------- LIBRARIES ----------------     51 # ----------------- LIBRARIES --------------------
 52                                                    52 
 53 import sys                                         53 import sys
 54 import time                                        54 import time
 55 import os                                          55 import os
 56 import string                                      56 import string
 57 import re                                          57 import re
 58 import platform                                    58 import platform
 59 import signal                                      59 import signal
 60 import codecs                                      60 import codecs
 61 from datetime import datetime, timedelta           61 from datetime import datetime, timedelta
 62 import struct                                      62 import struct
 63 import configparser                                63 import configparser
 64 import gzip                                        64 import gzip
 65 from threading import Thread                       65 from threading import Thread
 66 from subprocess import call, Popen, PIPE           66 from subprocess import call, Popen, PIPE
 67 import base64                                      67 import base64
 68                                                    68 
 69 debugtiming = False                                69 debugtiming = False
 70 mystarttime = time.time()                          70 mystarttime = time.time()
 71 def pprint(msg):                                   71 def pprint(msg):
 72         if debugtiming:                            72         if debugtiming:
 73                 print('[%09.3f] %s' % (time.ti     73                 print('[%09.3f] %s' % (time.time()-mystarttime, msg))
 74         else:                                      74         else:
 75                 print(msg)                         75                 print(msg)
 76         sys.stdout.flush()                         76         sys.stdout.flush()
 77                                                    77 
 78 def ascii(text):                                   78 def ascii(text):
 79         return text.decode('ascii', 'ignore')      79         return text.decode('ascii', 'ignore')
 80                                                    80 
 81 # ----------------- CLASSES ------------------     81 # ----------------- CLASSES --------------------
 82                                                    82 
 83 # Class: SystemValues                              83 # Class: SystemValues
 84 # Description:                                     84 # Description:
 85 #        A global, single-instance container u     85 #        A global, single-instance container used to
 86 #        store system values and test paramete     86 #        store system values and test parameters
 87 class SystemValues:                                87 class SystemValues:
 88         title = 'SleepGraph'                       88         title = 'SleepGraph'
 89         version = '5.12'                       !!  89         version = '5.9'
 90         ansi = False                               90         ansi = False
 91         rs = 0                                     91         rs = 0
 92         display = ''                               92         display = ''
 93         gzip = False                               93         gzip = False
 94         sync = False                               94         sync = False
 95         wifi = False                               95         wifi = False
 96         netfix = False                             96         netfix = False
 97         verbose = False                            97         verbose = False
 98         testlog = True                             98         testlog = True
 99         dmesglog = True                            99         dmesglog = True
100         ftracelog = False                         100         ftracelog = False
101         acpidebug = True                          101         acpidebug = True
102         tstat = True                              102         tstat = True
103         wifitrace = False                      << 
104         mindevlen = 0.0001                        103         mindevlen = 0.0001
105         mincglen = 0.0                            104         mincglen = 0.0
106         cgphase = ''                              105         cgphase = ''
107         cgtest = -1                               106         cgtest = -1
108         cgskip = ''                               107         cgskip = ''
109         maxfail = 0                               108         maxfail = 0
110         multitest = {'run': False, 'count': 10    109         multitest = {'run': False, 'count': 1000000, 'delay': 0}
111         max_graph_depth = 0                       110         max_graph_depth = 0
112         callloopmaxgap = 0.0001                   111         callloopmaxgap = 0.0001
113         callloopmaxlen = 0.005                    112         callloopmaxlen = 0.005
114         bufsize = 0                               113         bufsize = 0
115         cpucount = 0                              114         cpucount = 0
116         memtotal = 204800                         115         memtotal = 204800
117         memfree = 204800                          116         memfree = 204800
118         osversion = ''                            117         osversion = ''
119         srgap = 0                                 118         srgap = 0
120         cgexp = False                             119         cgexp = False
121         testdir = ''                              120         testdir = ''
122         outdir = ''                               121         outdir = ''
123         tpath = '/sys/kernel/tracing/'         !! 122         tpath = '/sys/kernel/debug/tracing/'
124         fpdtpath = '/sys/firmware/acpi/tables/    123         fpdtpath = '/sys/firmware/acpi/tables/FPDT'
125         epath = '/sys/kernel/tracing/events/po !! 124         epath = '/sys/kernel/debug/tracing/events/power/'
126         pmdpath = '/sys/power/pm_debug_message    125         pmdpath = '/sys/power/pm_debug_messages'
127         s0ixpath = '/sys/module/intel_pmc_core    126         s0ixpath = '/sys/module/intel_pmc_core/parameters/warn_on_s0ix_failures'
128         s0ixres = '/sys/devices/system/cpu/cpu << 
129         acpipath='/sys/module/acpi/parameters/    127         acpipath='/sys/module/acpi/parameters/debug_level'
130         traceevents = [                           128         traceevents = [
131                 'suspend_resume',                 129                 'suspend_resume',
132                 'wakeup_source_activate',         130                 'wakeup_source_activate',
133                 'wakeup_source_deactivate',       131                 'wakeup_source_deactivate',
134                 'device_pm_callback_end',         132                 'device_pm_callback_end',
135                 'device_pm_callback_start'        133                 'device_pm_callback_start'
136         ]                                         134         ]
137         logmsg = ''                               135         logmsg = ''
138         testcommand = ''                          136         testcommand = ''
139         mempath = '/dev/mem'                      137         mempath = '/dev/mem'
140         powerfile = '/sys/power/state'            138         powerfile = '/sys/power/state'
141         mempowerfile = '/sys/power/mem_sleep'     139         mempowerfile = '/sys/power/mem_sleep'
142         diskpowerfile = '/sys/power/disk'         140         diskpowerfile = '/sys/power/disk'
143         suspendmode = 'mem'                       141         suspendmode = 'mem'
144         memmode = ''                              142         memmode = ''
145         diskmode = ''                             143         diskmode = ''
146         hostname = 'localhost'                    144         hostname = 'localhost'
147         prefix = 'test'                           145         prefix = 'test'
148         teststamp = ''                            146         teststamp = ''
149         sysstamp = ''                             147         sysstamp = ''
150         dmesgstart = 0.0                          148         dmesgstart = 0.0
151         dmesgfile = ''                            149         dmesgfile = ''
152         ftracefile = ''                           150         ftracefile = ''
153         htmlfile = 'output.html'                  151         htmlfile = 'output.html'
154         result = ''                               152         result = ''
155         rtcwake = True                            153         rtcwake = True
156         rtcwaketime = 15                          154         rtcwaketime = 15
157         rtcpath = ''                              155         rtcpath = ''
158         devicefilter = []                         156         devicefilter = []
159         cgfilter = []                             157         cgfilter = []
160         stamp = 0                                 158         stamp = 0
161         execcount = 1                             159         execcount = 1
162         x2delay = 0                               160         x2delay = 0
163         skiphtml = False                          161         skiphtml = False
164         usecallgraph = False                      162         usecallgraph = False
165         ftopfunc = 'pm_suspend'                   163         ftopfunc = 'pm_suspend'
166         ftop = False                              164         ftop = False
167         usetraceevents = False                    165         usetraceevents = False
168         usetracemarkers = True                    166         usetracemarkers = True
169         useftrace = True                          167         useftrace = True
170         usekprobes = True                         168         usekprobes = True
171         usedevsrc = False                         169         usedevsrc = False
172         useprocmon = False                        170         useprocmon = False
173         notestrun = False                         171         notestrun = False
174         cgdump = False                            172         cgdump = False
175         devdump = False                           173         devdump = False
176         mixedphaseheight = True                   174         mixedphaseheight = True
177         devprops = dict()                         175         devprops = dict()
178         cfgdef = dict()                           176         cfgdef = dict()
179         platinfo = []                             177         platinfo = []
180         predelay = 0                              178         predelay = 0
181         postdelay = 0                             179         postdelay = 0
182         tmstart = 'SUSPEND START %Y%m%d-%H:%M:    180         tmstart = 'SUSPEND START %Y%m%d-%H:%M:%S.%f'
183         tmend = 'RESUME COMPLETE %Y%m%d-%H:%M:    181         tmend = 'RESUME COMPLETE %Y%m%d-%H:%M:%S.%f'
184         tracefuncs = {                            182         tracefuncs = {
185                 'async_synchronize_full': {},  << 
186                 'sys_sync': {},                   183                 'sys_sync': {},
187                 'ksys_sync': {},                  184                 'ksys_sync': {},
188                 '__pm_notifier_call_chain': {}    185                 '__pm_notifier_call_chain': {},
189                 'pm_prepare_console': {},         186                 'pm_prepare_console': {},
190                 'pm_notifier_call_chain': {},     187                 'pm_notifier_call_chain': {},
191                 'freeze_processes': {},           188                 'freeze_processes': {},
192                 'freeze_kernel_threads': {},      189                 'freeze_kernel_threads': {},
193                 'pm_restrict_gfp_mask': {},       190                 'pm_restrict_gfp_mask': {},
194                 'acpi_suspend_begin': {},         191                 'acpi_suspend_begin': {},
195                 'acpi_hibernation_begin': {},     192                 'acpi_hibernation_begin': {},
196                 'acpi_hibernation_enter': {},     193                 'acpi_hibernation_enter': {},
197                 'acpi_hibernation_leave': {},     194                 'acpi_hibernation_leave': {},
198                 'acpi_pm_freeze': {},             195                 'acpi_pm_freeze': {},
199                 'acpi_pm_thaw': {},               196                 'acpi_pm_thaw': {},
200                 'acpi_s2idle_end': {},            197                 'acpi_s2idle_end': {},
201                 'acpi_s2idle_sync': {},           198                 'acpi_s2idle_sync': {},
202                 'acpi_s2idle_begin': {},          199                 'acpi_s2idle_begin': {},
203                 'acpi_s2idle_prepare': {},        200                 'acpi_s2idle_prepare': {},
204                 'acpi_s2idle_prepare_late': {}    201                 'acpi_s2idle_prepare_late': {},
205                 'acpi_s2idle_wake': {},           202                 'acpi_s2idle_wake': {},
206                 'acpi_s2idle_wakeup': {},         203                 'acpi_s2idle_wakeup': {},
207                 'acpi_s2idle_restore': {},        204                 'acpi_s2idle_restore': {},
208                 'acpi_s2idle_restore_early': {    205                 'acpi_s2idle_restore_early': {},
209                 'hibernate_preallocate_memory'    206                 'hibernate_preallocate_memory': {},
210                 'create_basic_memory_bitmaps':    207                 'create_basic_memory_bitmaps': {},
211                 'swsusp_write': {},               208                 'swsusp_write': {},
212                 'suspend_console': {},            209                 'suspend_console': {},
213                 'acpi_pm_prepare': {},            210                 'acpi_pm_prepare': {},
214                 'syscore_suspend': {},            211                 'syscore_suspend': {},
215                 'arch_enable_nonboot_cpus_end'    212                 'arch_enable_nonboot_cpus_end': {},
216                 'syscore_resume': {},             213                 'syscore_resume': {},
217                 'acpi_pm_finish': {},             214                 'acpi_pm_finish': {},
218                 'resume_console': {},             215                 'resume_console': {},
219                 'acpi_pm_end': {},                216                 'acpi_pm_end': {},
220                 'pm_restore_gfp_mask': {},        217                 'pm_restore_gfp_mask': {},
221                 'thaw_processes': {},             218                 'thaw_processes': {},
222                 'pm_restore_console': {},         219                 'pm_restore_console': {},
223                 'CPU_OFF': {                      220                 'CPU_OFF': {
224                         'func':'_cpu_down',       221                         'func':'_cpu_down',
225                         'args_x86_64': {'cpu':    222                         'args_x86_64': {'cpu':'%di:s32'},
226                         'format': 'CPU_OFF[{cp    223                         'format': 'CPU_OFF[{cpu}]'
227                 },                                224                 },
228                 'CPU_ON': {                       225                 'CPU_ON': {
229                         'func':'_cpu_up',         226                         'func':'_cpu_up',
230                         'args_x86_64': {'cpu':    227                         'args_x86_64': {'cpu':'%di:s32'},
231                         'format': 'CPU_ON[{cpu    228                         'format': 'CPU_ON[{cpu}]'
232                 },                                229                 },
233         }                                         230         }
234         dev_tracefuncs = {                        231         dev_tracefuncs = {
235                 # general wait/delay/sleep        232                 # general wait/delay/sleep
236                 'msleep': { 'args_x86_64': {'t    233                 'msleep': { 'args_x86_64': {'time':'%di:s32'}, 'ub': 1 },
237                 'schedule_timeout': { 'args_x8    234                 'schedule_timeout': { 'args_x86_64': {'timeout':'%di:s32'}, 'ub': 1 },
238                 'udelay': { 'func':'__const_ud    235                 'udelay': { 'func':'__const_udelay', 'args_x86_64': {'loops':'%di:s32'}, 'ub': 1 },
239                 'usleep_range': { 'args_x86_64    236                 'usleep_range': { 'args_x86_64': {'min':'%di:s32', 'max':'%si:s32'}, 'ub': 1 },
240                 'mutex_lock_slowpath': { 'func    237                 'mutex_lock_slowpath': { 'func':'__mutex_lock_slowpath', 'ub': 1 },
241                 'acpi_os_stall': {'ub': 1},       238                 'acpi_os_stall': {'ub': 1},
242                 'rt_mutex_slowlock': {'ub': 1}    239                 'rt_mutex_slowlock': {'ub': 1},
243                 # ACPI                            240                 # ACPI
244                 'acpi_resume_power_resources':    241                 'acpi_resume_power_resources': {},
245                 'acpi_ps_execute_method': { 'a    242                 'acpi_ps_execute_method': { 'args_x86_64': {
246                         'fullpath':'+0(+40(%di    243                         'fullpath':'+0(+40(%di)):string',
247                 }},                               244                 }},
248                 # mei_me                          245                 # mei_me
249                 'mei_reset': {},                  246                 'mei_reset': {},
250                 # filesystem                      247                 # filesystem
251                 'ext4_sync_fs': {},               248                 'ext4_sync_fs': {},
252                 # 80211                           249                 # 80211
253                 'ath10k_bmi_read_memory': { 'a    250                 'ath10k_bmi_read_memory': { 'args_x86_64': {'length':'%cx:s32'} },
254                 'ath10k_bmi_write_memory': { '    251                 'ath10k_bmi_write_memory': { 'args_x86_64': {'length':'%cx:s32'} },
255                 'ath10k_bmi_fast_download': {     252                 'ath10k_bmi_fast_download': { 'args_x86_64': {'length':'%cx:s32'} },
256                 'iwlagn_mac_start': {},           253                 'iwlagn_mac_start': {},
257                 'iwlagn_alloc_bcast_station':     254                 'iwlagn_alloc_bcast_station': {},
258                 'iwl_trans_pcie_start_hw': {},    255                 'iwl_trans_pcie_start_hw': {},
259                 'iwl_trans_pcie_start_fw': {},    256                 'iwl_trans_pcie_start_fw': {},
260                 'iwl_run_init_ucode': {},         257                 'iwl_run_init_ucode': {},
261                 'iwl_load_ucode_wait_alive': {    258                 'iwl_load_ucode_wait_alive': {},
262                 'iwl_alive_start': {},            259                 'iwl_alive_start': {},
263                 'iwlagn_mac_stop': {},            260                 'iwlagn_mac_stop': {},
264                 'iwlagn_mac_suspend': {},         261                 'iwlagn_mac_suspend': {},
265                 'iwlagn_mac_resume': {},          262                 'iwlagn_mac_resume': {},
266                 'iwlagn_mac_add_interface': {}    263                 'iwlagn_mac_add_interface': {},
267                 'iwlagn_mac_remove_interface':    264                 'iwlagn_mac_remove_interface': {},
268                 'iwlagn_mac_change_interface':    265                 'iwlagn_mac_change_interface': {},
269                 'iwlagn_mac_config': {},          266                 'iwlagn_mac_config': {},
270                 'iwlagn_configure_filter': {},    267                 'iwlagn_configure_filter': {},
271                 'iwlagn_mac_hw_scan': {},         268                 'iwlagn_mac_hw_scan': {},
272                 'iwlagn_bss_info_changed': {},    269                 'iwlagn_bss_info_changed': {},
273                 'iwlagn_mac_channel_switch': {    270                 'iwlagn_mac_channel_switch': {},
274                 'iwlagn_mac_flush': {},           271                 'iwlagn_mac_flush': {},
275                 # ATA                             272                 # ATA
276                 'ata_eh_recover': { 'args_x86_    273                 'ata_eh_recover': { 'args_x86_64': {'port':'+36(%di):s32'} },
277                 # i915                            274                 # i915
278                 'i915_gem_resume': {},            275                 'i915_gem_resume': {},
279                 'i915_restore_state': {},         276                 'i915_restore_state': {},
280                 'intel_opregion_setup': {},       277                 'intel_opregion_setup': {},
281                 'g4x_pre_enable_dp': {},          278                 'g4x_pre_enable_dp': {},
282                 'vlv_pre_enable_dp': {},          279                 'vlv_pre_enable_dp': {},
283                 'chv_pre_enable_dp': {},          280                 'chv_pre_enable_dp': {},
284                 'g4x_enable_dp': {},              281                 'g4x_enable_dp': {},
285                 'vlv_enable_dp': {},              282                 'vlv_enable_dp': {},
286                 'intel_hpd_init': {},             283                 'intel_hpd_init': {},
287                 'intel_opregion_register': {},    284                 'intel_opregion_register': {},
288                 'intel_dp_detect': {},            285                 'intel_dp_detect': {},
289                 'intel_hdmi_detect': {},          286                 'intel_hdmi_detect': {},
290                 'intel_opregion_init': {},        287                 'intel_opregion_init': {},
291                 'intel_fbdev_set_suspend': {},    288                 'intel_fbdev_set_suspend': {},
292         }                                         289         }
293         infocmds = [                              290         infocmds = [
294                 [0, 'sysinfo', 'uname', '-a'],    291                 [0, 'sysinfo', 'uname', '-a'],
295                 [0, 'cpuinfo', 'head', '-7', '    292                 [0, 'cpuinfo', 'head', '-7', '/proc/cpuinfo'],
296                 [0, 'kparams', 'cat', '/proc/c    293                 [0, 'kparams', 'cat', '/proc/cmdline'],
297                 [0, 'mcelog', 'mcelog'],          294                 [0, 'mcelog', 'mcelog'],
298                 [0, 'pcidevices', 'lspci', '-t    295                 [0, 'pcidevices', 'lspci', '-tv'],
299                 [0, 'usbdevices', 'lsusb', '-t    296                 [0, 'usbdevices', 'lsusb', '-tv'],
300                 [0, 'acpidevices', 'sh', '-c',    297                 [0, 'acpidevices', 'sh', '-c', 'ls -l /sys/bus/acpi/devices/*/physical_node'],
301                 [0, 's0ix_require', 'cat', '/s    298                 [0, 's0ix_require', 'cat', '/sys/kernel/debug/pmc_core/substate_requirements'],
302                 [0, 's0ix_debug', 'cat', '/sys    299                 [0, 's0ix_debug', 'cat', '/sys/kernel/debug/pmc_core/slp_s0_debug_status'],
303                 [0, 'ethtool', 'ethtool', '{et << 
304                 [1, 's0ix_residency', 'cat', '    300                 [1, 's0ix_residency', 'cat', '/sys/kernel/debug/pmc_core/slp_s0_residency_usec'],
305                 [1, 'interrupts', 'cat', '/pro    301                 [1, 'interrupts', 'cat', '/proc/interrupts'],
306                 [1, 'wakeups', 'cat', '/sys/ke    302                 [1, 'wakeups', 'cat', '/sys/kernel/debug/wakeup_sources'],
307                 [2, 'gpecounts', 'sh', '-c', '    303                 [2, 'gpecounts', 'sh', '-c', 'grep -v invalid /sys/firmware/acpi/interrupts/*'],
308                 [2, 'suspendstats', 'sh', '-c'    304                 [2, 'suspendstats', 'sh', '-c', 'grep -v invalid /sys/power/suspend_stats/*'],
309                 [2, 'cpuidle', 'sh', '-c', 'gr    305                 [2, 'cpuidle', 'sh', '-c', 'grep -v invalid /sys/devices/system/cpu/cpu*/cpuidle/state*/s2idle/*'],
310                 [2, 'battery', 'sh', '-c', 'gr    306                 [2, 'battery', 'sh', '-c', 'grep -v invalid /sys/class/power_supply/*/*'],
311                 [2, 'thermal', 'sh', '-c', 'gr << 
312         ]                                         307         ]
313         cgblacklist = []                          308         cgblacklist = []
314         kprobes = dict()                          309         kprobes = dict()
315         timeformat = '%.3f'                       310         timeformat = '%.3f'
316         cmdline = '%s %s' % \                     311         cmdline = '%s %s' % \
317                         (os.path.basename(sys.    312                         (os.path.basename(sys.argv[0]), ' '.join(sys.argv[1:]))
318         sudouser = ''                             313         sudouser = ''
319         def __init__(self):                       314         def __init__(self):
320                 self.archargs = 'args_'+platfo    315                 self.archargs = 'args_'+platform.machine()
321                 self.hostname = platform.node(    316                 self.hostname = platform.node()
322                 if(self.hostname == ''):          317                 if(self.hostname == ''):
323                         self.hostname = 'local    318                         self.hostname = 'localhost'
324                 rtc = "rtc0"                      319                 rtc = "rtc0"
325                 if os.path.exists('/dev/rtc'):    320                 if os.path.exists('/dev/rtc'):
326                         rtc = os.readlink('/de    321                         rtc = os.readlink('/dev/rtc')
327                 rtc = '/sys/class/rtc/'+rtc       322                 rtc = '/sys/class/rtc/'+rtc
328                 if os.path.exists(rtc) and os.    323                 if os.path.exists(rtc) and os.path.exists(rtc+'/date') and \
329                         os.path.exists(rtc+'/t    324                         os.path.exists(rtc+'/time') and os.path.exists(rtc+'/wakealarm'):
330                         self.rtcpath = rtc        325                         self.rtcpath = rtc
331                 if (hasattr(sys.stdout, 'isatt    326                 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()):
332                         self.ansi = True          327                         self.ansi = True
333                 self.testdir = datetime.now().    328                 self.testdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S')
334                 if os.getuid() == 0 and 'SUDO_    329                 if os.getuid() == 0 and 'SUDO_USER' in os.environ and \
335                         os.environ['SUDO_USER'    330                         os.environ['SUDO_USER']:
336                         self.sudouser = os.env    331                         self.sudouser = os.environ['SUDO_USER']
337         def resetlog(self):                       332         def resetlog(self):
338                 self.logmsg = ''                  333                 self.logmsg = ''
339                 self.platinfo = []                334                 self.platinfo = []
340         def vprint(self, msg):                    335         def vprint(self, msg):
341                 self.logmsg += msg+'\n'           336                 self.logmsg += msg+'\n'
342                 if self.verbose or msg.startsw    337                 if self.verbose or msg.startswith('WARNING:'):
343                         pprint(msg)               338                         pprint(msg)
344         def signalHandler(self, signum, frame)    339         def signalHandler(self, signum, frame):
345                 if not self.result:               340                 if not self.result:
346                         return                    341                         return
347                 signame = self.signames[signum    342                 signame = self.signames[signum] if signum in self.signames else 'UNKNOWN'
348                 msg = 'Signal %s caused a tool    343                 msg = 'Signal %s caused a tool exit, line %d' % (signame, frame.f_lineno)
349                 self.outputResult({'error':msg    344                 self.outputResult({'error':msg})
350                 sys.exit(3)                       345                 sys.exit(3)
351         def signalHandlerInit(self):              346         def signalHandlerInit(self):
352                 capture = ['BUS', 'SYS', 'XCPU    347                 capture = ['BUS', 'SYS', 'XCPU', 'XFSZ', 'PWR', 'HUP', 'INT', 'QUIT',
353                         'ILL', 'ABRT', 'FPE',     348                         'ILL', 'ABRT', 'FPE', 'SEGV', 'TERM']
354                 self.signames = dict()            349                 self.signames = dict()
355                 for i in capture:                 350                 for i in capture:
356                         s = 'SIG'+i               351                         s = 'SIG'+i
357                         try:                      352                         try:
358                                 signum = getat    353                                 signum = getattr(signal, s)
359                                 signal.signal(    354                                 signal.signal(signum, self.signalHandler)
360                         except:                   355                         except:
361                                 continue          356                                 continue
362                         self.signames[signum]     357                         self.signames[signum] = s
363         def rootCheck(self, fatal=True):          358         def rootCheck(self, fatal=True):
364                 if(os.access(self.powerfile, o    359                 if(os.access(self.powerfile, os.W_OK)):
365                         return True               360                         return True
366                 if fatal:                         361                 if fatal:
367                         msg = 'This command re    362                         msg = 'This command requires sysfs mount and root access'
368                         pprint('ERROR: %s\n' %    363                         pprint('ERROR: %s\n' % msg)
369                         self.outputResult({'er    364                         self.outputResult({'error':msg})
370                         sys.exit(1)               365                         sys.exit(1)
371                 return False                      366                 return False
372         def rootUser(self, fatal=False):          367         def rootUser(self, fatal=False):
373                 if 'USER' in os.environ and os    368                 if 'USER' in os.environ and os.environ['USER'] == 'root':
374                         return True               369                         return True
375                 if fatal:                         370                 if fatal:
376                         msg = 'This command mu    371                         msg = 'This command must be run as root'
377                         pprint('ERROR: %s\n' %    372                         pprint('ERROR: %s\n' % msg)
378                         self.outputResult({'er    373                         self.outputResult({'error':msg})
379                         sys.exit(1)               374                         sys.exit(1)
380                 return False                      375                 return False
381         def usable(self, file, ishtml=False):     376         def usable(self, file, ishtml=False):
382                 if not os.path.exists(file) or    377                 if not os.path.exists(file) or os.path.getsize(file) < 1:
383                         return False              378                         return False
384                 if ishtml:                        379                 if ishtml:
385                         try:                      380                         try:
386                                 fp = open(file    381                                 fp = open(file, 'r')
387                                 res = fp.read(    382                                 res = fp.read(1000)
388                                 fp.close()        383                                 fp.close()
389                         except:                   384                         except:
390                                 return False      385                                 return False
391                         if '<html>' not in res    386                         if '<html>' not in res:
392                                 return False      387                                 return False
393                 return True                       388                 return True
394         def getExec(self, cmd):                   389         def getExec(self, cmd):
395                 try:                              390                 try:
396                         fp = Popen(['which', c    391                         fp = Popen(['which', cmd], stdout=PIPE, stderr=PIPE).stdout
397                         out = ascii(fp.read())    392                         out = ascii(fp.read()).strip()
398                         fp.close()                393                         fp.close()
399                 except:                           394                 except:
400                         out = ''                  395                         out = ''
401                 if out:                           396                 if out:
402                         return out                397                         return out
403                 for path in ['/sbin', '/bin',     398                 for path in ['/sbin', '/bin', '/usr/sbin', '/usr/bin',
404                         '/usr/local/sbin', '/u    399                         '/usr/local/sbin', '/usr/local/bin']:
405                         cmdfull = os.path.join    400                         cmdfull = os.path.join(path, cmd)
406                         if os.path.exists(cmdf    401                         if os.path.exists(cmdfull):
407                                 return cmdfull    402                                 return cmdfull
408                 return out                        403                 return out
409         def setPrecision(self, num):              404         def setPrecision(self, num):
410                 if num < 0 or num > 6:            405                 if num < 0 or num > 6:
411                         return                    406                         return
412                 self.timeformat = '%.{0}f'.for    407                 self.timeformat = '%.{0}f'.format(num)
413         def setOutputFolder(self, value):         408         def setOutputFolder(self, value):
414                 args = dict()                     409                 args = dict()
415                 n = datetime.now()                410                 n = datetime.now()
416                 args['date'] = n.strftime('%y%    411                 args['date'] = n.strftime('%y%m%d')
417                 args['time'] = n.strftime('%H%    412                 args['time'] = n.strftime('%H%M%S')
418                 args['hostname'] = args['host'    413                 args['hostname'] = args['host'] = self.hostname
419                 args['mode'] = self.suspendmod    414                 args['mode'] = self.suspendmode
420                 return value.format(**args)       415                 return value.format(**args)
421         def setOutputFile(self):                  416         def setOutputFile(self):
422                 if self.dmesgfile != '':          417                 if self.dmesgfile != '':
423                         m = re.match(r'(?P<nam !! 418                         m = re.match('(?P<name>.*)_dmesg\.txt.*', self.dmesgfile)
424                         if(m):                    419                         if(m):
425                                 self.htmlfile     420                                 self.htmlfile = m.group('name')+'.html'
426                 if self.ftracefile != '':         421                 if self.ftracefile != '':
427                         m = re.match(r'(?P<nam !! 422                         m = re.match('(?P<name>.*)_ftrace\.txt.*', self.ftracefile)
428                         if(m):                    423                         if(m):
429                                 self.htmlfile     424                                 self.htmlfile = m.group('name')+'.html'
430         def systemInfo(self, info):               425         def systemInfo(self, info):
431                 p = m = ''                        426                 p = m = ''
432                 if 'baseboard-manufacturer' in    427                 if 'baseboard-manufacturer' in info:
433                         m = info['baseboard-ma    428                         m = info['baseboard-manufacturer']
434                 elif 'system-manufacturer' in     429                 elif 'system-manufacturer' in info:
435                         m = info['system-manuf    430                         m = info['system-manufacturer']
436                 if 'system-product-name' in in    431                 if 'system-product-name' in info:
437                         p = info['system-produ    432                         p = info['system-product-name']
438                 elif 'baseboard-product-name'     433                 elif 'baseboard-product-name' in info:
439                         p = info['baseboard-pr    434                         p = info['baseboard-product-name']
440                 if m[:5].lower() == 'intel' an    435                 if m[:5].lower() == 'intel' and 'baseboard-product-name' in info:
441                         p = info['baseboard-pr    436                         p = info['baseboard-product-name']
442                 c = info['processor-version']     437                 c = info['processor-version'] if 'processor-version' in info else ''
443                 b = info['bios-version'] if 'b    438                 b = info['bios-version'] if 'bios-version' in info else ''
444                 r = info['bios-release-date']     439                 r = info['bios-release-date'] if 'bios-release-date' in info else ''
445                 self.sysstamp = '# sysinfo | m    440                 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    441                         (m, p, c, b, r, self.cpucount, self.memtotal, self.memfree)
447                 if self.osversion:                442                 if self.osversion:
448                         self.sysstamp += ' | o    443                         self.sysstamp += ' | os:%s' % self.osversion
449         def printSystemInfo(self, fatal=False)    444         def printSystemInfo(self, fatal=False):
450                 self.rootCheck(True)              445                 self.rootCheck(True)
451                 out = dmidecode(self.mempath,     446                 out = dmidecode(self.mempath, fatal)
452                 if len(out) < 1:                  447                 if len(out) < 1:
453                         return                    448                         return
454                 fmt = '%-24s: %s'                 449                 fmt = '%-24s: %s'
455                 if self.osversion:                450                 if self.osversion:
456                         print(fmt % ('os-versi    451                         print(fmt % ('os-version', self.osversion))
457                 for name in sorted(out):          452                 for name in sorted(out):
458                         print(fmt % (name, out    453                         print(fmt % (name, out[name]))
459                 print(fmt % ('cpucount', ('%d'    454                 print(fmt % ('cpucount', ('%d' % self.cpucount)))
460                 print(fmt % ('memtotal', ('%d     455                 print(fmt % ('memtotal', ('%d kB' % self.memtotal)))
461                 print(fmt % ('memfree', ('%d k    456                 print(fmt % ('memfree', ('%d kB' % self.memfree)))
462         def cpuInfo(self):                        457         def cpuInfo(self):
463                 self.cpucount = 0                 458                 self.cpucount = 0
464                 if os.path.exists('/proc/cpuin    459                 if os.path.exists('/proc/cpuinfo'):
465                         with open('/proc/cpuin    460                         with open('/proc/cpuinfo', 'r') as fp:
466                                 for line in fp    461                                 for line in fp:
467                                         if re. !! 462                                         if re.match('^processor[ \t]*:[ \t]*[0-9]*', line):
468                                                   463                                                 self.cpucount += 1
469                 if os.path.exists('/proc/memin    464                 if os.path.exists('/proc/meminfo'):
470                         with open('/proc/memin    465                         with open('/proc/meminfo', 'r') as fp:
471                                 for line in fp    466                                 for line in fp:
472                                         m = re !! 467                                         m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line)
473                                         if m:     468                                         if m:
474                                                   469                                                 self.memtotal = int(m.group('sz'))
475                                         m = re !! 470                                         m = re.match('^MemFree:[ \t]*(?P<sz>[0-9]*) *kB', line)
476                                         if m:     471                                         if m:
477                                                   472                                                 self.memfree = int(m.group('sz'))
478                 if os.path.exists('/etc/os-rel    473                 if os.path.exists('/etc/os-release'):
479                         with open('/etc/os-rel    474                         with open('/etc/os-release', 'r') as fp:
480                                 for line in fp    475                                 for line in fp:
481                                         if lin    476                                         if line.startswith('PRETTY_NAME='):
482                                                   477                                                 self.osversion = line[12:].strip().replace('"', '')
483         def initTestOutput(self, name):           478         def initTestOutput(self, name):
484                 self.prefix = self.hostname       479                 self.prefix = self.hostname
485                 v = open('/proc/version', 'r')    480                 v = open('/proc/version', 'r').read().strip()
486                 kver = v.split()[2]               481                 kver = v.split()[2]
487                 fmt = name+'-%m%d%y-%H%M%S'       482                 fmt = name+'-%m%d%y-%H%M%S'
488                 testtime = datetime.now().strf    483                 testtime = datetime.now().strftime(fmt)
489                 self.teststamp = \                484                 self.teststamp = \
490                         '# '+testtime+' '+self    485                         '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver
491                 ext = ''                          486                 ext = ''
492                 if self.gzip:                     487                 if self.gzip:
493                         ext = '.gz'               488                         ext = '.gz'
494                 self.dmesgfile = \                489                 self.dmesgfile = \
495                         self.testdir+'/'+self.    490                         self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt'+ext
496                 self.ftracefile = \               491                 self.ftracefile = \
497                         self.testdir+'/'+self.    492                         self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt'+ext
498                 self.htmlfile = \                 493                 self.htmlfile = \
499                         self.testdir+'/'+self.    494                         self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html'
500                 if not os.path.isdir(self.test    495                 if not os.path.isdir(self.testdir):
501                         os.makedirs(self.testd    496                         os.makedirs(self.testdir)
502                 self.sudoUserchown(self.testdi    497                 self.sudoUserchown(self.testdir)
503         def getValueList(self, value):            498         def getValueList(self, value):
504                 out = []                          499                 out = []
505                 for i in value.split(','):        500                 for i in value.split(','):
506                         if i.strip():             501                         if i.strip():
507                                 out.append(i.s    502                                 out.append(i.strip())
508                 return out                        503                 return out
509         def setDeviceFilter(self, value):         504         def setDeviceFilter(self, value):
510                 self.devicefilter = self.getVa    505                 self.devicefilter = self.getValueList(value)
511         def setCallgraphFilter(self, value):      506         def setCallgraphFilter(self, value):
512                 self.cgfilter = self.getValueL    507                 self.cgfilter = self.getValueList(value)
513         def skipKprobes(self, value):             508         def skipKprobes(self, value):
514                 for k in self.getValueList(val    509                 for k in self.getValueList(value):
515                         if k in self.tracefunc    510                         if k in self.tracefuncs:
516                                 del self.trace    511                                 del self.tracefuncs[k]
517                         if k in self.dev_trace    512                         if k in self.dev_tracefuncs:
518                                 del self.dev_t    513                                 del self.dev_tracefuncs[k]
519         def setCallgraphBlacklist(self, file):    514         def setCallgraphBlacklist(self, file):
520                 self.cgblacklist = self.listFr    515                 self.cgblacklist = self.listFromFile(file)
521         def rtcWakeAlarmOn(self):                 516         def rtcWakeAlarmOn(self):
522                 call('echo 0 > '+self.rtcpath+    517                 call('echo 0 > '+self.rtcpath+'/wakealarm', shell=True)
523                 nowtime = open(self.rtcpath+'/    518                 nowtime = open(self.rtcpath+'/since_epoch', 'r').read().strip()
524                 if nowtime:                       519                 if nowtime:
525                         nowtime = int(nowtime)    520                         nowtime = int(nowtime)
526                 else:                             521                 else:
527                         # if hardware time fai    522                         # if hardware time fails, use the software time
528                         nowtime = int(datetime    523                         nowtime = int(datetime.now().strftime('%s'))
529                 alarm = nowtime + self.rtcwake    524                 alarm = nowtime + self.rtcwaketime
530                 call('echo %d > %s/wakealarm'     525                 call('echo %d > %s/wakealarm' % (alarm, self.rtcpath), shell=True)
531         def rtcWakeAlarmOff(self):                526         def rtcWakeAlarmOff(self):
532                 call('echo 0 > %s/wakealarm' %    527                 call('echo 0 > %s/wakealarm' % self.rtcpath, shell=True)
533         def initdmesg(self):                      528         def initdmesg(self):
534                 # get the latest time stamp fr    529                 # get the latest time stamp from the dmesg log
535                 lines = Popen('dmesg', stdout=    530                 lines = Popen('dmesg', stdout=PIPE).stdout.readlines()
536                 ktime = '0'                       531                 ktime = '0'
537                 for line in reversed(lines):      532                 for line in reversed(lines):
538                         line = ascii(line).rep    533                         line = ascii(line).replace('\r\n', '')
539                         idx = line.find('[')      534                         idx = line.find('[')
540                         if idx > 1:               535                         if idx > 1:
541                                 line = line[id    536                                 line = line[idx:]
542                         m = re.match(r'[ \t]*( !! 537                         m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
543                         if(m):                    538                         if(m):
544                                 ktime = m.grou    539                                 ktime = m.group('ktime')
545                                 break             540                                 break
546                 self.dmesgstart = float(ktime)    541                 self.dmesgstart = float(ktime)
547         def getdmesg(self, testdata):             542         def getdmesg(self, testdata):
548                 op = self.writeDatafileHeader(    543                 op = self.writeDatafileHeader(self.dmesgfile, testdata)
549                 # store all new dmesg lines si    544                 # store all new dmesg lines since initdmesg was called
550                 fp = Popen('dmesg', stdout=PIP    545                 fp = Popen('dmesg', stdout=PIPE).stdout
551                 for line in fp:                   546                 for line in fp:
552                         line = ascii(line).rep    547                         line = ascii(line).replace('\r\n', '')
553                         idx = line.find('[')      548                         idx = line.find('[')
554                         if idx > 1:               549                         if idx > 1:
555                                 line = line[id    550                                 line = line[idx:]
556                         m = re.match(r'[ \t]*( !! 551                         m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
557                         if(not m):                552                         if(not m):
558                                 continue          553                                 continue
559                         ktime = float(m.group(    554                         ktime = float(m.group('ktime'))
560                         if ktime > self.dmesgs    555                         if ktime > self.dmesgstart:
561                                 op.write(line)    556                                 op.write(line)
562                 fp.close()                        557                 fp.close()
563                 op.close()                        558                 op.close()
564         def listFromFile(self, file):             559         def listFromFile(self, file):
565                 list = []                         560                 list = []
566                 fp = open(file)                   561                 fp = open(file)
567                 for i in fp.read().split('\n')    562                 for i in fp.read().split('\n'):
568                         i = i.strip()             563                         i = i.strip()
569                         if i and i[0] != '#':     564                         if i and i[0] != '#':
570                                 list.append(i)    565                                 list.append(i)
571                 fp.close()                        566                 fp.close()
572                 return list                       567                 return list
573         def addFtraceFilterFunctions(self, fil    568         def addFtraceFilterFunctions(self, file):
574                 for i in self.listFromFile(fil    569                 for i in self.listFromFile(file):
575                         if len(i) < 2:            570                         if len(i) < 2:
576                                 continue          571                                 continue
577                         self.tracefuncs[i] = d    572                         self.tracefuncs[i] = dict()
578         def getFtraceFilterFunctions(self, cur    573         def getFtraceFilterFunctions(self, current):
579                 self.rootCheck(True)              574                 self.rootCheck(True)
580                 if not current:                   575                 if not current:
581                         call('cat '+self.tpath    576                         call('cat '+self.tpath+'available_filter_functions', shell=True)
582                         return                    577                         return
583                 master = self.listFromFile(sel    578                 master = self.listFromFile(self.tpath+'available_filter_functions')
584                 for i in sorted(self.tracefunc    579                 for i in sorted(self.tracefuncs):
585                         if 'func' in self.trac    580                         if 'func' in self.tracefuncs[i]:
586                                 i = self.trace    581                                 i = self.tracefuncs[i]['func']
587                         if i in master:           582                         if i in master:
588                                 print(i)          583                                 print(i)
589                         else:                     584                         else:
590                                 print(self.col    585                                 print(self.colorText(i))
591         def setFtraceFilterFunctions(self, lis    586         def setFtraceFilterFunctions(self, list):
592                 master = self.listFromFile(sel    587                 master = self.listFromFile(self.tpath+'available_filter_functions')
593                 flist = ''                        588                 flist = ''
594                 for i in list:                    589                 for i in list:
595                         if i not in master:       590                         if i not in master:
596                                 continue          591                                 continue
597                         if ' [' in i:             592                         if ' [' in i:
598                                 flist += i.spl    593                                 flist += i.split(' ')[0]+'\n'
599                         else:                     594                         else:
600                                 flist += i+'\n    595                                 flist += i+'\n'
601                 fp = open(self.tpath+'set_grap    596                 fp = open(self.tpath+'set_graph_function', 'w')
602                 fp.write(flist)                   597                 fp.write(flist)
603                 fp.close()                        598                 fp.close()
604         def basicKprobe(self, name):              599         def basicKprobe(self, name):
605                 self.kprobes[name] = {'name':     600                 self.kprobes[name] = {'name': name,'func': name,'args': dict(),'format': name}
606         def defaultKprobe(self, name, kdata):     601         def defaultKprobe(self, name, kdata):
607                 k = kdata                         602                 k = kdata
608                 for field in ['name', 'format'    603                 for field in ['name', 'format', 'func']:
609                         if field not in k:        604                         if field not in k:
610                                 k[field] = nam    605                                 k[field] = name
611                 if self.archargs in k:            606                 if self.archargs in k:
612                         k['args'] = k[self.arc    607                         k['args'] = k[self.archargs]
613                 else:                             608                 else:
614                         k['args'] = dict()        609                         k['args'] = dict()
615                         k['format'] = name        610                         k['format'] = name
616                 self.kprobes[name] = k            611                 self.kprobes[name] = k
617         def kprobeColor(self, name):              612         def kprobeColor(self, name):
618                 if name not in self.kprobes or    613                 if name not in self.kprobes or 'color' not in self.kprobes[name]:
619                         return ''                 614                         return ''
620                 return self.kprobes[name]['col    615                 return self.kprobes[name]['color']
621         def kprobeDisplayName(self, name, data    616         def kprobeDisplayName(self, name, dataraw):
622                 if name not in self.kprobes:      617                 if name not in self.kprobes:
623                         self.basicKprobe(name)    618                         self.basicKprobe(name)
624                 data = ''                         619                 data = ''
625                 quote=0                           620                 quote=0
626                 # first remvoe any spaces insi    621                 # first remvoe any spaces inside quotes, and the quotes
627                 for c in dataraw:                 622                 for c in dataraw:
628                         if c == '"':              623                         if c == '"':
629                                 quote = (quote    624                                 quote = (quote + 1) % 2
630                         if quote and c == ' ':    625                         if quote and c == ' ':
631                                 data += '_'       626                                 data += '_'
632                         elif c != '"':            627                         elif c != '"':
633                                 data += c         628                                 data += c
634                 fmt, args = self.kprobes[name]    629                 fmt, args = self.kprobes[name]['format'], self.kprobes[name]['args']
635                 arglist = dict()                  630                 arglist = dict()
636                 # now process the args            631                 # now process the args
637                 for arg in sorted(args):          632                 for arg in sorted(args):
638                         arglist[arg] = ''         633                         arglist[arg] = ''
639                         m = re.match(r'.* '+ar !! 634                         m = re.match('.* '+arg+'=(?P<arg>.*) ', data);
640                         if m:                     635                         if m:
641                                 arglist[arg] =    636                                 arglist[arg] = m.group('arg')
642                         else:                     637                         else:
643                                 m = re.match(r !! 638                                 m = re.match('.* '+arg+'=(?P<arg>.*)', data);
644                                 if m:             639                                 if m:
645                                         arglis    640                                         arglist[arg] = m.group('arg')
646                 out = fmt.format(**arglist)       641                 out = fmt.format(**arglist)
647                 out = out.replace(' ', '_').re    642                 out = out.replace(' ', '_').replace('"', '')
648                 return out                        643                 return out
649         def kprobeText(self, kname, kprobe):      644         def kprobeText(self, kname, kprobe):
650                 name = fmt = func = kname         645                 name = fmt = func = kname
651                 args = dict()                     646                 args = dict()
652                 if 'name' in kprobe:              647                 if 'name' in kprobe:
653                         name = kprobe['name']     648                         name = kprobe['name']
654                 if 'format' in kprobe:            649                 if 'format' in kprobe:
655                         fmt = kprobe['format']    650                         fmt = kprobe['format']
656                 if 'func' in kprobe:              651                 if 'func' in kprobe:
657                         func = kprobe['func']     652                         func = kprobe['func']
658                 if self.archargs in kprobe:       653                 if self.archargs in kprobe:
659                         args = kprobe[self.arc    654                         args = kprobe[self.archargs]
660                 if 'args' in kprobe:              655                 if 'args' in kprobe:
661                         args = kprobe['args']     656                         args = kprobe['args']
662                 if re.findall('{(?P<n>[a-z,A-Z    657                 if re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', func):
663                         doError('Kprobe "%s" h    658                         doError('Kprobe "%s" has format info in the function name "%s"' % (name, func))
664                 for arg in re.findall('{(?P<n>    659                 for arg in re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', fmt):
665                         if arg not in args:       660                         if arg not in args:
666                                 doError('Kprob    661                                 doError('Kprobe "%s" is missing argument "%s"' % (name, arg))
667                 val = 'p:%s_cal %s' % (name, f    662                 val = 'p:%s_cal %s' % (name, func)
668                 for i in sorted(args):            663                 for i in sorted(args):
669                         val += ' %s=%s' % (i,     664                         val += ' %s=%s' % (i, args[i])
670                 val += '\nr:%s_ret %s $retval\    665                 val += '\nr:%s_ret %s $retval\n' % (name, func)
671                 return val                        666                 return val
672         def addKprobes(self, output=False):       667         def addKprobes(self, output=False):
673                 if len(self.kprobes) < 1:         668                 if len(self.kprobes) < 1:
674                         return                    669                         return
675                 if output:                        670                 if output:
676                         pprint('    kprobe fun    671                         pprint('    kprobe functions in this kernel:')
677                 # first test each kprobe          672                 # first test each kprobe
678                 rejects = []                      673                 rejects = []
679                 # sort kprobes: trace, ub-dev,    674                 # sort kprobes: trace, ub-dev, custom, dev
680                 kpl = [[], [], [], []]            675                 kpl = [[], [], [], []]
681                 linesout = len(self.kprobes)      676                 linesout = len(self.kprobes)
682                 for name in sorted(self.kprobe    677                 for name in sorted(self.kprobes):
683                         res = self.colorText('    678                         res = self.colorText('YES', 32)
684                         if not self.testKprobe    679                         if not self.testKprobe(name, self.kprobes[name]):
685                                 res = self.col    680                                 res = self.colorText('NO')
686                                 rejects.append    681                                 rejects.append(name)
687                         else:                     682                         else:
688                                 if name in sel    683                                 if name in self.tracefuncs:
689                                         kpl[0]    684                                         kpl[0].append(name)
690                                 elif name in s    685                                 elif name in self.dev_tracefuncs:
691                                         if 'ub    686                                         if 'ub' in self.dev_tracefuncs[name]:
692                                                   687                                                 kpl[1].append(name)
693                                         else:     688                                         else:
694                                                   689                                                 kpl[3].append(name)
695                                 else:             690                                 else:
696                                         kpl[2]    691                                         kpl[2].append(name)
697                         if output:                692                         if output:
698                                 pprint('          693                                 pprint('         %s: %s' % (name, res))
699                 kplist = kpl[0] + kpl[1] + kpl    694                 kplist = kpl[0] + kpl[1] + kpl[2] + kpl[3]
700                 # remove all failed ones from     695                 # remove all failed ones from the list
701                 for name in rejects:              696                 for name in rejects:
702                         self.kprobes.pop(name)    697                         self.kprobes.pop(name)
703                 # set the kprobes all at once     698                 # set the kprobes all at once
704                 self.fsetVal('', 'kprobe_event    699                 self.fsetVal('', 'kprobe_events')
705                 kprobeevents = ''                 700                 kprobeevents = ''
706                 for kp in kplist:                 701                 for kp in kplist:
707                         kprobeevents += self.k    702                         kprobeevents += self.kprobeText(kp, self.kprobes[kp])
708                 self.fsetVal(kprobeevents, 'kp    703                 self.fsetVal(kprobeevents, 'kprobe_events')
709                 if output:                        704                 if output:
710                         check = self.fgetVal('    705                         check = self.fgetVal('kprobe_events')
711                         linesack = (len(check.    706                         linesack = (len(check.split('\n')) - 1) // 2
712                         pprint('    kprobe fun    707                         pprint('    kprobe functions enabled: %d/%d' % (linesack, linesout))
713                 self.fsetVal('1', 'events/kpro    708                 self.fsetVal('1', 'events/kprobes/enable')
714         def testKprobe(self, kname, kprobe):      709         def testKprobe(self, kname, kprobe):
715                 self.fsetVal('0', 'events/kpro    710                 self.fsetVal('0', 'events/kprobes/enable')
716                 kprobeevents = self.kprobeText    711                 kprobeevents = self.kprobeText(kname, kprobe)
717                 if not kprobeevents:              712                 if not kprobeevents:
718                         return False              713                         return False
719                 try:                              714                 try:
720                         self.fsetVal(kprobeeve    715                         self.fsetVal(kprobeevents, 'kprobe_events')
721                         check = self.fgetVal('    716                         check = self.fgetVal('kprobe_events')
722                 except:                           717                 except:
723                         return False              718                         return False
724                 linesout = len(kprobeevents.sp    719                 linesout = len(kprobeevents.split('\n'))
725                 linesack = len(check.split('\n    720                 linesack = len(check.split('\n'))
726                 if linesack < linesout:           721                 if linesack < linesout:
727                         return False              722                         return False
728                 return True                       723                 return True
729         def setVal(self, val, file):              724         def setVal(self, val, file):
730                 if not os.path.exists(file):      725                 if not os.path.exists(file):
731                         return False              726                         return False
732                 try:                              727                 try:
733                         fp = open(file, 'wb',     728                         fp = open(file, 'wb', 0)
734                         fp.write(val.encode())    729                         fp.write(val.encode())
735                         fp.flush()                730                         fp.flush()
736                         fp.close()                731                         fp.close()
737                 except:                           732                 except:
738                         return False              733                         return False
739                 return True                       734                 return True
740         def fsetVal(self, val, path):             735         def fsetVal(self, val, path):
741                 if not self.useftrace:            736                 if not self.useftrace:
742                         return False              737                         return False
743                 return self.setVal(val, self.t    738                 return self.setVal(val, self.tpath+path)
744         def getVal(self, file):                   739         def getVal(self, file):
745                 res = ''                          740                 res = ''
746                 if not os.path.exists(file):      741                 if not os.path.exists(file):
747                         return res                742                         return res
748                 try:                              743                 try:
749                         fp = open(file, 'r')      744                         fp = open(file, 'r')
750                         res = fp.read()           745                         res = fp.read()
751                         fp.close()                746                         fp.close()
752                 except:                           747                 except:
753                         pass                      748                         pass
754                 return res                        749                 return res
755         def fgetVal(self, path):                  750         def fgetVal(self, path):
756                 if not self.useftrace:            751                 if not self.useftrace:
757                         return ''                 752                         return ''
758                 return self.getVal(self.tpath+    753                 return self.getVal(self.tpath+path)
759         def cleanupFtrace(self):                  754         def cleanupFtrace(self):
760                 if self.useftrace:                755                 if self.useftrace:
761                         self.fsetVal('0', 'eve    756                         self.fsetVal('0', 'events/kprobes/enable')
762                         self.fsetVal('', 'kpro    757                         self.fsetVal('', 'kprobe_events')
763                         self.fsetVal('1024', '    758                         self.fsetVal('1024', 'buffer_size_kb')
764         def setupAllKprobes(self):                759         def setupAllKprobes(self):
765                 for name in self.tracefuncs:      760                 for name in self.tracefuncs:
766                         self.defaultKprobe(nam    761                         self.defaultKprobe(name, self.tracefuncs[name])
767                 for name in self.dev_tracefunc    762                 for name in self.dev_tracefuncs:
768                         self.defaultKprobe(nam    763                         self.defaultKprobe(name, self.dev_tracefuncs[name])
769         def isCallgraphFunc(self, name):          764         def isCallgraphFunc(self, name):
770                 if len(self.tracefuncs) < 1 an    765                 if len(self.tracefuncs) < 1 and self.suspendmode == 'command':
771                         return True               766                         return True
772                 for i in self.tracefuncs:         767                 for i in self.tracefuncs:
773                         if 'func' in self.trac    768                         if 'func' in self.tracefuncs[i]:
774                                 f = self.trace    769                                 f = self.tracefuncs[i]['func']
775                         else:                     770                         else:
776                                 f = i             771                                 f = i
777                         if name == f:             772                         if name == f:
778                                 return True       773                                 return True
779                 return False                      774                 return False
780         def initFtrace(self, quiet=False):        775         def initFtrace(self, quiet=False):
781                 if not self.useftrace:            776                 if not self.useftrace:
782                         return                    777                         return
783                 if not quiet:                     778                 if not quiet:
784                         sysvals.printSystemInf    779                         sysvals.printSystemInfo(False)
785                         pprint('INITIALIZING F !! 780                         pprint('INITIALIZING FTRACE...')
786                 # turn trace off                  781                 # turn trace off
787                 self.fsetVal('0', 'tracing_on'    782                 self.fsetVal('0', 'tracing_on')
788                 self.cleanupFtrace()              783                 self.cleanupFtrace()
789                 # set the trace clock to globa    784                 # set the trace clock to global
790                 self.fsetVal('global', 'trace_    785                 self.fsetVal('global', 'trace_clock')
791                 self.fsetVal('nop', 'current_t    786                 self.fsetVal('nop', 'current_tracer')
792                 # set trace buffer to an appro    787                 # set trace buffer to an appropriate value
793                 cpus = max(1, self.cpucount)      788                 cpus = max(1, self.cpucount)
794                 if self.bufsize > 0:              789                 if self.bufsize > 0:
795                         tgtsize = self.bufsize    790                         tgtsize = self.bufsize
796                 elif self.usecallgraph or self    791                 elif self.usecallgraph or self.usedevsrc:
797                         bmax = (1*1024*1024) i    792                         bmax = (1*1024*1024) if self.suspendmode in ['disk', 'command'] \
798                                 else (3*1024*1    793                                 else (3*1024*1024)
799                         tgtsize = min(self.mem    794                         tgtsize = min(self.memfree, bmax)
800                 else:                             795                 else:
801                         tgtsize = 65536           796                         tgtsize = 65536
802                 while not self.fsetVal('%d' %     797                 while not self.fsetVal('%d' % (tgtsize // cpus), 'buffer_size_kb'):
803                         # if the size failed t    798                         # if the size failed to set, lower it and keep trying
804                         tgtsize -= 65536          799                         tgtsize -= 65536
805                         if tgtsize < 65536:       800                         if tgtsize < 65536:
806                                 tgtsize = int(    801                                 tgtsize = int(self.fgetVal('buffer_size_kb')) * cpus
807                                 break             802                                 break
808                 self.vprint('Setting trace buf    803                 self.vprint('Setting trace buffers to %d kB (%d kB per cpu)' % (tgtsize, tgtsize/cpus))
809                 # initialize the callgraph tra    804                 # initialize the callgraph trace
810                 if(self.usecallgraph):            805                 if(self.usecallgraph):
811                         # set trace type          806                         # set trace type
812                         self.fsetVal('function    807                         self.fsetVal('function_graph', 'current_tracer')
813                         self.fsetVal('', 'set_    808                         self.fsetVal('', 'set_ftrace_filter')
814                         # temporary hack to fi    809                         # temporary hack to fix https://bugzilla.kernel.org/show_bug.cgi?id=212761
815                         fp = open(self.tpath+'    810                         fp = open(self.tpath+'set_ftrace_notrace', 'w')
816                         fp.write('native_queue    811                         fp.write('native_queued_spin_lock_slowpath\ndev_driver_string')
817                         fp.close()                812                         fp.close()
818                         # set trace format opt    813                         # set trace format options
819                         self.fsetVal('print-pa    814                         self.fsetVal('print-parent', 'trace_options')
820                         self.fsetVal('funcgrap    815                         self.fsetVal('funcgraph-abstime', 'trace_options')
821                         self.fsetVal('funcgrap    816                         self.fsetVal('funcgraph-cpu', 'trace_options')
822                         self.fsetVal('funcgrap    817                         self.fsetVal('funcgraph-duration', 'trace_options')
823                         self.fsetVal('funcgrap    818                         self.fsetVal('funcgraph-proc', 'trace_options')
824                         self.fsetVal('funcgrap    819                         self.fsetVal('funcgraph-tail', 'trace_options')
825                         self.fsetVal('nofuncgr    820                         self.fsetVal('nofuncgraph-overhead', 'trace_options')
826                         self.fsetVal('context-    821                         self.fsetVal('context-info', 'trace_options')
827                         self.fsetVal('graph-ti    822                         self.fsetVal('graph-time', 'trace_options')
828                         self.fsetVal('%d' % se    823                         self.fsetVal('%d' % self.max_graph_depth, 'max_graph_depth')
829                         cf = ['dpm_run_callbac    824                         cf = ['dpm_run_callback']
830                         if(self.usetraceevents    825                         if(self.usetraceevents):
831                                 cf += ['dpm_pr    826                                 cf += ['dpm_prepare', 'dpm_complete']
832                         for fn in self.tracefu    827                         for fn in self.tracefuncs:
833                                 if 'func' in s    828                                 if 'func' in self.tracefuncs[fn]:
834                                         cf.app    829                                         cf.append(self.tracefuncs[fn]['func'])
835                                 else:             830                                 else:
836                                         cf.app    831                                         cf.append(fn)
837                         if self.ftop:             832                         if self.ftop:
838                                 self.setFtrace    833                                 self.setFtraceFilterFunctions([self.ftopfunc])
839                         else:                     834                         else:
840                                 self.setFtrace    835                                 self.setFtraceFilterFunctions(cf)
841                 # initialize the kprobe trace     836                 # initialize the kprobe trace
842                 elif self.usekprobes:             837                 elif self.usekprobes:
843                         for name in self.trace    838                         for name in self.tracefuncs:
844                                 self.defaultKp    839                                 self.defaultKprobe(name, self.tracefuncs[name])
845                         if self.usedevsrc:        840                         if self.usedevsrc:
846                                 for name in se    841                                 for name in self.dev_tracefuncs:
847                                         self.d    842                                         self.defaultKprobe(name, self.dev_tracefuncs[name])
848                         if not quiet:             843                         if not quiet:
849                                 pprint('INITIA !! 844                                 pprint('INITIALIZING KPROBES...')
850                         self.addKprobes(self.v    845                         self.addKprobes(self.verbose)
851                 if(self.usetraceevents):          846                 if(self.usetraceevents):
852                         # turn trace events on    847                         # turn trace events on
853                         events = iter(self.tra    848                         events = iter(self.traceevents)
854                         for e in events:          849                         for e in events:
855                                 self.fsetVal('    850                                 self.fsetVal('1', 'events/power/'+e+'/enable')
856                 # clear the trace buffer          851                 # clear the trace buffer
857                 self.fsetVal('', 'trace')         852                 self.fsetVal('', 'trace')
858         def verifyFtrace(self):                   853         def verifyFtrace(self):
859                 # files needed for any trace d    854                 # files needed for any trace data
860                 files = ['buffer_size_kb', 'cu    855                 files = ['buffer_size_kb', 'current_tracer', 'trace', 'trace_clock',
861                                  'trace_marker    856                                  'trace_marker', 'trace_options', 'tracing_on']
862                 # files needed for callgraph t    857                 # files needed for callgraph trace data
863                 tp = self.tpath                   858                 tp = self.tpath
864                 if(self.usecallgraph):            859                 if(self.usecallgraph):
865                         files += [                860                         files += [
866                                 'available_fil    861                                 'available_filter_functions',
867                                 'set_ftrace_fi    862                                 'set_ftrace_filter',
868                                 'set_graph_fun    863                                 'set_graph_function'
869                         ]                         864                         ]
870                 for f in files:                   865                 for f in files:
871                         if(os.path.exists(tp+f    866                         if(os.path.exists(tp+f) == False):
872                                 return False      867                                 return False
873                 return True                       868                 return True
874         def verifyKprobes(self):                  869         def verifyKprobes(self):
875                 # files needed for kprobes to     870                 # files needed for kprobes to work
876                 files = ['kprobe_events', 'eve    871                 files = ['kprobe_events', 'events']
877                 tp = self.tpath                   872                 tp = self.tpath
878                 for f in files:                   873                 for f in files:
879                         if(os.path.exists(tp+f    874                         if(os.path.exists(tp+f) == False):
880                                 return False      875                                 return False
881                 return True                       876                 return True
882         def colorText(self, str, color=31):       877         def colorText(self, str, color=31):
883                 if not self.ansi:                 878                 if not self.ansi:
884                         return str                879                         return str
885                 return '\x1B[%d;40m%s\x1B[m' %    880                 return '\x1B[%d;40m%s\x1B[m' % (color, str)
886         def writeDatafileHeader(self, filename    881         def writeDatafileHeader(self, filename, testdata):
887                 fp = self.openlog(filename, 'w    882                 fp = self.openlog(filename, 'w')
888                 fp.write('%s\n%s\n# command |     883                 fp.write('%s\n%s\n# command | %s\n' % (self.teststamp, self.sysstamp, self.cmdline))
889                 for test in testdata:             884                 for test in testdata:
890                         if 'fw' in test:          885                         if 'fw' in test:
891                                 fw = test['fw'    886                                 fw = test['fw']
892                                 if(fw):           887                                 if(fw):
893                                         fp.wri    888                                         fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1]))
894                         if 'turbo' in test:       889                         if 'turbo' in test:
895                                 fp.write('# tu    890                                 fp.write('# turbostat %s\n' % test['turbo'])
896                         if 'wifi' in test:        891                         if 'wifi' in test:
897                                 fp.write('# wi    892                                 fp.write('# wifi %s\n' % test['wifi'])
898                         if 'netfix' in test:      893                         if 'netfix' in test:
899                                 fp.write('# ne    894                                 fp.write('# netfix %s\n' % test['netfix'])
900                         if test['error'] or le    895                         if test['error'] or len(testdata) > 1:
901                                 fp.write('# en    896                                 fp.write('# enter_sleep_error %s\n' % test['error'])
902                 return fp                         897                 return fp
903         def sudoUserchown(self, dir):             898         def sudoUserchown(self, dir):
904                 if os.path.exists(dir) and sel    899                 if os.path.exists(dir) and self.sudouser:
905                         cmd = 'chown -R {0}:{0    900                         cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1'
906                         call(cmd.format(self.s    901                         call(cmd.format(self.sudouser, dir), shell=True)
907         def outputResult(self, testdata, num=0    902         def outputResult(self, testdata, num=0):
908                 if not self.result:               903                 if not self.result:
909                         return                    904                         return
910                 n = ''                            905                 n = ''
911                 if num > 0:                       906                 if num > 0:
912                         n = '%d' % num            907                         n = '%d' % num
913                 fp = open(self.result, 'a')       908                 fp = open(self.result, 'a')
914                 if 'error' in testdata:           909                 if 'error' in testdata:
915                         fp.write('result%s: fa    910                         fp.write('result%s: fail\n' % n)
916                         fp.write('error%s: %s\    911                         fp.write('error%s: %s\n' % (n, testdata['error']))
917                 else:                             912                 else:
918                         fp.write('result%s: pa    913                         fp.write('result%s: pass\n' % n)
919                 if 'mode' in testdata:            914                 if 'mode' in testdata:
920                         fp.write('mode%s: %s\n    915                         fp.write('mode%s: %s\n' % (n, testdata['mode']))
921                 for v in ['suspend', 'resume',    916                 for v in ['suspend', 'resume', 'boot', 'lastinit']:
922                         if v in testdata:         917                         if v in testdata:
923                                 fp.write('%s%s    918                                 fp.write('%s%s: %.3f\n' % (v, n, testdata[v]))
924                 for v in ['fwsuspend', 'fwresu    919                 for v in ['fwsuspend', 'fwresume']:
925                         if v in testdata:         920                         if v in testdata:
926                                 fp.write('%s%s    921                                 fp.write('%s%s: %.3f\n' % (v, n, testdata[v] / 1000000.0))
927                 if 'bugurl' in testdata:          922                 if 'bugurl' in testdata:
928                         fp.write('url%s: %s\n'    923                         fp.write('url%s: %s\n' % (n, testdata['bugurl']))
929                 fp.close()                        924                 fp.close()
930                 self.sudoUserchown(self.result    925                 self.sudoUserchown(self.result)
931         def configFile(self, file):               926         def configFile(self, file):
932                 dir = os.path.dirname(os.path.    927                 dir = os.path.dirname(os.path.realpath(__file__))
933                 if os.path.exists(file):          928                 if os.path.exists(file):
934                         return file               929                         return file
935                 elif os.path.exists(dir+'/'+fi    930                 elif os.path.exists(dir+'/'+file):
936                         return dir+'/'+file       931                         return dir+'/'+file
937                 elif os.path.exists(dir+'/conf    932                 elif os.path.exists(dir+'/config/'+file):
938                         return dir+'/config/'+    933                         return dir+'/config/'+file
939                 return ''                         934                 return ''
940         def openlog(self, filename, mode):        935         def openlog(self, filename, mode):
941                 isgz = self.gzip                  936                 isgz = self.gzip
942                 if mode == 'r':                   937                 if mode == 'r':
943                         try:                      938                         try:
944                                 with gzip.open    939                                 with gzip.open(filename, mode+'t') as fp:
945                                         test =    940                                         test = fp.read(64)
946                                 isgz = True       941                                 isgz = True
947                         except:                   942                         except:
948                                 isgz = False      943                                 isgz = False
949                 if isgz:                          944                 if isgz:
950                         return gzip.open(filen    945                         return gzip.open(filename, mode+'t')
951                 return open(filename, mode)       946                 return open(filename, mode)
952         def putlog(self, filename, text):         947         def putlog(self, filename, text):
953                 with self.openlog(filename, 'a    948                 with self.openlog(filename, 'a') as fp:
954                         fp.write(text)            949                         fp.write(text)
955                         fp.close()                950                         fp.close()
956         def dlog(self, text):                     951         def dlog(self, text):
957                 if not self.dmesgfile:            952                 if not self.dmesgfile:
958                         return                    953                         return
959                 self.putlog(self.dmesgfile, '#    954                 self.putlog(self.dmesgfile, '# %s\n' % text)
960         def flog(self, text):                     955         def flog(self, text):
961                 self.putlog(self.ftracefile, t    956                 self.putlog(self.ftracefile, text)
962         def b64unzip(self, data):                 957         def b64unzip(self, data):
963                 try:                              958                 try:
964                         out = codecs.decode(ba    959                         out = codecs.decode(base64.b64decode(data), 'zlib').decode()
965                 except:                           960                 except:
966                         out = data                961                         out = data
967                 return out                        962                 return out
968         def b64zip(self, data):                   963         def b64zip(self, data):
969                 out = base64.b64encode(codecs.    964                 out = base64.b64encode(codecs.encode(data.encode(), 'zlib')).decode()
970                 return out                        965                 return out
971         def platforminfo(self, cmdafter):         966         def platforminfo(self, cmdafter):
972                 # add platform info on to a co    967                 # add platform info on to a completed ftrace file
973                 if not os.path.exists(self.ftr    968                 if not os.path.exists(self.ftracefile):
974                         return False              969                         return False
975                 footer = '#\n'                    970                 footer = '#\n'
976                                                   971 
977                 # add test command string line    972                 # add test command string line if need be
978                 if self.suspendmode == 'comman    973                 if self.suspendmode == 'command' and self.testcommand:
979                         footer += '# platform-    974                         footer += '# platform-testcmd: %s\n' % (self.testcommand)
980                                                   975 
981                 # get a list of target devices    976                 # get a list of target devices from the ftrace file
982                 props = dict()                    977                 props = dict()
983                 tp = TestProps()                  978                 tp = TestProps()
984                 tf = self.openlog(self.ftracef    979                 tf = self.openlog(self.ftracefile, 'r')
985                 for line in tf:                   980                 for line in tf:
986                         if tp.stampInfo(line,     981                         if tp.stampInfo(line, self):
987                                 continue          982                                 continue
988                         # parse only valid lin    983                         # parse only valid lines, if this is not one move on
989                         m = re.match(tp.ftrace    984                         m = re.match(tp.ftrace_line_fmt, line)
990                         if(not m or 'device_pm    985                         if(not m or 'device_pm_callback_start' not in line):
991                                 continue          986                                 continue
992                         m = re.match(r'.*: (?P !! 987                         m = re.match('.*: (?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*', m.group('msg'));
993                         if(not m):                988                         if(not m):
994                                 continue          989                                 continue
995                         dev = m.group('d')        990                         dev = m.group('d')
996                         if dev not in props:      991                         if dev not in props:
997                                 props[dev] = D    992                                 props[dev] = DevProps()
998                 tf.close()                        993                 tf.close()
999                                                   994 
1000                 # now get the syspath for eac    995                 # now get the syspath for each target device
1001                 for dirname, dirnames, filena    996                 for dirname, dirnames, filenames in os.walk('/sys/devices'):
1002                         if(re.match(r'.*/powe !! 997                         if(re.match('.*/power', dirname) and 'async' in filenames):
1003                                 dev = dirname    998                                 dev = dirname.split('/')[-2]
1004                                 if dev in pro    999                                 if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)):
1005                                         props    1000                                         props[dev].syspath = dirname[:-6]
1006                                                  1001 
1007                 # now fill in the properties     1002                 # now fill in the properties for our target devices
1008                 for dev in sorted(props):        1003                 for dev in sorted(props):
1009                         dirname = props[dev].    1004                         dirname = props[dev].syspath
1010                         if not dirname or not    1005                         if not dirname or not os.path.exists(dirname):
1011                                 continue         1006                                 continue
1012                         props[dev].isasync =     1007                         props[dev].isasync = False
1013                         if os.path.exists(dir    1008                         if os.path.exists(dirname+'/power/async'):
1014                                 fp = open(dir    1009                                 fp = open(dirname+'/power/async')
1015                                 if 'enabled'     1010                                 if 'enabled' in fp.read():
1016                                         props    1011                                         props[dev].isasync = True
1017                                 fp.close()       1012                                 fp.close()
1018                         fields = os.listdir(d    1013                         fields = os.listdir(dirname)
1019                         for file in ['product    1014                         for file in ['product', 'name', 'model', 'description', 'id', 'idVendor']:
1020                                 if file not i    1015                                 if file not in fields:
1021                                         conti    1016                                         continue
1022                                 try:             1017                                 try:
1023                                         with     1018                                         with open(os.path.join(dirname, file), 'rb') as fp:
1024                                                  1019                                                 props[dev].altname = ascii(fp.read())
1025                                 except:          1020                                 except:
1026                                         conti    1021                                         continue
1027                                 if file == 'i    1022                                 if file == 'idVendor':
1028                                         idv,     1023                                         idv, idp = props[dev].altname.strip(), ''
1029                                         try:     1024                                         try:
1030                                                  1025                                                 with open(os.path.join(dirname, 'idProduct'), 'rb') as fp:
1031                                                  1026                                                         idp = ascii(fp.read()).strip()
1032                                         excep    1027                                         except:
1033                                                  1028                                                 props[dev].altname = ''
1034                                                  1029                                                 break
1035                                         props    1030                                         props[dev].altname = '%s:%s' % (idv, idp)
1036                                 break            1031                                 break
1037                         if props[dev].altname    1032                         if props[dev].altname:
1038                                 out = props[d    1033                                 out = props[dev].altname.strip().replace('\n', ' ')\
1039                                         .repl    1034                                         .replace(',', ' ').replace(';', ' ')
1040                                 props[dev].al    1035                                 props[dev].altname = out
1041                                                  1036 
1042                 # add a devinfo line to the b    1037                 # add a devinfo line to the bottom of ftrace
1043                 out = ''                         1038                 out = ''
1044                 for dev in sorted(props):        1039                 for dev in sorted(props):
1045                         out += props[dev].out    1040                         out += props[dev].out(dev)
1046                 footer += '# platform-devinfo    1041                 footer += '# platform-devinfo: %s\n' % self.b64zip(out)
1047                                                  1042 
1048                 # add a line for each of thes    1043                 # add a line for each of these commands with their outputs
1049                 for name, cmdline, info in cm    1044                 for name, cmdline, info in cmdafter:
1050                         footer += '# platform    1045                         footer += '# platform-%s: %s | %s\n' % (name, cmdline, self.b64zip(info))
1051                 self.flog(footer)                1046                 self.flog(footer)
1052                 return True                      1047                 return True
1053         def commonPrefix(self, list):            1048         def commonPrefix(self, list):
1054                 if len(list) < 2:                1049                 if len(list) < 2:
1055                         return ''                1050                         return ''
1056                 prefix = list[0]                 1051                 prefix = list[0]
1057                 for s in list[1:]:               1052                 for s in list[1:]:
1058                         while s[:len(prefix)]    1053                         while s[:len(prefix)] != prefix and prefix:
1059                                 prefix = pref    1054                                 prefix = prefix[:len(prefix)-1]
1060                         if not prefix:           1055                         if not prefix:
1061                                 break            1056                                 break
1062                 if '/' in prefix and prefix[-    1057                 if '/' in prefix and prefix[-1] != '/':
1063                         prefix = prefix[0:pre    1058                         prefix = prefix[0:prefix.rfind('/')+1]
1064                 return prefix                    1059                 return prefix
1065         def dictify(self, text, format):         1060         def dictify(self, text, format):
1066                 out = dict()                     1061                 out = dict()
1067                 header = True if format == 1     1062                 header = True if format == 1 else False
1068                 delim = ' ' if format == 1 el    1063                 delim = ' ' if format == 1 else ':'
1069                 for line in text.split('\n'):    1064                 for line in text.split('\n'):
1070                         if header:               1065                         if header:
1071                                 header, out['    1066                                 header, out['@'] = False, line
1072                                 continue         1067                                 continue
1073                         line = line.strip()      1068                         line = line.strip()
1074                         if delim in line:        1069                         if delim in line:
1075                                 data = line.s    1070                                 data = line.split(delim, 1)
1076                                 num = re.sear    1071                                 num = re.search(r'[\d]+', data[1])
1077                                 if format ==     1072                                 if format == 2 and num:
1078                                         out[d    1073                                         out[data[0].strip()] = num.group()
1079                                 else:            1074                                 else:
1080                                         out[d    1075                                         out[data[0].strip()] = data[1]
1081                 return out                       1076                 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)    1077         def cmdinfo(self, begin, debug=False):
1097                 out = []                         1078                 out = []
1098                 if begin:                        1079                 if begin:
1099                         self.cmd1 = dict()       1080                         self.cmd1 = dict()
1100                 for cargs in self.infocmds:      1081                 for cargs in self.infocmds:
1101                         delta, name, args = c !! 1082                         delta, name = cargs[0], cargs[1]
1102                         for i in range(len(ar !! 1083                         cmdline, cmdpath = ' '.join(cargs[2:]), self.getExec(cargs[2])
1103                                 if args[i][0] << 
1104                                         args[ << 
1105                         cmdline, cmdpath = '  << 
1106                         if not cmdpath or (be    1084                         if not cmdpath or (begin and not delta):
1107                                 continue         1085                                 continue
1108                         self.dlog('[%s]' % cm    1086                         self.dlog('[%s]' % cmdline)
1109                         try:                     1087                         try:
1110                                 fp = Popen([c !! 1088                                 fp = Popen([cmdpath]+cargs[3:], stdout=PIPE, stderr=PIPE).stdout
1111                                 info = ascii(    1089                                 info = ascii(fp.read()).strip()
1112                                 fp.close()       1090                                 fp.close()
1113                         except:                  1091                         except:
1114                                 continue         1092                                 continue
1115                         if not debug and begi    1093                         if not debug and begin:
1116                                 self.cmd1[nam    1094                                 self.cmd1[name] = self.dictify(info, delta)
1117                         elif not debug and de    1095                         elif not debug and delta and name in self.cmd1:
1118                                 before, after    1096                                 before, after = self.cmd1[name], self.dictify(info, delta)
1119                                 dinfo = ('\t%    1097                                 dinfo = ('\t%s\n' % before['@']) if '@' in before and len(before) > 1 else ''
1120                                 prefix = self    1098                                 prefix = self.commonPrefix(list(before.keys()))
1121                                 for key in so    1099                                 for key in sorted(before):
1122                                         if ke    1100                                         if key in after and before[key] != after[key]:
1123                                                  1101                                                 title = key.replace(prefix, '')
1124                                                  1102                                                 if delta == 2:
1125                                                  1103                                                         dinfo += '\t%s : %s -> %s\n' % \
1126                                                  1104                                                                 (title, before[key].strip(), after[key].strip())
1127                                                  1105                                                 else:
1128                                                  1106                                                         dinfo += '%10s (start) : %s\n%10s (after) : %s\n' % \
1129                                                  1107                                                                 (title, before[key], title, after[key])
1130                                 dinfo = '\tno    1108                                 dinfo = '\tnothing changed' if not dinfo else dinfo.rstrip()
1131                                 out.append((n    1109                                 out.append((name, cmdline, dinfo))
1132                         else:                    1110                         else:
1133                                 out.append((n    1111                                 out.append((name, cmdline, '\tnothing' if not info else info))
1134                 return out                       1112                 return out
1135         def testVal(self, file, fmt='basic',     1113         def testVal(self, file, fmt='basic', value=''):
1136                 if file == 'restoreall':         1114                 if file == 'restoreall':
1137                         for f in self.cfgdef:    1115                         for f in self.cfgdef:
1138                                 if os.path.ex    1116                                 if os.path.exists(f):
1139                                         fp =     1117                                         fp = open(f, 'w')
1140                                         fp.wr    1118                                         fp.write(self.cfgdef[f])
1141                                         fp.cl    1119                                         fp.close()
1142                         self.cfgdef = dict()     1120                         self.cfgdef = dict()
1143                 elif value and os.path.exists    1121                 elif value and os.path.exists(file):
1144                         fp = open(file, 'r+')    1122                         fp = open(file, 'r+')
1145                         if fmt == 'radio':       1123                         if fmt == 'radio':
1146                                 m = re.match( !! 1124                                 m = re.match('.*\[(?P<v>.*)\].*', fp.read())
1147                                 if m:            1125                                 if m:
1148                                         self.    1126                                         self.cfgdef[file] = m.group('v')
1149                         elif fmt == 'acpi':      1127                         elif fmt == 'acpi':
1150                                 line = fp.rea    1128                                 line = fp.read().strip().split('\n')[-1]
1151                                 m = re.match( !! 1129                                 m = re.match('.* (?P<v>[0-9A-Fx]*) .*', line)
1152                                 if m:            1130                                 if m:
1153                                         self.    1131                                         self.cfgdef[file] = m.group('v')
1154                         else:                    1132                         else:
1155                                 self.cfgdef[f    1133                                 self.cfgdef[file] = fp.read().strip()
1156                         fp.write(value)          1134                         fp.write(value)
1157                         fp.close()               1135                         fp.close()
1158         def s0ixSupport(self):                << 
1159                 if not os.path.exists(self.s0 << 
1160                         return False          << 
1161                 fp = open(sysvals.mempowerfil << 
1162                 data = fp.read().strip()      << 
1163                 fp.close()                    << 
1164                 if '[s2idle]' in data:        << 
1165                         return True           << 
1166                 return False                  << 
1167         def haveTurbostat(self):                 1136         def haveTurbostat(self):
1168                 if not self.tstat:               1137                 if not self.tstat:
1169                         return False             1138                         return False
1170                 cmd = self.getExec('turbostat    1139                 cmd = self.getExec('turbostat')
1171                 if not cmd:                      1140                 if not cmd:
1172                         return False             1141                         return False
1173                 fp = Popen([cmd, '-v'], stdou    1142                 fp = Popen([cmd, '-v'], stdout=PIPE, stderr=PIPE).stderr
1174                 out = ascii(fp.read()).strip(    1143                 out = ascii(fp.read()).strip()
1175                 fp.close()                       1144                 fp.close()
1176                 if re.match(r'turbostat versi !! 1145                 if re.match('turbostat version .*', out):
1177                         self.vprint(out)         1146                         self.vprint(out)
1178                         return True              1147                         return True
1179                 return False                     1148                 return False
1180         def turbostat(self, s0ixready):       !! 1149         def turbostat(self):
1181                 cmd = self.getExec('turbostat    1150                 cmd = self.getExec('turbostat')
1182                 rawout = keyline = valline =     1151                 rawout = keyline = valline = ''
1183                 fullcmd = '%s -q -S echo free    1152                 fullcmd = '%s -q -S echo freeze > %s' % (cmd, self.powerfile)
1184                 fp = Popen(['sh', '-c', fullc !! 1153                 fp = Popen(['sh', '-c', fullcmd], stdout=PIPE, stderr=PIPE).stderr
1185                 for line in fp.stderr:        !! 1154                 for line in fp:
1186                         line = ascii(line)       1155                         line = ascii(line)
1187                         rawout += line           1156                         rawout += line
1188                         if keyline and vallin    1157                         if keyline and valline:
1189                                 continue         1158                                 continue
1190                         if re.match(r'(?i)Avg !! 1159                         if re.match('(?i)Avg_MHz.*', line):
1191                                 keyline = lin    1160                                 keyline = line.strip().split()
1192                         elif keyline:            1161                         elif keyline:
1193                                 valline = lin    1162                                 valline = line.strip().split()
1194                 fp.wait()                     !! 1163                 fp.close()
1195                 if not keyline or not valline    1164                 if not keyline or not valline or len(keyline) != len(valline):
1196                         errmsg = 'unrecognize    1165                         errmsg = 'unrecognized turbostat output:\n'+rawout.strip()
1197                         self.vprint(errmsg)      1166                         self.vprint(errmsg)
1198                         if not self.verbose:     1167                         if not self.verbose:
1199                                 pprint(errmsg    1168                                 pprint(errmsg)
1200                         return (fp.returncode !! 1169                         return ''
1201                 if self.verbose:                 1170                 if self.verbose:
1202                         pprint(rawout.strip()    1171                         pprint(rawout.strip())
1203                 out = []                         1172                 out = []
1204                 for key in keyline:              1173                 for key in keyline:
1205                         idx = keyline.index(k    1174                         idx = keyline.index(key)
1206                         val = valline[idx]       1175                         val = valline[idx]
1207                         if key == 'SYS%LPI' a << 
1208                                 continue      << 
1209                         out.append('%s=%s' %     1176                         out.append('%s=%s' % (key, val))
1210                 return (fp.returncode, '|'.jo !! 1177                 return '|'.join(out)
1211         def netfixon(self, net='both'):          1178         def netfixon(self, net='both'):
1212                 cmd = self.getExec('netfix')     1179                 cmd = self.getExec('netfix')
1213                 if not cmd:                      1180                 if not cmd:
1214                         return ''                1181                         return ''
1215                 fp = Popen([cmd, '-s', net, '    1182                 fp = Popen([cmd, '-s', net, 'on'], stdout=PIPE, stderr=PIPE).stdout
1216                 out = ascii(fp.read()).strip(    1183                 out = ascii(fp.read()).strip()
1217                 fp.close()                       1184                 fp.close()
1218                 return out                       1185                 return out
                                                   >> 1186         def wifiRepair(self):
                                                   >> 1187                 out = self.netfixon('wifi')
                                                   >> 1188                 if not out or 'error' in out.lower():
                                                   >> 1189                         return ''
                                                   >> 1190                 m = re.match('WIFI \S* ONLINE (?P<action>\S*)', out)
                                                   >> 1191                 if not m:
                                                   >> 1192                         return 'dead'
                                                   >> 1193                 return m.group('action')
1219         def wifiDetails(self, dev):              1194         def wifiDetails(self, dev):
1220                 try:                             1195                 try:
1221                         info = open('/sys/cla    1196                         info = open('/sys/class/net/%s/device/uevent' % dev, 'r').read().strip()
1222                 except:                          1197                 except:
1223                         return dev               1198                         return dev
1224                 vals = [dev]                     1199                 vals = [dev]
1225                 for prop in info.split('\n'):    1200                 for prop in info.split('\n'):
1226                         if prop.startswith('D    1201                         if prop.startswith('DRIVER=') or prop.startswith('PCI_ID='):
1227                                 vals.append(p    1202                                 vals.append(prop.split('=')[-1])
1228                 return ':'.join(vals)            1203                 return ':'.join(vals)
1229         def checkWifi(self, dev=''):             1204         def checkWifi(self, dev=''):
1230                 try:                             1205                 try:
1231                         w = open('/proc/net/w    1206                         w = open('/proc/net/wireless', 'r').read().strip()
1232                 except:                          1207                 except:
1233                         return ''                1208                         return ''
1234                 for line in reversed(w.split(    1209                 for line in reversed(w.split('\n')):
1235                         m = re.match(r' *(?P< !! 1210                         m = re.match(' *(?P<dev>.*): (?P<stat>[0-9a-f]*) .*', line)
1236                         if not m or (dev and     1211                         if not m or (dev and dev != m.group('dev')):
1237                                 continue         1212                                 continue
1238                         return m.group('dev')    1213                         return m.group('dev')
1239                 return ''                        1214                 return ''
1240         def pollWifi(self, dev, timeout=10):     1215         def pollWifi(self, dev, timeout=10):
1241                 start = time.time()              1216                 start = time.time()
1242                 while (time.time() - start) <    1217                 while (time.time() - start) < timeout:
1243                         w = self.checkWifi(de    1218                         w = self.checkWifi(dev)
1244                         if w:                    1219                         if w:
1245                                 return '%s re    1220                                 return '%s reconnected %.2f' % \
1246                                         (self    1221                                         (self.wifiDetails(dev), max(0, time.time() - start))
1247                         time.sleep(0.01)         1222                         time.sleep(0.01)
                                                   >> 1223                 if self.netfix:
                                                   >> 1224                         res = self.wifiRepair()
                                                   >> 1225                         if res:
                                                   >> 1226                                 timeout = max(0, time.time() - start)
                                                   >> 1227                                 return '%s %s %d' % (self.wifiDetails(dev), res, timeout)
1248                 return '%s timeout %d' % (sel    1228                 return '%s timeout %d' % (self.wifiDetails(dev), timeout)
1249         def errorSummary(self, errinfo, msg):    1229         def errorSummary(self, errinfo, msg):
1250                 found = False                    1230                 found = False
1251                 for entry in errinfo:            1231                 for entry in errinfo:
1252                         if re.match(entry['ma    1232                         if re.match(entry['match'], msg):
1253                                 entry['count'    1233                                 entry['count'] += 1
1254                                 if self.hostn    1234                                 if self.hostname not in entry['urls']:
1255                                         entry    1235                                         entry['urls'][self.hostname] = [self.htmlfile]
1256                                 elif self.htm    1236                                 elif self.htmlfile not in entry['urls'][self.hostname]:
1257                                         entry    1237                                         entry['urls'][self.hostname].append(self.htmlfile)
1258                                 found = True     1238                                 found = True
1259                                 break            1239                                 break
1260                 if found:                        1240                 if found:
1261                         return                   1241                         return
1262                 arr = msg.split()                1242                 arr = msg.split()
1263                 for j in range(len(arr)):        1243                 for j in range(len(arr)):
1264                         if re.match(r'^[0-9,\ !! 1244                         if re.match('^[0-9,\-\.]*$', arr[j]):
1265                                 arr[j] = r'[0 !! 1245                                 arr[j] = '[0-9,\-\.]*'
1266                         else:                    1246                         else:
1267                                 arr[j] = arr[    1247                                 arr[j] = arr[j]\
1268                                         .repl !! 1248                                         .replace('\\', '\\\\').replace(']', '\]').replace('[', '\[')\
1269                                         .repl !! 1249                                         .replace('.', '\.').replace('+', '\+').replace('*', '\*')\
1270                                         .repl !! 1250                                         .replace('(', '\(').replace(')', '\)').replace('}', '\}')\
1271                                         .repl !! 1251                                         .replace('{', '\{')
1272                 mstr = ' *'.join(arr)            1252                 mstr = ' *'.join(arr)
1273                 entry = {                        1253                 entry = {
1274                         'line': msg,             1254                         'line': msg,
1275                         'match': mstr,           1255                         'match': mstr,
1276                         'count': 1,              1256                         'count': 1,
1277                         'urls': {self.hostnam    1257                         'urls': {self.hostname: [self.htmlfile]}
1278                 }                                1258                 }
1279                 errinfo.append(entry)            1259                 errinfo.append(entry)
1280         def multistat(self, start, idx, finis    1260         def multistat(self, start, idx, finish):
1281                 if 'time' in self.multitest:     1261                 if 'time' in self.multitest:
1282                         id = '%d Duration=%dm    1262                         id = '%d Duration=%dmin' % (idx+1, self.multitest['time'])
1283                 else:                            1263                 else:
1284                         id = '%d/%d' % (idx+1    1264                         id = '%d/%d' % (idx+1, self.multitest['count'])
1285                 t = time.time()                  1265                 t = time.time()
1286                 if 'start' not in self.multit    1266                 if 'start' not in self.multitest:
1287                         self.multitest['start    1267                         self.multitest['start'] = self.multitest['last'] = t
1288                         self.multitest['total    1268                         self.multitest['total'] = 0.0
1289                         pprint('TEST (%s) STA    1269                         pprint('TEST (%s) START' % id)
1290                         return                   1270                         return
1291                 dt = t - self.multitest['last    1271                 dt = t - self.multitest['last']
1292                 if not start:                    1272                 if not start:
1293                         if idx == 0 and self.    1273                         if idx == 0 and self.multitest['delay'] > 0:
1294                                 self.multites    1274                                 self.multitest['total'] += self.multitest['delay']
1295                         pprint('TEST (%s) COM    1275                         pprint('TEST (%s) COMPLETE -- Duration %.1fs' % (id, dt))
1296                         return                   1276                         return
1297                 self.multitest['total'] += dt    1277                 self.multitest['total'] += dt
1298                 self.multitest['last'] = t       1278                 self.multitest['last'] = t
1299                 avg = self.multitest['total']    1279                 avg = self.multitest['total'] / idx
1300                 if 'time' in self.multitest:     1280                 if 'time' in self.multitest:
1301                         left = finish - datet    1281                         left = finish - datetime.now()
1302                         left -= timedelta(mic    1282                         left -= timedelta(microseconds=left.microseconds)
1303                 else:                            1283                 else:
1304                         left = timedelta(seco    1284                         left = timedelta(seconds=((self.multitest['count'] - idx) * int(avg)))
1305                 pprint('TEST (%s) START - Avg    1285                 pprint('TEST (%s) START - Avg Duration %.1fs, Time left %s' % \
1306                         (id, avg, str(left)))    1286                         (id, avg, str(left)))
1307         def multiinit(self, c, d):               1287         def multiinit(self, c, d):
1308                 sz, unit = 'count', 'm'          1288                 sz, unit = 'count', 'm'
1309                 if c.endswith('d') or c.endsw    1289                 if c.endswith('d') or c.endswith('h') or c.endswith('m'):
1310                         sz, unit, c = 'time',    1290                         sz, unit, c = 'time', c[-1], c[:-1]
1311                 self.multitest['run'] = True     1291                 self.multitest['run'] = True
1312                 self.multitest[sz] = getArgIn    1292                 self.multitest[sz] = getArgInt('multi: n d (exec count)', c, 1, 1000000, False)
1313                 self.multitest['delay'] = get    1293                 self.multitest['delay'] = getArgInt('multi: n d (delay between tests)', d, 0, 3600, False)
1314                 if unit == 'd':                  1294                 if unit == 'd':
1315                         self.multitest[sz] *=    1295                         self.multitest[sz] *= 1440
1316                 elif unit == 'h':                1296                 elif unit == 'h':
1317                         self.multitest[sz] *=    1297                         self.multitest[sz] *= 60
1318         def displayControl(self, cmd):           1298         def displayControl(self, cmd):
1319                 xset, ret = 'timeout 10 xset     1299                 xset, ret = 'timeout 10 xset -d :0.0 {0}', 0
1320                 if self.sudouser:                1300                 if self.sudouser:
1321                         xset = 'sudo -u %s %s    1301                         xset = 'sudo -u %s %s' % (self.sudouser, xset)
1322                 if cmd == 'init':                1302                 if cmd == 'init':
1323                         ret = call(xset.forma    1303                         ret = call(xset.format('dpms 0 0 0'), shell=True)
1324                         if not ret:              1304                         if not ret:
1325                                 ret = call(xs    1305                                 ret = call(xset.format('s off'), shell=True)
1326                 elif cmd == 'reset':             1306                 elif cmd == 'reset':
1327                         ret = call(xset.forma    1307                         ret = call(xset.format('s reset'), shell=True)
1328                 elif cmd in ['on', 'off', 'st    1308                 elif cmd in ['on', 'off', 'standby', 'suspend']:
1329                         b4 = self.displayCont    1309                         b4 = self.displayControl('stat')
1330                         ret = call(xset.forma    1310                         ret = call(xset.format('dpms force %s' % cmd), shell=True)
1331                         if not ret:              1311                         if not ret:
1332                                 curr = self.d    1312                                 curr = self.displayControl('stat')
1333                                 self.vprint('    1313                                 self.vprint('Display Switched: %s -> %s' % (b4, curr))
1334                                 if curr != cm    1314                                 if curr != cmd:
1335                                         self.    1315                                         self.vprint('WARNING: Display failed to change to %s' % cmd)
1336                         if ret:                  1316                         if ret:
1337                                 self.vprint('    1317                                 self.vprint('WARNING: Display failed to change to %s with xset' % cmd)
1338                                 return ret       1318                                 return ret
1339                 elif cmd == 'stat':              1319                 elif cmd == 'stat':
1340                         fp = Popen(xset.forma    1320                         fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout
1341                         ret = 'unknown'          1321                         ret = 'unknown'
1342                         for line in fp:          1322                         for line in fp:
1343                                 m = re.match( !! 1323                                 m = re.match('[\s]*Monitor is (?P<m>.*)', ascii(line))
1344                                 if(m and len(    1324                                 if(m and len(m.group('m')) >= 2):
1345                                         out =    1325                                         out = m.group('m').lower()
1346                                         ret =    1326                                         ret = out[3:] if out[0:2] == 'in' else out
1347                                         break    1327                                         break
1348                         fp.close()               1328                         fp.close()
1349                 return ret                       1329                 return ret
1350         def setRuntimeSuspend(self, before=Tr    1330         def setRuntimeSuspend(self, before=True):
1351                 if before:                       1331                 if before:
1352                         # runtime suspend dis    1332                         # runtime suspend disable or enable
1353                         if self.rs > 0:          1333                         if self.rs > 0:
1354                                 self.rstgt, s    1334                                 self.rstgt, self.rsval, self.rsdir = 'on', 'auto', 'enabled'
1355                         else:                    1335                         else:
1356                                 self.rstgt, s    1336                                 self.rstgt, self.rsval, self.rsdir = 'auto', 'on', 'disabled'
1357                         pprint('CONFIGURING R    1337                         pprint('CONFIGURING RUNTIME SUSPEND...')
1358                         self.rslist = deviceI    1338                         self.rslist = deviceInfo(self.rstgt)
1359                         for i in self.rslist:    1339                         for i in self.rslist:
1360                                 self.setVal(s    1340                                 self.setVal(self.rsval, i)
1361                         pprint('runtime suspe    1341                         pprint('runtime suspend %s on all devices (%d changed)' % (self.rsdir, len(self.rslist)))
1362                         pprint('waiting 5 sec    1342                         pprint('waiting 5 seconds...')
1363                         time.sleep(5)            1343                         time.sleep(5)
1364                 else:                            1344                 else:
1365                         # runtime suspend re-    1345                         # runtime suspend re-enable or re-disable
1366                         for i in self.rslist:    1346                         for i in self.rslist:
1367                                 self.setVal(s    1347                                 self.setVal(self.rstgt, i)
1368                         pprint('runtime suspe    1348                         pprint('runtime suspend settings restored on %d devices' % len(self.rslist))
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                                                  1349 
1384 sysvals = SystemValues()                         1350 sysvals = SystemValues()
1385 switchvalues = ['enable', 'disable', 'on', 'o    1351 switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0']
1386 switchoff = ['disable', 'off', 'false', '0']     1352 switchoff = ['disable', 'off', 'false', '0']
1387 suspendmodename = {                              1353 suspendmodename = {
1388         'standby': 'standby (S1)',               1354         'standby': 'standby (S1)',
1389         'freeze': 'freeze (S2idle)',             1355         'freeze': 'freeze (S2idle)',
1390         'mem': 'suspend (S3)',                   1356         'mem': 'suspend (S3)',
1391         'disk': 'hibernate (S4)'                 1357         'disk': 'hibernate (S4)'
1392 }                                                1358 }
1393                                                  1359 
1394 # Class: DevProps                                1360 # Class: DevProps
1395 # Description:                                   1361 # Description:
1396 #        Simple class which holds property va    1362 #        Simple class which holds property values collected
1397 #        for all the devices used in the time    1363 #        for all the devices used in the timeline.
1398 class DevProps:                                  1364 class DevProps:
1399         def __init__(self):                      1365         def __init__(self):
1400                 self.syspath = ''                1366                 self.syspath = ''
1401                 self.altname = ''                1367                 self.altname = ''
1402                 self.isasync = True              1368                 self.isasync = True
1403                 self.xtraclass = ''              1369                 self.xtraclass = ''
1404                 self.xtrainfo = ''               1370                 self.xtrainfo = ''
1405         def out(self, dev):                      1371         def out(self, dev):
1406                 return '%s,%s,%d;' % (dev, se    1372                 return '%s,%s,%d;' % (dev, self.altname, self.isasync)
1407         def debug(self, dev):                    1373         def debug(self, dev):
1408                 pprint('%s:\n\taltname = %s\n    1374                 pprint('%s:\n\taltname = %s\n\t  async = %s' % (dev, self.altname, self.isasync))
1409         def altName(self, dev):                  1375         def altName(self, dev):
1410                 if not self.altname or self.a    1376                 if not self.altname or self.altname == dev:
1411                         return dev               1377                         return dev
1412                 return '%s [%s]' % (self.altn    1378                 return '%s [%s]' % (self.altname, dev)
1413         def xtraClass(self):                     1379         def xtraClass(self):
1414                 if self.xtraclass:               1380                 if self.xtraclass:
1415                         return ' '+self.xtrac    1381                         return ' '+self.xtraclass
1416                 if not self.isasync:             1382                 if not self.isasync:
1417                         return ' sync'           1383                         return ' sync'
1418                 return ''                        1384                 return ''
1419         def xtraInfo(self):                      1385         def xtraInfo(self):
1420                 if self.xtraclass:               1386                 if self.xtraclass:
1421                         return ' '+self.xtrac    1387                         return ' '+self.xtraclass
1422                 if self.isasync:                 1388                 if self.isasync:
1423                         return ' (async)'        1389                         return ' (async)'
1424                 return ' (sync)'                 1390                 return ' (sync)'
1425                                                  1391 
1426 # Class: DeviceNode                              1392 # Class: DeviceNode
1427 # Description:                                   1393 # Description:
1428 #        A container used to create a device     1394 #        A container used to create a device hierachy, with a single root node
1429 #        and a tree of child nodes. Used by D    1395 #        and a tree of child nodes. Used by Data.deviceTopology()
1430 class DeviceNode:                                1396 class DeviceNode:
1431         def __init__(self, nodename, nodedept    1397         def __init__(self, nodename, nodedepth):
1432                 self.name = nodename             1398                 self.name = nodename
1433                 self.children = []               1399                 self.children = []
1434                 self.depth = nodedepth           1400                 self.depth = nodedepth
1435                                                  1401 
1436 # Class: Data                                    1402 # Class: Data
1437 # Description:                                   1403 # Description:
1438 #        The primary container for suspend/re    1404 #        The primary container for suspend/resume test data. There is one for
1439 #        each test run. The data is organized    1405 #        each test run. The data is organized into a cronological hierarchy:
1440 #        Data.dmesg {                            1406 #        Data.dmesg {
1441 #               phases {                         1407 #               phases {
1442 #                       10 sequential, non-ov    1408 #                       10 sequential, non-overlapping phases of S/R
1443 #                       contents: times for p    1409 #                       contents: times for phase start/end, order/color data for html
1444 #                       devlist {                1410 #                       devlist {
1445 #                               device callba    1411 #                               device callback or action list for this phase
1446 #                               device {         1412 #                               device {
1447 #                                       a sin    1413 #                                       a single device callback or generic action
1448 #                                       conte    1414 #                                       contents: start/stop times, pid/cpu/driver info
1449 #                                                1415 #                                               parents/children, html id for timeline/callgraph
1450 #                                                1416 #                                               optionally includes an ftrace callgraph
1451 #                                                1417 #                                               optionally includes dev/ps data
1452 #                               }                1418 #                               }
1453 #                       }                        1419 #                       }
1454 #               }                                1420 #               }
1455 #       }                                        1421 #       }
1456 #                                                1422 #
1457 class Data:                                      1423 class Data:
1458         phasedef = {                             1424         phasedef = {
1459                 'suspend_prepare': {'order':     1425                 'suspend_prepare': {'order': 0, 'color': '#CCFFCC'},
1460                         'suspend': {'order':     1426                         'suspend': {'order': 1, 'color': '#88FF88'},
1461                    'suspend_late': {'order':     1427                    'suspend_late': {'order': 2, 'color': '#00AA00'},
1462                   'suspend_noirq': {'order':     1428                   'suspend_noirq': {'order': 3, 'color': '#008888'},
1463                 'suspend_machine': {'order':     1429                 'suspend_machine': {'order': 4, 'color': '#0000FF'},
1464                  'resume_machine': {'order':     1430                  'resume_machine': {'order': 5, 'color': '#FF0000'},
1465                    'resume_noirq': {'order':     1431                    'resume_noirq': {'order': 6, 'color': '#FF9900'},
1466                    'resume_early': {'order':     1432                    'resume_early': {'order': 7, 'color': '#FFCC00'},
1467                          'resume': {'order':     1433                          'resume': {'order': 8, 'color': '#FFFF88'},
1468                 'resume_complete': {'order':     1434                 'resume_complete': {'order': 9, 'color': '#FFFFCC'},
1469         }                                        1435         }
1470         errlist = {                              1436         errlist = {
1471                 'HWERROR' : r'.*\[ *Hardware     1437                 'HWERROR' : r'.*\[ *Hardware Error *\].*',
1472                 'FWBUG'   : r'.*\[ *Firmware     1438                 'FWBUG'   : r'.*\[ *Firmware Bug *\].*',
1473                 'TASKFAIL': r'.*Freezing .*af << 
1474                 'BUG'     : r'(?i).*\bBUG\b.*    1439                 'BUG'     : r'(?i).*\bBUG\b.*',
1475                 'ERROR'   : r'(?i).*\bERROR\b    1440                 'ERROR'   : r'(?i).*\bERROR\b.*',
1476                 'WARNING' : r'(?i).*\bWARNING    1441                 'WARNING' : r'(?i).*\bWARNING\b.*',
1477                 'FAULT'   : r'(?i).*\bFAULT\b    1442                 'FAULT'   : r'(?i).*\bFAULT\b.*',
1478                 'FAIL'    : r'(?i).*\bFAILED\    1443                 'FAIL'    : r'(?i).*\bFAILED\b.*',
1479                 'INVALID' : r'(?i).*\bINVALID    1444                 'INVALID' : r'(?i).*\bINVALID\b.*',
1480                 'CRASH'   : r'(?i).*\bCRASHED    1445                 'CRASH'   : r'(?i).*\bCRASHED\b.*',
1481                 'TIMEOUT' : r'(?i).*\bTIMEOUT    1446                 'TIMEOUT' : r'(?i).*\bTIMEOUT\b.*',
1482                 'ABORT'   : r'(?i).*\bABORT\b    1447                 'ABORT'   : r'(?i).*\bABORT\b.*',
1483                 'IRQ'     : r'.*\bgenirq: .*'    1448                 'IRQ'     : r'.*\bgenirq: .*',
                                                   >> 1449                 'TASKFAIL': r'.*Freezing of tasks *.*',
1484                 'ACPI'    : r'.*\bACPI *(?P<b    1450                 'ACPI'    : r'.*\bACPI *(?P<b>[A-Za-z]*) *Error[: ].*',
1485                 'DISKFULL': r'.*\bNo space le    1451                 'DISKFULL': r'.*\bNo space left on device.*',
1486                 'USBERR'  : r'.*usb .*device     1452                 'USBERR'  : r'.*usb .*device .*, error [0-9-]*',
1487                 'ATAERR'  : r' *ata[0-9\.]*:     1453                 'ATAERR'  : r' *ata[0-9\.]*: .*failed.*',
1488                 'MEIERR'  : r' *mei.*: .*fail    1454                 'MEIERR'  : r' *mei.*: .*failed.*',
1489                 'TPMERR'  : r'(?i) *tpm *tpm[    1455                 'TPMERR'  : r'(?i) *tpm *tpm[0-9]*: .*error.*',
1490         }                                        1456         }
1491         def __init__(self, num):                 1457         def __init__(self, num):
1492                 idchar = 'abcdefghij'            1458                 idchar = 'abcdefghij'
1493                 self.start = 0.0 # test start    1459                 self.start = 0.0 # test start
1494                 self.end = 0.0   # test end      1460                 self.end = 0.0   # test end
1495                 self.hwstart = 0 # rtc test s    1461                 self.hwstart = 0 # rtc test start
1496                 self.hwend = 0   # rtc test e    1462                 self.hwend = 0   # rtc test end
1497                 self.tSuspended = 0.0 # low-l    1463                 self.tSuspended = 0.0 # low-level suspend start
1498                 self.tResumed = 0.0   # low-l    1464                 self.tResumed = 0.0   # low-level resume start
1499                 self.tKernSus = 0.0   # kerne    1465                 self.tKernSus = 0.0   # kernel level suspend start
1500                 self.tKernRes = 0.0   # kerne    1466                 self.tKernRes = 0.0   # kernel level resume end
1501                 self.fwValid = False  # is fi    1467                 self.fwValid = False  # is firmware data available
1502                 self.fwSuspend = 0    # time     1468                 self.fwSuspend = 0    # time spent in firmware suspend
1503                 self.fwResume = 0     # time     1469                 self.fwResume = 0     # time spent in firmware resume
1504                 self.html_device_id = 0          1470                 self.html_device_id = 0
1505                 self.stamp = 0                   1471                 self.stamp = 0
1506                 self.outfile = ''                1472                 self.outfile = ''
1507                 self.kerror = False              1473                 self.kerror = False
1508                 self.wifi = dict()               1474                 self.wifi = dict()
1509                 self.turbostat = 0               1475                 self.turbostat = 0
1510                 self.enterfail = ''              1476                 self.enterfail = ''
1511                 self.currphase = ''              1477                 self.currphase = ''
1512                 self.pstl = dict()    # proce    1478                 self.pstl = dict()    # process timeline
1513                 self.testnumber = num            1479                 self.testnumber = num
1514                 self.idstr = idchar[num]         1480                 self.idstr = idchar[num]
1515                 self.dmesgtext = []   # dmesg    1481                 self.dmesgtext = []   # dmesg text file in memory
1516                 self.dmesg = dict()   # root     1482                 self.dmesg = dict()   # root data structure
1517                 self.errorinfo = {'suspend':[    1483                 self.errorinfo = {'suspend':[],'resume':[]}
1518                 self.tLow = []        # time     1484                 self.tLow = []        # time spent in low-level suspends (standby/freeze)
1519                 self.devpids = []                1485                 self.devpids = []
1520                 self.devicegroups = 0            1486                 self.devicegroups = 0
1521         def sortedPhases(self):                  1487         def sortedPhases(self):
1522                 return sorted(self.dmesg, key    1488                 return sorted(self.dmesg, key=lambda k:self.dmesg[k]['order'])
1523         def initDevicegroups(self):              1489         def initDevicegroups(self):
1524                 # called when phases are all     1490                 # called when phases are all finished being added
1525                 for phase in sorted(self.dmes    1491                 for phase in sorted(self.dmesg.keys()):
1526                         if '*' in phase:         1492                         if '*' in phase:
1527                                 p = phase.spl    1493                                 p = phase.split('*')
1528                                 pnew = '%s%d'    1494                                 pnew = '%s%d' % (p[0], len(p))
1529                                 self.dmesg[pn    1495                                 self.dmesg[pnew] = self.dmesg.pop(phase)
1530                 self.devicegroups = []           1496                 self.devicegroups = []
1531                 for phase in self.sortedPhase    1497                 for phase in self.sortedPhases():
1532                         self.devicegroups.app    1498                         self.devicegroups.append([phase])
1533         def nextPhase(self, phase, offset):      1499         def nextPhase(self, phase, offset):
1534                 order = self.dmesg[phase]['or    1500                 order = self.dmesg[phase]['order'] + offset
1535                 for p in self.dmesg:             1501                 for p in self.dmesg:
1536                         if self.dmesg[p]['ord    1502                         if self.dmesg[p]['order'] == order:
1537                                 return p         1503                                 return p
1538                 return ''                        1504                 return ''
1539         def lastPhase(self, depth=1):            1505         def lastPhase(self, depth=1):
1540                 plist = self.sortedPhases()      1506                 plist = self.sortedPhases()
1541                 if len(plist) < depth:           1507                 if len(plist) < depth:
1542                         return ''                1508                         return ''
1543                 return plist[-1*depth]           1509                 return plist[-1*depth]
1544         def turbostatInfo(self):                 1510         def turbostatInfo(self):
1545                 tp = TestProps()                 1511                 tp = TestProps()
1546                 out = {'syslpi':'N/A','pkgpc1    1512                 out = {'syslpi':'N/A','pkgpc10':'N/A'}
1547                 for line in self.dmesgtext:      1513                 for line in self.dmesgtext:
1548                         m = re.match(tp.tstat    1514                         m = re.match(tp.tstatfmt, line)
1549                         if not m:                1515                         if not m:
1550                                 continue         1516                                 continue
1551                         for i in m.group('t')    1517                         for i in m.group('t').split('|'):
1552                                 if 'SYS%LPI'     1518                                 if 'SYS%LPI' in i:
1553                                         out['    1519                                         out['syslpi'] = i.split('=')[-1]+'%'
1554                                 elif 'pc10' i    1520                                 elif 'pc10' in i:
1555                                         out['    1521                                         out['pkgpc10'] = i.split('=')[-1]+'%'
1556                         break                    1522                         break
1557                 return out                       1523                 return out
1558         def extractErrorInfo(self):              1524         def extractErrorInfo(self):
1559                 lf = self.dmesgtext              1525                 lf = self.dmesgtext
1560                 if len(self.dmesgtext) < 1 an    1526                 if len(self.dmesgtext) < 1 and sysvals.dmesgfile:
1561                         lf = sysvals.openlog(    1527                         lf = sysvals.openlog(sysvals.dmesgfile, 'r')
1562                 i = 0                            1528                 i = 0
1563                 tp = TestProps()                 1529                 tp = TestProps()
1564                 list = []                        1530                 list = []
1565                 for line in lf:                  1531                 for line in lf:
1566                         i += 1                   1532                         i += 1
1567                         if tp.stampInfo(line,    1533                         if tp.stampInfo(line, sysvals):
1568                                 continue         1534                                 continue
1569                         m = re.match(r'[ \t]* !! 1535                         m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
1570                         if not m:                1536                         if not m:
1571                                 continue         1537                                 continue
1572                         t = float(m.group('kt    1538                         t = float(m.group('ktime'))
1573                         if t < self.start or     1539                         if t < self.start or t > self.end:
1574                                 continue         1540                                 continue
1575                         dir = 'suspend' if t     1541                         dir = 'suspend' if t < self.tSuspended else 'resume'
1576                         msg = m.group('msg')     1542                         msg = m.group('msg')
1577                         if re.match(r'capabil !! 1543                         if re.match('capability: warning: .*', msg):
1578                                 continue         1544                                 continue
1579                         for err in self.errli    1545                         for err in self.errlist:
1580                                 if re.match(s    1546                                 if re.match(self.errlist[err], msg):
1581                                         list.    1547                                         list.append((msg, err, dir, t, i, i))
1582                                         self.    1548                                         self.kerror = True
1583                                         break    1549                                         break
1584                 tp.msglist = []                  1550                 tp.msglist = []
1585                 for msg, type, dir, t, idx1,     1551                 for msg, type, dir, t, idx1, idx2 in list:
1586                         tp.msglist.append(msg    1552                         tp.msglist.append(msg)
1587                         self.errorinfo[dir].a    1553                         self.errorinfo[dir].append((type, t, idx1, idx2))
1588                 if self.kerror:                  1554                 if self.kerror:
1589                         sysvals.dmesglog = Tr    1555                         sysvals.dmesglog = True
1590                 if len(self.dmesgtext) < 1 an    1556                 if len(self.dmesgtext) < 1 and sysvals.dmesgfile:
1591                         lf.close()               1557                         lf.close()
1592                 return tp                        1558                 return tp
1593         def setStart(self, time, msg=''):        1559         def setStart(self, time, msg=''):
1594                 self.start = time                1560                 self.start = time
1595                 if msg:                          1561                 if msg:
1596                         try:                     1562                         try:
1597                                 self.hwstart     1563                                 self.hwstart = datetime.strptime(msg, sysvals.tmstart)
1598                         except:                  1564                         except:
1599                                 self.hwstart     1565                                 self.hwstart = 0
1600         def setEnd(self, time, msg=''):          1566         def setEnd(self, time, msg=''):
1601                 self.end = time                  1567                 self.end = time
1602                 if msg:                          1568                 if msg:
1603                         try:                     1569                         try:
1604                                 self.hwend =     1570                                 self.hwend = datetime.strptime(msg, sysvals.tmend)
1605                         except:                  1571                         except:
1606                                 self.hwend =     1572                                 self.hwend = 0
1607         def isTraceEventOutsideDeviceCalls(se    1573         def isTraceEventOutsideDeviceCalls(self, pid, time):
1608                 for phase in self.sortedPhase    1574                 for phase in self.sortedPhases():
1609                         list = self.dmesg[pha    1575                         list = self.dmesg[phase]['list']
1610                         for dev in list:         1576                         for dev in list:
1611                                 d = list[dev]    1577                                 d = list[dev]
1612                                 if(d['pid'] =    1578                                 if(d['pid'] == pid and time >= d['start'] and
1613                                         time     1579                                         time < d['end']):
1614                                         retur    1580                                         return False
1615                 return True                      1581                 return True
1616         def sourcePhase(self, start):            1582         def sourcePhase(self, start):
1617                 for phase in self.sortedPhase    1583                 for phase in self.sortedPhases():
1618                         if 'machine' in phase    1584                         if 'machine' in phase:
1619                                 continue         1585                                 continue
1620                         pend = self.dmesg[pha    1586                         pend = self.dmesg[phase]['end']
1621                         if start <= pend:        1587                         if start <= pend:
1622                                 return phase     1588                                 return phase
1623                 return 'resume_complete' if ' !! 1589                 return 'resume_complete'
1624         def sourceDevice(self, phaselist, sta    1590         def sourceDevice(self, phaselist, start, end, pid, type):
1625                 tgtdev = ''                      1591                 tgtdev = ''
1626                 for phase in phaselist:          1592                 for phase in phaselist:
1627                         list = self.dmesg[pha    1593                         list = self.dmesg[phase]['list']
1628                         for devname in list:     1594                         for devname in list:
1629                                 dev = list[de    1595                                 dev = list[devname]
1630                                 # pid must ma    1596                                 # pid must match
1631                                 if dev['pid']    1597                                 if dev['pid'] != pid:
1632                                         conti    1598                                         continue
1633                                 devS = dev['s    1599                                 devS = dev['start']
1634                                 devE = dev['e    1600                                 devE = dev['end']
1635                                 if type == 'd    1601                                 if type == 'device':
1636                                         # dev    1602                                         # device target event is entirely inside the source boundary
1637                                         if(st    1603                                         if(start < devS or start >= devE or end <= devS or end > devE):
1638                                                  1604                                                 continue
1639                                 elif type ==     1605                                 elif type == 'thread':
1640                                         # thr    1606                                         # thread target event will expand the source boundary
1641                                         if st    1607                                         if start < devS:
1642                                                  1608                                                 dev['start'] = start
1643                                         if en    1609                                         if end > devE:
1644                                                  1610                                                 dev['end'] = end
1645                                 tgtdev = dev     1611                                 tgtdev = dev
1646                                 break            1612                                 break
1647                 return tgtdev                    1613                 return tgtdev
1648         def addDeviceFunctionCall(self, displ    1614         def addDeviceFunctionCall(self, displayname, kprobename, proc, pid, start, end, cdata, rdata):
1649                 # try to place the call in a     1615                 # try to place the call in a device
1650                 phases = self.sortedPhases()     1616                 phases = self.sortedPhases()
1651                 tgtdev = self.sourceDevice(ph    1617                 tgtdev = self.sourceDevice(phases, start, end, pid, 'device')
1652                 # calls with device pids that    1618                 # calls with device pids that occur outside device bounds are dropped
1653                 # TODO: include these somehow    1619                 # TODO: include these somehow
1654                 if not tgtdev and pid in self    1620                 if not tgtdev and pid in self.devpids:
1655                         return False             1621                         return False
1656                 # try to place the call in a     1622                 # try to place the call in a thread
1657                 if not tgtdev:                   1623                 if not tgtdev:
1658                         tgtdev = self.sourceD    1624                         tgtdev = self.sourceDevice(phases, start, end, pid, 'thread')
1659                 # create new thread blocks, e    1625                 # create new thread blocks, expand as new calls are found
1660                 if not tgtdev:                   1626                 if not tgtdev:
1661                         if proc == '<...>':      1627                         if proc == '<...>':
1662                                 threadname =     1628                                 threadname = 'kthread-%d' % (pid)
1663                         else:                    1629                         else:
1664                                 threadname =     1630                                 threadname = '%s-%d' % (proc, pid)
1665                         tgtphase = self.sourc    1631                         tgtphase = self.sourcePhase(start)
1666                         if not tgtphase:      << 
1667                                 return False  << 
1668                         self.newAction(tgtpha    1632                         self.newAction(tgtphase, threadname, pid, '', start, end, '', ' kth', '')
1669                         return self.addDevice    1633                         return self.addDeviceFunctionCall(displayname, kprobename, proc, pid, start, end, cdata, rdata)
1670                 # this should not happen         1634                 # this should not happen
1671                 if not tgtdev:                   1635                 if not tgtdev:
1672                         sysvals.vprint('[%f -    1636                         sysvals.vprint('[%f - %f] %s-%d %s %s %s' % \
1673                                 (start, end,     1637                                 (start, end, proc, pid, kprobename, cdata, rdata))
1674                         return False             1638                         return False
1675                 # place the call data inside     1639                 # place the call data inside the src element of the tgtdev
1676                 if('src' not in tgtdev):         1640                 if('src' not in tgtdev):
1677                         tgtdev['src'] = []       1641                         tgtdev['src'] = []
1678                 dtf = sysvals.dev_tracefuncs     1642                 dtf = sysvals.dev_tracefuncs
1679                 ubiquitous = False               1643                 ubiquitous = False
1680                 if kprobename in dtf and 'ub'    1644                 if kprobename in dtf and 'ub' in dtf[kprobename]:
1681                         ubiquitous = True        1645                         ubiquitous = True
1682                 mc = re.match(r'\(.*\) *(?P<a !! 1646                 title = cdata+' '+rdata
1683                 mr = re.match(r'\((?P<caller> !! 1647                 mstr = '\(.*\) *(?P<args>.*) *\((?P<caller>.*)\+.* arg1=(?P<ret>.*)'
1684                 if mc and mr:                 !! 1648                 m = re.match(mstr, title)
1685                         c = mr.group('caller' !! 1649                 if m:
1686                         a = mc.group('args'). !! 1650                         c = m.group('caller')
1687                         r = mr.group('ret')   !! 1651                         a = m.group('args').strip()
                                                   >> 1652                         r = m.group('ret')
1688                         if len(r) > 6:           1653                         if len(r) > 6:
1689                                 r = ''           1654                                 r = ''
1690                         else:                    1655                         else:
1691                                 r = 'ret=%s '    1656                                 r = 'ret=%s ' % r
1692                         if ubiquitous and c i    1657                         if ubiquitous and c in dtf and 'ub' in dtf[c]:
1693                                 return False     1658                                 return False
1694                 else:                         << 
1695                         return False          << 
1696                 color = sysvals.kprobeColor(k    1659                 color = sysvals.kprobeColor(kprobename)
1697                 e = DevFunction(displayname,     1660                 e = DevFunction(displayname, a, c, r, start, end, ubiquitous, proc, pid, color)
1698                 tgtdev['src'].append(e)          1661                 tgtdev['src'].append(e)
1699                 return True                      1662                 return True
1700         def overflowDevices(self):               1663         def overflowDevices(self):
1701                 # get a list of devices that     1664                 # get a list of devices that extend beyond the end of this test run
1702                 devlist = []                     1665                 devlist = []
1703                 for phase in self.sortedPhase    1666                 for phase in self.sortedPhases():
1704                         list = self.dmesg[pha    1667                         list = self.dmesg[phase]['list']
1705                         for devname in list:     1668                         for devname in list:
1706                                 dev = list[de    1669                                 dev = list[devname]
1707                                 if dev['end']    1670                                 if dev['end'] > self.end:
1708                                         devli    1671                                         devlist.append(dev)
1709                 return devlist                   1672                 return devlist
1710         def mergeOverlapDevices(self, devlist    1673         def mergeOverlapDevices(self, devlist):
1711                 # merge any devices that over    1674                 # merge any devices that overlap devlist
1712                 for dev in devlist:              1675                 for dev in devlist:
1713                         devname = dev['name']    1676                         devname = dev['name']
1714                         for phase in self.sor    1677                         for phase in self.sortedPhases():
1715                                 list = self.d    1678                                 list = self.dmesg[phase]['list']
1716                                 if devname no    1679                                 if devname not in list:
1717                                         conti    1680                                         continue
1718                                 tdev = list[d    1681                                 tdev = list[devname]
1719                                 o = min(dev['    1682                                 o = min(dev['end'], tdev['end']) - max(dev['start'], tdev['start'])
1720                                 if o <= 0:       1683                                 if o <= 0:
1721                                         conti    1684                                         continue
1722                                 dev['end'] =     1685                                 dev['end'] = tdev['end']
1723                                 if 'src' not     1686                                 if 'src' not in dev or 'src' not in tdev:
1724                                         conti    1687                                         continue
1725                                 dev['src'] +=    1688                                 dev['src'] += tdev['src']
1726                                 del list[devn    1689                                 del list[devname]
1727         def usurpTouchingThread(self, name, d    1690         def usurpTouchingThread(self, name, dev):
1728                 # the caller test has priorit    1691                 # the caller test has priority of this thread, give it to him
1729                 for phase in self.sortedPhase    1692                 for phase in self.sortedPhases():
1730                         list = self.dmesg[pha    1693                         list = self.dmesg[phase]['list']
1731                         if name in list:         1694                         if name in list:
1732                                 tdev = list[n    1695                                 tdev = list[name]
1733                                 if tdev['star    1696                                 if tdev['start'] - dev['end'] < 0.1:
1734                                         dev['    1697                                         dev['end'] = tdev['end']
1735                                         if 's    1698                                         if 'src' not in dev:
1736                                                  1699                                                 dev['src'] = []
1737                                         if 's    1700                                         if 'src' in tdev:
1738                                                  1701                                                 dev['src'] += tdev['src']
1739                                         del l    1702                                         del list[name]
1740                                 break            1703                                 break
1741         def stitchTouchingThreads(self, testl    1704         def stitchTouchingThreads(self, testlist):
1742                 # merge any threads between t    1705                 # merge any threads between tests that touch
1743                 for phase in self.sortedPhase    1706                 for phase in self.sortedPhases():
1744                         list = self.dmesg[pha    1707                         list = self.dmesg[phase]['list']
1745                         for devname in list:     1708                         for devname in list:
1746                                 dev = list[de    1709                                 dev = list[devname]
1747                                 if 'htmlclass    1710                                 if 'htmlclass' not in dev or 'kth' not in dev['htmlclass']:
1748                                         conti    1711                                         continue
1749                                 for data in t    1712                                 for data in testlist:
1750                                         data.    1713                                         data.usurpTouchingThread(devname, dev)
1751         def optimizeDevSrc(self):                1714         def optimizeDevSrc(self):
1752                 # merge any src call loops to    1715                 # merge any src call loops to reduce timeline size
1753                 for phase in self.sortedPhase    1716                 for phase in self.sortedPhases():
1754                         list = self.dmesg[pha    1717                         list = self.dmesg[phase]['list']
1755                         for dev in list:         1718                         for dev in list:
1756                                 if 'src' not     1719                                 if 'src' not in list[dev]:
1757                                         conti    1720                                         continue
1758                                 src = list[de    1721                                 src = list[dev]['src']
1759                                 p = 0            1722                                 p = 0
1760                                 for e in sort    1723                                 for e in sorted(src, key=lambda event: event.time):
1761                                         if no    1724                                         if not p or not e.repeat(p):
1762                                                  1725                                                 p = e
1763                                                  1726                                                 continue
1764                                         # e i    1727                                         # e is another iteration of p, move it into p
1765                                         p.end    1728                                         p.end = e.end
1766                                         p.len    1729                                         p.length = p.end - p.time
1767                                         p.cou    1730                                         p.count += 1
1768                                         src.r    1731                                         src.remove(e)
1769         def trimTimeVal(self, t, t0, dT, left    1732         def trimTimeVal(self, t, t0, dT, left):
1770                 if left:                         1733                 if left:
1771                         if(t > t0):              1734                         if(t > t0):
1772                                 if(t - dT < t    1735                                 if(t - dT < t0):
1773                                         retur    1736                                         return t0
1774                                 return t - dT    1737                                 return t - dT
1775                         else:                    1738                         else:
1776                                 return t         1739                                 return t
1777                 else:                            1740                 else:
1778                         if(t < t0 + dT):         1741                         if(t < t0 + dT):
1779                                 if(t > t0):      1742                                 if(t > t0):
1780                                         retur    1743                                         return t0 + dT
1781                                 return t + dT    1744                                 return t + dT
1782                         else:                    1745                         else:
1783                                 return t         1746                                 return t
1784         def trimTime(self, t0, dT, left):        1747         def trimTime(self, t0, dT, left):
1785                 self.tSuspended = self.trimTi    1748                 self.tSuspended = self.trimTimeVal(self.tSuspended, t0, dT, left)
1786                 self.tResumed = self.trimTime    1749                 self.tResumed = self.trimTimeVal(self.tResumed, t0, dT, left)
1787                 self.start = self.trimTimeVal    1750                 self.start = self.trimTimeVal(self.start, t0, dT, left)
1788                 self.tKernSus = self.trimTime    1751                 self.tKernSus = self.trimTimeVal(self.tKernSus, t0, dT, left)
1789                 self.tKernRes = self.trimTime    1752                 self.tKernRes = self.trimTimeVal(self.tKernRes, t0, dT, left)
1790                 self.end = self.trimTimeVal(s    1753                 self.end = self.trimTimeVal(self.end, t0, dT, left)
1791                 for phase in self.sortedPhase    1754                 for phase in self.sortedPhases():
1792                         p = self.dmesg[phase]    1755                         p = self.dmesg[phase]
1793                         p['start'] = self.tri    1756                         p['start'] = self.trimTimeVal(p['start'], t0, dT, left)
1794                         p['end'] = self.trimT    1757                         p['end'] = self.trimTimeVal(p['end'], t0, dT, left)
1795                         list = p['list']         1758                         list = p['list']
1796                         for name in list:        1759                         for name in list:
1797                                 d = list[name    1760                                 d = list[name]
1798                                 d['start'] =     1761                                 d['start'] = self.trimTimeVal(d['start'], t0, dT, left)
1799                                 d['end'] = se    1762                                 d['end'] = self.trimTimeVal(d['end'], t0, dT, left)
1800                                 d['length'] =    1763                                 d['length'] = d['end'] - d['start']
1801                                 if('ftrace' i    1764                                 if('ftrace' in d):
1802                                         cg =     1765                                         cg = d['ftrace']
1803                                         cg.st    1766                                         cg.start = self.trimTimeVal(cg.start, t0, dT, left)
1804                                         cg.en    1767                                         cg.end = self.trimTimeVal(cg.end, t0, dT, left)
1805                                         for l    1768                                         for line in cg.list:
1806                                                  1769                                                 line.time = self.trimTimeVal(line.time, t0, dT, left)
1807                                 if('src' in d    1770                                 if('src' in d):
1808                                         for e    1771                                         for e in d['src']:
1809                                                  1772                                                 e.time = self.trimTimeVal(e.time, t0, dT, left)
1810                                                  1773                                                 e.end = self.trimTimeVal(e.end, t0, dT, left)
1811                                                  1774                                                 e.length = e.end - e.time
1812                                 if('cpuexec'  << 
1813                                         cpuex << 
1814                                         for e << 
1815                                               << 
1816                                               << 
1817                                               << 
1818                                               << 
1819                                         d['cp << 
1820                 for dir in ['suspend', 'resum    1775                 for dir in ['suspend', 'resume']:
1821                         list = []                1776                         list = []
1822                         for e in self.errorin    1777                         for e in self.errorinfo[dir]:
1823                                 type, tm, idx    1778                                 type, tm, idx1, idx2 = e
1824                                 tm = self.tri    1779                                 tm = self.trimTimeVal(tm, t0, dT, left)
1825                                 list.append((    1780                                 list.append((type, tm, idx1, idx2))
1826                         self.errorinfo[dir] =    1781                         self.errorinfo[dir] = list
1827         def trimFreezeTime(self, tZero):         1782         def trimFreezeTime(self, tZero):
1828                 # trim out any standby or fre    1783                 # trim out any standby or freeze clock time
1829                 lp = ''                          1784                 lp = ''
1830                 for phase in self.sortedPhase    1785                 for phase in self.sortedPhases():
1831                         if 'resume_machine' i    1786                         if 'resume_machine' in phase and 'suspend_machine' in lp:
1832                                 tS, tR = self    1787                                 tS, tR = self.dmesg[lp]['end'], self.dmesg[phase]['start']
1833                                 tL = tR - tS     1788                                 tL = tR - tS
1834                                 if tL <= 0:      1789                                 if tL <= 0:
1835                                         conti    1790                                         continue
1836                                 left = True i    1791                                 left = True if tR > tZero else False
1837                                 self.trimTime    1792                                 self.trimTime(tS, tL, left)
1838                                 if 'waking' i    1793                                 if 'waking' in self.dmesg[lp]:
1839                                         tCnt     1794                                         tCnt = self.dmesg[lp]['waking'][0]
1840                                         if se    1795                                         if self.dmesg[lp]['waking'][1] >= 0.001:
1841                                                  1796                                                 tTry = '%.0f' % (round(self.dmesg[lp]['waking'][1] * 1000))
1842                                         else:    1797                                         else:
1843                                                  1798                                                 tTry = '%.3f' % (self.dmesg[lp]['waking'][1] * 1000)
1844                                         text     1799                                         text = '%.0f (%s ms waking %d times)' % (tL * 1000, tTry, tCnt)
1845                                 else:            1800                                 else:
1846                                         text     1801                                         text = '%.0f' % (tL * 1000)
1847                                 self.tLow.app    1802                                 self.tLow.append(text)
1848                         lp = phase               1803                         lp = phase
1849         def getMemTime(self):                    1804         def getMemTime(self):
1850                 if not self.hwstart or not se    1805                 if not self.hwstart or not self.hwend:
1851                         return                   1806                         return
1852                 stime = (self.tSuspended - se    1807                 stime = (self.tSuspended - self.start) * 1000000
1853                 rtime = (self.end - self.tRes    1808                 rtime = (self.end - self.tResumed) * 1000000
1854                 hws = self.hwstart + timedelt    1809                 hws = self.hwstart + timedelta(microseconds=stime)
1855                 hwr = self.hwend - timedelta(    1810                 hwr = self.hwend - timedelta(microseconds=rtime)
1856                 self.tLow.append('%.0f'%((hwr    1811                 self.tLow.append('%.0f'%((hwr - hws).total_seconds() * 1000))
1857         def getTimeValues(self):                 1812         def getTimeValues(self):
1858                 s = (self.tSuspended - self.t !! 1813                 sktime = (self.tSuspended - self.tKernSus) * 1000
1859                 r = (self.tKernRes - self.tRe !! 1814                 rktime = (self.tKernRes - self.tResumed) * 1000
1860                 return (max(s, 0), max(r, 0)) !! 1815                 return (sktime, rktime)
1861         def setPhase(self, phase, ktime, isbe    1816         def setPhase(self, phase, ktime, isbegin, order=-1):
1862                 if(isbegin):                     1817                 if(isbegin):
1863                         # phase start over cu    1818                         # phase start over current phase
1864                         if self.currphase:       1819                         if self.currphase:
1865                                 if 'resume_ma    1820                                 if 'resume_machine' not in self.currphase:
1866                                         sysva    1821                                         sysvals.vprint('WARNING: phase %s failed to end' % self.currphase)
1867                                 self.dmesg[se    1822                                 self.dmesg[self.currphase]['end'] = ktime
1868                         phases = self.dmesg.k    1823                         phases = self.dmesg.keys()
1869                         color = self.phasedef    1824                         color = self.phasedef[phase]['color']
1870                         count = len(phases) i    1825                         count = len(phases) if order < 0 else order
1871                         # create unique name     1826                         # create unique name for every new phase
1872                         while phase in phases    1827                         while phase in phases:
1873                                 phase += '*'     1828                                 phase += '*'
1874                         self.dmesg[phase] = {    1829                         self.dmesg[phase] = {'list': dict(), 'start': -1.0, 'end': -1.0,
1875                                 'row': 0, 'co    1830                                 'row': 0, 'color': color, 'order': count}
1876                         self.dmesg[phase]['st    1831                         self.dmesg[phase]['start'] = ktime
1877                         self.currphase = phas    1832                         self.currphase = phase
1878                 else:                            1833                 else:
1879                         # phase end without a    1834                         # phase end without a start
1880                         if phase not in self.    1835                         if phase not in self.currphase:
1881                                 if self.currp    1836                                 if self.currphase:
1882                                         sysva    1837                                         sysvals.vprint('WARNING: %s ended instead of %s, ftrace corruption?' % (phase, self.currphase))
1883                                 else:            1838                                 else:
1884                                         sysva    1839                                         sysvals.vprint('WARNING: %s ended without a start, ftrace corruption?' % phase)
1885                                         retur    1840                                         return phase
1886                         phase = self.currphas    1841                         phase = self.currphase
1887                         self.dmesg[phase]['en    1842                         self.dmesg[phase]['end'] = ktime
1888                         self.currphase = ''      1843                         self.currphase = ''
1889                 return phase                     1844                 return phase
1890         def sortedDevices(self, phase):          1845         def sortedDevices(self, phase):
1891                 list = self.dmesg[phase]['lis    1846                 list = self.dmesg[phase]['list']
1892                 return sorted(list, key=lambd    1847                 return sorted(list, key=lambda k:list[k]['start'])
1893         def fixupInitcalls(self, phase):         1848         def fixupInitcalls(self, phase):
1894                 # if any calls never returned    1849                 # if any calls never returned, clip them at system resume end
1895                 phaselist = self.dmesg[phase]    1850                 phaselist = self.dmesg[phase]['list']
1896                 for devname in phaselist:        1851                 for devname in phaselist:
1897                         dev = phaselist[devna    1852                         dev = phaselist[devname]
1898                         if(dev['end'] < 0):      1853                         if(dev['end'] < 0):
1899                                 for p in self    1854                                 for p in self.sortedPhases():
1900                                         if se    1855                                         if self.dmesg[p]['end'] > dev['start']:
1901                                                  1856                                                 dev['end'] = self.dmesg[p]['end']
1902                                                  1857                                                 break
1903                                 sysvals.vprin    1858                                 sysvals.vprint('%s (%s): callback didnt return' % (devname, phase))
1904         def deviceFilter(self, devicefilter):    1859         def deviceFilter(self, devicefilter):
1905                 for phase in self.sortedPhase    1860                 for phase in self.sortedPhases():
1906                         list = self.dmesg[pha    1861                         list = self.dmesg[phase]['list']
1907                         rmlist = []              1862                         rmlist = []
1908                         for name in list:        1863                         for name in list:
1909                                 keep = False     1864                                 keep = False
1910                                 for filter in    1865                                 for filter in devicefilter:
1911                                         if fi    1866                                         if filter in name or \
1912                                                  1867                                                 ('drv' in list[name] and filter in list[name]['drv']):
1913                                                  1868                                                 keep = True
1914                                 if not keep:     1869                                 if not keep:
1915                                         rmlis    1870                                         rmlist.append(name)
1916                         for name in rmlist:      1871                         for name in rmlist:
1917                                 del list[name    1872                                 del list[name]
1918         def fixupInitcallsThatDidntReturn(sel    1873         def fixupInitcallsThatDidntReturn(self):
1919                 # if any calls never returned    1874                 # if any calls never returned, clip them at system resume end
1920                 for phase in self.sortedPhase    1875                 for phase in self.sortedPhases():
1921                         self.fixupInitcalls(p    1876                         self.fixupInitcalls(phase)
1922         def phaseOverlap(self, phases):          1877         def phaseOverlap(self, phases):
1923                 rmgroups = []                    1878                 rmgroups = []
1924                 newgroup = []                    1879                 newgroup = []
1925                 for group in self.devicegroup    1880                 for group in self.devicegroups:
1926                         for phase in phases:     1881                         for phase in phases:
1927                                 if phase not     1882                                 if phase not in group:
1928                                         conti    1883                                         continue
1929                                 for p in grou    1884                                 for p in group:
1930                                         if p     1885                                         if p not in newgroup:
1931                                                  1886                                                 newgroup.append(p)
1932                                 if group not     1887                                 if group not in rmgroups:
1933                                         rmgro    1888                                         rmgroups.append(group)
1934                 for group in rmgroups:           1889                 for group in rmgroups:
1935                         self.devicegroups.rem    1890                         self.devicegroups.remove(group)
1936                 self.devicegroups.append(newg    1891                 self.devicegroups.append(newgroup)
1937         def newActionGlobal(self, name, start    1892         def newActionGlobal(self, name, start, end, pid=-1, color=''):
1938                 # which phase is this device     1893                 # which phase is this device callback or action in
1939                 phases = self.sortedPhases()     1894                 phases = self.sortedPhases()
1940                 targetphase = 'none'             1895                 targetphase = 'none'
1941                 htmlclass = ''                   1896                 htmlclass = ''
1942                 overlap = 0.0                    1897                 overlap = 0.0
1943                 myphases = []                    1898                 myphases = []
1944                 for phase in phases:             1899                 for phase in phases:
1945                         pstart = self.dmesg[p    1900                         pstart = self.dmesg[phase]['start']
1946                         pend = self.dmesg[pha    1901                         pend = self.dmesg[phase]['end']
1947                         # see if the action o    1902                         # see if the action overlaps this phase
1948                         o = max(0, min(end, p    1903                         o = max(0, min(end, pend) - max(start, pstart))
1949                         if o > 0:                1904                         if o > 0:
1950                                 myphases.appe    1905                                 myphases.append(phase)
1951                         # set the target phas    1906                         # set the target phase to the one that overlaps most
1952                         if o > overlap:          1907                         if o > overlap:
1953                                 if overlap >     1908                                 if overlap > 0 and phase == 'post_resume':
1954                                         conti    1909                                         continue
1955                                 targetphase =    1910                                 targetphase = phase
1956                                 overlap = o      1911                                 overlap = o
1957                 # if no target phase was foun    1912                 # if no target phase was found, pin it to the edge
1958                 if targetphase == 'none':        1913                 if targetphase == 'none':
1959                         p0start = self.dmesg[    1914                         p0start = self.dmesg[phases[0]]['start']
1960                         if start <= p0start:     1915                         if start <= p0start:
1961                                 targetphase =    1916                                 targetphase = phases[0]
1962                         else:                    1917                         else:
1963                                 targetphase =    1918                                 targetphase = phases[-1]
1964                 if pid == -2:                    1919                 if pid == -2:
1965                         htmlclass = ' bg'        1920                         htmlclass = ' bg'
1966                 elif pid == -3:                  1921                 elif pid == -3:
1967                         htmlclass = ' ps'        1922                         htmlclass = ' ps'
1968                 if len(myphases) > 1:            1923                 if len(myphases) > 1:
1969                         htmlclass = ' bg'        1924                         htmlclass = ' bg'
1970                         self.phaseOverlap(myp    1925                         self.phaseOverlap(myphases)
1971                 if targetphase in phases:        1926                 if targetphase in phases:
1972                         newname = self.newAct    1927                         newname = self.newAction(targetphase, name, pid, '', start, end, '', htmlclass, color)
1973                         return (targetphase,     1928                         return (targetphase, newname)
1974                 return False                     1929                 return False
1975         def newAction(self, phase, name, pid,    1930         def newAction(self, phase, name, pid, parent, start, end, drv, htmlclass='', color=''):
1976                 # new device callback for a s    1931                 # new device callback for a specific phase
1977                 self.html_device_id += 1         1932                 self.html_device_id += 1
1978                 devid = '%s%d' % (self.idstr,    1933                 devid = '%s%d' % (self.idstr, self.html_device_id)
1979                 list = self.dmesg[phase]['lis    1934                 list = self.dmesg[phase]['list']
1980                 length = -1.0                    1935                 length = -1.0
1981                 if(start >= 0 and end >= 0):     1936                 if(start >= 0 and end >= 0):
1982                         length = end - start     1937                         length = end - start
1983                 if pid == -2 or name not in s    1938                 if pid == -2 or name not in sysvals.tracefuncs.keys():
1984                         i = 2                    1939                         i = 2
1985                         origname = name          1940                         origname = name
1986                         while(name in list):     1941                         while(name in list):
1987                                 name = '%s[%d    1942                                 name = '%s[%d]' % (origname, i)
1988                                 i += 1           1943                                 i += 1
1989                 list[name] = {'name': name, '    1944                 list[name] = {'name': name, 'start': start, 'end': end, 'pid': pid,
1990                         'par': parent, 'lengt    1945                         'par': parent, 'length': length, 'row': 0, 'id': devid, 'drv': drv }
1991                 if htmlclass:                    1946                 if htmlclass:
1992                         list[name]['htmlclass    1947                         list[name]['htmlclass'] = htmlclass
1993                 if color:                        1948                 if color:
1994                         list[name]['color'] =    1949                         list[name]['color'] = color
1995                 return name                      1950                 return name
1996         def findDevice(self, phase, name):       1951         def findDevice(self, phase, name):
1997                 list = self.dmesg[phase]['lis    1952                 list = self.dmesg[phase]['list']
1998                 mydev = ''                       1953                 mydev = ''
1999                 for devname in sorted(list):     1954                 for devname in sorted(list):
2000                         if name == devname or !! 1955                         if name == devname or re.match('^%s\[(?P<num>[0-9]*)\]$' % name, devname):
2001                                 mydev = devna    1956                                 mydev = devname
2002                 if mydev:                        1957                 if mydev:
2003                         return list[mydev]       1958                         return list[mydev]
2004                 return False                     1959                 return False
2005         def deviceChildren(self, devname, pha    1960         def deviceChildren(self, devname, phase):
2006                 devlist = []                     1961                 devlist = []
2007                 list = self.dmesg[phase]['lis    1962                 list = self.dmesg[phase]['list']
2008                 for child in list:               1963                 for child in list:
2009                         if(list[child]['par']    1964                         if(list[child]['par'] == devname):
2010                                 devlist.appen    1965                                 devlist.append(child)
2011                 return devlist                   1966                 return devlist
2012         def maxDeviceNameSize(self, phase):      1967         def maxDeviceNameSize(self, phase):
2013                 size = 0                         1968                 size = 0
2014                 for name in self.dmesg[phase]    1969                 for name in self.dmesg[phase]['list']:
2015                         if len(name) > size:     1970                         if len(name) > size:
2016                                 size = len(na    1971                                 size = len(name)
2017                 return size                      1972                 return size
2018         def printDetails(self):                  1973         def printDetails(self):
2019                 sysvals.vprint('Timeline Deta    1974                 sysvals.vprint('Timeline Details:')
2020                 sysvals.vprint('          tes    1975                 sysvals.vprint('          test start: %f' % self.start)
2021                 sysvals.vprint('kernel suspen    1976                 sysvals.vprint('kernel suspend start: %f' % self.tKernSus)
2022                 tS = tR = False                  1977                 tS = tR = False
2023                 for phase in self.sortedPhase    1978                 for phase in self.sortedPhases():
2024                         devlist = self.dmesg[    1979                         devlist = self.dmesg[phase]['list']
2025                         dc, ps, pe = len(devl    1980                         dc, ps, pe = len(devlist), self.dmesg[phase]['start'], self.dmesg[phase]['end']
2026                         if not tS and ps >= s    1981                         if not tS and ps >= self.tSuspended:
2027                                 sysvals.vprin    1982                                 sysvals.vprint('   machine suspended: %f' % self.tSuspended)
2028                                 tS = True        1983                                 tS = True
2029                         if not tR and ps >= s    1984                         if not tR and ps >= self.tResumed:
2030                                 sysvals.vprin    1985                                 sysvals.vprint('     machine resumed: %f' % self.tResumed)
2031                                 tR = True        1986                                 tR = True
2032                         sysvals.vprint('%20s:    1987                         sysvals.vprint('%20s: %f - %f (%d devices)' % (phase, ps, pe, dc))
2033                         if sysvals.devdump:      1988                         if sysvals.devdump:
2034                                 sysvals.vprin    1989                                 sysvals.vprint(''.join('-' for i in range(80)))
2035                                 maxname = '%d    1990                                 maxname = '%d' % self.maxDeviceNameSize(phase)
2036                                 fmt = '%3d) %    1991                                 fmt = '%3d) %'+maxname+'s - %f - %f'
2037                                 c = 1            1992                                 c = 1
2038                                 for name in s    1993                                 for name in sorted(devlist):
2039                                         s = d    1994                                         s = devlist[name]['start']
2040                                         e = d    1995                                         e = devlist[name]['end']
2041                                         sysva    1996                                         sysvals.vprint(fmt % (c, name, s, e))
2042                                         c +=     1997                                         c += 1
2043                                 sysvals.vprin    1998                                 sysvals.vprint(''.join('-' for i in range(80)))
2044                 sysvals.vprint('   kernel res    1999                 sysvals.vprint('   kernel resume end: %f' % self.tKernRes)
2045                 sysvals.vprint('            t    2000                 sysvals.vprint('            test end: %f' % self.end)
2046         def deviceChildrenAllPhases(self, dev    2001         def deviceChildrenAllPhases(self, devname):
2047                 devlist = []                     2002                 devlist = []
2048                 for phase in self.sortedPhase    2003                 for phase in self.sortedPhases():
2049                         list = self.deviceChi    2004                         list = self.deviceChildren(devname, phase)
2050                         for dev in sorted(lis    2005                         for dev in sorted(list):
2051                                 if dev not in    2006                                 if dev not in devlist:
2052                                         devli    2007                                         devlist.append(dev)
2053                 return devlist                   2008                 return devlist
2054         def masterTopology(self, name, list,     2009         def masterTopology(self, name, list, depth):
2055                 node = DeviceNode(name, depth    2010                 node = DeviceNode(name, depth)
2056                 for cname in list:               2011                 for cname in list:
2057                         # avoid recursions       2012                         # avoid recursions
2058                         if name == cname:        2013                         if name == cname:
2059                                 continue         2014                                 continue
2060                         clist = self.deviceCh    2015                         clist = self.deviceChildrenAllPhases(cname)
2061                         cnode = self.masterTo    2016                         cnode = self.masterTopology(cname, clist, depth+1)
2062                         node.children.append(    2017                         node.children.append(cnode)
2063                 return node                      2018                 return node
2064         def printTopology(self, node):           2019         def printTopology(self, node):
2065                 html = ''                        2020                 html = ''
2066                 if node.name:                    2021                 if node.name:
2067                         info = ''                2022                         info = ''
2068                         drv = ''                 2023                         drv = ''
2069                         for phase in self.sor    2024                         for phase in self.sortedPhases():
2070                                 list = self.d    2025                                 list = self.dmesg[phase]['list']
2071                                 if node.name     2026                                 if node.name in list:
2072                                         s = l    2027                                         s = list[node.name]['start']
2073                                         e = l    2028                                         e = list[node.name]['end']
2074                                         if li    2029                                         if list[node.name]['drv']:
2075                                                  2030                                                 drv = ' {'+list[node.name]['drv']+'}'
2076                                         info     2031                                         info += ('<li>%s: %.3fms</li>' % (phase, (e-s)*1000))
2077                         html += '<li><b>'+nod    2032                         html += '<li><b>'+node.name+drv+'</b>'
2078                         if info:                 2033                         if info:
2079                                 html += '<ul>    2034                                 html += '<ul>'+info+'</ul>'
2080                         html += '</li>'          2035                         html += '</li>'
2081                 if len(node.children) > 0:       2036                 if len(node.children) > 0:
2082                         html += '<ul>'           2037                         html += '<ul>'
2083                         for cnode in node.chi    2038                         for cnode in node.children:
2084                                 html += self.    2039                                 html += self.printTopology(cnode)
2085                         html += '</ul>'          2040                         html += '</ul>'
2086                 return html                      2041                 return html
2087         def rootDeviceList(self):                2042         def rootDeviceList(self):
2088                 # list of devices graphed        2043                 # list of devices graphed
2089                 real = []                        2044                 real = []
2090                 for phase in self.sortedPhase    2045                 for phase in self.sortedPhases():
2091                         list = self.dmesg[pha    2046                         list = self.dmesg[phase]['list']
2092                         for dev in sorted(lis    2047                         for dev in sorted(list):
2093                                 if list[dev][    2048                                 if list[dev]['pid'] >= 0 and dev not in real:
2094                                         real.    2049                                         real.append(dev)
2095                 # list of top-most root devic    2050                 # list of top-most root devices
2096                 rootlist = []                    2051                 rootlist = []
2097                 for phase in self.sortedPhase    2052                 for phase in self.sortedPhases():
2098                         list = self.dmesg[pha    2053                         list = self.dmesg[phase]['list']
2099                         for dev in sorted(lis    2054                         for dev in sorted(list):
2100                                 pdev = list[d    2055                                 pdev = list[dev]['par']
2101                                 pid = list[de    2056                                 pid = list[dev]['pid']
2102                                 if(pid < 0 or !! 2057                                 if(pid < 0 or re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)):
2103                                         conti    2058                                         continue
2104                                 if pdev and p    2059                                 if pdev and pdev not in real and pdev not in rootlist:
2105                                         rootl    2060                                         rootlist.append(pdev)
2106                 return rootlist                  2061                 return rootlist
2107         def deviceTopology(self):                2062         def deviceTopology(self):
2108                 rootlist = self.rootDeviceLis    2063                 rootlist = self.rootDeviceList()
2109                 master = self.masterTopology(    2064                 master = self.masterTopology('', rootlist, 0)
2110                 return self.printTopology(mas    2065                 return self.printTopology(master)
2111         def selectTimelineDevices(self, widfm    2066         def selectTimelineDevices(self, widfmt, tTotal, mindevlen):
2112                 # only select devices that wi    2067                 # only select devices that will actually show up in html
2113                 self.tdevlist = dict()           2068                 self.tdevlist = dict()
2114                 for phase in self.dmesg:         2069                 for phase in self.dmesg:
2115                         devlist = []             2070                         devlist = []
2116                         list = self.dmesg[pha    2071                         list = self.dmesg[phase]['list']
2117                         for dev in list:         2072                         for dev in list:
2118                                 length = (lis    2073                                 length = (list[dev]['end'] - list[dev]['start']) * 1000
2119                                 width = widfm    2074                                 width = widfmt % (((list[dev]['end']-list[dev]['start'])*100)/tTotal)
2120                                 if length >=     2075                                 if length >= mindevlen:
2121                                         devli    2076                                         devlist.append(dev)
2122                         self.tdevlist[phase]     2077                         self.tdevlist[phase] = devlist
2123         def addHorizontalDivider(self, devnam    2078         def addHorizontalDivider(self, devname, devend):
2124                 phase = 'suspend_prepare'        2079                 phase = 'suspend_prepare'
2125                 self.newAction(phase, devname    2080                 self.newAction(phase, devname, -2, '', \
2126                         self.start, devend, '    2081                         self.start, devend, '', ' sec', '')
2127                 if phase not in self.tdevlist    2082                 if phase not in self.tdevlist:
2128                         self.tdevlist[phase]     2083                         self.tdevlist[phase] = []
2129                 self.tdevlist[phase].append(d    2084                 self.tdevlist[phase].append(devname)
2130                 d = DevItem(0, phase, self.dm    2085                 d = DevItem(0, phase, self.dmesg[phase]['list'][devname])
2131                 return d                         2086                 return d
2132         def addProcessUsageEvent(self, name,     2087         def addProcessUsageEvent(self, name, times):
2133                 # get the start and end times    2088                 # get the start and end times for this process
2134                 cpuexec = dict()              !! 2089                 maxC = 0
2135                 tlast = start = end = -1      !! 2090                 tlast = 0
                                                   >> 2091                 start = -1
                                                   >> 2092                 end = -1
2136                 for t in sorted(times):          2093                 for t in sorted(times):
2137                         if tlast < 0:         !! 2094                         if tlast == 0:
2138                                 tlast = t        2095                                 tlast = t
2139                                 continue         2096                                 continue
2140                         if name in self.pstl[ !! 2097                         if name in self.pstl[t]:
2141                                 if start < 0: !! 2098                                 if start == -1 or tlast < start:
2142                                         start    2099                                         start = tlast
2143                                 end, key = t, !! 2100                                 if end == -1 or t > end:
2144                                 maxj = (t - t !! 2101                                         end = t
2145                                 cpuexec[key]  << 
2146                         tlast = t                2102                         tlast = t
2147                 if start < 0 or end < 0:      !! 2103                 if start == -1 or end == -1:
2148                         return                !! 2104                         return 0
2149                 # add a new action for this p    2105                 # add a new action for this process and get the object
2150                 out = self.newActionGlobal(na    2106                 out = self.newActionGlobal(name, start, end, -3)
2151                 if out:                       !! 2107                 if not out:
2152                         phase, devname = out  !! 2108                         return 0
2153                         dev = self.dmesg[phas !! 2109                 phase, devname = out
2154                         dev['cpuexec'] = cpue !! 2110                 dev = self.dmesg[phase]['list'][devname]
                                                   >> 2111                 # get the cpu exec data
                                                   >> 2112                 tlast = 0
                                                   >> 2113                 clast = 0
                                                   >> 2114                 cpuexec = dict()
                                                   >> 2115                 for t in sorted(times):
                                                   >> 2116                         if tlast == 0 or t <= start or t > end:
                                                   >> 2117                                 tlast = t
                                                   >> 2118                                 continue
                                                   >> 2119                         list = self.pstl[t]
                                                   >> 2120                         c = 0
                                                   >> 2121                         if name in list:
                                                   >> 2122                                 c = list[name]
                                                   >> 2123                         if c > maxC:
                                                   >> 2124                                 maxC = c
                                                   >> 2125                         if c != clast:
                                                   >> 2126                                 key = (tlast, t)
                                                   >> 2127                                 cpuexec[key] = c
                                                   >> 2128                                 tlast = t
                                                   >> 2129                                 clast = c
                                                   >> 2130                 dev['cpuexec'] = cpuexec
                                                   >> 2131                 return maxC
2155         def createProcessUsageEvents(self):      2132         def createProcessUsageEvents(self):
2156                 # get an array of process nam !! 2133                 # get an array of process names
2157                 proclist = {'sus': dict(), 'r !! 2134                 proclist = []
2158                 tdata = {'sus': [], 'res': [] << 
2159                 for t in sorted(self.pstl):      2135                 for t in sorted(self.pstl):
2160                         dir = 'sus' if t < se !! 2136                         pslist = self.pstl[t]
2161                         for ps in sorted(self !! 2137                         for ps in sorted(pslist):
2162                                 if ps not in  !! 2138                                 if ps not in proclist:
2163                                         procl !! 2139                                         proclist.append(ps)
2164                         tdata[dir].append(t)  !! 2140                 # get a list of data points for suspend and resume
                                                   >> 2141                 tsus = []
                                                   >> 2142                 tres = []
                                                   >> 2143                 for t in sorted(self.pstl):
                                                   >> 2144                         if t < self.tSuspended:
                                                   >> 2145                                 tsus.append(t)
                                                   >> 2146                         else:
                                                   >> 2147                                 tres.append(t)
2165                 # process the events for susp    2148                 # process the events for suspend and resume
2166                 if len(proclist['sus']) > 0 o !! 2149                 if len(proclist) > 0:
2167                         sysvals.vprint('Proce    2150                         sysvals.vprint('Process Execution:')
2168                 for dir in ['sus', 'res']:    !! 2151                 for ps in proclist:
2169                         for ps in sorted(proc !! 2152                         c = self.addProcessUsageEvent(ps, tsus)
2170                                 self.addProce !! 2153                         if c > 0:
                                                   >> 2154                                 sysvals.vprint('%25s (sus): %d' % (ps, c))
                                                   >> 2155                         c = self.addProcessUsageEvent(ps, tres)
                                                   >> 2156                         if c > 0:
                                                   >> 2157                                 sysvals.vprint('%25s (res): %d' % (ps, c))
2171         def handleEndMarker(self, time, msg='    2158         def handleEndMarker(self, time, msg=''):
2172                 dm = self.dmesg                  2159                 dm = self.dmesg
2173                 self.setEnd(time, msg)           2160                 self.setEnd(time, msg)
2174                 self.initDevicegroups()          2161                 self.initDevicegroups()
2175                 # give suspend_prepare an end    2162                 # give suspend_prepare an end if needed
2176                 if 'suspend_prepare' in dm an    2163                 if 'suspend_prepare' in dm and dm['suspend_prepare']['end'] < 0:
2177                         dm['suspend_prepare']    2164                         dm['suspend_prepare']['end'] = time
2178                 # assume resume machine ends     2165                 # assume resume machine ends at next phase start
2179                 if 'resume_machine' in dm and    2166                 if 'resume_machine' in dm and dm['resume_machine']['end'] < 0:
2180                         np = self.nextPhase('    2167                         np = self.nextPhase('resume_machine', 1)
2181                         if np:                   2168                         if np:
2182                                 dm['resume_ma    2169                                 dm['resume_machine']['end'] = dm[np]['start']
2183                 # if kernel resume end not fo    2170                 # if kernel resume end not found, assume its the end marker
2184                 if self.tKernRes == 0.0:         2171                 if self.tKernRes == 0.0:
2185                         self.tKernRes = time     2172                         self.tKernRes = time
2186                 # if kernel suspend start not    2173                 # if kernel suspend start not found, assume its the end marker
2187                 if self.tKernSus == 0.0:         2174                 if self.tKernSus == 0.0:
2188                         self.tKernSus = time     2175                         self.tKernSus = time
2189                 # set resume complete to end     2176                 # set resume complete to end at end marker
2190                 if 'resume_complete' in dm:      2177                 if 'resume_complete' in dm:
2191                         dm['resume_complete']    2178                         dm['resume_complete']['end'] = time
2192         def initcall_debug_call(self, line, q    2179         def initcall_debug_call(self, line, quick=False):
2193                 m = re.match(r'.*(\[ *)(?P<t> !! 2180                 m = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) .* (?P<f>.*)\: '+\
2194                         r'PM: *calling .* @ ( !! 2181                         'PM: *calling .* @ (?P<n>.*), parent: (?P<p>.*)', line)
2195                 if not m:                        2182                 if not m:
2196                         m = re.match(r'.*(\[  !! 2183                         m = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) .* (?P<f>.*)\: '+\
2197                                 r'calling .*  !! 2184                                 'calling .* @ (?P<n>.*), parent: (?P<p>.*)', line)
2198                 if not m:                        2185                 if not m:
2199                         m = re.match(r'.*(\[  !! 2186                         m = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) calling  '+\
2200                                 r'(?P<f>.*)\+  !! 2187                                 '(?P<f>.*)\+ @ (?P<n>.*), parent: (?P<p>.*)', line)
2201                 if m:                            2188                 if m:
2202                         return True if quick     2189                         return True if quick else m.group('t', 'f', 'n', 'p')
2203                 return False if quick else ('    2190                 return False if quick else ('', '', '', '')
2204         def initcall_debug_return(self, line,    2191         def initcall_debug_return(self, line, quick=False):
2205                 m = re.match(r'.*(\[ *)(?P<t> !! 2192                 m = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) .* (?P<f>.*)\: PM: '+\
2206                         r'.* returned (?P<r>[ !! 2193                         '.* returned (?P<r>[0-9]*) after (?P<dt>[0-9]*) usecs', line)
2207                 if not m:                        2194                 if not m:
2208                         m = re.match(r'.*(\[  !! 2195                         m = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) .* (?P<f>.*)\: '+\
2209                                 r'.* returned !! 2196                                 '.* returned (?P<r>[0-9]*) after (?P<dt>[0-9]*) usecs', line)
2210                 if not m:                        2197                 if not m:
2211                         m = re.match(r'.*(\[  !! 2198                         m = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) call '+\
2212                                 r'(?P<f>.*)\+ !! 2199                                 '(?P<f>.*)\+ returned .* after (?P<dt>.*) usecs', line)
2213                 if m:                            2200                 if m:
2214                         return True if quick     2201                         return True if quick else m.group('t', 'f', 'dt')
2215                 return False if quick else ('    2202                 return False if quick else ('', '', '')
2216         def debugPrint(self):                    2203         def debugPrint(self):
2217                 for p in self.sortedPhases():    2204                 for p in self.sortedPhases():
2218                         list = self.dmesg[p][    2205                         list = self.dmesg[p]['list']
2219                         for devname in sorted    2206                         for devname in sorted(list):
2220                                 dev = list[de    2207                                 dev = list[devname]
2221                                 if 'ftrace' i    2208                                 if 'ftrace' in dev:
2222                                         dev['    2209                                         dev['ftrace'].debugPrint(' [%s]' % devname)
2223                                                  2210 
2224 # Class: DevFunction                             2211 # Class: DevFunction
2225 # Description:                                   2212 # Description:
2226 #        A container for kprobe function data    2213 #        A container for kprobe function data we want in the dev timeline
2227 class DevFunction:                               2214 class DevFunction:
2228         def __init__(self, name, args, caller    2215         def __init__(self, name, args, caller, ret, start, end, u, proc, pid, color):
2229                 self.row = 0                     2216                 self.row = 0
2230                 self.count = 1                   2217                 self.count = 1
2231                 self.name = name                 2218                 self.name = name
2232                 self.args = args                 2219                 self.args = args
2233                 self.caller = caller             2220                 self.caller = caller
2234                 self.ret = ret                   2221                 self.ret = ret
2235                 self.time = start                2222                 self.time = start
2236                 self.length = end - start        2223                 self.length = end - start
2237                 self.end = end                   2224                 self.end = end
2238                 self.ubiquitous = u              2225                 self.ubiquitous = u
2239                 self.proc = proc                 2226                 self.proc = proc
2240                 self.pid = pid                   2227                 self.pid = pid
2241                 self.color = color               2228                 self.color = color
2242         def title(self):                         2229         def title(self):
2243                 cnt = ''                         2230                 cnt = ''
2244                 if self.count > 1:               2231                 if self.count > 1:
2245                         cnt = '(x%d)' % self.    2232                         cnt = '(x%d)' % self.count
2246                 l = '%0.3fms' % (self.length     2233                 l = '%0.3fms' % (self.length * 1000)
2247                 if self.ubiquitous:              2234                 if self.ubiquitous:
2248                         title = '%s(%s)%s <-     2235                         title = '%s(%s)%s <- %s, %s(%s)' % \
2249                                 (self.name, s    2236                                 (self.name, self.args, cnt, self.caller, self.ret, l)
2250                 else:                            2237                 else:
2251                         title = '%s(%s) %s%s(    2238                         title = '%s(%s) %s%s(%s)' % (self.name, self.args, self.ret, cnt, l)
2252                 return title.replace('"', '')    2239                 return title.replace('"', '')
2253         def text(self):                          2240         def text(self):
2254                 if self.count > 1:               2241                 if self.count > 1:
2255                         text = '%s(x%d)' % (s    2242                         text = '%s(x%d)' % (self.name, self.count)
2256                 else:                            2243                 else:
2257                         text = self.name         2244                         text = self.name
2258                 return text                      2245                 return text
2259         def repeat(self, tgt):                   2246         def repeat(self, tgt):
2260                 # is the tgt call just a repe    2247                 # is the tgt call just a repeat of this call (e.g. are we in a loop)
2261                 dt = self.time - tgt.end         2248                 dt = self.time - tgt.end
2262                 # only combine calls if -all-    2249                 # only combine calls if -all- attributes are identical
2263                 if tgt.caller == self.caller     2250                 if tgt.caller == self.caller and \
2264                         tgt.name == self.name    2251                         tgt.name == self.name and tgt.args == self.args and \
2265                         tgt.proc == self.proc    2252                         tgt.proc == self.proc and tgt.pid == self.pid and \
2266                         tgt.ret == self.ret a    2253                         tgt.ret == self.ret and dt >= 0 and \
2267                         dt <= sysvals.callloo    2254                         dt <= sysvals.callloopmaxgap and \
2268                         self.length < sysvals    2255                         self.length < sysvals.callloopmaxlen:
2269                         return True              2256                         return True
2270                 return False                     2257                 return False
2271                                                  2258 
2272 # Class: FTraceLine                              2259 # Class: FTraceLine
2273 # Description:                                   2260 # Description:
2274 #        A container for a single line of ftr    2261 #        A container for a single line of ftrace data. There are six basic types:
2275 #                callgraph line:                 2262 #                callgraph line:
2276 #                         call: "  dpm_run_ca    2263 #                         call: "  dpm_run_callback() {"
2277 #                       return: "  }"            2264 #                       return: "  }"
2278 #                         leaf: " dpm_run_cal    2265 #                         leaf: " dpm_run_callback();"
2279 #                trace event:                    2266 #                trace event:
2280 #                        tracing_mark_write:     2267 #                        tracing_mark_write: SUSPEND START or RESUME COMPLETE
2281 #                        suspend_resume: phas    2268 #                        suspend_resume: phase or custom exec block data
2282 #                        device_pm_callback:     2269 #                        device_pm_callback: device callback info
2283 class FTraceLine:                                2270 class FTraceLine:
2284         def __init__(self, t, m='', d=''):       2271         def __init__(self, t, m='', d=''):
2285                 self.length = 0.0                2272                 self.length = 0.0
2286                 self.fcall = False               2273                 self.fcall = False
2287                 self.freturn = False             2274                 self.freturn = False
2288                 self.fevent = False              2275                 self.fevent = False
2289                 self.fkprobe = False             2276                 self.fkprobe = False
2290                 self.depth = 0                   2277                 self.depth = 0
2291                 self.name = ''                   2278                 self.name = ''
2292                 self.type = ''                   2279                 self.type = ''
2293                 self.time = float(t)             2280                 self.time = float(t)
2294                 if not m and not d:              2281                 if not m and not d:
2295                         return                   2282                         return
2296                 # is this a trace event          2283                 # is this a trace event
2297                 if(d == 'traceevent' or re.ma !! 2284                 if(d == 'traceevent' or re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m)):
2298                         if(d == 'traceevent')    2285                         if(d == 'traceevent'):
2299                                 # nop format     2286                                 # nop format trace event
2300                                 msg = m          2287                                 msg = m
2301                         else:                    2288                         else:
2302                                 # function_gr    2289                                 # function_graph format trace event
2303                                 em = re.match !! 2290                                 em = re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m)
2304                                 msg = em.grou    2291                                 msg = em.group('msg')
2305                                                  2292 
2306                         emm = re.match(r'^(?P !! 2293                         emm = re.match('^(?P<call>.*?): (?P<msg>.*)', msg)
2307                         if(emm):                 2294                         if(emm):
2308                                 self.name = e    2295                                 self.name = emm.group('msg')
2309                                 self.type = e    2296                                 self.type = emm.group('call')
2310                         else:                    2297                         else:
2311                                 self.name = m    2298                                 self.name = msg
2312                         km = re.match(r'^(?P< !! 2299                         km = re.match('^(?P<n>.*)_cal$', self.type)
2313                         if km:                   2300                         if km:
2314                                 self.fcall =     2301                                 self.fcall = True
2315                                 self.fkprobe     2302                                 self.fkprobe = True
2316                                 self.type = k    2303                                 self.type = km.group('n')
2317                                 return           2304                                 return
2318                         km = re.match(r'^(?P< !! 2305                         km = re.match('^(?P<n>.*)_ret$', self.type)
2319                         if km:                   2306                         if km:
2320                                 self.freturn     2307                                 self.freturn = True
2321                                 self.fkprobe     2308                                 self.fkprobe = True
2322                                 self.type = k    2309                                 self.type = km.group('n')
2323                                 return           2310                                 return
2324                         self.fevent = True       2311                         self.fevent = True
2325                         return                   2312                         return
2326                 # convert the duration to sec    2313                 # convert the duration to seconds
2327                 if(d):                           2314                 if(d):
2328                         self.length = float(d    2315                         self.length = float(d)/1000000
2329                 # the indentation determines     2316                 # the indentation determines the depth
2330                 match = re.match(r'^(?P<d> *) !! 2317                 match = re.match('^(?P<d> *)(?P<o>.*)$', m)
2331                 if(not match):                   2318                 if(not match):
2332                         return                   2319                         return
2333                 self.depth = self.getDepth(ma    2320                 self.depth = self.getDepth(match.group('d'))
2334                 m = match.group('o')             2321                 m = match.group('o')
2335                 # function return                2322                 # function return
2336                 if(m[0] == '}'):                 2323                 if(m[0] == '}'):
2337                         self.freturn = True      2324                         self.freturn = True
2338                         if(len(m) > 1):          2325                         if(len(m) > 1):
2339                                 # includes co    2326                                 # includes comment with function name
2340                                 match = re.ma !! 2327                                 match = re.match('^} *\/\* *(?P<n>.*) *\*\/$', m)
2341                                 if(match):       2328                                 if(match):
2342                                         self.    2329                                         self.name = match.group('n').strip()
2343                 # function call                  2330                 # function call
2344                 else:                            2331                 else:
2345                         self.fcall = True        2332                         self.fcall = True
2346                         # function call with     2333                         # function call with children
2347                         if(m[-1] == '{'):        2334                         if(m[-1] == '{'):
2348                                 match = re.ma !! 2335                                 match = re.match('^(?P<n>.*) *\(.*', m)
2349                                 if(match):       2336                                 if(match):
2350                                         self.    2337                                         self.name = match.group('n').strip()
2351                         # function call with     2338                         # function call with no children (leaf)
2352                         elif(m[-1] == ';'):      2339                         elif(m[-1] == ';'):
2353                                 self.freturn     2340                                 self.freturn = True
2354                                 match = re.ma !! 2341                                 match = re.match('^(?P<n>.*) *\(.*', m)
2355                                 if(match):       2342                                 if(match):
2356                                         self.    2343                                         self.name = match.group('n').strip()
2357                         # something else (pos    2344                         # something else (possibly a trace marker)
2358                         else:                    2345                         else:
2359                                 self.name = m    2346                                 self.name = m
2360         def isCall(self):                        2347         def isCall(self):
2361                 return self.fcall and not sel    2348                 return self.fcall and not self.freturn
2362         def isReturn(self):                      2349         def isReturn(self):
2363                 return self.freturn and not s    2350                 return self.freturn and not self.fcall
2364         def isLeaf(self):                        2351         def isLeaf(self):
2365                 return self.fcall and self.fr    2352                 return self.fcall and self.freturn
2366         def getDepth(self, str):                 2353         def getDepth(self, str):
2367                 return len(str)/2                2354                 return len(str)/2
2368         def debugPrint(self, info=''):           2355         def debugPrint(self, info=''):
2369                 if self.isLeaf():                2356                 if self.isLeaf():
2370                         pprint(' -- %12.6f (d    2357                         pprint(' -- %12.6f (depth=%02d): %s(); (%.3f us) %s' % (self.time, \
2371                                 self.depth, s    2358                                 self.depth, self.name, self.length*1000000, info))
2372                 elif self.freturn:               2359                 elif self.freturn:
2373                         pprint(' -- %12.6f (d    2360                         pprint(' -- %12.6f (depth=%02d): %s} (%.3f us) %s' % (self.time, \
2374                                 self.depth, s    2361                                 self.depth, self.name, self.length*1000000, info))
2375                 else:                            2362                 else:
2376                         pprint(' -- %12.6f (d    2363                         pprint(' -- %12.6f (depth=%02d): %s() { (%.3f us) %s' % (self.time, \
2377                                 self.depth, s    2364                                 self.depth, self.name, self.length*1000000, info))
2378         def startMarker(self):                   2365         def startMarker(self):
2379                 # Is this the starting line o    2366                 # Is this the starting line of a suspend?
2380                 if not self.fevent:              2367                 if not self.fevent:
2381                         return False             2368                         return False
2382                 if sysvals.usetracemarkers:      2369                 if sysvals.usetracemarkers:
2383                         if(self.name.startswi    2370                         if(self.name.startswith('SUSPEND START')):
2384                                 return True      2371                                 return True
2385                         return False             2372                         return False
2386                 else:                            2373                 else:
2387                         if(self.type == 'susp    2374                         if(self.type == 'suspend_resume' and
2388                                 re.match(r'su !! 2375                                 re.match('suspend_enter\[.*\] begin', self.name)):
2389                                 return True      2376                                 return True
2390                         return False             2377                         return False
2391         def endMarker(self):                     2378         def endMarker(self):
2392                 # Is this the ending line of     2379                 # Is this the ending line of a resume?
2393                 if not self.fevent:              2380                 if not self.fevent:
2394                         return False             2381                         return False
2395                 if sysvals.usetracemarkers:      2382                 if sysvals.usetracemarkers:
2396                         if(self.name.startswi    2383                         if(self.name.startswith('RESUME COMPLETE')):
2397                                 return True      2384                                 return True
2398                         return False             2385                         return False
2399                 else:                            2386                 else:
2400                         if(self.type == 'susp    2387                         if(self.type == 'suspend_resume' and
2401                                 re.match(r'th !! 2388                                 re.match('thaw_processes\[.*\] end', self.name)):
2402                                 return True      2389                                 return True
2403                         return False             2390                         return False
2404                                                  2391 
2405 # Class: FTraceCallGraph                         2392 # Class: FTraceCallGraph
2406 # Description:                                   2393 # Description:
2407 #        A container for the ftrace callgraph    2394 #        A container for the ftrace callgraph of a single recursive function.
2408 #        This can be a dpm_run_callback, dpm_    2395 #        This can be a dpm_run_callback, dpm_prepare, or dpm_complete callgraph
2409 #        Each instance is tied to a single de    2396 #        Each instance is tied to a single device in a single phase, and is
2410 #        comprised of an ordered list of FTra    2397 #        comprised of an ordered list of FTraceLine objects
2411 class FTraceCallGraph:                           2398 class FTraceCallGraph:
2412         vfname = 'missing_function_name'         2399         vfname = 'missing_function_name'
2413         def __init__(self, pid, sv):             2400         def __init__(self, pid, sv):
2414                 self.id = ''                     2401                 self.id = ''
2415                 self.invalid = False             2402                 self.invalid = False
2416                 self.name = ''                   2403                 self.name = ''
2417                 self.partial = False             2404                 self.partial = False
2418                 self.ignore = False              2405                 self.ignore = False
2419                 self.start = -1.0                2406                 self.start = -1.0
2420                 self.end = -1.0                  2407                 self.end = -1.0
2421                 self.list = []                   2408                 self.list = []
2422                 self.depth = 0                   2409                 self.depth = 0
2423                 self.pid = pid                   2410                 self.pid = pid
2424                 self.sv = sv                     2411                 self.sv = sv
2425         def addLine(self, line):                 2412         def addLine(self, line):
2426                 # if this is already invalid,    2413                 # if this is already invalid, just leave
2427                 if(self.invalid):                2414                 if(self.invalid):
2428                         if(line.depth == 0 an    2415                         if(line.depth == 0 and line.freturn):
2429                                 return 1         2416                                 return 1
2430                         return 0                 2417                         return 0
2431                 # invalidate on bad depth        2418                 # invalidate on bad depth
2432                 if(self.depth < 0):              2419                 if(self.depth < 0):
2433                         self.invalidate(line)    2420                         self.invalidate(line)
2434                         return 0                 2421                         return 0
2435                 # ignore data til we return t    2422                 # ignore data til we return to the current depth
2436                 if self.ignore:                  2423                 if self.ignore:
2437                         if line.depth > self.    2424                         if line.depth > self.depth:
2438                                 return 0         2425                                 return 0
2439                         else:                    2426                         else:
2440                                 self.list[-1]    2427                                 self.list[-1].freturn = True
2441                                 self.list[-1]    2428                                 self.list[-1].length = line.time - self.list[-1].time
2442                                 self.ignore =    2429                                 self.ignore = False
2443                                 # if this is     2430                                 # if this is a return at self.depth, no more work is needed
2444                                 if line.depth    2431                                 if line.depth == self.depth and line.isReturn():
2445                                         if li    2432                                         if line.depth == 0:
2446                                                  2433                                                 self.end = line.time
2447                                                  2434                                                 return 1
2448                                         retur    2435                                         return 0
2449                 # compare current depth with     2436                 # compare current depth with this lines pre-call depth
2450                 prelinedep = line.depth          2437                 prelinedep = line.depth
2451                 if line.isReturn():              2438                 if line.isReturn():
2452                         prelinedep += 1          2439                         prelinedep += 1
2453                 last = 0                         2440                 last = 0
2454                 lasttime = line.time             2441                 lasttime = line.time
2455                 if len(self.list) > 0:           2442                 if len(self.list) > 0:
2456                         last = self.list[-1]     2443                         last = self.list[-1]
2457                         lasttime = last.time     2444                         lasttime = last.time
2458                         if last.isLeaf():        2445                         if last.isLeaf():
2459                                 lasttime += l    2446                                 lasttime += last.length
2460                 # handle low misalignments by    2447                 # handle low misalignments by inserting returns
2461                 mismatch = prelinedep - self.    2448                 mismatch = prelinedep - self.depth
2462                 warning = self.sv.verbose and    2449                 warning = self.sv.verbose and abs(mismatch) > 1
2463                 info = []                        2450                 info = []
2464                 if mismatch < 0:                 2451                 if mismatch < 0:
2465                         idx = 0                  2452                         idx = 0
2466                         # add return calls to    2453                         # add return calls to get the depth down
2467                         while prelinedep < se    2454                         while prelinedep < self.depth:
2468                                 self.depth -=    2455                                 self.depth -= 1
2469                                 if idx == 0 a    2456                                 if idx == 0 and last and last.isCall():
2470                                         # spe    2457                                         # special case, turn last call into a leaf
2471                                         last.    2458                                         last.depth = self.depth
2472                                         last.    2459                                         last.freturn = True
2473                                         last.    2460                                         last.length = line.time - last.time
2474                                         if wa    2461                                         if warning:
2475                                                  2462                                                 info.append(('[make leaf]', last))
2476                                 else:            2463                                 else:
2477                                         vline    2464                                         vline = FTraceLine(lasttime)
2478                                         vline    2465                                         vline.depth = self.depth
2479                                         vline    2466                                         vline.name = self.vfname
2480                                         vline    2467                                         vline.freturn = True
2481                                         self.    2468                                         self.list.append(vline)
2482                                         if wa    2469                                         if warning:
2483                                                  2470                                                 if idx == 0:
2484                                                  2471                                                         info.append(('', last))
2485                                                  2472                                                 info.append(('[add return]', vline))
2486                                 idx += 1         2473                                 idx += 1
2487                         if warning:              2474                         if warning:
2488                                 info.append((    2475                                 info.append(('', line))
2489                 # handle high misalignments b    2476                 # handle high misalignments by inserting calls
2490                 elif mismatch > 0:               2477                 elif mismatch > 0:
2491                         idx = 0                  2478                         idx = 0
2492                         if warning:              2479                         if warning:
2493                                 info.append((    2480                                 info.append(('', last))
2494                         # add calls to get th    2481                         # add calls to get the depth up
2495                         while prelinedep > se    2482                         while prelinedep > self.depth:
2496                                 if idx == 0 a    2483                                 if idx == 0 and line.isReturn():
2497                                         # spe    2484                                         # special case, turn this return into a leaf
2498                                         line.    2485                                         line.fcall = True
2499                                         preli    2486                                         prelinedep -= 1
2500                                         if wa    2487                                         if warning:
2501                                                  2488                                                 info.append(('[make leaf]', line))
2502                                 else:            2489                                 else:
2503                                         vline    2490                                         vline = FTraceLine(lasttime)
2504                                         vline    2491                                         vline.depth = self.depth
2505                                         vline    2492                                         vline.name = self.vfname
2506                                         vline    2493                                         vline.fcall = True
2507                                         self.    2494                                         self.list.append(vline)
2508                                         self.    2495                                         self.depth += 1
2509                                         if no    2496                                         if not last:
2510                                                  2497                                                 self.start = vline.time
2511                                         if wa    2498                                         if warning:
2512                                                  2499                                                 info.append(('[add call]', vline))
2513                                 idx += 1         2500                                 idx += 1
2514                         if warning and ('[mak    2501                         if warning and ('[make leaf]', line) not in info:
2515                                 info.append((    2502                                 info.append(('', line))
2516                 if warning:                      2503                 if warning:
2517                         pprint('WARNING: ftra    2504                         pprint('WARNING: ftrace data missing, corrections made:')
2518                         for i in info:           2505                         for i in info:
2519                                 t, obj = i       2506                                 t, obj = i
2520                                 if obj:          2507                                 if obj:
2521                                         obj.d    2508                                         obj.debugPrint(t)
2522                 # process the call and set th    2509                 # process the call and set the new depth
2523                 skipadd = False                  2510                 skipadd = False
2524                 md = self.sv.max_graph_depth     2511                 md = self.sv.max_graph_depth
2525                 if line.isCall():                2512                 if line.isCall():
2526                         # ignore blacklisted/    2513                         # ignore blacklisted/overdepth funcs
2527                         if (md and self.depth    2514                         if (md and self.depth >= md - 1) or (line.name in self.sv.cgblacklist):
2528                                 self.ignore =    2515                                 self.ignore = True
2529                         else:                    2516                         else:
2530                                 self.depth +=    2517                                 self.depth += 1
2531                 elif line.isReturn():            2518                 elif line.isReturn():
2532                         self.depth -= 1          2519                         self.depth -= 1
2533                         # remove blacklisted/    2520                         # remove blacklisted/overdepth/empty funcs that slipped through
2534                         if (last and last.isC    2521                         if (last and last.isCall() and last.depth == line.depth) or \
2535                                 (md and last     2522                                 (md and last and last.depth >= md) or \
2536                                 (line.name in    2523                                 (line.name in self.sv.cgblacklist):
2537                                 while len(sel    2524                                 while len(self.list) > 0 and self.list[-1].depth > line.depth:
2538                                         self.    2525                                         self.list.pop(-1)
2539                                 if len(self.l    2526                                 if len(self.list) == 0:
2540                                         self.    2527                                         self.invalid = True
2541                                         retur    2528                                         return 1
2542                                 self.list[-1]    2529                                 self.list[-1].freturn = True
2543                                 self.list[-1]    2530                                 self.list[-1].length = line.time - self.list[-1].time
2544                                 self.list[-1]    2531                                 self.list[-1].name = line.name
2545                                 skipadd = Tru    2532                                 skipadd = True
2546                 if len(self.list) < 1:           2533                 if len(self.list) < 1:
2547                         self.start = line.tim    2534                         self.start = line.time
2548                 # check for a mismatch that r    2535                 # check for a mismatch that returned all the way to callgraph end
2549                 res = 1                          2536                 res = 1
2550                 if mismatch < 0 and self.list    2537                 if mismatch < 0 and self.list[-1].depth == 0 and self.list[-1].freturn:
2551                         line = self.list[-1]     2538                         line = self.list[-1]
2552                         skipadd = True           2539                         skipadd = True
2553                         res = -1                 2540                         res = -1
2554                 if not skipadd:                  2541                 if not skipadd:
2555                         self.list.append(line    2542                         self.list.append(line)
2556                 if(line.depth == 0 and line.f    2543                 if(line.depth == 0 and line.freturn):
2557                         if(self.start < 0):      2544                         if(self.start < 0):
2558                                 self.start =     2545                                 self.start = line.time
2559                         self.end = line.time     2546                         self.end = line.time
2560                         if line.fcall:           2547                         if line.fcall:
2561                                 self.end += l    2548                                 self.end += line.length
2562                         if self.list[0].name     2549                         if self.list[0].name == self.vfname:
2563                                 self.invalid     2550                                 self.invalid = True
2564                         if res == -1:            2551                         if res == -1:
2565                                 self.partial     2552                                 self.partial = True
2566                         return res               2553                         return res
2567                 return 0                         2554                 return 0
2568         def invalidate(self, line):              2555         def invalidate(self, line):
2569                 if(len(self.list) > 0):          2556                 if(len(self.list) > 0):
2570                         first = self.list[0]     2557                         first = self.list[0]
2571                         self.list = []           2558                         self.list = []
2572                         self.list.append(firs    2559                         self.list.append(first)
2573                 self.invalid = True              2560                 self.invalid = True
2574                 id = 'task %s' % (self.pid)      2561                 id = 'task %s' % (self.pid)
2575                 window = '(%f - %f)' % (self.    2562                 window = '(%f - %f)' % (self.start, line.time)
2576                 if(self.depth < 0):              2563                 if(self.depth < 0):
2577                         pprint('Data misalign    2564                         pprint('Data misalignment for '+id+\
2578                                 ' (buffer ove    2565                                 ' (buffer overflow), ignoring this callback')
2579                 else:                            2566                 else:
2580                         pprint('Too much data    2567                         pprint('Too much data for '+id+\
2581                                 ' '+window+',    2568                                 ' '+window+', ignoring this callback')
2582         def slice(self, dev):                    2569         def slice(self, dev):
2583                 minicg = FTraceCallGraph(dev[    2570                 minicg = FTraceCallGraph(dev['pid'], self.sv)
2584                 minicg.name = self.name          2571                 minicg.name = self.name
2585                 mydepth = -1                     2572                 mydepth = -1
2586                 good = False                     2573                 good = False
2587                 for l in self.list:              2574                 for l in self.list:
2588                         if(l.time < dev['star    2575                         if(l.time < dev['start'] or l.time > dev['end']):
2589                                 continue         2576                                 continue
2590                         if mydepth < 0:          2577                         if mydepth < 0:
2591                                 if l.name ==     2578                                 if l.name == 'mutex_lock' and l.freturn:
2592                                         mydep    2579                                         mydepth = l.depth
2593                                 continue         2580                                 continue
2594                         elif l.depth == mydep    2581                         elif l.depth == mydepth and l.name == 'mutex_unlock' and l.fcall:
2595                                 good = True      2582                                 good = True
2596                                 break            2583                                 break
2597                         l.depth -= mydepth       2584                         l.depth -= mydepth
2598                         minicg.addLine(l)        2585                         minicg.addLine(l)
2599                 if not good or len(minicg.lis    2586                 if not good or len(minicg.list) < 1:
2600                         return 0                 2587                         return 0
2601                 return minicg                    2588                 return minicg
2602         def repair(self, enddepth):              2589         def repair(self, enddepth):
2603                 # bring the depth back to 0 w    2590                 # bring the depth back to 0 with additional returns
2604                 fixed = False                    2591                 fixed = False
2605                 last = self.list[-1]             2592                 last = self.list[-1]
2606                 for i in reversed(range(endde    2593                 for i in reversed(range(enddepth)):
2607                         t = FTraceLine(last.t    2594                         t = FTraceLine(last.time)
2608                         t.depth = i              2595                         t.depth = i
2609                         t.freturn = True         2596                         t.freturn = True
2610                         fixed = self.addLine(    2597                         fixed = self.addLine(t)
2611                         if fixed != 0:           2598                         if fixed != 0:
2612                                 self.end = la    2599                                 self.end = last.time
2613                                 return True      2600                                 return True
2614                 return False                     2601                 return False
2615         def postProcess(self):                   2602         def postProcess(self):
2616                 if len(self.list) > 0:           2603                 if len(self.list) > 0:
2617                         self.name = self.list    2604                         self.name = self.list[0].name
2618                 stack = dict()                   2605                 stack = dict()
2619                 cnt = 0                          2606                 cnt = 0
2620                 last = 0                         2607                 last = 0
2621                 for l in self.list:              2608                 for l in self.list:
2622                         # ftrace bug: reporte    2609                         # ftrace bug: reported duration is not reliable
2623                         # check each leaf and    2610                         # check each leaf and clip it at max possible length
2624                         if last and last.isLe    2611                         if last and last.isLeaf():
2625                                 if last.lengt    2612                                 if last.length > l.time - last.time:
2626                                         last.    2613                                         last.length = l.time - last.time
2627                         if l.isCall():           2614                         if l.isCall():
2628                                 stack[l.depth    2615                                 stack[l.depth] = l
2629                                 cnt += 1         2616                                 cnt += 1
2630                         elif l.isReturn():       2617                         elif l.isReturn():
2631                                 if(l.depth no    2618                                 if(l.depth not in stack):
2632                                         if se    2619                                         if self.sv.verbose:
2633                                                  2620                                                 pprint('Post Process Error: Depth missing')
2634                                                  2621                                                 l.debugPrint()
2635                                         retur    2622                                         return False
2636                                 # calculate c    2623                                 # calculate call length from call/return lines
2637                                 cl = stack[l.    2624                                 cl = stack[l.depth]
2638                                 cl.length = l    2625                                 cl.length = l.time - cl.time
2639                                 if cl.name ==    2626                                 if cl.name == self.vfname:
2640                                         cl.na    2627                                         cl.name = l.name
2641                                 stack.pop(l.d    2628                                 stack.pop(l.depth)
2642                                 l.length = 0     2629                                 l.length = 0
2643                                 cnt -= 1         2630                                 cnt -= 1
2644                         last = l                 2631                         last = l
2645                 if(cnt == 0):                    2632                 if(cnt == 0):
2646                         # trace caught the wh    2633                         # trace caught the whole call tree
2647                         return True              2634                         return True
2648                 elif(cnt < 0):                   2635                 elif(cnt < 0):
2649                         if self.sv.verbose:      2636                         if self.sv.verbose:
2650                                 pprint('Post     2637                                 pprint('Post Process Error: Depth is less than 0')
2651                         return False             2638                         return False
2652                 # trace ended before call tre    2639                 # trace ended before call tree finished
2653                 return self.repair(cnt)          2640                 return self.repair(cnt)
2654         def deviceMatch(self, pid, data):        2641         def deviceMatch(self, pid, data):
2655                 found = ''                       2642                 found = ''
2656                 # add the callgraph data to t    2643                 # add the callgraph data to the device hierarchy
2657                 borderphase = {                  2644                 borderphase = {
2658                         'dpm_prepare': 'suspe    2645                         'dpm_prepare': 'suspend_prepare',
2659                         'dpm_complete': 'resu    2646                         'dpm_complete': 'resume_complete'
2660                 }                                2647                 }
2661                 if(self.name in borderphase):    2648                 if(self.name in borderphase):
2662                         p = borderphase[self.    2649                         p = borderphase[self.name]
2663                         list = data.dmesg[p][    2650                         list = data.dmesg[p]['list']
2664                         for devname in list:     2651                         for devname in list:
2665                                 dev = list[de    2652                                 dev = list[devname]
2666                                 if(pid == dev    2653                                 if(pid == dev['pid'] and
2667                                         self.    2654                                         self.start <= dev['start'] and
2668                                         self.    2655                                         self.end >= dev['end']):
2669                                         cg =     2656                                         cg = self.slice(dev)
2670                                         if cg    2657                                         if cg:
2671                                                  2658                                                 dev['ftrace'] = cg
2672                                         found    2659                                         found = devname
2673                         return found             2660                         return found
2674                 for p in data.sortedPhases():    2661                 for p in data.sortedPhases():
2675                         if(data.dmesg[p]['sta    2662                         if(data.dmesg[p]['start'] <= self.start and
2676                                 self.start <=    2663                                 self.start <= data.dmesg[p]['end']):
2677                                 list = data.d    2664                                 list = data.dmesg[p]['list']
2678                                 for devname i    2665                                 for devname in sorted(list, key=lambda k:list[k]['start']):
2679                                         dev =    2666                                         dev = list[devname]
2680                                         if(pi    2667                                         if(pid == dev['pid'] and
2681                                                  2668                                                 self.start <= dev['start'] and
2682                                                  2669                                                 self.end >= dev['end']):
2683                                                  2670                                                 dev['ftrace'] = self
2684                                                  2671                                                 found = devname
2685                                                  2672                                                 break
2686                                 break            2673                                 break
2687                 return found                     2674                 return found
2688         def newActionFromFunction(self, data)    2675         def newActionFromFunction(self, data):
2689                 name = self.name                 2676                 name = self.name
2690                 if name in ['dpm_run_callback    2677                 if name in ['dpm_run_callback', 'dpm_prepare', 'dpm_complete']:
2691                         return                   2678                         return
2692                 fs = self.start                  2679                 fs = self.start
2693                 fe = self.end                    2680                 fe = self.end
2694                 if fs < data.start or fe > da    2681                 if fs < data.start or fe > data.end:
2695                         return                   2682                         return
2696                 phase = ''                       2683                 phase = ''
2697                 for p in data.sortedPhases():    2684                 for p in data.sortedPhases():
2698                         if(data.dmesg[p]['sta    2685                         if(data.dmesg[p]['start'] <= self.start and
2699                                 self.start <     2686                                 self.start < data.dmesg[p]['end']):
2700                                 phase = p        2687                                 phase = p
2701                                 break            2688                                 break
2702                 if not phase:                    2689                 if not phase:
2703                         return                   2690                         return
2704                 out = data.newActionGlobal(na    2691                 out = data.newActionGlobal(name, fs, fe, -2)
2705                 if out:                          2692                 if out:
2706                         phase, myname = out      2693                         phase, myname = out
2707                         data.dmesg[phase]['li    2694                         data.dmesg[phase]['list'][myname]['ftrace'] = self
2708         def debugPrint(self, info=''):           2695         def debugPrint(self, info=''):
2709                 pprint('%s pid=%d [%f - %f] %    2696                 pprint('%s pid=%d [%f - %f] %.3f us' % \
2710                         (self.name, self.pid,    2697                         (self.name, self.pid, self.start, self.end,
2711                         (self.end - self.star    2698                         (self.end - self.start)*1000000))
2712                 for l in self.list:              2699                 for l in self.list:
2713                         if l.isLeaf():           2700                         if l.isLeaf():
2714                                 pprint('%f (%    2701                                 pprint('%f (%02d): %s(); (%.3f us)%s' % (l.time, \
2715                                         l.dep    2702                                         l.depth, l.name, l.length*1000000, info))
2716                         elif l.freturn:          2703                         elif l.freturn:
2717                                 pprint('%f (%    2704                                 pprint('%f (%02d): %s} (%.3f us)%s' % (l.time, \
2718                                         l.dep    2705                                         l.depth, l.name, l.length*1000000, info))
2719                         else:                    2706                         else:
2720                                 pprint('%f (%    2707                                 pprint('%f (%02d): %s() { (%.3f us)%s' % (l.time, \
2721                                         l.dep    2708                                         l.depth, l.name, l.length*1000000, info))
2722                 pprint(' ')                      2709                 pprint(' ')
2723                                                  2710 
2724 class DevItem:                                   2711 class DevItem:
2725         def __init__(self, test, phase, dev):    2712         def __init__(self, test, phase, dev):
2726                 self.test = test                 2713                 self.test = test
2727                 self.phase = phase               2714                 self.phase = phase
2728                 self.dev = dev                   2715                 self.dev = dev
2729         def isa(self, cls):                      2716         def isa(self, cls):
2730                 if 'htmlclass' in self.dev an    2717                 if 'htmlclass' in self.dev and cls in self.dev['htmlclass']:
2731                         return True              2718                         return True
2732                 return False                     2719                 return False
2733                                                  2720 
2734 # Class: Timeline                                2721 # Class: Timeline
2735 # Description:                                   2722 # Description:
2736 #        A container for a device timeline wh    2723 #        A container for a device timeline which calculates
2737 #        all the html properties to display i    2724 #        all the html properties to display it correctly
2738 class Timeline:                                  2725 class Timeline:
2739         html_tblock = '<div id="block{0}" cla    2726         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="{    2727         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    2728         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=    2729         html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background:{3}"></div>\n'
2743         html_legend = '<div id="p{3}" class="    2730         html_legend = '<div id="p{3}" class="square" style="left:{0}%;background:{1}">&nbsp;{2}</div>\n'
2744         def __init__(self, rowheight, scalehe    2731         def __init__(self, rowheight, scaleheight):
2745                 self.html = ''                   2732                 self.html = ''
2746                 self.height = 0  # total time    2733                 self.height = 0  # total timeline height
2747                 self.scaleH = scaleheight # t    2734                 self.scaleH = scaleheight # timescale (top) row height
2748                 self.rowH = rowheight     # d    2735                 self.rowH = rowheight     # device row height
2749                 self.bodyH = 0   # body heigh    2736                 self.bodyH = 0   # body height
2750                 self.rows = 0    # total time    2737                 self.rows = 0    # total timeline rows
2751                 self.rowlines = dict()           2738                 self.rowlines = dict()
2752                 self.rowheight = dict()          2739                 self.rowheight = dict()
2753         def createHeader(self, sv, stamp):       2740         def createHeader(self, sv, stamp):
2754                 if(not stamp['time']):           2741                 if(not stamp['time']):
2755                         return                   2742                         return
2756                 self.html += '<div class="ver    2743                 self.html += '<div class="version"><a href="https://01.org/pm-graph">%s v%s</a></div>' \
2757                         % (sv.title, sv.versi    2744                         % (sv.title, sv.version)
2758                 if sv.logmsg and sv.testlog:     2745                 if sv.logmsg and sv.testlog:
2759                         self.html += '<button    2746                         self.html += '<button id="showtest" class="logbtn btnfmt">log</button>'
2760                 if sv.dmesglog:                  2747                 if sv.dmesglog:
2761                         self.html += '<button    2748                         self.html += '<button id="showdmesg" class="logbtn btnfmt">dmesg</button>'
2762                 if sv.ftracelog:                 2749                 if sv.ftracelog:
2763                         self.html += '<button    2750                         self.html += '<button id="showftrace" class="logbtn btnfmt">ftrace</button>'
2764                 headline_stamp = '<div class=    2751                 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n'
2765                 self.html += headline_stamp.f    2752                 self.html += headline_stamp.format(stamp['host'], stamp['kernel'],
2766                         stamp['mode'], stamp[    2753                         stamp['mode'], stamp['time'])
2767                 if 'man' in stamp and 'plat'     2754                 if 'man' in stamp and 'plat' in stamp and 'cpu' in stamp and \
2768                         stamp['man'] and stam    2755                         stamp['man'] and stamp['plat'] and stamp['cpu']:
2769                         headline_sysinfo = '<    2756                         headline_sysinfo = '<div class="stamp sysinfo">{0} {1} <i>with</i> {2}</div>\n'
2770                         self.html += headline    2757                         self.html += headline_sysinfo.format(stamp['man'], stamp['plat'], stamp['cpu'])
2771                                                  2758 
2772         # Function: getDeviceRows                2759         # Function: getDeviceRows
2773         # Description:                           2760         # Description:
2774         #    determine how may rows the devic    2761         #    determine how may rows the device funcs will take
2775         # Arguments:                             2762         # Arguments:
2776         #        rawlist: the list of devices    2763         #        rawlist: the list of devices/actions for a single phase
2777         # Output:                                2764         # Output:
2778         #        The total number of rows nee    2765         #        The total number of rows needed to display this phase of the timeline
2779         def getDeviceRows(self, rawlist):        2766         def getDeviceRows(self, rawlist):
2780                 # clear all rows and set them    2767                 # clear all rows and set them to undefined
2781                 sortdict = dict()                2768                 sortdict = dict()
2782                 for item in rawlist:             2769                 for item in rawlist:
2783                         item.row = -1            2770                         item.row = -1
2784                         sortdict[item] = item    2771                         sortdict[item] = item.length
2785                 sortlist = sorted(sortdict, k    2772                 sortlist = sorted(sortdict, key=sortdict.get, reverse=True)
2786                 remaining = len(sortlist)        2773                 remaining = len(sortlist)
2787                 rowdata = dict()                 2774                 rowdata = dict()
2788                 row = 1                          2775                 row = 1
2789                 # try to pack each row with a    2776                 # try to pack each row with as many ranges as possible
2790                 while(remaining > 0):            2777                 while(remaining > 0):
2791                         if(row not in rowdata    2778                         if(row not in rowdata):
2792                                 rowdata[row]     2779                                 rowdata[row] = []
2793                         for i in sortlist:       2780                         for i in sortlist:
2794                                 if(i.row >= 0    2781                                 if(i.row >= 0):
2795                                         conti    2782                                         continue
2796                                 s = i.time       2783                                 s = i.time
2797                                 e = i.time +     2784                                 e = i.time + i.length
2798                                 valid = True     2785                                 valid = True
2799                                 for ritem in     2786                                 for ritem in rowdata[row]:
2800                                         rs =     2787                                         rs = ritem.time
2801                                         re =     2788                                         re = ritem.time + ritem.length
2802                                         if(no    2789                                         if(not (((s <= rs) and (e <= rs)) or
2803                                                  2790                                                 ((s >= re) and (e >= re)))):
2804                                                  2791                                                 valid = False
2805                                                  2792                                                 break
2806                                 if(valid):       2793                                 if(valid):
2807                                         rowda    2794                                         rowdata[row].append(i)
2808                                         i.row    2795                                         i.row = row
2809                                         remai    2796                                         remaining -= 1
2810                         row += 1                 2797                         row += 1
2811                 return row                       2798                 return row
2812         # Function: getPhaseRows                 2799         # Function: getPhaseRows
2813         # Description:                           2800         # Description:
2814         #        Organize the timeline entrie    2801         #        Organize the timeline entries into the smallest
2815         #        number of rows possible, wit    2802         #        number of rows possible, with no entry overlapping
2816         # Arguments:                             2803         # Arguments:
2817         #        devlist: the list of devices    2804         #        devlist: the list of devices/actions in a group of contiguous phases
2818         # Output:                                2805         # Output:
2819         #        The total number of rows nee    2806         #        The total number of rows needed to display this phase of the timeline
2820         def getPhaseRows(self, devlist, row=0    2807         def getPhaseRows(self, devlist, row=0, sortby='length'):
2821                 # clear all rows and set them    2808                 # clear all rows and set them to undefined
2822                 remaining = len(devlist)         2809                 remaining = len(devlist)
2823                 rowdata = dict()                 2810                 rowdata = dict()
2824                 sortdict = dict()                2811                 sortdict = dict()
2825                 myphases = []                    2812                 myphases = []
2826                 # initialize all device rows     2813                 # initialize all device rows to -1 and calculate devrows
2827                 for item in devlist:             2814                 for item in devlist:
2828                         dev = item.dev           2815                         dev = item.dev
2829                         tp = (item.test, item    2816                         tp = (item.test, item.phase)
2830                         if tp not in myphases    2817                         if tp not in myphases:
2831                                 myphases.appe    2818                                 myphases.append(tp)
2832                         dev['row'] = -1          2819                         dev['row'] = -1
2833                         if sortby == 'start':    2820                         if sortby == 'start':
2834                                 # sort by sta    2821                                 # sort by start 1st, then length 2nd
2835                                 sortdict[item    2822                                 sortdict[item] = (-1*float(dev['start']), float(dev['end']) - float(dev['start']))
2836                         else:                    2823                         else:
2837                                 # sort by len    2824                                 # sort by length 1st, then name 2nd
2838                                 sortdict[item    2825                                 sortdict[item] = (float(dev['end']) - float(dev['start']), item.dev['name'])
2839                         if 'src' in dev:         2826                         if 'src' in dev:
2840                                 dev['devrows'    2827                                 dev['devrows'] = self.getDeviceRows(dev['src'])
2841                 # sort the devlist by length     2828                 # sort the devlist by length so that large items graph on top
2842                 sortlist = sorted(sortdict, k    2829                 sortlist = sorted(sortdict, key=sortdict.get, reverse=True)
2843                 orderedlist = []                 2830                 orderedlist = []
2844                 for item in sortlist:            2831                 for item in sortlist:
2845                         if item.dev['pid'] ==    2832                         if item.dev['pid'] == -2:
2846                                 orderedlist.a    2833                                 orderedlist.append(item)
2847                 for item in sortlist:            2834                 for item in sortlist:
2848                         if item not in ordere    2835                         if item not in orderedlist:
2849                                 orderedlist.a    2836                                 orderedlist.append(item)
2850                 # try to pack each row with a    2837                 # try to pack each row with as many devices as possible
2851                 while(remaining > 0):            2838                 while(remaining > 0):
2852                         rowheight = 1            2839                         rowheight = 1
2853                         if(row not in rowdata    2840                         if(row not in rowdata):
2854                                 rowdata[row]     2841                                 rowdata[row] = []
2855                         for item in orderedli    2842                         for item in orderedlist:
2856                                 dev = item.de    2843                                 dev = item.dev
2857                                 if(dev['row']    2844                                 if(dev['row'] < 0):
2858                                         s = d    2845                                         s = dev['start']
2859                                         e = d    2846                                         e = dev['end']
2860                                         valid    2847                                         valid = True
2861                                         for r    2848                                         for ritem in rowdata[row]:
2862                                                  2849                                                 rs = ritem.dev['start']
2863                                                  2850                                                 re = ritem.dev['end']
2864                                                  2851                                                 if(not (((s <= rs) and (e <= rs)) or
2865                                                  2852                                                         ((s >= re) and (e >= re)))):
2866                                                  2853                                                         valid = False
2867                                                  2854                                                         break
2868                                         if(va    2855                                         if(valid):
2869                                                  2856                                                 rowdata[row].append(item)
2870                                                  2857                                                 dev['row'] = row
2871                                                  2858                                                 remaining -= 1
2872                                                  2859                                                 if 'devrows' in dev and dev['devrows'] > rowheight:
2873                                                  2860                                                         rowheight = dev['devrows']
2874                         for t, p in myphases:    2861                         for t, p in myphases:
2875                                 if t not in s    2862                                 if t not in self.rowlines or t not in self.rowheight:
2876                                         self.    2863                                         self.rowlines[t] = dict()
2877                                         self.    2864                                         self.rowheight[t] = dict()
2878                                 if p not in s    2865                                 if p not in self.rowlines[t] or p not in self.rowheight[t]:
2879                                         self.    2866                                         self.rowlines[t][p] = dict()
2880                                         self.    2867                                         self.rowheight[t][p] = dict()
2881                                 rh = self.row    2868                                 rh = self.rowH
2882                                 # section hea    2869                                 # section headers should use a different row height
2883                                 if len(rowdat    2870                                 if len(rowdata[row]) == 1 and \
2884                                         'html    2871                                         'htmlclass' in rowdata[row][0].dev and \
2885                                         'sec'    2872                                         'sec' in rowdata[row][0].dev['htmlclass']:
2886                                         rh =     2873                                         rh = 15
2887                                 self.rowlines    2874                                 self.rowlines[t][p][row] = rowheight
2888                                 self.rowheigh    2875                                 self.rowheight[t][p][row] = rowheight * rh
2889                         row += 1                 2876                         row += 1
2890                 if(row > self.rows):             2877                 if(row > self.rows):
2891                         self.rows = int(row)     2878                         self.rows = int(row)
2892                 return row                       2879                 return row
2893         def phaseRowHeight(self, test, phase,    2880         def phaseRowHeight(self, test, phase, row):
2894                 return self.rowheight[test][p    2881                 return self.rowheight[test][phase][row]
2895         def phaseRowTop(self, test, phase, ro    2882         def phaseRowTop(self, test, phase, row):
2896                 top = 0                          2883                 top = 0
2897                 for i in sorted(self.rowheigh    2884                 for i in sorted(self.rowheight[test][phase]):
2898                         if i >= row:             2885                         if i >= row:
2899                                 break            2886                                 break
2900                         top += self.rowheight    2887                         top += self.rowheight[test][phase][i]
2901                 return top                       2888                 return top
2902         def calcTotalRows(self):                 2889         def calcTotalRows(self):
2903                 # Calculate the heights and o    2890                 # Calculate the heights and offsets for the header and rows
2904                 maxrows = 0                      2891                 maxrows = 0
2905                 standardphases = []              2892                 standardphases = []
2906                 for t in self.rowlines:          2893                 for t in self.rowlines:
2907                         for p in self.rowline    2894                         for p in self.rowlines[t]:
2908                                 total = 0        2895                                 total = 0
2909                                 for i in sort    2896                                 for i in sorted(self.rowlines[t][p]):
2910                                         total    2897                                         total += self.rowlines[t][p][i]
2911                                 if total > ma    2898                                 if total > maxrows:
2912                                         maxro    2899                                         maxrows = total
2913                                 if total == l    2900                                 if total == len(self.rowlines[t][p]):
2914                                         stand    2901                                         standardphases.append((t, p))
2915                 self.height = self.scaleH + (    2902                 self.height = self.scaleH + (maxrows*self.rowH)
2916                 self.bodyH = self.height - se    2903                 self.bodyH = self.height - self.scaleH
2917                 # if there is 1 line per row,    2904                 # if there is 1 line per row, draw them the standard way
2918                 for t, p in standardphases:      2905                 for t, p in standardphases:
2919                         for i in sorted(self.    2906                         for i in sorted(self.rowheight[t][p]):
2920                                 self.rowheigh    2907                                 self.rowheight[t][p][i] = float(self.bodyH)/len(self.rowlines[t][p])
2921         def createZoomBox(self, mode='command    2908         def createZoomBox(self, mode='command', testcount=1):
2922                 # Create bounding box, add bu    2909                 # Create bounding box, add buttons
2923                 html_zoombox = '<center><butt    2910                 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    2911                 html_timeline = '<div id="dmesgzoombox" class="zoombox">\n<div id="{0}" class="timeline" style="height:{1}px">\n'
2925                 html_devlist1 = '<button id="    2912                 html_devlist1 = '<button id="devlist1" class="devlist" style="float:left;">Device Detail{0}</button>'
2926                 html_devlist2 = '<button id="    2913                 html_devlist2 = '<button id="devlist2" class="devlist" style="float:right;">Device Detail2</button>\n'
2927                 if mode != 'command':            2914                 if mode != 'command':
2928                         if testcount > 1:        2915                         if testcount > 1:
2929                                 self.html +=     2916                                 self.html += html_devlist2
2930                                 self.html +=     2917                                 self.html += html_devlist1.format('1')
2931                         else:                    2918                         else:
2932                                 self.html +=     2919                                 self.html += html_devlist1.format('')
2933                 self.html += html_zoombox        2920                 self.html += html_zoombox
2934                 self.html += html_timeline.fo    2921                 self.html += html_timeline.format('dmesg', self.height)
2935         # Function: createTimeScale              2922         # Function: createTimeScale
2936         # Description:                           2923         # Description:
2937         #        Create the timescale for a t    2924         #        Create the timescale for a timeline block
2938         # Arguments:                             2925         # Arguments:
2939         #        m0: start time (mode begin)     2926         #        m0: start time (mode begin)
2940         #        mMax: end time (mode end)       2927         #        mMax: end time (mode end)
2941         #        tTotal: total timeline time     2928         #        tTotal: total timeline time
2942         #        mode: suspend or resume         2929         #        mode: suspend or resume
2943         # Output:                                2930         # Output:
2944         #        The html code needed to disp    2931         #        The html code needed to display the time scale
2945         def createTimeScale(self, m0, mMax, t    2932         def createTimeScale(self, m0, mMax, tTotal, mode):
2946                 timescale = '<div class="t" s    2933                 timescale = '<div class="t" style="right:{0}%">{1}</div>\n'
2947                 rline = '<div class="t" style    2934                 rline = '<div class="t" style="left:0;border-left:1px solid black;border-right:0;">{0}</div>\n'
2948                 output = '<div class="timesca    2935                 output = '<div class="timescale">\n'
2949                 # set scale for timeline         2936                 # set scale for timeline
2950                 mTotal = mMax - m0               2937                 mTotal = mMax - m0
2951                 tS = 0.1                         2938                 tS = 0.1
2952                 if(tTotal <= 0):                 2939                 if(tTotal <= 0):
2953                         return output+'</div>    2940                         return output+'</div>\n'
2954                 if(tTotal > 4):                  2941                 if(tTotal > 4):
2955                         tS = 1                   2942                         tS = 1
2956                 divTotal = int(mTotal/tS) + 1    2943                 divTotal = int(mTotal/tS) + 1
2957                 divEdge = (mTotal - tS*(divTo    2944                 divEdge = (mTotal - tS*(divTotal-1))*100/mTotal
2958                 for i in range(divTotal):        2945                 for i in range(divTotal):
2959                         htmlline = ''            2946                         htmlline = ''
2960                         if(mode == 'suspend')    2947                         if(mode == 'suspend'):
2961                                 pos = '%0.3f'    2948                                 pos = '%0.3f' % (100 - ((float(i)*tS*100)/mTotal) - divEdge)
2962                                 val = '%0.fms    2949                                 val = '%0.fms' % (float(i-divTotal+1)*tS*1000)
2963                                 if(i == divTo    2950                                 if(i == divTotal - 1):
2964                                         val =    2951                                         val = mode
2965                                 htmlline = ti    2952                                 htmlline = timescale.format(pos, val)
2966                         else:                    2953                         else:
2967                                 pos = '%0.3f'    2954                                 pos = '%0.3f' % (100 - ((float(i)*tS*100)/mTotal))
2968                                 val = '%0.fms    2955                                 val = '%0.fms' % (float(i)*tS*1000)
2969                                 htmlline = ti    2956                                 htmlline = timescale.format(pos, val)
2970                                 if(i == 0):      2957                                 if(i == 0):
2971                                         htmll    2958                                         htmlline = rline.format(mode)
2972                         output += htmlline       2959                         output += htmlline
2973                 self.html += output+'</div>\n    2960                 self.html += output+'</div>\n'
2974                                                  2961 
2975 # Class: TestProps                               2962 # Class: TestProps
2976 # Description:                                   2963 # Description:
2977 #        A list of values describing the prop    2964 #        A list of values describing the properties of these test runs
2978 class TestProps:                                 2965 class TestProps:
2979         stampfmt = r'# [a-z]*-(?P<m>[0-9]{2}) !! 2966         stampfmt = '# [a-z]*-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\
2980                                 r'(?P<H>[0-9] !! 2967                                 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\
2981                                 r' (?P<host>. !! 2968                                 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
2982         wififmt    = r'^# wifi *(?P<d>\S*) *( !! 2969         wififmt    = '^# wifi *(?P<d>\S*) *(?P<s>\S*) *(?P<t>[0-9\.]+).*'
2983         tstatfmt   = r'^# turbostat (?P<t>\S* !! 2970         tstatfmt   = '^# turbostat (?P<t>\S*)'
2984         testerrfmt = r'^# enter_sleep_error ( !! 2971         testerrfmt = '^# enter_sleep_error (?P<e>.*)'
2985         sysinfofmt = r'^# sysinfo .*'         !! 2972         sysinfofmt = '^# sysinfo .*'
2986         cmdlinefmt = r'^# command \| (?P<cmd> !! 2973         cmdlinefmt = '^# command \| (?P<cmd>.*)'
2987         kparamsfmt = r'^# kparams \| (?P<kp>. !! 2974         kparamsfmt = '^# kparams \| (?P<kp>.*)'
2988         devpropfmt = r'# Device Properties: . !! 2975         devpropfmt = '# Device Properties: .*'
2989         pinfofmt   = r'# platform-(?P<val>[a- !! 2976         pinfofmt   = '# platform-(?P<val>[a-z,A-Z,0-9,_]*): (?P<info>.*)'
2990         tracertypefmt = r'# tracer: (?P<t>.*) !! 2977         tracertypefmt = '# tracer: (?P<t>.*)'
2991         firmwarefmt = r'# fwsuspend (?P<s>[0- !! 2978         firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$'
2992         procexecfmt = r'ps - (?P<ps>.*)$'     !! 2979         procexecfmt = 'ps - (?P<ps>.*)$'
2993         procmultifmt = r'@(?P<n>[0-9]*)\|(?P< !! 2980         procmultifmt = '@(?P<n>[0-9]*)\|(?P<ps>.*)$'
2994         ftrace_line_fmt_fg = \                   2981         ftrace_line_fmt_fg = \
2995                 r'^ *(?P<time>[0-9\.]*) *\| * !! 2982                 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\
2996                 r' *(?P<proc>.*)-(?P<pid>[0-9 !! 2983                 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\
2997                 r'[ +!#\*@$]*(?P<dur>[0-9\.]* !! 2984                 '[ +!#\*@$]*(?P<dur>[0-9\.]*) .*\|  (?P<msg>.*)'
2998         ftrace_line_fmt_nop = \                  2985         ftrace_line_fmt_nop = \
2999                 r' *(?P<proc>.*)-(?P<pid>[0-9 !! 2986                 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\[(?P<cpu>[0-9]*)\] *'+\
3000                 r'(?P<flags>\S*) *(?P<time>[0 !! 2987                 '(?P<flags>\S*) *(?P<time>[0-9\.]*): *'+\
3001                 r'(?P<msg>.*)'                !! 2988                 '(?P<msg>.*)'
3002         machinesuspend = r'machine_suspend\[. !! 2989         machinesuspend = 'machine_suspend\[.*'
3003         multiproclist = dict()                   2990         multiproclist = dict()
3004         multiproctime = 0.0                      2991         multiproctime = 0.0
3005         multiproccnt = 0                         2992         multiproccnt = 0
3006         def __init__(self):                      2993         def __init__(self):
3007                 self.stamp = ''                  2994                 self.stamp = ''
3008                 self.sysinfo = ''                2995                 self.sysinfo = ''
3009                 self.cmdline = ''                2996                 self.cmdline = ''
3010                 self.testerror = []              2997                 self.testerror = []
3011                 self.turbostat = []              2998                 self.turbostat = []
3012                 self.wifi = []                   2999                 self.wifi = []
3013                 self.fwdata = []                 3000                 self.fwdata = []
3014                 self.ftrace_line_fmt = self.f    3001                 self.ftrace_line_fmt = self.ftrace_line_fmt_nop
3015                 self.cgformat = False            3002                 self.cgformat = False
3016                 self.data = 0                    3003                 self.data = 0
3017                 self.ktemp = dict()              3004                 self.ktemp = dict()
3018         def setTracerType(self, tracer):         3005         def setTracerType(self, tracer):
3019                 if(tracer == 'function_graph'    3006                 if(tracer == 'function_graph'):
3020                         self.cgformat = True     3007                         self.cgformat = True
3021                         self.ftrace_line_fmt     3008                         self.ftrace_line_fmt = self.ftrace_line_fmt_fg
3022                 elif(tracer == 'nop'):           3009                 elif(tracer == 'nop'):
3023                         self.ftrace_line_fmt     3010                         self.ftrace_line_fmt = self.ftrace_line_fmt_nop
3024                 else:                            3011                 else:
3025                         doError('Invalid trac    3012                         doError('Invalid tracer format: [%s]' % tracer)
3026         def stampInfo(self, line, sv):           3013         def stampInfo(self, line, sv):
3027                 if re.match(self.stampfmt, li    3014                 if re.match(self.stampfmt, line):
3028                         self.stamp = line        3015                         self.stamp = line
3029                         return True              3016                         return True
3030                 elif re.match(self.sysinfofmt    3017                 elif re.match(self.sysinfofmt, line):
3031                         self.sysinfo = line      3018                         self.sysinfo = line
3032                         return True              3019                         return True
3033                 elif re.match(self.tstatfmt,     3020                 elif re.match(self.tstatfmt, line):
3034                         self.turbostat.append    3021                         self.turbostat.append(line)
3035                         return True              3022                         return True
3036                 elif re.match(self.wififmt, l    3023                 elif re.match(self.wififmt, line):
3037                         self.wifi.append(line    3024                         self.wifi.append(line)
3038                         return True              3025                         return True
3039                 elif re.match(self.testerrfmt    3026                 elif re.match(self.testerrfmt, line):
3040                         self.testerror.append    3027                         self.testerror.append(line)
3041                         return True              3028                         return True
3042                 elif re.match(self.firmwarefm    3029                 elif re.match(self.firmwarefmt, line):
3043                         self.fwdata.append(li    3030                         self.fwdata.append(line)
3044                         return True              3031                         return True
3045                 elif(re.match(self.devpropfmt    3032                 elif(re.match(self.devpropfmt, line)):
3046                         self.parseDevprops(li    3033                         self.parseDevprops(line, sv)
3047                         return True              3034                         return True
3048                 elif(re.match(self.pinfofmt,     3035                 elif(re.match(self.pinfofmt, line)):
3049                         self.parsePlatformInf    3036                         self.parsePlatformInfo(line, sv)
3050                         return True              3037                         return True
3051                 m = re.match(self.cmdlinefmt,    3038                 m = re.match(self.cmdlinefmt, line)
3052                 if m:                            3039                 if m:
3053                         self.cmdline = m.grou    3040                         self.cmdline = m.group('cmd')
3054                         return True              3041                         return True
3055                 m = re.match(self.tracertypef    3042                 m = re.match(self.tracertypefmt, line)
3056                 if(m):                           3043                 if(m):
3057                         self.setTracerType(m.    3044                         self.setTracerType(m.group('t'))
3058                         return True              3045                         return True
3059                 return False                     3046                 return False
3060         def parseStamp(self, data, sv):          3047         def parseStamp(self, data, sv):
3061                 # global test data               3048                 # global test data
3062                 m = re.match(self.stampfmt, s    3049                 m = re.match(self.stampfmt, self.stamp)
3063                 if not self.stamp or not m:      3050                 if not self.stamp or not m:
3064                         doError('data does no    3051                         doError('data does not include the expected stamp')
3065                 data.stamp = {'time': '', 'ho    3052                 data.stamp = {'time': '', 'host': '', 'mode': ''}
3066                 dt = datetime(int(m.group('y'    3053                 dt = datetime(int(m.group('y'))+2000, int(m.group('m')),
3067                         int(m.group('d')), in    3054                         int(m.group('d')), int(m.group('H')), int(m.group('M')),
3068                         int(m.group('S')))       3055                         int(m.group('S')))
3069                 data.stamp['time'] = dt.strft    3056                 data.stamp['time'] = dt.strftime('%B %d %Y, %I:%M:%S %p')
3070                 data.stamp['host'] = m.group(    3057                 data.stamp['host'] = m.group('host')
3071                 data.stamp['mode'] = m.group(    3058                 data.stamp['mode'] = m.group('mode')
3072                 data.stamp['kernel'] = m.grou    3059                 data.stamp['kernel'] = m.group('kernel')
3073                 if re.match(self.sysinfofmt,     3060                 if re.match(self.sysinfofmt, self.sysinfo):
3074                         for f in self.sysinfo    3061                         for f in self.sysinfo.split('|'):
3075                                 if '#' in f:     3062                                 if '#' in f:
3076                                         conti    3063                                         continue
3077                                 tmp = f.strip    3064                                 tmp = f.strip().split(':', 1)
3078                                 key = tmp[0]     3065                                 key = tmp[0]
3079                                 val = tmp[1]     3066                                 val = tmp[1]
3080                                 data.stamp[ke    3067                                 data.stamp[key] = val
3081                 sv.hostname = data.stamp['hos    3068                 sv.hostname = data.stamp['host']
3082                 sv.suspendmode = data.stamp['    3069                 sv.suspendmode = data.stamp['mode']
3083                 if sv.suspendmode == 'freeze'    3070                 if sv.suspendmode == 'freeze':
3084                         self.machinesuspend = !! 3071                         self.machinesuspend = 'timekeeping_freeze\[.*'
3085                 else:                            3072                 else:
3086                         self.machinesuspend = !! 3073                         self.machinesuspend = 'machine_suspend\[.*'
3087                 if sv.suspendmode == 'command    3074                 if sv.suspendmode == 'command' and sv.ftracefile != '':
3088                         modes = ['on', 'freez    3075                         modes = ['on', 'freeze', 'standby', 'mem', 'disk']
3089                         fp = sv.openlog(sv.ft    3076                         fp = sv.openlog(sv.ftracefile, 'r')
3090                         for line in fp:          3077                         for line in fp:
3091                                 m = re.match( !! 3078                                 m = re.match('.* machine_suspend\[(?P<mode>.*)\]', line)
3092                                 if m and m.gr    3079                                 if m and m.group('mode') in ['1', '2', '3', '4']:
3093                                         sv.su    3080                                         sv.suspendmode = modes[int(m.group('mode'))]
3094                                         data.    3081                                         data.stamp['mode'] = sv.suspendmode
3095                                         break    3082                                         break
3096                         fp.close()               3083                         fp.close()
3097                 sv.cmdline = self.cmdline        3084                 sv.cmdline = self.cmdline
3098                 if not sv.stamp:                 3085                 if not sv.stamp:
3099                         sv.stamp = data.stamp    3086                         sv.stamp = data.stamp
3100                 # firmware data                  3087                 # firmware data
3101                 if sv.suspendmode == 'mem' an    3088                 if sv.suspendmode == 'mem' and len(self.fwdata) > data.testnumber:
3102                         m = re.match(self.fir    3089                         m = re.match(self.firmwarefmt, self.fwdata[data.testnumber])
3103                         if m:                    3090                         if m:
3104                                 data.fwSuspen    3091                                 data.fwSuspend, data.fwResume = int(m.group('s')), int(m.group('r'))
3105                                 if(data.fwSus    3092                                 if(data.fwSuspend > 0 or data.fwResume > 0):
3106                                         data.    3093                                         data.fwValid = True
3107                 # turbostat data                 3094                 # turbostat data
3108                 if len(self.turbostat) > data    3095                 if len(self.turbostat) > data.testnumber:
3109                         m = re.match(self.tst    3096                         m = re.match(self.tstatfmt, self.turbostat[data.testnumber])
3110                         if m:                    3097                         if m:
3111                                 data.turbosta    3098                                 data.turbostat = m.group('t')
3112                 # wifi data                      3099                 # wifi data
3113                 if len(self.wifi) > data.test    3100                 if len(self.wifi) > data.testnumber:
3114                         m = re.match(self.wif    3101                         m = re.match(self.wififmt, self.wifi[data.testnumber])
3115                         if m:                    3102                         if m:
3116                                 data.wifi = {    3103                                 data.wifi = {'dev': m.group('d'), 'stat': m.group('s'),
3117                                         'time    3104                                         'time': float(m.group('t'))}
3118                                 data.stamp['w    3105                                 data.stamp['wifi'] = m.group('d')
3119                 # sleep mode enter errors        3106                 # sleep mode enter errors
3120                 if len(self.testerror) > data    3107                 if len(self.testerror) > data.testnumber:
3121                         m = re.match(self.tes    3108                         m = re.match(self.testerrfmt, self.testerror[data.testnumber])
3122                         if m:                    3109                         if m:
3123                                 data.enterfai    3110                                 data.enterfail = m.group('e')
3124         def devprops(self, data):                3111         def devprops(self, data):
3125                 props = dict()                   3112                 props = dict()
3126                 devlist = data.split(';')        3113                 devlist = data.split(';')
3127                 for dev in devlist:              3114                 for dev in devlist:
3128                         f = dev.split(',')       3115                         f = dev.split(',')
3129                         if len(f) < 3:           3116                         if len(f) < 3:
3130                                 continue         3117                                 continue
3131                         dev = f[0]               3118                         dev = f[0]
3132                         props[dev] = DevProps    3119                         props[dev] = DevProps()
3133                         props[dev].altname =     3120                         props[dev].altname = f[1]
3134                         if int(f[2]):            3121                         if int(f[2]):
3135                                 props[dev].is    3122                                 props[dev].isasync = True
3136                         else:                    3123                         else:
3137                                 props[dev].is    3124                                 props[dev].isasync = False
3138                 return props                     3125                 return props
3139         def parseDevprops(self, line, sv):       3126         def parseDevprops(self, line, sv):
3140                 idx = line.index(': ') + 2       3127                 idx = line.index(': ') + 2
3141                 if idx >= len(line):             3128                 if idx >= len(line):
3142                         return                   3129                         return
3143                 props = self.devprops(line[id    3130                 props = self.devprops(line[idx:])
3144                 if sv.suspendmode == 'command    3131                 if sv.suspendmode == 'command' and 'testcommandstring' in props:
3145                         sv.testcommand = prop    3132                         sv.testcommand = props['testcommandstring'].altname
3146                 sv.devprops = props              3133                 sv.devprops = props
3147         def parsePlatformInfo(self, line, sv)    3134         def parsePlatformInfo(self, line, sv):
3148                 m = re.match(self.pinfofmt, l    3135                 m = re.match(self.pinfofmt, line)
3149                 if not m:                        3136                 if not m:
3150                         return                   3137                         return
3151                 name, info = m.group('val'),     3138                 name, info = m.group('val'), m.group('info')
3152                 if name == 'devinfo':            3139                 if name == 'devinfo':
3153                         sv.devprops = self.de    3140                         sv.devprops = self.devprops(sv.b64unzip(info))
3154                         return                   3141                         return
3155                 elif name == 'testcmd':          3142                 elif name == 'testcmd':
3156                         sv.testcommand = info    3143                         sv.testcommand = info
3157                         return                   3144                         return
3158                 field = info.split('|')          3145                 field = info.split('|')
3159                 if len(field) < 2:               3146                 if len(field) < 2:
3160                         return                   3147                         return
3161                 cmdline = field[0].strip()       3148                 cmdline = field[0].strip()
3162                 output = sv.b64unzip(field[1]    3149                 output = sv.b64unzip(field[1].strip())
3163                 sv.platinfo.append([name, cmd    3150                 sv.platinfo.append([name, cmdline, output])
3164                                                  3151 
3165 # Class: TestRun                                 3152 # Class: TestRun
3166 # Description:                                   3153 # Description:
3167 #        A container for a suspend/resume tes    3154 #        A container for a suspend/resume test run. This is necessary as
3168 #        there could be more than one, and th    3155 #        there could be more than one, and they need to be separate.
3169 class TestRun:                                   3156 class TestRun:
3170         def __init__(self, dataobj):             3157         def __init__(self, dataobj):
3171                 self.data = dataobj              3158                 self.data = dataobj
3172                 self.ftemp = dict()              3159                 self.ftemp = dict()
3173                 self.ttemp = dict()              3160                 self.ttemp = dict()
3174                                                  3161 
3175 class ProcessMonitor:                            3162 class ProcessMonitor:
3176         maxchars = 512                           3163         maxchars = 512
3177         def __init__(self):                      3164         def __init__(self):
3178                 self.proclist = dict()           3165                 self.proclist = dict()
3179                 self.running = False             3166                 self.running = False
3180         def procstat(self):                      3167         def procstat(self):
3181                 c = ['cat /proc/[1-9]*/stat 2    3168                 c = ['cat /proc/[1-9]*/stat 2>/dev/null']
3182                 process = Popen(c, shell=True    3169                 process = Popen(c, shell=True, stdout=PIPE)
3183                 running = dict()                 3170                 running = dict()
3184                 for line in process.stdout:      3171                 for line in process.stdout:
3185                         data = ascii(line).sp    3172                         data = ascii(line).split()
3186                         pid = data[0]            3173                         pid = data[0]
3187                         name = re.sub('[()]',    3174                         name = re.sub('[()]', '', data[1])
3188                         user = int(data[13])     3175                         user = int(data[13])
3189                         kern = int(data[14])     3176                         kern = int(data[14])
3190                         kjiff = ujiff = 0        3177                         kjiff = ujiff = 0
3191                         if pid not in self.pr    3178                         if pid not in self.proclist:
3192                                 self.proclist    3179                                 self.proclist[pid] = {'name' : name, 'user' : user, 'kern' : kern}
3193                         else:                    3180                         else:
3194                                 val = self.pr    3181                                 val = self.proclist[pid]
3195                                 ujiff = user     3182                                 ujiff = user - val['user']
3196                                 kjiff = kern     3183                                 kjiff = kern - val['kern']
3197                                 val['user'] =    3184                                 val['user'] = user
3198                                 val['kern'] =    3185                                 val['kern'] = kern
3199                         if ujiff > 0 or kjiff    3186                         if ujiff > 0 or kjiff > 0:
3200                                 running[pid]     3187                                 running[pid] = ujiff + kjiff
3201                 process.wait()                   3188                 process.wait()
3202                 out = ['']                       3189                 out = ['']
3203                 for pid in running:              3190                 for pid in running:
3204                         jiffies = running[pid    3191                         jiffies = running[pid]
3205                         val = self.proclist[p    3192                         val = self.proclist[pid]
3206                         if len(out[-1]) > sel    3193                         if len(out[-1]) > self.maxchars:
3207                                 out.append(''    3194                                 out.append('')
3208                         elif len(out[-1]) > 0    3195                         elif len(out[-1]) > 0:
3209                                 out[-1] += ',    3196                                 out[-1] += ','
3210                         out[-1] += '%s-%s %d'    3197                         out[-1] += '%s-%s %d' % (val['name'], pid, jiffies)
3211                 if len(out) > 1:                 3198                 if len(out) > 1:
3212                         for line in out:         3199                         for line in out:
3213                                 sysvals.fsetV    3200                                 sysvals.fsetVal('ps - @%d|%s' % (len(out), line), 'trace_marker')
3214                 else:                            3201                 else:
3215                         sysvals.fsetVal('ps -    3202                         sysvals.fsetVal('ps - %s' % out[0], 'trace_marker')
3216         def processMonitor(self, tid):           3203         def processMonitor(self, tid):
3217                 while self.running:              3204                 while self.running:
3218                         self.procstat()          3205                         self.procstat()
3219         def start(self):                         3206         def start(self):
3220                 self.thread = Thread(target=s    3207                 self.thread = Thread(target=self.processMonitor, args=(0,))
3221                 self.running = True              3208                 self.running = True
3222                 self.thread.start()              3209                 self.thread.start()
3223         def stop(self):                          3210         def stop(self):
3224                 self.running = False             3211                 self.running = False
3225                                                  3212 
3226 # ----------------- FUNCTIONS ---------------    3213 # ----------------- FUNCTIONS --------------------
3227                                                  3214 
3228 # Function: doesTraceLogHaveTraceEvents          3215 # Function: doesTraceLogHaveTraceEvents
3229 # Description:                                   3216 # Description:
3230 #        Quickly determine if the ftrace log     3217 #        Quickly determine if the ftrace log has all of the trace events,
3231 #        markers, and/or kprobes required for    3218 #        markers, and/or kprobes required for primary parsing.
3232 def doesTraceLogHaveTraceEvents():               3219 def doesTraceLogHaveTraceEvents():
3233         kpcheck = ['_cal: (', '_ret: (']         3220         kpcheck = ['_cal: (', '_ret: (']
3234         techeck = ['suspend_resume', 'device_ !! 3221         techeck = ['suspend_resume', 'device_pm_callback']
3235         tmcheck = ['SUSPEND START', 'RESUME C    3222         tmcheck = ['SUSPEND START', 'RESUME COMPLETE']
3236         sysvals.usekprobes = False               3223         sysvals.usekprobes = False
3237         fp = sysvals.openlog(sysvals.ftracefi    3224         fp = sysvals.openlog(sysvals.ftracefile, 'r')
3238         for line in fp:                          3225         for line in fp:
3239                 # check for kprobes              3226                 # check for kprobes
3240                 if not sysvals.usekprobes:       3227                 if not sysvals.usekprobes:
3241                         for i in kpcheck:        3228                         for i in kpcheck:
3242                                 if i in line:    3229                                 if i in line:
3243                                         sysva    3230                                         sysvals.usekprobes = True
3244                 # check for all necessary tra    3231                 # check for all necessary trace events
3245                 check = techeck[:]               3232                 check = techeck[:]
3246                 for i in techeck:                3233                 for i in techeck:
3247                         if i in line:            3234                         if i in line:
3248                                 check.remove(    3235                                 check.remove(i)
3249                 techeck = check                  3236                 techeck = check
3250                 # check for all necessary tra    3237                 # check for all necessary trace markers
3251                 check = tmcheck[:]               3238                 check = tmcheck[:]
3252                 for i in tmcheck:                3239                 for i in tmcheck:
3253                         if i in line:            3240                         if i in line:
3254                                 check.remove(    3241                                 check.remove(i)
3255                 tmcheck = check                  3242                 tmcheck = check
3256         fp.close()                               3243         fp.close()
3257         sysvals.usetraceevents = True if len( !! 3244         sysvals.usetraceevents = True if len(techeck) < 2 else False
3258         sysvals.usetracemarkers = True if len    3245         sysvals.usetracemarkers = True if len(tmcheck) == 0 else False
3259                                                  3246 
3260 # Function: appendIncompleteTraceLog             3247 # Function: appendIncompleteTraceLog
3261 # Description:                                   3248 # Description:
3262 #        Adds callgraph data which lacks trac    3249 #        Adds callgraph data which lacks trace event data. This is only
3263 #        for timelines generated from 3.15 or    3250 #        for timelines generated from 3.15 or older
3264 # Arguments:                                     3251 # Arguments:
3265 #        testruns: the array of Data objects     3252 #        testruns: the array of Data objects obtained from parseKernelLog
3266 def appendIncompleteTraceLog(testruns):          3253 def appendIncompleteTraceLog(testruns):
3267         # create TestRun vessels for ftrace p    3254         # create TestRun vessels for ftrace parsing
3268         testcnt = len(testruns)                  3255         testcnt = len(testruns)
3269         testidx = 0                              3256         testidx = 0
3270         testrun = []                             3257         testrun = []
3271         for data in testruns:                    3258         for data in testruns:
3272                 testrun.append(TestRun(data))    3259                 testrun.append(TestRun(data))
3273                                                  3260 
3274         # extract the callgraph and traceeven    3261         # extract the callgraph and traceevent data
3275         sysvals.vprint('Analyzing the ftrace     3262         sysvals.vprint('Analyzing the ftrace data (%s)...' % \
3276                 os.path.basename(sysvals.ftra    3263                 os.path.basename(sysvals.ftracefile))
3277         tp = TestProps()                         3264         tp = TestProps()
3278         tf = sysvals.openlog(sysvals.ftracefi    3265         tf = sysvals.openlog(sysvals.ftracefile, 'r')
3279         data = 0                                 3266         data = 0
3280         for line in tf:                          3267         for line in tf:
3281                 # remove any latent carriage     3268                 # remove any latent carriage returns
3282                 line = line.replace('\r\n', '    3269                 line = line.replace('\r\n', '')
3283                 if tp.stampInfo(line, sysvals    3270                 if tp.stampInfo(line, sysvals):
3284                         continue                 3271                         continue
3285                 # parse only valid lines, if     3272                 # parse only valid lines, if this is not one move on
3286                 m = re.match(tp.ftrace_line_f    3273                 m = re.match(tp.ftrace_line_fmt, line)
3287                 if(not m):                       3274                 if(not m):
3288                         continue                 3275                         continue
3289                 # gather the basic message da    3276                 # gather the basic message data from the line
3290                 m_time = m.group('time')         3277                 m_time = m.group('time')
3291                 m_pid = m.group('pid')           3278                 m_pid = m.group('pid')
3292                 m_msg = m.group('msg')           3279                 m_msg = m.group('msg')
3293                 if(tp.cgformat):                 3280                 if(tp.cgformat):
3294                         m_param3 = m.group('d    3281                         m_param3 = m.group('dur')
3295                 else:                            3282                 else:
3296                         m_param3 = 'traceeven    3283                         m_param3 = 'traceevent'
3297                 if(m_time and m_pid and m_msg    3284                 if(m_time and m_pid and m_msg):
3298                         t = FTraceLine(m_time    3285                         t = FTraceLine(m_time, m_msg, m_param3)
3299                         pid = int(m_pid)         3286                         pid = int(m_pid)
3300                 else:                            3287                 else:
3301                         continue                 3288                         continue
3302                 # the line should be a call,     3289                 # the line should be a call, return, or event
3303                 if(not t.fcall and not t.fret    3290                 if(not t.fcall and not t.freturn and not t.fevent):
3304                         continue                 3291                         continue
3305                 # look for the suspend start     3292                 # look for the suspend start marker
3306                 if(t.startMarker()):             3293                 if(t.startMarker()):
3307                         data = testrun[testid    3294                         data = testrun[testidx].data
3308                         tp.parseStamp(data, s    3295                         tp.parseStamp(data, sysvals)
3309                         data.setStart(t.time,    3296                         data.setStart(t.time, t.name)
3310                         continue                 3297                         continue
3311                 if(not data):                    3298                 if(not data):
3312                         continue                 3299                         continue
3313                 # find the end of resume         3300                 # find the end of resume
3314                 if(t.endMarker()):               3301                 if(t.endMarker()):
3315                         data.setEnd(t.time, t    3302                         data.setEnd(t.time, t.name)
3316                         testidx += 1             3303                         testidx += 1
3317                         if(testidx >= testcnt    3304                         if(testidx >= testcnt):
3318                                 break            3305                                 break
3319                         continue                 3306                         continue
3320                 # trace event processing         3307                 # trace event processing
3321                 if(t.fevent):                    3308                 if(t.fevent):
3322                         continue                 3309                         continue
3323                 # call/return processing         3310                 # call/return processing
3324                 elif sysvals.usecallgraph:       3311                 elif sysvals.usecallgraph:
3325                         # create a callgraph     3312                         # create a callgraph object for the data
3326                         if(pid not in testrun    3313                         if(pid not in testrun[testidx].ftemp):
3327                                 testrun[testi    3314                                 testrun[testidx].ftemp[pid] = []
3328                                 testrun[testi    3315                                 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals))
3329                         # when the call is fi    3316                         # when the call is finished, see which device matches it
3330                         cg = testrun[testidx]    3317                         cg = testrun[testidx].ftemp[pid][-1]
3331                         res = cg.addLine(t)      3318                         res = cg.addLine(t)
3332                         if(res != 0):            3319                         if(res != 0):
3333                                 testrun[testi    3320                                 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals))
3334                         if(res == -1):           3321                         if(res == -1):
3335                                 testrun[testi    3322                                 testrun[testidx].ftemp[pid][-1].addLine(t)
3336         tf.close()                               3323         tf.close()
3337                                                  3324 
3338         for test in testrun:                     3325         for test in testrun:
3339                 # add the callgraph data to t    3326                 # add the callgraph data to the device hierarchy
3340                 for pid in test.ftemp:           3327                 for pid in test.ftemp:
3341                         for cg in test.ftemp[    3328                         for cg in test.ftemp[pid]:
3342                                 if len(cg.lis    3329                                 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0):
3343                                         conti    3330                                         continue
3344                                 if(not cg.pos    3331                                 if(not cg.postProcess()):
3345                                         id =     3332                                         id = 'task %s cpu %s' % (pid, m.group('cpu'))
3346                                         sysva    3333                                         sysvals.vprint('Sanity check failed for '+\
3347                                                  3334                                                 id+', ignoring this callback')
3348                                         conti    3335                                         continue
3349                                 callstart = c    3336                                 callstart = cg.start
3350                                 callend = cg.    3337                                 callend = cg.end
3351                                 for p in test    3338                                 for p in test.data.sortedPhases():
3352                                         if(te    3339                                         if(test.data.dmesg[p]['start'] <= callstart and
3353                                                  3340                                                 callstart <= test.data.dmesg[p]['end']):
3354                                                  3341                                                 list = test.data.dmesg[p]['list']
3355                                                  3342                                                 for devname in list:
3356                                                  3343                                                         dev = list[devname]
3357                                                  3344                                                         if(pid == dev['pid'] and
3358                                                  3345                                                                 callstart <= dev['start'] and
3359                                                  3346                                                                 callend >= dev['end']):
3360                                                  3347                                                                 dev['ftrace'] = cg
3361                                                  3348                                                 break
3362                                                  3349 
3363 # Function: loadTraceLog                         3350 # Function: loadTraceLog
3364 # Description:                                   3351 # Description:
3365 #        load the ftrace file into memory and    3352 #        load the ftrace file into memory and fix up any ordering issues
3366 # Output:                                        3353 # Output:
3367 #        TestProps instance and an array of l    3354 #        TestProps instance and an array of lines in proper order
3368 def loadTraceLog():                              3355 def loadTraceLog():
3369         tp, data, lines, trace = TestProps(),    3356         tp, data, lines, trace = TestProps(), dict(), [], []
3370         tf = sysvals.openlog(sysvals.ftracefi    3357         tf = sysvals.openlog(sysvals.ftracefile, 'r')
3371         for line in tf:                          3358         for line in tf:
3372                 # remove any latent carriage     3359                 # remove any latent carriage returns
3373                 line = line.replace('\r\n', '    3360                 line = line.replace('\r\n', '')
3374                 if tp.stampInfo(line, sysvals    3361                 if tp.stampInfo(line, sysvals):
3375                         continue                 3362                         continue
3376                 # ignore all other commented     3363                 # ignore all other commented lines
3377                 if line[0] == '#':               3364                 if line[0] == '#':
3378                         continue                 3365                         continue
3379                 # ftrace line: parse only val    3366                 # ftrace line: parse only valid lines
3380                 m = re.match(tp.ftrace_line_f    3367                 m = re.match(tp.ftrace_line_fmt, line)
3381                 if(not m):                       3368                 if(not m):
3382                         continue                 3369                         continue
3383                 dur = m.group('dur') if tp.cg    3370                 dur = m.group('dur') if tp.cgformat else 'traceevent'
3384                 info = (m.group('time'), m.gr    3371                 info = (m.group('time'), m.group('proc'), m.group('pid'),
3385                         m.group('msg'), dur)     3372                         m.group('msg'), dur)
3386                 # group the data by timestamp    3373                 # group the data by timestamp
3387                 t = float(info[0])               3374                 t = float(info[0])
3388                 if t in data:                    3375                 if t in data:
3389                         data[t].append(info)     3376                         data[t].append(info)
3390                 else:                            3377                 else:
3391                         data[t] = [info]         3378                         data[t] = [info]
3392                 # we only care about trace ev    3379                 # we only care about trace event ordering
3393                 if (info[3].startswith('suspe    3380                 if (info[3].startswith('suspend_resume:') or \
3394                         info[3].startswith('t    3381                         info[3].startswith('tracing_mark_write:')) and t not in trace:
3395                                 trace.append(    3382                                 trace.append(t)
3396         tf.close()                               3383         tf.close()
3397         for t in sorted(data):                   3384         for t in sorted(data):
3398                 first, last, blk = [], [], da    3385                 first, last, blk = [], [], data[t]
3399                 if len(blk) > 1 and t in trac    3386                 if len(blk) > 1 and t in trace:
3400                         # move certain lines     3387                         # move certain lines to the start or end of a timestamp block
3401                         for i in range(len(bl    3388                         for i in range(len(blk)):
3402                                 if 'SUSPEND S    3389                                 if 'SUSPEND START' in blk[i][3]:
3403                                         first    3390                                         first.append(i)
3404                                 elif re.match !! 3391                                 elif re.match('.* timekeeping_freeze.*begin', blk[i][3]):
3405                                         last.    3392                                         last.append(i)
3406                                 elif re.match !! 3393                                 elif re.match('.* timekeeping_freeze.*end', blk[i][3]):
3407                                         first    3394                                         first.append(i)
3408                                 elif 'RESUME     3395                                 elif 'RESUME COMPLETE' in blk[i][3]:
3409                                         last.    3396                                         last.append(i)
3410                         if len(first) == 1 an    3397                         if len(first) == 1 and len(last) == 0:
3411                                 blk.insert(0,    3398                                 blk.insert(0, blk.pop(first[0]))
3412                         elif len(last) == 1 a    3399                         elif len(last) == 1 and len(first) == 0:
3413                                 blk.append(bl    3400                                 blk.append(blk.pop(last[0]))
3414                 for info in blk:                 3401                 for info in blk:
3415                         lines.append(info)       3402                         lines.append(info)
3416         return (tp, lines)                       3403         return (tp, lines)
3417                                                  3404 
3418 # Function: parseTraceLog                        3405 # Function: parseTraceLog
3419 # Description:                                   3406 # Description:
3420 #        Analyze an ftrace log output file ge    3407 #        Analyze an ftrace log output file generated from this app during
3421 #        the execution phase. Used when the f    3408 #        the execution phase. Used when the ftrace log is the primary data source
3422 #        and includes the suspend_resume and     3409 #        and includes the suspend_resume and device_pm_callback trace events
3423 #        The ftrace filename is taken from sy    3410 #        The ftrace filename is taken from sysvals
3424 # Output:                                        3411 # Output:
3425 #        An array of Data objects                3412 #        An array of Data objects
3426 def parseTraceLog(live=False):                   3413 def parseTraceLog(live=False):
3427         sysvals.vprint('Analyzing the ftrace     3414         sysvals.vprint('Analyzing the ftrace data (%s)...' % \
3428                 os.path.basename(sysvals.ftra    3415                 os.path.basename(sysvals.ftracefile))
3429         if(os.path.exists(sysvals.ftracefile)    3416         if(os.path.exists(sysvals.ftracefile) == False):
3430                 doError('%s does not exist' %    3417                 doError('%s does not exist' % sysvals.ftracefile)
3431         if not live:                             3418         if not live:
3432                 sysvals.setupAllKprobes()        3419                 sysvals.setupAllKprobes()
3433         ksuscalls = ['ksys_sync', 'pm_prepare    3420         ksuscalls = ['ksys_sync', 'pm_prepare_console']
3434         krescalls = ['pm_restore_console']       3421         krescalls = ['pm_restore_console']
3435         tracewatch = ['irq_wakeup']              3422         tracewatch = ['irq_wakeup']
3436         if sysvals.usekprobes:                   3423         if sysvals.usekprobes:
3437                 tracewatch += ['sync_filesyst    3424                 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend',
3438                         'syscore_resume', 're    3425                         'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON',
3439                         'CPU_OFF', 'acpi_susp    3426                         'CPU_OFF', 'acpi_suspend']
3440                                                  3427 
3441         # extract the callgraph and traceeven    3428         # extract the callgraph and traceevent data
3442         s2idle_enter = hwsus = False             3429         s2idle_enter = hwsus = False
3443         testruns, testdata = [], []              3430         testruns, testdata = [], []
3444         testrun, data, limbo = 0, 0, True        3431         testrun, data, limbo = 0, 0, True
3445         phase = 'suspend_prepare'                3432         phase = 'suspend_prepare'
3446         tp, tf = loadTraceLog()                  3433         tp, tf = loadTraceLog()
3447         for m_time, m_proc, m_pid, m_msg, m_p    3434         for m_time, m_proc, m_pid, m_msg, m_param3 in tf:
3448                 # gather the basic message da    3435                 # gather the basic message data from the line
3449                 if(m_time and m_pid and m_msg    3436                 if(m_time and m_pid and m_msg):
3450                         t = FTraceLine(m_time    3437                         t = FTraceLine(m_time, m_msg, m_param3)
3451                         pid = int(m_pid)         3438                         pid = int(m_pid)
3452                 else:                            3439                 else:
3453                         continue                 3440                         continue
3454                 # the line should be a call,     3441                 # the line should be a call, return, or event
3455                 if(not t.fcall and not t.fret    3442                 if(not t.fcall and not t.freturn and not t.fevent):
3456                         continue                 3443                         continue
3457                 # find the start of suspend      3444                 # find the start of suspend
3458                 if(t.startMarker()):             3445                 if(t.startMarker()):
3459                         data, limbo = Data(le    3446                         data, limbo = Data(len(testdata)), False
3460                         testdata.append(data)    3447                         testdata.append(data)
3461                         testrun = TestRun(dat    3448                         testrun = TestRun(data)
3462                         testruns.append(testr    3449                         testruns.append(testrun)
3463                         tp.parseStamp(data, s    3450                         tp.parseStamp(data, sysvals)
3464                         data.setStart(t.time,    3451                         data.setStart(t.time, t.name)
3465                         data.first_suspend_pr    3452                         data.first_suspend_prepare = True
3466                         phase = data.setPhase    3453                         phase = data.setPhase('suspend_prepare', t.time, True)
3467                         continue                 3454                         continue
3468                 if(not data or limbo):           3455                 if(not data or limbo):
3469                         continue                 3456                         continue
3470                 # process cpu exec line          3457                 # process cpu exec line
3471                 if t.type == 'tracing_mark_wr    3458                 if t.type == 'tracing_mark_write':
3472                         if t.name == 'CMD COM << 
3473                                 data.tKernRes << 
3474                         m = re.match(tp.proce    3459                         m = re.match(tp.procexecfmt, t.name)
3475                         if(m):                   3460                         if(m):
3476                                 parts, msg =     3461                                 parts, msg = 1, m.group('ps')
3477                                 m = re.match(    3462                                 m = re.match(tp.procmultifmt, msg)
3478                                 if(m):           3463                                 if(m):
3479                                         parts    3464                                         parts, msg = int(m.group('n')), m.group('ps')
3480                                         if tp    3465                                         if tp.multiproccnt == 0:
3481                                                  3466                                                 tp.multiproctime = t.time
3482                                                  3467                                                 tp.multiproclist = dict()
3483                                         procl    3468                                         proclist = tp.multiproclist
3484                                         tp.mu    3469                                         tp.multiproccnt += 1
3485                                 else:            3470                                 else:
3486                                         procl    3471                                         proclist = dict()
3487                                         tp.mu    3472                                         tp.multiproccnt = 0
3488                                 for ps in msg    3473                                 for ps in msg.split(','):
3489                                         val =    3474                                         val = ps.split()
3490                                         if no    3475                                         if not val or len(val) != 2:
3491                                                  3476                                                 continue
3492                                         name     3477                                         name = val[0].replace('--', '-')
3493                                         procl    3478                                         proclist[name] = int(val[1])
3494                                 if parts == 1    3479                                 if parts == 1:
3495                                         data.    3480                                         data.pstl[t.time] = proclist
3496                                 elif parts ==    3481                                 elif parts == tp.multiproccnt:
3497                                         data.    3482                                         data.pstl[tp.multiproctime] = proclist
3498                                         tp.mu    3483                                         tp.multiproccnt = 0
3499                                 continue         3484                                 continue
3500                 # find the end of resume         3485                 # find the end of resume
3501                 if(t.endMarker()):               3486                 if(t.endMarker()):
3502                         if data.tKernRes == 0    3487                         if data.tKernRes == 0:
3503                                 data.tKernRes    3488                                 data.tKernRes = t.time
3504                         data.handleEndMarker(    3489                         data.handleEndMarker(t.time, t.name)
3505                         if(not sysvals.usetra    3490                         if(not sysvals.usetracemarkers):
3506                                 # no trace ma    3491                                 # no trace markers? then quit and be sure to finish recording
3507                                 # the event w    3492                                 # the event we used to trigger resume end
3508                                 if('thaw_proc    3493                                 if('thaw_processes' in testrun.ttemp and len(testrun.ttemp['thaw_processes']) > 0):
3509                                         # if     3494                                         # if an entry exists, assume this is its end
3510                                         testr    3495                                         testrun.ttemp['thaw_processes'][-1]['end'] = t.time
3511                         limbo = True             3496                         limbo = True
3512                         continue                 3497                         continue
3513                 # trace event processing         3498                 # trace event processing
3514                 if(t.fevent):                    3499                 if(t.fevent):
3515                         if(t.type == 'suspend    3500                         if(t.type == 'suspend_resume'):
3516                                 # suspend_res    3501                                 # suspend_resume trace events have two types, begin and end
3517                                 if(re.match(r !! 3502                                 if(re.match('(?P<name>.*) begin$', t.name)):
3518                                         isbeg    3503                                         isbegin = True
3519                                 elif(re.match !! 3504                                 elif(re.match('(?P<name>.*) end$', t.name)):
3520                                         isbeg    3505                                         isbegin = False
3521                                 else:            3506                                 else:
3522                                         conti    3507                                         continue
3523                                 if '[' in t.n    3508                                 if '[' in t.name:
3524                                         m = r !! 3509                                         m = re.match('(?P<name>.*)\[.*', t.name)
3525                                 else:            3510                                 else:
3526                                         m = r !! 3511                                         m = re.match('(?P<name>.*) .*', t.name)
3527                                 name = m.grou    3512                                 name = m.group('name')
3528                                 # ignore thes    3513                                 # ignore these events
3529                                 if(name.split    3514                                 if(name.split('[')[0] in tracewatch):
3530                                         conti    3515                                         continue
3531                                 # -- phase ch    3516                                 # -- phase changes --
3532                                 # start of ke    3517                                 # start of kernel suspend
3533                                 if(re.match(r !! 3518                                 if(re.match('suspend_enter\[.*', t.name)):
3534                                         if(is    3519                                         if(isbegin and data.tKernSus == 0):
3535                                                  3520                                                 data.tKernSus = t.time
3536                                         conti    3521                                         continue
3537                                 # suspend_pre    3522                                 # suspend_prepare start
3538                                 elif(re.match !! 3523                                 elif(re.match('dpm_prepare\[.*', t.name)):
3539                                         if is    3524                                         if isbegin and data.first_suspend_prepare:
3540                                                  3525                                                 data.first_suspend_prepare = False
3541                                                  3526                                                 if data.tKernSus == 0:
3542                                                  3527                                                         data.tKernSus = t.time
3543                                                  3528                                                 continue
3544                                         phase    3529                                         phase = data.setPhase('suspend_prepare', t.time, isbegin)
3545                                         conti    3530                                         continue
3546                                 # suspend sta    3531                                 # suspend start
3547                                 elif(re.match !! 3532                                 elif(re.match('dpm_suspend\[.*', t.name)):
3548                                         phase    3533                                         phase = data.setPhase('suspend', t.time, isbegin)
3549                                         conti    3534                                         continue
3550                                 # suspend_lat    3535                                 # suspend_late start
3551                                 elif(re.match !! 3536                                 elif(re.match('dpm_suspend_late\[.*', t.name)):
3552                                         phase    3537                                         phase = data.setPhase('suspend_late', t.time, isbegin)
3553                                         conti    3538                                         continue
3554                                 # suspend_noi    3539                                 # suspend_noirq start
3555                                 elif(re.match !! 3540                                 elif(re.match('dpm_suspend_noirq\[.*', t.name)):
3556                                         phase    3541                                         phase = data.setPhase('suspend_noirq', t.time, isbegin)
3557                                         conti    3542                                         continue
3558                                 # suspend_mac    3543                                 # suspend_machine/resume_machine
3559                                 elif(re.match    3544                                 elif(re.match(tp.machinesuspend, t.name)):
3560                                         lp =     3545                                         lp = data.lastPhase()
3561                                         if(is    3546                                         if(isbegin):
3562                                                  3547                                                 hwsus = True
3563                                                  3548                                                 if lp.startswith('resume_machine'):
3564                                                  3549                                                         # trim out s2idle loops, track time trying to freeze
3565                                                  3550                                                         llp = data.lastPhase(2)
3566                                                  3551                                                         if llp.startswith('suspend_machine'):
3567                                                  3552                                                                 if 'waking' not in data.dmesg[llp]:
3568                                                  3553                                                                         data.dmesg[llp]['waking'] = [0, 0.0]
3569                                                  3554                                                                 data.dmesg[llp]['waking'][0] += 1
3570                                                  3555                                                                 data.dmesg[llp]['waking'][1] += \
3571                                                  3556                                                                         t.time - data.dmesg[lp]['start']
3572                                                  3557                                                         data.currphase = ''
3573                                                  3558                                                         del data.dmesg[lp]
3574                                                  3559                                                         continue
3575                                                  3560                                                 phase = data.setPhase('suspend_machine', data.dmesg[lp]['end'], True)
3576                                                  3561                                                 data.setPhase(phase, t.time, False)
3577                                                  3562                                                 if data.tSuspended == 0:
3578                                                  3563                                                         data.tSuspended = t.time
3579                                         else:    3564                                         else:
3580                                                  3565                                                 if lp.startswith('resume_machine'):
3581                                                  3566                                                         data.dmesg[lp]['end'] = t.time
3582                                                  3567                                                         continue
3583                                                  3568                                                 phase = data.setPhase('resume_machine', t.time, True)
3584                                                  3569                                                 if(sysvals.suspendmode in ['mem', 'disk']):
3585                                                  3570                                                         susp = phase.replace('resume', 'suspend')
3586                                                  3571                                                         if susp in data.dmesg:
3587                                                  3572                                                                 data.dmesg[susp]['end'] = t.time
3588                                                  3573                                                         data.tSuspended = t.time
3589                                                  3574                                                 data.tResumed = t.time
3590                                         conti    3575                                         continue
3591                                 # resume_noir    3576                                 # resume_noirq start
3592                                 elif(re.match !! 3577                                 elif(re.match('dpm_resume_noirq\[.*', t.name)):
3593                                         phase    3578                                         phase = data.setPhase('resume_noirq', t.time, isbegin)
3594                                         conti    3579                                         continue
3595                                 # resume_earl    3580                                 # resume_early start
3596                                 elif(re.match !! 3581                                 elif(re.match('dpm_resume_early\[.*', t.name)):
3597                                         phase    3582                                         phase = data.setPhase('resume_early', t.time, isbegin)
3598                                         conti    3583                                         continue
3599                                 # resume star    3584                                 # resume start
3600                                 elif(re.match !! 3585                                 elif(re.match('dpm_resume\[.*', t.name)):
3601                                         phase    3586                                         phase = data.setPhase('resume', t.time, isbegin)
3602                                         conti    3587                                         continue
3603                                 # resume comp    3588                                 # resume complete start
3604                                 elif(re.match !! 3589                                 elif(re.match('dpm_complete\[.*', t.name)):
3605                                         phase    3590                                         phase = data.setPhase('resume_complete', t.time, isbegin)
3606                                         conti    3591                                         continue
3607                                 # skip trace     3592                                 # skip trace events inside devices calls
3608                                 if(not data.i    3593                                 if(not data.isTraceEventOutsideDeviceCalls(pid, t.time)):
3609                                         conti    3594                                         continue
3610                                 # global even    3595                                 # global events (outside device calls) are graphed
3611                                 if(name not i    3596                                 if(name not in testrun.ttemp):
3612                                         testr    3597                                         testrun.ttemp[name] = []
3613                                 # special han    3598                                 # special handling for s2idle_enter
3614                                 if name == 'm    3599                                 if name == 'machine_suspend':
3615                                         if hw    3600                                         if hwsus:
3616                                                  3601                                                 s2idle_enter = hwsus = False
3617                                         elif     3602                                         elif s2idle_enter and not isbegin:
3618                                                  3603                                                 if(len(testrun.ttemp[name]) > 0):
3619                                                  3604                                                         testrun.ttemp[name][-1]['end'] = t.time
3620                                                  3605                                                         testrun.ttemp[name][-1]['loop'] += 1
3621                                         elif     3606                                         elif not s2idle_enter and isbegin:
3622                                                  3607                                                 s2idle_enter = True
3623                                                  3608                                                 testrun.ttemp[name].append({'begin': t.time,
3624                                                  3609                                                         'end': t.time, 'pid': pid, 'loop': 0})
3625                                         conti    3610                                         continue
3626                                 if(isbegin):     3611                                 if(isbegin):
3627                                         # cre    3612                                         # create a new list entry
3628                                         testr    3613                                         testrun.ttemp[name].append(\
3629                                                  3614                                                 {'begin': t.time, 'end': t.time, 'pid': pid})
3630                                 else:            3615                                 else:
3631                                         if(le    3616                                         if(len(testrun.ttemp[name]) > 0):
3632                                                  3617                                                 # if an entry exists, assume this is its end
3633                                                  3618                                                 testrun.ttemp[name][-1]['end'] = t.time
3634                         # device callback sta    3619                         # device callback start
3635                         elif(t.type == 'devic    3620                         elif(t.type == 'device_pm_callback_start'):
3636                                 if phase not     3621                                 if phase not in data.dmesg:
3637                                         conti    3622                                         continue
3638                                 m = re.match( !! 3623                                 m = re.match('(?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*',\
3639                                         t.nam    3624                                         t.name);
3640                                 if(not m):       3625                                 if(not m):
3641                                         conti    3626                                         continue
3642                                 drv = m.group    3627                                 drv = m.group('drv')
3643                                 n = m.group('    3628                                 n = m.group('d')
3644                                 p = m.group('    3629                                 p = m.group('p')
3645                                 if(n and p):     3630                                 if(n and p):
3646                                         data.    3631                                         data.newAction(phase, n, pid, p, t.time, -1, drv)
3647                                         if pi    3632                                         if pid not in data.devpids:
3648                                                  3633                                                 data.devpids.append(pid)
3649                         # device callback fin    3634                         # device callback finish
3650                         elif(t.type == 'devic    3635                         elif(t.type == 'device_pm_callback_end'):
3651                                 if phase not     3636                                 if phase not in data.dmesg:
3652                                         conti    3637                                         continue
3653                                 m = re.match( !! 3638                                 m = re.match('(?P<drv>.*) (?P<d>.*), err.*', t.name);
3654                                 if(not m):       3639                                 if(not m):
3655                                         conti    3640                                         continue
3656                                 n = m.group('    3641                                 n = m.group('d')
3657                                 dev = data.fi    3642                                 dev = data.findDevice(phase, n)
3658                                 if dev:          3643                                 if dev:
3659                                         dev['    3644                                         dev['length'] = t.time - dev['start']
3660                                         dev['    3645                                         dev['end'] = t.time
3661                 # kprobe event processing        3646                 # kprobe event processing
3662                 elif(t.fkprobe):                 3647                 elif(t.fkprobe):
3663                         kprobename = t.type      3648                         kprobename = t.type
3664                         kprobedata = t.name      3649                         kprobedata = t.name
3665                         key = (kprobename, pi    3650                         key = (kprobename, pid)
3666                         # displayname is gene    3651                         # displayname is generated from kprobe data
3667                         displayname = ''         3652                         displayname = ''
3668                         if(t.fcall):             3653                         if(t.fcall):
3669                                 displayname =    3654                                 displayname = sysvals.kprobeDisplayName(kprobename, kprobedata)
3670                                 if not displa    3655                                 if not displayname:
3671                                         conti    3656                                         continue
3672                                 if(key not in    3657                                 if(key not in tp.ktemp):
3673                                         tp.kt    3658                                         tp.ktemp[key] = []
3674                                 tp.ktemp[key]    3659                                 tp.ktemp[key].append({
3675                                         'pid'    3660                                         'pid': pid,
3676                                         'begi    3661                                         'begin': t.time,
3677                                         'end'    3662                                         'end': -1,
3678                                         'name    3663                                         'name': displayname,
3679                                         'cdat    3664                                         'cdata': kprobedata,
3680                                         'proc    3665                                         'proc': m_proc,
3681                                 })               3666                                 })
3682                                 # start of ke    3667                                 # start of kernel resume
3683                                 if(data.tKern    3668                                 if(data.tKernSus == 0 and phase == 'suspend_prepare' \
3684                                         and k    3669                                         and kprobename in ksuscalls):
3685                                         data.    3670                                         data.tKernSus = t.time
3686                         elif(t.freturn):         3671                         elif(t.freturn):
3687                                 if(key not in    3672                                 if(key not in tp.ktemp) or len(tp.ktemp[key]) < 1:
3688                                         conti    3673                                         continue
3689                                 e = next((x f    3674                                 e = next((x for x in reversed(tp.ktemp[key]) if x['end'] < 0), 0)
3690                                 if not e:        3675                                 if not e:
3691                                         conti    3676                                         continue
3692                                 if (t.time -  << 
3693                                         tp.kt << 
3694                                         conti << 
3695                                 e['end'] = t.    3677                                 e['end'] = t.time
3696                                 e['rdata'] =     3678                                 e['rdata'] = kprobedata
3697                                 # end of kern    3679                                 # end of kernel resume
3698                                 if(phase != '    3680                                 if(phase != 'suspend_prepare' and kprobename in krescalls):
3699                                         if ph    3681                                         if phase in data.dmesg:
3700                                                  3682                                                 data.dmesg[phase]['end'] = t.time
3701                                         data.    3683                                         data.tKernRes = t.time
3702                                                  3684 
3703                 # callgraph processing           3685                 # callgraph processing
3704                 elif sysvals.usecallgraph:       3686                 elif sysvals.usecallgraph:
3705                         # create a callgraph     3687                         # create a callgraph object for the data
3706                         key = (m_proc, pid)      3688                         key = (m_proc, pid)
3707                         if(key not in testrun    3689                         if(key not in testrun.ftemp):
3708                                 testrun.ftemp    3690                                 testrun.ftemp[key] = []
3709                                 testrun.ftemp    3691                                 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals))
3710                         # when the call is fi    3692                         # when the call is finished, see which device matches it
3711                         cg = testrun.ftemp[ke    3693                         cg = testrun.ftemp[key][-1]
3712                         res = cg.addLine(t)      3694                         res = cg.addLine(t)
3713                         if(res != 0):            3695                         if(res != 0):
3714                                 testrun.ftemp    3696                                 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals))
3715                         if(res == -1):           3697                         if(res == -1):
3716                                 testrun.ftemp    3698                                 testrun.ftemp[key][-1].addLine(t)
3717         if len(testdata) < 1:                    3699         if len(testdata) < 1:
3718                 sysvals.vprint('WARNING: ftra    3700                 sysvals.vprint('WARNING: ftrace start marker is missing')
3719         if data and not data.devicegroups:       3701         if data and not data.devicegroups:
3720                 sysvals.vprint('WARNING: ftra    3702                 sysvals.vprint('WARNING: ftrace end marker is missing')
3721                 data.handleEndMarker(t.time,     3703                 data.handleEndMarker(t.time, t.name)
3722                                                  3704 
3723         if sysvals.suspendmode == 'command':     3705         if sysvals.suspendmode == 'command':
3724                 for test in testruns:            3706                 for test in testruns:
3725                         for p in test.data.so    3707                         for p in test.data.sortedPhases():
3726                                 if p == 'susp    3708                                 if p == 'suspend_prepare':
3727                                         test.    3709                                         test.data.dmesg[p]['start'] = test.data.start
3728                                         test.    3710                                         test.data.dmesg[p]['end'] = test.data.end
3729                                 else:            3711                                 else:
3730                                         test.    3712                                         test.data.dmesg[p]['start'] = test.data.end
3731                                         test.    3713                                         test.data.dmesg[p]['end'] = test.data.end
3732                         test.data.tSuspended     3714                         test.data.tSuspended = test.data.end
3733                         test.data.tResumed =     3715                         test.data.tResumed = test.data.end
3734                         test.data.fwValid = F    3716                         test.data.fwValid = False
3735                                                  3717 
3736         # dev source and procmon events can b    3718         # dev source and procmon events can be unreadable with mixed phase height
3737         if sysvals.usedevsrc or sysvals.usepr    3719         if sysvals.usedevsrc or sysvals.useprocmon:
3738                 sysvals.mixedphaseheight = Fa    3720                 sysvals.mixedphaseheight = False
3739                                                  3721 
3740         # expand phase boundaries so there ar    3722         # expand phase boundaries so there are no gaps
3741         for data in testdata:                    3723         for data in testdata:
3742                 lp = data.sortedPhases()[0]      3724                 lp = data.sortedPhases()[0]
3743                 for p in data.sortedPhases():    3725                 for p in data.sortedPhases():
3744                         if(p != lp and not ('    3726                         if(p != lp and not ('machine' in p and 'machine' in lp)):
3745                                 data.dmesg[lp    3727                                 data.dmesg[lp]['end'] = data.dmesg[p]['start']
3746                         lp = p                   3728                         lp = p
3747                                                  3729 
3748         for i in range(len(testruns)):           3730         for i in range(len(testruns)):
3749                 test = testruns[i]               3731                 test = testruns[i]
3750                 data = test.data                 3732                 data = test.data
3751                 # find the total time range f    3733                 # find the total time range for this test (begin, end)
3752                 tlb, tle = data.start, data.e    3734                 tlb, tle = data.start, data.end
3753                 if i < len(testruns) - 1:        3735                 if i < len(testruns) - 1:
3754                         tle = testruns[i+1].d    3736                         tle = testruns[i+1].data.start
3755                 # add the process usage data     3737                 # add the process usage data to the timeline
3756                 if sysvals.useprocmon:           3738                 if sysvals.useprocmon:
3757                         data.createProcessUsa    3739                         data.createProcessUsageEvents()
3758                 # add the traceevent data to     3740                 # add the traceevent data to the device hierarchy
3759                 if(sysvals.usetraceevents):      3741                 if(sysvals.usetraceevents):
3760                         # add actual trace fu    3742                         # add actual trace funcs
3761                         for name in sorted(te    3743                         for name in sorted(test.ttemp):
3762                                 for event in     3744                                 for event in test.ttemp[name]:
3763                                         if ev    3745                                         if event['end'] - event['begin'] <= 0:
3764                                                  3746                                                 continue
3765                                         title    3747                                         title = name
3766                                         if na    3748                                         if name == 'machine_suspend' and 'loop' in event:
3767                                                  3749                                                 title = 's2idle_enter_%dx' % event['loop']
3768                                         data.    3750                                         data.newActionGlobal(title, event['begin'], event['end'], event['pid'])
3769                         # add the kprobe base    3751                         # add the kprobe based virtual tracefuncs as actual devices
3770                         for key in sorted(tp.    3752                         for key in sorted(tp.ktemp):
3771                                 name, pid = k    3753                                 name, pid = key
3772                                 if name not i    3754                                 if name not in sysvals.tracefuncs:
3773                                         conti    3755                                         continue
3774                                 if pid not in    3756                                 if pid not in data.devpids:
3775                                         data.    3757                                         data.devpids.append(pid)
3776                                 for e in tp.k    3758                                 for e in tp.ktemp[key]:
3777                                         kb, k    3759                                         kb, ke = e['begin'], e['end']
3778                                         if ke    3760                                         if ke - kb < 0.000001 or tlb > kb or tle <= kb:
3779                                                  3761                                                 continue
3780                                         color    3762                                         color = sysvals.kprobeColor(name)
3781                                         data.    3763                                         data.newActionGlobal(e['name'], kb, ke, pid, color)
3782                         # add config base kpr    3764                         # add config base kprobes and dev kprobes
3783                         if sysvals.usedevsrc:    3765                         if sysvals.usedevsrc:
3784                                 for key in so    3766                                 for key in sorted(tp.ktemp):
3785                                         name,    3767                                         name, pid = key
3786                                         if na    3768                                         if name in sysvals.tracefuncs or name not in sysvals.dev_tracefuncs:
3787                                                  3769                                                 continue
3788                                         for e    3770                                         for e in tp.ktemp[key]:
3789                                                  3771                                                 kb, ke = e['begin'], e['end']
3790                                                  3772                                                 if ke - kb < 0.000001 or tlb > kb or tle <= kb:
3791                                                  3773                                                         continue
3792                                                  3774                                                 data.addDeviceFunctionCall(e['name'], name, e['proc'], pid, kb,
3793                                                  3775                                                         ke, e['cdata'], e['rdata'])
3794                 if sysvals.usecallgraph:         3776                 if sysvals.usecallgraph:
3795                         # add the callgraph d    3777                         # add the callgraph data to the device hierarchy
3796                         sortlist = dict()        3778                         sortlist = dict()
3797                         for key in sorted(tes    3779                         for key in sorted(test.ftemp):
3798                                 proc, pid = k    3780                                 proc, pid = key
3799                                 for cg in tes    3781                                 for cg in test.ftemp[key]:
3800                                         if le    3782                                         if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0):
3801                                                  3783                                                 continue
3802                                         if(no    3784                                         if(not cg.postProcess()):
3803                                                  3785                                                 id = 'task %s' % (pid)
3804                                                  3786                                                 sysvals.vprint('Sanity check failed for '+\
3805                                                  3787                                                         id+', ignoring this callback')
3806                                                  3788                                                 continue
3807                                         # mat    3789                                         # match cg data to devices
3808                                         devna    3790                                         devname = ''
3809                                         if sy    3791                                         if sysvals.suspendmode != 'command':
3810                                                  3792                                                 devname = cg.deviceMatch(pid, data)
3811                                         if no    3793                                         if not devname:
3812                                                  3794                                                 sortkey = '%f%f%d' % (cg.start, cg.end, pid)
3813                                                  3795                                                 sortlist[sortkey] = cg
3814                                         elif     3796                                         elif len(cg.list) > 1000000 and cg.name != sysvals.ftopfunc:
3815                                                  3797                                                 sysvals.vprint('WARNING: the callgraph for %s is massive (%d lines)' %\
3816                                                  3798                                                         (devname, len(cg.list)))
3817                         # create blocks for o    3799                         # create blocks for orphan cg data
3818                         for sortkey in sorted    3800                         for sortkey in sorted(sortlist):
3819                                 cg = sortlist    3801                                 cg = sortlist[sortkey]
3820                                 name = cg.nam    3802                                 name = cg.name
3821                                 if sysvals.is    3803                                 if sysvals.isCallgraphFunc(name):
3822                                         sysva    3804                                         sysvals.vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name))
3823                                         cg.ne    3805                                         cg.newActionFromFunction(data)
3824         if sysvals.suspendmode == 'command':     3806         if sysvals.suspendmode == 'command':
3825                 return (testdata, '')            3807                 return (testdata, '')
3826                                                  3808 
3827         # fill in any missing phases             3809         # fill in any missing phases
3828         error = []                               3810         error = []
3829         for data in testdata:                    3811         for data in testdata:
3830                 tn = '' if len(testdata) == 1    3812                 tn = '' if len(testdata) == 1 else ('%d' % (data.testnumber + 1))
3831                 terr = ''                        3813                 terr = ''
3832                 phasedef = data.phasedef         3814                 phasedef = data.phasedef
3833                 lp = 'suspend_prepare'           3815                 lp = 'suspend_prepare'
3834                 for p in sorted(phasedef, key    3816                 for p in sorted(phasedef, key=lambda k:phasedef[k]['order']):
3835                         if p not in data.dmes    3817                         if p not in data.dmesg:
3836                                 if not terr:     3818                                 if not terr:
3837                                         ph =     3819                                         ph = p if 'machine' in p else lp
3838                                         if p     3820                                         if p == 'suspend_machine':
3839                                                  3821                                                 sm = sysvals.suspendmode
3840                                                  3822                                                 if sm in suspendmodename:
3841                                                  3823                                                         sm = suspendmodename[sm]
3842                                                  3824                                                 terr = 'test%s did not enter %s power mode' % (tn, sm)
3843                                         else:    3825                                         else:
3844                                                  3826                                                 terr = '%s%s failed in %s phase' % (sysvals.suspendmode, tn, ph)
3845                                         pprin    3827                                         pprint('TEST%s FAILED: %s' % (tn, terr))
3846                                         error    3828                                         error.append(terr)
3847                                         if da    3829                                         if data.tSuspended == 0:
3848                                                  3830                                                 data.tSuspended = data.dmesg[lp]['end']
3849                                         if da    3831                                         if data.tResumed == 0:
3850                                                  3832                                                 data.tResumed = data.dmesg[lp]['end']
3851                                         data.    3833                                         data.fwValid = False
3852                                 sysvals.vprin    3834                                 sysvals.vprint('WARNING: phase "%s" is missing!' % p)
3853                         lp = p                   3835                         lp = p
3854                 if not terr and 'dev' in data    3836                 if not terr and 'dev' in data.wifi and data.wifi['stat'] == 'timeout':
3855                         terr = '%s%s failed i    3837                         terr = '%s%s failed in wifi_resume <i>(%s %.0fs timeout)</i>' % \
3856                                 (sysvals.susp    3838                                 (sysvals.suspendmode, tn, data.wifi['dev'], data.wifi['time'])
3857                         error.append(terr)       3839                         error.append(terr)
3858                 if not terr and data.enterfai    3840                 if not terr and data.enterfail:
3859                         pprint('test%s FAILED    3841                         pprint('test%s FAILED: enter %s failed with %s' % (tn, sysvals.suspendmode, data.enterfail))
3860                         terr = 'test%s failed    3842                         terr = 'test%s failed to enter %s mode' % (tn, sysvals.suspendmode)
3861                         error.append(terr)       3843                         error.append(terr)
3862                 if data.tSuspended == 0:         3844                 if data.tSuspended == 0:
3863                         data.tSuspended = dat    3845                         data.tSuspended = data.tKernRes
3864                 if data.tResumed == 0:           3846                 if data.tResumed == 0:
3865                         data.tResumed = data.    3847                         data.tResumed = data.tSuspended
3866                                                  3848 
3867                 if(len(sysvals.devicefilter)     3849                 if(len(sysvals.devicefilter) > 0):
3868                         data.deviceFilter(sys    3850                         data.deviceFilter(sysvals.devicefilter)
3869                 data.fixupInitcallsThatDidntR    3851                 data.fixupInitcallsThatDidntReturn()
3870                 if sysvals.usedevsrc:            3852                 if sysvals.usedevsrc:
3871                         data.optimizeDevSrc()    3853                         data.optimizeDevSrc()
3872                                                  3854 
3873         # x2: merge any overlapping devices b    3855         # x2: merge any overlapping devices between test runs
3874         if sysvals.usedevsrc and len(testdata    3856         if sysvals.usedevsrc and len(testdata) > 1:
3875                 tc = len(testdata)               3857                 tc = len(testdata)
3876                 for i in range(tc - 1):          3858                 for i in range(tc - 1):
3877                         devlist = testdata[i]    3859                         devlist = testdata[i].overflowDevices()
3878                         for j in range(i + 1,    3860                         for j in range(i + 1, tc):
3879                                 testdata[j].m    3861                                 testdata[j].mergeOverlapDevices(devlist)
3880                 testdata[0].stitchTouchingThr    3862                 testdata[0].stitchTouchingThreads(testdata[1:])
3881         return (testdata, ', '.join(error))      3863         return (testdata, ', '.join(error))
3882                                                  3864 
3883 # Function: loadKernelLog                        3865 # Function: loadKernelLog
3884 # Description:                                   3866 # Description:
3885 #        load the dmesg file into memory and     3867 #        load the dmesg file into memory and fix up any ordering issues
3886 # Output:                                        3868 # Output:
3887 #        An array of empty Data objects with     3869 #        An array of empty Data objects with only their dmesgtext attributes set
3888 def loadKernelLog():                             3870 def loadKernelLog():
3889         sysvals.vprint('Analyzing the dmesg d    3871         sysvals.vprint('Analyzing the dmesg data (%s)...' % \
3890                 os.path.basename(sysvals.dmes    3872                 os.path.basename(sysvals.dmesgfile))
3891         if(os.path.exists(sysvals.dmesgfile)     3873         if(os.path.exists(sysvals.dmesgfile) == False):
3892                 doError('%s does not exist' %    3874                 doError('%s does not exist' % sysvals.dmesgfile)
3893                                                  3875 
3894         # there can be multiple test runs in     3876         # there can be multiple test runs in a single file
3895         tp = TestProps()                         3877         tp = TestProps()
3896         tp.stamp = datetime.now().strftime('#    3878         tp.stamp = datetime.now().strftime('# suspend-%m%d%y-%H%M%S localhost mem unknown')
3897         testruns = []                            3879         testruns = []
3898         data = 0                                 3880         data = 0
3899         lf = sysvals.openlog(sysvals.dmesgfil    3881         lf = sysvals.openlog(sysvals.dmesgfile, 'r')
3900         for line in lf:                          3882         for line in lf:
3901                 line = line.replace('\r\n', '    3883                 line = line.replace('\r\n', '')
3902                 idx = line.find('[')             3884                 idx = line.find('[')
3903                 if idx > 1:                      3885                 if idx > 1:
3904                         line = line[idx:]        3886                         line = line[idx:]
3905                 if tp.stampInfo(line, sysvals    3887                 if tp.stampInfo(line, sysvals):
3906                         continue                 3888                         continue
3907                 m = re.match(r'[ \t]*(\[ *)(? !! 3889                 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
3908                 if(not m):                       3890                 if(not m):
3909                         continue                 3891                         continue
3910                 msg = m.group("msg")             3892                 msg = m.group("msg")
3911                 if re.match(r'PM: Syncing fil !! 3893                 if re.match('PM: Syncing filesystems.*', msg) or \
3912                         re.match(r'PM: suspen !! 3894                         re.match('PM: suspend entry.*', msg):
3913                         if(data):                3895                         if(data):
3914                                 testruns.appe    3896                                 testruns.append(data)
3915                         data = Data(len(testr    3897                         data = Data(len(testruns))
3916                         tp.parseStamp(data, s    3898                         tp.parseStamp(data, sysvals)
3917                 if(not data):                    3899                 if(not data):
3918                         continue                 3900                         continue
3919                 m = re.match(r'.* *(?P<k>[0-9 !! 3901                 m = re.match('.* *(?P<k>[0-9]\.[0-9]{2}\.[0-9]-.*) .*', msg)
3920                 if(m):                           3902                 if(m):
3921                         sysvals.stamp['kernel    3903                         sysvals.stamp['kernel'] = m.group('k')
3922                 m = re.match(r'PM: Preparing  !! 3904                 m = re.match('PM: Preparing system for (?P<m>.*) sleep', msg)
3923                 if not m:                        3905                 if not m:
3924                         m = re.match(r'PM: Pr !! 3906                         m = re.match('PM: Preparing system for sleep \((?P<m>.*)\)', msg)
3925                 if m:                            3907                 if m:
3926                         sysvals.stamp['mode']    3908                         sysvals.stamp['mode'] = sysvals.suspendmode = m.group('m')
3927                 data.dmesgtext.append(line)      3909                 data.dmesgtext.append(line)
3928         lf.close()                               3910         lf.close()
3929                                                  3911 
3930         if sysvals.suspendmode == 's2idle':      3912         if sysvals.suspendmode == 's2idle':
3931                 sysvals.suspendmode = 'freeze    3913                 sysvals.suspendmode = 'freeze'
3932         elif sysvals.suspendmode == 'deep':      3914         elif sysvals.suspendmode == 'deep':
3933                 sysvals.suspendmode = 'mem'      3915                 sysvals.suspendmode = 'mem'
3934         if data:                                 3916         if data:
3935                 testruns.append(data)            3917                 testruns.append(data)
3936         if len(testruns) < 1:                    3918         if len(testruns) < 1:
3937                 doError('dmesg log has no sus    3919                 doError('dmesg log has no suspend/resume data: %s' \
3938                         % sysvals.dmesgfile)     3920                         % sysvals.dmesgfile)
3939                                                  3921 
3940         # fix lines with same timestamp/funct    3922         # fix lines with same timestamp/function with the call and return swapped
3941         for data in testruns:                    3923         for data in testruns:
3942                 last = ''                        3924                 last = ''
3943                 for line in data.dmesgtext:      3925                 for line in data.dmesgtext:
3944                         ct, cf, n, p = data.i    3926                         ct, cf, n, p = data.initcall_debug_call(line)
3945                         rt, rf, l = data.init    3927                         rt, rf, l = data.initcall_debug_return(last)
3946                         if ct and rt and ct =    3928                         if ct and rt and ct == rt and cf == rf:
3947                                 i = data.dmes    3929                                 i = data.dmesgtext.index(last)
3948                                 j = data.dmes    3930                                 j = data.dmesgtext.index(line)
3949                                 data.dmesgtex    3931                                 data.dmesgtext[i] = line
3950                                 data.dmesgtex    3932                                 data.dmesgtext[j] = last
3951                         last = line              3933                         last = line
3952         return testruns                          3934         return testruns
3953                                                  3935 
3954 # Function: parseKernelLog                       3936 # Function: parseKernelLog
3955 # Description:                                   3937 # Description:
3956 #        Analyse a dmesg log output file gene    3938 #        Analyse a dmesg log output file generated from this app during
3957 #        the execution phase. Create a set of    3939 #        the execution phase. Create a set of device structures in memory
3958 #        for subsequent formatting in the htm    3940 #        for subsequent formatting in the html output file
3959 #        This call is only for legacy support    3941 #        This call is only for legacy support on kernels where the ftrace
3960 #        data lacks the suspend_resume or dev    3942 #        data lacks the suspend_resume or device_pm_callbacks trace events.
3961 # Arguments:                                     3943 # Arguments:
3962 #        data: an empty Data object (with dme    3944 #        data: an empty Data object (with dmesgtext) obtained from loadKernelLog
3963 # Output:                                        3945 # Output:
3964 #        The filled Data object                  3946 #        The filled Data object
3965 def parseKernelLog(data):                        3947 def parseKernelLog(data):
3966         phase = 'suspend_runtime'                3948         phase = 'suspend_runtime'
3967                                                  3949 
3968         if(data.fwValid):                        3950         if(data.fwValid):
3969                 sysvals.vprint('Firmware Susp    3951                 sysvals.vprint('Firmware Suspend = %u ns, Firmware Resume = %u ns' % \
3970                         (data.fwSuspend, data    3952                         (data.fwSuspend, data.fwResume))
3971                                                  3953 
3972         # dmesg phase match table                3954         # dmesg phase match table
3973         dm = {                                   3955         dm = {
3974                 'suspend_prepare': ['PM: Sync    3956                 'suspend_prepare': ['PM: Syncing filesystems.*', 'PM: suspend entry.*'],
3975                         'suspend': ['PM: Ente    3957                         'suspend': ['PM: Entering [a-z]* sleep.*', 'Suspending console.*',
3976                                     'PM: Susp    3958                                     'PM: Suspending system .*'],
3977                    'suspend_late': ['PM: susp    3959                    'suspend_late': ['PM: suspend of devices complete after.*',
3978                                                  3960                                                         'PM: freeze of devices complete after.*'],
3979                   'suspend_noirq': ['PM: late    3961                   'suspend_noirq': ['PM: late suspend of devices complete after.*',
3980                                                  3962                                                         'PM: late freeze of devices complete after.*'],
3981                 'suspend_machine': ['PM: susp    3963                 'suspend_machine': ['PM: suspend-to-idle',
3982                                                  3964                                                         'PM: noirq suspend of devices complete after.*',
3983                                                  3965                                                         'PM: noirq freeze of devices complete after.*'],
3984                  'resume_machine': ['[PM: ]*T !! 3966                  'resume_machine': ['PM: Timekeeping suspended for.*',
3985                                                  3967                                                         'ACPI: Low-level resume complete.*',
3986                                                  3968                                                         'ACPI: resume from mwait',
3987                                               !! 3969                                                         'Suspended for [0-9\.]* seconds'],
3988                    'resume_noirq': ['PM: resu    3970                    'resume_noirq': ['PM: resume from suspend-to-idle',
3989                                                  3971                                                         'ACPI: Waking up from system sleep state.*'],
3990                    'resume_early': ['PM: noir    3972                    'resume_early': ['PM: noirq resume of devices complete after.*',
3991                                                  3973                                                         'PM: noirq restore of devices complete after.*'],
3992                          'resume': ['PM: earl    3974                          'resume': ['PM: early resume of devices complete after.*',
3993                                                  3975                                                         'PM: early restore of devices complete after.*'],
3994                 'resume_complete': ['PM: resu    3976                 'resume_complete': ['PM: resume of devices complete after.*',
3995                                                  3977                                                         'PM: restore of devices complete after.*'],
3996                     'post_resume': [r'.*Resta !! 3978                     'post_resume': ['.*Restarting tasks \.\.\..*'],
3997         }                                        3979         }
3998                                                  3980 
3999         # action table (expected events that     3981         # action table (expected events that occur and show up in dmesg)
4000         at = {                                   3982         at = {
4001                 'sync_filesystems': {            3983                 'sync_filesystems': {
4002                         'smsg': '.*[Ff]+ilesy !! 3984                         'smsg': 'PM: Syncing filesystems.*',
4003                         'emsg': 'PM: Preparin !! 3985                         'emsg': 'PM: Preparing system for mem sleep.*' },
4004                 'freeze_user_processes': {       3986                 'freeze_user_processes': {
4005                         'smsg': 'Freezing use !! 3987                         'smsg': 'Freezing user space processes .*',
4006                         'emsg': 'Freezing rem    3988                         'emsg': 'Freezing remaining freezable tasks.*' },
4007                 'freeze_tasks': {                3989                 'freeze_tasks': {
4008                         'smsg': 'Freezing rem    3990                         'smsg': 'Freezing remaining freezable tasks.*',
4009                         'emsg': 'PM: Suspendi !! 3991                         'emsg': 'PM: Entering (?P<mode>[a-z,A-Z]*) sleep.*' },
4010                 'ACPI prepare': {                3992                 'ACPI prepare': {
4011                         'smsg': 'ACPI: Prepar    3993                         'smsg': 'ACPI: Preparing to enter system sleep state.*',
4012                         'emsg': 'PM: Saving p    3994                         'emsg': 'PM: Saving platform NVS memory.*' },
4013                 'PM vns': {                      3995                 'PM vns': {
4014                         'smsg': 'PM: Saving p    3996                         'smsg': 'PM: Saving platform NVS memory.*',
4015                         'emsg': 'Disabling no    3997                         'emsg': 'Disabling non-boot CPUs .*' },
4016         }                                        3998         }
4017                                                  3999 
4018         t0 = -1.0                                4000         t0 = -1.0
4019         cpu_start = -1.0                         4001         cpu_start = -1.0
4020         prevktime = -1.0                         4002         prevktime = -1.0
4021         actions = dict()                         4003         actions = dict()
4022         for line in data.dmesgtext:              4004         for line in data.dmesgtext:
4023                 # parse each dmesg line into     4005                 # parse each dmesg line into the time and message
4024                 m = re.match(r'[ \t]*(\[ *)(? !! 4006                 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
4025                 if(m):                           4007                 if(m):
4026                         val = m.group('ktime'    4008                         val = m.group('ktime')
4027                         try:                     4009                         try:
4028                                 ktime = float    4010                                 ktime = float(val)
4029                         except:                  4011                         except:
4030                                 continue         4012                                 continue
4031                         msg = m.group('msg')     4013                         msg = m.group('msg')
4032                         # initialize data sta    4014                         # initialize data start to first line time
4033                         if t0 < 0:               4015                         if t0 < 0:
4034                                 data.setStart    4016                                 data.setStart(ktime)
4035                                 t0 = ktime       4017                                 t0 = ktime
4036                 else:                            4018                 else:
4037                         continue                 4019                         continue
4038                                                  4020 
4039                 # check for a phase change li    4021                 # check for a phase change line
4040                 phasechange = False              4022                 phasechange = False
4041                 for p in dm:                     4023                 for p in dm:
4042                         for s in dm[p]:          4024                         for s in dm[p]:
4043                                 if(re.match(s    4025                                 if(re.match(s, msg)):
4044                                         phase    4026                                         phasechange, phase = True, p
4045                                         dm[p]    4027                                         dm[p] = [s]
4046                                         break    4028                                         break
4047                                                  4029 
4048                 # hack for determining resume    4030                 # hack for determining resume_machine end for freeze
4049                 if(not sysvals.usetraceevents    4031                 if(not sysvals.usetraceevents and sysvals.suspendmode == 'freeze' \
4050                         and phase == 'resume_    4032                         and phase == 'resume_machine' and \
4051                         data.initcall_debug_c    4033                         data.initcall_debug_call(line, True)):
4052                         data.setPhase(phase,     4034                         data.setPhase(phase, ktime, False)
4053                         phase = 'resume_noirq    4035                         phase = 'resume_noirq'
4054                         data.setPhase(phase,     4036                         data.setPhase(phase, ktime, True)
4055                                                  4037 
4056                 if phasechange:                  4038                 if phasechange:
4057                         if phase == 'suspend_    4039                         if phase == 'suspend_prepare':
4058                                 data.setPhase    4040                                 data.setPhase(phase, ktime, True)
4059                                 data.setStart    4041                                 data.setStart(ktime)
4060                                 data.tKernSus    4042                                 data.tKernSus = ktime
4061                         elif phase == 'suspen    4043                         elif phase == 'suspend':
4062                                 lp = data.las    4044                                 lp = data.lastPhase()
4063                                 if lp:           4045                                 if lp:
4064                                         data.    4046                                         data.setPhase(lp, ktime, False)
4065                                 data.setPhase    4047                                 data.setPhase(phase, ktime, True)
4066                         elif phase == 'suspen    4048                         elif phase == 'suspend_late':
4067                                 lp = data.las    4049                                 lp = data.lastPhase()
4068                                 if lp:           4050                                 if lp:
4069                                         data.    4051                                         data.setPhase(lp, ktime, False)
4070                                 data.setPhase    4052                                 data.setPhase(phase, ktime, True)
4071                         elif phase == 'suspen    4053                         elif phase == 'suspend_noirq':
4072                                 lp = data.las    4054                                 lp = data.lastPhase()
4073                                 if lp:           4055                                 if lp:
4074                                         data.    4056                                         data.setPhase(lp, ktime, False)
4075                                 data.setPhase    4057                                 data.setPhase(phase, ktime, True)
4076                         elif phase == 'suspen    4058                         elif phase == 'suspend_machine':
4077                                 lp = data.las    4059                                 lp = data.lastPhase()
4078                                 if lp:           4060                                 if lp:
4079                                         data.    4061                                         data.setPhase(lp, ktime, False)
4080                                 data.setPhase    4062                                 data.setPhase(phase, ktime, True)
4081                         elif phase == 'resume    4063                         elif phase == 'resume_machine':
4082                                 lp = data.las    4064                                 lp = data.lastPhase()
4083                                 if(sysvals.su    4065                                 if(sysvals.suspendmode in ['freeze', 'standby']):
4084                                         data.    4066                                         data.tSuspended = prevktime
4085                                         if lp    4067                                         if lp:
4086                                                  4068                                                 data.setPhase(lp, prevktime, False)
4087                                 else:            4069                                 else:
4088                                         data.    4070                                         data.tSuspended = ktime
4089                                         if lp    4071                                         if lp:
4090                                                  4072                                                 data.setPhase(lp, prevktime, False)
4091                                 data.tResumed    4073                                 data.tResumed = ktime
4092                                 data.setPhase    4074                                 data.setPhase(phase, ktime, True)
4093                         elif phase == 'resume    4075                         elif phase == 'resume_noirq':
4094                                 lp = data.las    4076                                 lp = data.lastPhase()
4095                                 if lp:           4077                                 if lp:
4096                                         data.    4078                                         data.setPhase(lp, ktime, False)
4097                                 data.setPhase    4079                                 data.setPhase(phase, ktime, True)
4098                         elif phase == 'resume    4080                         elif phase == 'resume_early':
4099                                 lp = data.las    4081                                 lp = data.lastPhase()
4100                                 if lp:           4082                                 if lp:
4101                                         data.    4083                                         data.setPhase(lp, ktime, False)
4102                                 data.setPhase    4084                                 data.setPhase(phase, ktime, True)
4103                         elif phase == 'resume    4085                         elif phase == 'resume':
4104                                 lp = data.las    4086                                 lp = data.lastPhase()
4105                                 if lp:           4087                                 if lp:
4106                                         data.    4088                                         data.setPhase(lp, ktime, False)
4107                                 data.setPhase    4089                                 data.setPhase(phase, ktime, True)
4108                         elif phase == 'resume    4090                         elif phase == 'resume_complete':
4109                                 lp = data.las    4091                                 lp = data.lastPhase()
4110                                 if lp:           4092                                 if lp:
4111                                         data.    4093                                         data.setPhase(lp, ktime, False)
4112                                 data.setPhase    4094                                 data.setPhase(phase, ktime, True)
4113                         elif phase == 'post_r    4095                         elif phase == 'post_resume':
4114                                 lp = data.las    4096                                 lp = data.lastPhase()
4115                                 if lp:           4097                                 if lp:
4116                                         data.    4098                                         data.setPhase(lp, ktime, False)
4117                                 data.setEnd(k    4099                                 data.setEnd(ktime)
4118                                 data.tKernRes    4100                                 data.tKernRes = ktime
4119                                 break            4101                                 break
4120                                                  4102 
4121                 # -- device callbacks --         4103                 # -- device callbacks --
4122                 if(phase in data.sortedPhases    4104                 if(phase in data.sortedPhases()):
4123                         # device init call       4105                         # device init call
4124                         t, f, n, p = data.ini    4106                         t, f, n, p = data.initcall_debug_call(line)
4125                         if t and f and n and     4107                         if t and f and n and p:
4126                                 data.newActio    4108                                 data.newAction(phase, f, int(n), p, ktime, -1, '')
4127                         else:                    4109                         else:
4128                                 # device init    4110                                 # device init return
4129                                 t, f, l = dat    4111                                 t, f, l = data.initcall_debug_return(line)
4130                                 if t and f an    4112                                 if t and f and l:
4131                                         list     4113                                         list = data.dmesg[phase]['list']
4132                                         if(f     4114                                         if(f in list):
4133                                                  4115                                                 dev = list[f]
4134                                                  4116                                                 dev['length'] = int(l)
4135                                                  4117                                                 dev['end'] = ktime
4136                                                  4118 
4137                 # if trace events are not ava    4119                 # if trace events are not available, these are better than nothing
4138                 if(not sysvals.usetraceevents    4120                 if(not sysvals.usetraceevents):
4139                         # look for known acti    4121                         # look for known actions
4140                         for a in sorted(at):     4122                         for a in sorted(at):
4141                                 if(re.match(a    4123                                 if(re.match(at[a]['smsg'], msg)):
4142                                         if(a     4124                                         if(a not in actions):
4143                                               !! 4125                                                 actions[a] = []
                                                   >> 4126                                         actions[a].append({'begin': ktime, 'end': ktime})
4144                                 if(re.match(a    4127                                 if(re.match(at[a]['emsg'], msg)):
4145                                         if(a  !! 4128                                         if(a in actions):
4146                                                  4129                                                 actions[a][-1]['end'] = ktime
4147                         # now look for CPU on    4130                         # now look for CPU on/off events
4148                         if(re.match(r'Disabli !! 4131                         if(re.match('Disabling non-boot CPUs .*', msg)):
4149                                 # start of fi    4132                                 # start of first cpu suspend
4150                                 cpu_start = k    4133                                 cpu_start = ktime
4151                         elif(re.match(r'Enabl !! 4134                         elif(re.match('Enabling non-boot CPUs .*', msg)):
4152                                 # start of fi    4135                                 # start of first cpu resume
4153                                 cpu_start = k    4136                                 cpu_start = ktime
4154                         elif(re.match(r'smpbo !! 4137                         elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)):
4155                                 or re.match(r << 
4156                                 # end of a cp    4138                                 # end of a cpu suspend, start of the next
4157                                 m = re.match( !! 4139                                 m = re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)
4158                                 if(not m):    << 
4159                                         m = r << 
4160                                 cpu = 'CPU'+m    4140                                 cpu = 'CPU'+m.group('cpu')
4161                                 if(cpu not in    4141                                 if(cpu not in actions):
4162                                         actio    4142                                         actions[cpu] = []
4163                                 actions[cpu].    4143                                 actions[cpu].append({'begin': cpu_start, 'end': ktime})
4164                                 cpu_start = k    4144                                 cpu_start = ktime
4165                         elif(re.match(r'CPU(? !! 4145                         elif(re.match('CPU(?P<cpu>[0-9]*) is up', msg)):
4166                                 # end of a cp    4146                                 # end of a cpu resume, start of the next
4167                                 m = re.match( !! 4147                                 m = re.match('CPU(?P<cpu>[0-9]*) is up', msg)
4168                                 cpu = 'CPU'+m    4148                                 cpu = 'CPU'+m.group('cpu')
4169                                 if(cpu not in    4149                                 if(cpu not in actions):
4170                                         actio    4150                                         actions[cpu] = []
4171                                 actions[cpu].    4151                                 actions[cpu].append({'begin': cpu_start, 'end': ktime})
4172                                 cpu_start = k    4152                                 cpu_start = ktime
4173                 prevktime = ktime                4153                 prevktime = ktime
4174         data.initDevicegroups()                  4154         data.initDevicegroups()
4175                                                  4155 
4176         # fill in any missing phases             4156         # fill in any missing phases
4177         phasedef = data.phasedef                 4157         phasedef = data.phasedef
4178         terr, lp = '', 'suspend_prepare'         4158         terr, lp = '', 'suspend_prepare'
4179         if lp not in data.dmesg:                 4159         if lp not in data.dmesg:
4180                 doError('dmesg log format has    4160                 doError('dmesg log format has changed, could not find start of suspend')
4181         for p in sorted(phasedef, key=lambda     4161         for p in sorted(phasedef, key=lambda k:phasedef[k]['order']):
4182                 if p not in data.dmesg:          4162                 if p not in data.dmesg:
4183                         if not terr:             4163                         if not terr:
4184                                 pprint('TEST     4164                                 pprint('TEST FAILED: %s failed in %s phase' % (sysvals.suspendmode, lp))
4185                                 terr = '%s fa    4165                                 terr = '%s failed in %s phase' % (sysvals.suspendmode, lp)
4186                                 if data.tSusp    4166                                 if data.tSuspended == 0:
4187                                         data.    4167                                         data.tSuspended = data.dmesg[lp]['end']
4188                                 if data.tResu    4168                                 if data.tResumed == 0:
4189                                         data.    4169                                         data.tResumed = data.dmesg[lp]['end']
4190                         sysvals.vprint('WARNI    4170                         sysvals.vprint('WARNING: phase "%s" is missing!' % p)
4191                 lp = p                           4171                 lp = p
4192         lp = data.sortedPhases()[0]              4172         lp = data.sortedPhases()[0]
4193         for p in data.sortedPhases():            4173         for p in data.sortedPhases():
4194                 if(p != lp and not ('machine'    4174                 if(p != lp and not ('machine' in p and 'machine' in lp)):
4195                         data.dmesg[lp]['end']    4175                         data.dmesg[lp]['end'] = data.dmesg[p]['start']
4196                 lp = p                           4176                 lp = p
4197         if data.tSuspended == 0:                 4177         if data.tSuspended == 0:
4198                 data.tSuspended = data.tKernR    4178                 data.tSuspended = data.tKernRes
4199         if data.tResumed == 0:                   4179         if data.tResumed == 0:
4200                 data.tResumed = data.tSuspend    4180                 data.tResumed = data.tSuspended
4201                                                  4181 
4202         # fill in any actions we've found        4182         # fill in any actions we've found
4203         for name in sorted(actions):             4183         for name in sorted(actions):
4204                 for event in actions[name]:      4184                 for event in actions[name]:
4205                         data.newActionGlobal(    4185                         data.newActionGlobal(name, event['begin'], event['end'])
4206                                                  4186 
4207         if(len(sysvals.devicefilter) > 0):       4187         if(len(sysvals.devicefilter) > 0):
4208                 data.deviceFilter(sysvals.dev    4188                 data.deviceFilter(sysvals.devicefilter)
4209         data.fixupInitcallsThatDidntReturn()     4189         data.fixupInitcallsThatDidntReturn()
4210         return True                              4190         return True
4211                                                  4191 
4212 def callgraphHTML(sv, hf, num, cg, title, col    4192 def callgraphHTML(sv, hf, num, cg, title, color, devid):
4213         html_func_top = '<article id="{0}" cl    4193         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     4194         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'           4195         html_func_end = '</article>\n'
4216         html_func_leaf = '<article>{0} {1}</a    4196         html_func_leaf = '<article>{0} {1}</article>\n'
4217                                                  4197 
4218         cgid = devid                             4198         cgid = devid
4219         if cg.id:                                4199         if cg.id:
4220                 cgid += cg.id                    4200                 cgid += cg.id
4221         cglen = (cg.end - cg.start) * 1000       4201         cglen = (cg.end - cg.start) * 1000
4222         if cglen < sv.mincglen:                  4202         if cglen < sv.mincglen:
4223                 return num                       4203                 return num
4224                                                  4204 
4225         fmt = '<r>(%.3f ms @ '+sv.timeformat+'    4205         fmt = '<r>(%.3f ms @ '+sv.timeformat+' to '+sv.timeformat+')</r>'
4226         flen = fmt % (cglen, cg.start, cg.end    4206         flen = fmt % (cglen, cg.start, cg.end)
4227         hf.write(html_func_top.format(cgid, c    4207         hf.write(html_func_top.format(cgid, color, num, title, flen))
4228         num += 1                                 4208         num += 1
4229         for line in cg.list:                     4209         for line in cg.list:
4230                 if(line.length < 0.000000001)    4210                 if(line.length < 0.000000001):
4231                         flen = ''                4211                         flen = ''
4232                 else:                            4212                 else:
4233                         fmt = '<n>(%.3f ms @ '    4213                         fmt = '<n>(%.3f ms @ '+sv.timeformat+')</n>'
4234                         flen = fmt % (line.le    4214                         flen = fmt % (line.length*1000, line.time)
4235                 if line.isLeaf():                4215                 if line.isLeaf():
4236                         if line.length * 1000 << 
4237                                 continue      << 
4238                         hf.write(html_func_le    4216                         hf.write(html_func_leaf.format(line.name, flen))
4239                 elif line.freturn:               4217                 elif line.freturn:
4240                         hf.write(html_func_en    4218                         hf.write(html_func_end)
4241                 else:                            4219                 else:
4242                         hf.write(html_func_st    4220                         hf.write(html_func_start.format(num, line.name, flen))
4243                         num += 1                 4221                         num += 1
4244         hf.write(html_func_end)                  4222         hf.write(html_func_end)
4245         return num                               4223         return num
4246                                                  4224 
4247 def addCallgraphs(sv, hf, data):                 4225 def addCallgraphs(sv, hf, data):
4248         hf.write('<section id="callgraphs" cl    4226         hf.write('<section id="callgraphs" class="callgraph">\n')
4249         # write out the ftrace data converted    4227         # write out the ftrace data converted to html
4250         num = 0                                  4228         num = 0
4251         for p in data.sortedPhases():            4229         for p in data.sortedPhases():
4252                 if sv.cgphase and p != sv.cgp    4230                 if sv.cgphase and p != sv.cgphase:
4253                         continue                 4231                         continue
4254                 list = data.dmesg[p]['list']     4232                 list = data.dmesg[p]['list']
4255                 for d in data.sortedDevices(p    4233                 for d in data.sortedDevices(p):
4256                         if len(sv.cgfilter) >    4234                         if len(sv.cgfilter) > 0 and d not in sv.cgfilter:
4257                                 continue         4235                                 continue
4258                         dev = list[d]            4236                         dev = list[d]
4259                         color = 'white'          4237                         color = 'white'
4260                         if 'color' in data.dm    4238                         if 'color' in data.dmesg[p]:
4261                                 color = data.    4239                                 color = data.dmesg[p]['color']
4262                         if 'color' in dev:       4240                         if 'color' in dev:
4263                                 color = dev['    4241                                 color = dev['color']
4264                         name = d if '[' not i    4242                         name = d if '[' not in d else d.split('[')[0]
4265                         if(d in sv.devprops):    4243                         if(d in sv.devprops):
4266                                 name = sv.dev    4244                                 name = sv.devprops[d].altName(d)
4267                         if 'drv' in dev and d    4245                         if 'drv' in dev and dev['drv']:
4268                                 name += ' {%s    4246                                 name += ' {%s}' % dev['drv']
4269                         if sv.suspendmode in     4247                         if sv.suspendmode in suspendmodename:
4270                                 name += ' '+p    4248                                 name += ' '+p
4271                         if('ftrace' in dev):     4249                         if('ftrace' in dev):
4272                                 cg = dev['ftr    4250                                 cg = dev['ftrace']
4273                                 if cg.name ==    4251                                 if cg.name == sv.ftopfunc:
4274                                         name     4252                                         name = 'top level suspend/resume call'
4275                                 num = callgra    4253                                 num = callgraphHTML(sv, hf, num, cg,
4276                                         name,    4254                                         name, color, dev['id'])
4277                         if('ftraces' in dev):    4255                         if('ftraces' in dev):
4278                                 for cg in dev    4256                                 for cg in dev['ftraces']:
4279                                         num =    4257                                         num = callgraphHTML(sv, hf, num, cg,
4280                                                  4258                                                 name+' &rarr; '+cg.name, color, dev['id'])
4281         hf.write('\n\n    </section>\n')         4259         hf.write('\n\n    </section>\n')
4282                                                  4260 
4283 def summaryCSS(title, center=True):              4261 def summaryCSS(title, center=True):
4284         tdcenter = 'text-align:center;' if ce    4262         tdcenter = 'text-align:center;' if center else ''
4285         out = '<!DOCTYPE html>\n<html>\n<head    4263         out = '<!DOCTYPE html>\n<html>\n<head>\n\
4286         <meta http-equiv="content-type" conte    4264         <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\
4287         <title>'+title+'</title>\n\              4265         <title>'+title+'</title>\n\
4288         <style type=\'text/css\'>\n\             4266         <style type=\'text/css\'>\n\
4289                 .stamp {width: 100%;text-alig    4267                 .stamp {width: 100%;text-align:center;background:#888;line-height:30px;color:white;font: 25px Arial;}\n\
4290                 table {width:100%;border-coll    4268                 table {width:100%;border-collapse: collapse;border:1px solid;}\n\
4291                 th {border: 1px solid black;b    4269                 th {border: 1px solid black;background:#222;color:white;}\n\
4292                 td {font: 14px "Times New Rom    4270                 td {font: 14px "Times New Roman";'+tdcenter+'}\n\
4293                 tr.head td {border: 1px solid    4271                 tr.head td {border: 1px solid black;background:#aaa;}\n\
4294                 tr.alt {background-color:#ddd    4272                 tr.alt {background-color:#ddd;}\n\
4295                 tr.notice {color:red;}\n\        4273                 tr.notice {color:red;}\n\
4296                 .minval {background-color:#BB    4274                 .minval {background-color:#BBFFBB;}\n\
4297                 .medval {background-color:#BB    4275                 .medval {background-color:#BBBBFF;}\n\
4298                 .maxval {background-color:#FF    4276                 .maxval {background-color:#FFBBBB;}\n\
4299                 .head a {color:#000;text-deco    4277                 .head a {color:#000;text-decoration: none;}\n\
4300         </style>\n</head>\n<body>\n'             4278         </style>\n</head>\n<body>\n'
4301         return out                               4279         return out
4302                                                  4280 
4303 # Function: createHTMLSummarySimple              4281 # Function: createHTMLSummarySimple
4304 # Description:                                   4282 # Description:
4305 #        Create summary html file for a serie    4283 #        Create summary html file for a series of tests
4306 # Arguments:                                     4284 # Arguments:
4307 #        testruns: array of Data objects from    4285 #        testruns: array of Data objects from parseTraceLog
4308 def createHTMLSummarySimple(testruns, htmlfil    4286 def createHTMLSummarySimple(testruns, htmlfile, title):
4309         # write the html header first (html h    4287         # write the html header first (html head, css code, up to body start)
4310         html = summaryCSS('Summary - SleepGra    4288         html = summaryCSS('Summary - SleepGraph')
4311                                                  4289 
4312         # extract the test data into list        4290         # extract the test data into list
4313         list = dict()                            4291         list = dict()
4314         tAvg, tMin, tMax, tMed = [0.0, 0.0],     4292         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    4293         iMin, iMed, iMax = [0, 0], [0, 0], [0, 0]
4316         num = 0                                  4294         num = 0
4317         useturbo = usewifi = False               4295         useturbo = usewifi = False
4318         lastmode = ''                            4296         lastmode = ''
4319         cnt = dict()                             4297         cnt = dict()
4320         for data in sorted(testruns, key=lamb    4298         for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])):
4321                 mode = data['mode']              4299                 mode = data['mode']
4322                 if mode not in list:             4300                 if mode not in list:
4323                         list[mode] = {'data':    4301                         list[mode] = {'data': [], 'avg': [0,0], 'min': [0,0], 'max': [0,0], 'med': [0,0]}
4324                 if lastmode and lastmode != m    4302                 if lastmode and lastmode != mode and num > 0:
4325                         for i in range(2):       4303                         for i in range(2):
4326                                 s = sorted(tM    4304                                 s = sorted(tMed[i])
4327                                 list[lastmode    4305                                 list[lastmode]['med'][i] = s[int(len(s)//2)]
4328                                 iMed[i] = tMe    4306                                 iMed[i] = tMed[i][list[lastmode]['med'][i]]
4329                         list[lastmode]['avg']    4307                         list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num]
4330                         list[lastmode]['min']    4308                         list[lastmode]['min'] = tMin
4331                         list[lastmode]['max']    4309                         list[lastmode]['max'] = tMax
4332                         list[lastmode]['idx']    4310                         list[lastmode]['idx'] = (iMin, iMed, iMax)
4333                         tAvg, tMin, tMax, tMe    4311                         tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [dict(), dict()]
4334                         iMin, iMed, iMax = [0    4312                         iMin, iMed, iMax = [0, 0], [0, 0], [0, 0]
4335                         num = 0                  4313                         num = 0
4336                 pkgpc10 = syslpi = wifi = ''     4314                 pkgpc10 = syslpi = wifi = ''
4337                 if 'pkgpc10' in data and 'sys    4315                 if 'pkgpc10' in data and 'syslpi' in data:
4338                         pkgpc10, syslpi, uset    4316                         pkgpc10, syslpi, useturbo = data['pkgpc10'], data['syslpi'], True
4339                 if 'wifi' in data:               4317                 if 'wifi' in data:
4340                         wifi, usewifi = data[    4318                         wifi, usewifi = data['wifi'], True
4341                 res = data['result']             4319                 res = data['result']
4342                 tVal = [float(data['suspend']    4320                 tVal = [float(data['suspend']), float(data['resume'])]
4343                 list[mode]['data'].append([da    4321                 list[mode]['data'].append([data['host'], data['kernel'],
4344                         data['time'], tVal[0]    4322                         data['time'], tVal[0], tVal[1], data['url'], res,
4345                         data['issues'], data[    4323                         data['issues'], data['sus_worst'], data['sus_worsttime'],
4346                         data['res_worst'], da !! 4324                         data['res_worst'], data['res_worsttime'], pkgpc10, syslpi, wifi])
4347                         (data['fullmode'] if  << 
4348                 idx = len(list[mode]['data'])    4325                 idx = len(list[mode]['data']) - 1
4349                 if res.startswith('fail in'):    4326                 if res.startswith('fail in'):
4350                         res = 'fail'             4327                         res = 'fail'
4351                 if res not in cnt:               4328                 if res not in cnt:
4352                         cnt[res] = 1             4329                         cnt[res] = 1
4353                 else:                            4330                 else:
4354                         cnt[res] += 1            4331                         cnt[res] += 1
4355                 if res == 'pass':                4332                 if res == 'pass':
4356                         for i in range(2):       4333                         for i in range(2):
4357                                 tMed[i][tVal[    4334                                 tMed[i][tVal[i]] = idx
4358                                 tAvg[i] += tV    4335                                 tAvg[i] += tVal[i]
4359                                 if tMin[i] ==    4336                                 if tMin[i] == 0 or tVal[i] < tMin[i]:
4360                                         iMin[    4337                                         iMin[i] = idx
4361                                         tMin[    4338                                         tMin[i] = tVal[i]
4362                                 if tMax[i] ==    4339                                 if tMax[i] == 0 or tVal[i] > tMax[i]:
4363                                         iMax[    4340                                         iMax[i] = idx
4364                                         tMax[    4341                                         tMax[i] = tVal[i]
4365                         num += 1                 4342                         num += 1
4366                 lastmode = mode                  4343                 lastmode = mode
4367         if lastmode and num > 0:                 4344         if lastmode and num > 0:
4368                 for i in range(2):               4345                 for i in range(2):
4369                         s = sorted(tMed[i])      4346                         s = sorted(tMed[i])
4370                         list[lastmode]['med']    4347                         list[lastmode]['med'][i] = s[int(len(s)//2)]
4371                         iMed[i] = tMed[i][lis    4348                         iMed[i] = tMed[i][list[lastmode]['med'][i]]
4372                 list[lastmode]['avg'] = [tAvg    4349                 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num]
4373                 list[lastmode]['min'] = tMin     4350                 list[lastmode]['min'] = tMin
4374                 list[lastmode]['max'] = tMax     4351                 list[lastmode]['max'] = tMax
4375                 list[lastmode]['idx'] = (iMin    4352                 list[lastmode]['idx'] = (iMin, iMed, iMax)
4376                                                  4353 
4377         # group test header                      4354         # group test header
4378         desc = []                                4355         desc = []
4379         for ilk in sorted(cnt, reverse=True):    4356         for ilk in sorted(cnt, reverse=True):
4380                 if cnt[ilk] > 0:                 4357                 if cnt[ilk] > 0:
4381                         desc.append('%d %s' %    4358                         desc.append('%d %s' % (cnt[ilk], ilk))
4382         html += '<div class="stamp">%s (%d te    4359         html += '<div class="stamp">%s (%d tests: %s)</div>\n' % (title, len(testruns), ', '.join(desc))
4383         th = '\t<th>{0}</th>\n'                  4360         th = '\t<th>{0}</th>\n'
4384         td = '\t<td>{0}</td>\n'                  4361         td = '\t<td>{0}</td>\n'
4385         tdh = '\t<td{1}>{0}</td>\n'              4362         tdh = '\t<td{1}>{0}</td>\n'
4386         tdlink = '\t<td><a href="{0}">html</a    4363         tdlink = '\t<td><a href="{0}">html</a></td>\n'
4387         cols = 12                                4364         cols = 12
4388         if useturbo:                             4365         if useturbo:
4389                 cols += 2                        4366                 cols += 2
4390         if usewifi:                              4367         if usewifi:
4391                 cols += 1                        4368                 cols += 1
4392         colspan = '%d' % cols                    4369         colspan = '%d' % cols
4393                                                  4370 
4394         # table header                           4371         # table header
4395         html += '<table>\n<tr>\n' + th.format    4372         html += '<table>\n<tr>\n' + th.format('#') +\
4396                 th.format('Mode') + th.format    4373                 th.format('Mode') + th.format('Host') + th.format('Kernel') +\
4397                 th.format('Test Time') + th.f    4374                 th.format('Test Time') + th.format('Result') + th.format('Issues') +\
4398                 th.format('Suspend') + th.for    4375                 th.format('Suspend') + th.format('Resume') +\
4399                 th.format('Worst Suspend Devi    4376                 th.format('Worst Suspend Device') + th.format('SD Time') +\
4400                 th.format('Worst Resume Devic    4377                 th.format('Worst Resume Device') + th.format('RD Time')
4401         if useturbo:                             4378         if useturbo:
4402                 html += th.format('PkgPC10')     4379                 html += th.format('PkgPC10') + th.format('SysLPI')
4403         if usewifi:                              4380         if usewifi:
4404                 html += th.format('Wifi')        4381                 html += th.format('Wifi')
4405         html += th.format('Detail')+'</tr>\n'    4382         html += th.format('Detail')+'</tr>\n'
4406         # export list into html                  4383         # export list into html
4407         head = '<tr class="head"><td>{0}</td>    4384         head = '<tr class="head"><td>{0}</td><td>{1}</td>'+\
4408                 '<td colspan='+colspan+' clas    4385                 '<td colspan='+colspan+' class="sus">Suspend Avg={2} '+\
4409                 '<span class=minval><a href="    4386                 '<span class=minval><a href="#s{10}min">Min={3}</a></span> '+\
4410                 '<span class=medval><a href="    4387                 '<span class=medval><a href="#s{10}med">Med={4}</a></span> '+\
4411                 '<span class=maxval><a href="    4388                 '<span class=maxval><a href="#s{10}max">Max={5}</a></span> '+\
4412                 'Resume Avg={6} '+\              4389                 'Resume Avg={6} '+\
4413                 '<span class=minval><a href="    4390                 '<span class=minval><a href="#r{10}min">Min={7}</a></span> '+\
4414                 '<span class=medval><a href="    4391                 '<span class=medval><a href="#r{10}med">Med={8}</a></span> '+\
4415                 '<span class=maxval><a href="    4392                 '<span class=maxval><a href="#r{10}max">Max={9}</a></span></td>'+\
4416                 '</tr>\n'                        4393                 '</tr>\n'
4417         headnone = '<tr class="head"><td>{0}<    4394         headnone = '<tr class="head"><td>{0}</td><td>{1}</td><td colspan='+\
4418                 colspan+'></td></tr>\n'          4395                 colspan+'></td></tr>\n'
4419         for mode in sorted(list):                4396         for mode in sorted(list):
4420                 # header line for each suspen    4397                 # header line for each suspend mode
4421                 num = 0                          4398                 num = 0
4422                 tAvg, tMin, tMax, tMed = list    4399                 tAvg, tMin, tMax, tMed = list[mode]['avg'], list[mode]['min'],\
4423                         list[mode]['max'], li    4400                         list[mode]['max'], list[mode]['med']
4424                 count = len(list[mode]['data'    4401                 count = len(list[mode]['data'])
4425                 if 'idx' in list[mode]:          4402                 if 'idx' in list[mode]:
4426                         iMin, iMed, iMax = li    4403                         iMin, iMed, iMax = list[mode]['idx']
4427                         html += head.format('    4404                         html += head.format('%d' % count, mode.upper(),
4428                                 '%.3f' % tAvg    4405                                 '%.3f' % tAvg[0], '%.3f' % tMin[0], '%.3f' % tMed[0], '%.3f' % tMax[0],
4429                                 '%.3f' % tAvg    4406                                 '%.3f' % tAvg[1], '%.3f' % tMin[1], '%.3f' % tMed[1], '%.3f' % tMax[1],
4430                                 mode.lower()     4407                                 mode.lower()
4431                         )                        4408                         )
4432                 else:                            4409                 else:
4433                         iMin = iMed = iMax =     4410                         iMin = iMed = iMax = [-1, -1, -1]
4434                         html += headnone.form    4411                         html += headnone.format('%d' % count, mode.upper())
4435                 for d in list[mode]['data']:     4412                 for d in list[mode]['data']:
4436                         # row classes - alter    4413                         # row classes - alternate row color
4437                         rcls = ['alt'] if num    4414                         rcls = ['alt'] if num % 2 == 1 else []
4438                         if d[6] != 'pass':       4415                         if d[6] != 'pass':
4439                                 rcls.append('    4416                                 rcls.append('notice')
4440                         html += '<tr class="'    4417                         html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n'
4441                         # figure out if the l    4418                         # figure out if the line has sus or res highlighted
4442                         idx = list[mode]['dat    4419                         idx = list[mode]['data'].index(d)
4443                         tHigh = ['', '']         4420                         tHigh = ['', '']
4444                         for i in range(2):       4421                         for i in range(2):
4445                                 tag = 's%s' %    4422                                 tag = 's%s' % mode if i == 0 else 'r%s' % mode
4446                                 if idx == iMi    4423                                 if idx == iMin[i]:
4447                                         tHigh    4424                                         tHigh[i] = ' id="%smin" class=minval title="Minimum"' % tag
4448                                 elif idx == i    4425                                 elif idx == iMax[i]:
4449                                         tHigh    4426                                         tHigh[i] = ' id="%smax" class=maxval title="Maximum"' % tag
4450                                 elif idx == i    4427                                 elif idx == iMed[i]:
4451                                         tHigh    4428                                         tHigh[i] = ' id="%smed" class=medval title="Median"' % tag
4452                         html += td.format("%d    4429                         html += td.format("%d" % (list[mode]['data'].index(d) + 1)) # row
4453                         html += td.format(d[1 !! 4430                         html += td.format(mode)                                                                         # mode
4454                         html += td.format(d[0    4431                         html += td.format(d[0])                                                                         # host
4455                         html += td.format(d[1    4432                         html += td.format(d[1])                                                                         # kernel
4456                         html += td.format(d[2    4433                         html += td.format(d[2])                                                                         # time
4457                         html += td.format(d[6    4434                         html += td.format(d[6])                                                                         # result
4458                         html += td.format(d[7    4435                         html += td.format(d[7])                                                                         # issues
4459                         html += tdh.format('%    4436                         html += tdh.format('%.3f ms' % d[3], tHigh[0]) if d[3] else td.format('')       # suspend
4460                         html += tdh.format('%    4437                         html += tdh.format('%.3f ms' % d[4], tHigh[1]) if d[4] else td.format('')       # resume
4461                         html += td.format(d[8    4438                         html += td.format(d[8])                                                                         # sus_worst
4462                         html += td.format('%.    4439                         html += td.format('%.3f ms' % d[9])     if d[9] else td.format('')              # sus_worst time
4463                         html += td.format(d[1    4440                         html += td.format(d[10])                                                                        # res_worst
4464                         html += td.format('%.    4441                         html += td.format('%.3f ms' % d[11]) if d[11] else td.format('')        # res_worst time
4465                         if useturbo:             4442                         if useturbo:
4466                                 html += td.fo    4443                                 html += td.format(d[12])                                                                # pkg_pc10
4467                                 html += td.fo    4444                                 html += td.format(d[13])                                                                # syslpi
4468                         if usewifi:              4445                         if usewifi:
4469                                 html += td.fo    4446                                 html += td.format(d[14])                                                                # wifi
4470                         html += tdlink.format    4447                         html += tdlink.format(d[5]) if d[5] else td.format('')          # url
4471                         html += '</tr>\n'        4448                         html += '</tr>\n'
4472                         num += 1                 4449                         num += 1
4473                                                  4450 
4474         # flush the data to file                 4451         # flush the data to file
4475         hf = open(htmlfile, 'w')                 4452         hf = open(htmlfile, 'w')
4476         hf.write(html+'</table>\n</body>\n</h    4453         hf.write(html+'</table>\n</body>\n</html>\n')
4477         hf.close()                               4454         hf.close()
4478                                                  4455 
4479 def createHTMLDeviceSummary(testruns, htmlfil    4456 def createHTMLDeviceSummary(testruns, htmlfile, title):
4480         html = summaryCSS('Device Summary - S    4457         html = summaryCSS('Device Summary - SleepGraph', False)
4481                                                  4458 
4482         # create global device list from all     4459         # create global device list from all tests
4483         devall = dict()                          4460         devall = dict()
4484         for data in testruns:                    4461         for data in testruns:
4485                 host, url, devlist = data['ho    4462                 host, url, devlist = data['host'], data['url'], data['devlist']
4486                 for type in devlist:             4463                 for type in devlist:
4487                         if type not in devall    4464                         if type not in devall:
4488                                 devall[type]     4465                                 devall[type] = dict()
4489                         mdevlist, devlist = d    4466                         mdevlist, devlist = devall[type], data['devlist'][type]
4490                         for name in devlist:     4467                         for name in devlist:
4491                                 length = devl    4468                                 length = devlist[name]
4492                                 if name not i    4469                                 if name not in mdevlist:
4493                                         mdevl    4470                                         mdevlist[name] = {'name': name, 'host': host,
4494                                                  4471                                                 'worst': length, 'total': length, 'count': 1,
4495                                                  4472                                                 'url': url}
4496                                 else:            4473                                 else:
4497                                         if le    4474                                         if length > mdevlist[name]['worst']:
4498                                                  4475                                                 mdevlist[name]['worst'] = length
4499                                                  4476                                                 mdevlist[name]['url'] = url
4500                                                  4477                                                 mdevlist[name]['host'] = host
4501                                         mdevl    4478                                         mdevlist[name]['total'] += length
4502                                         mdevl    4479                                         mdevlist[name]['count'] += 1
4503                                                  4480 
4504         # generate the html                      4481         # generate the html
4505         th = '\t<th>{0}</th>\n'                  4482         th = '\t<th>{0}</th>\n'
4506         td = '\t<td align=center>{0}</td>\n'     4483         td = '\t<td align=center>{0}</td>\n'
4507         tdr = '\t<td align=right>{0}</td>\n'     4484         tdr = '\t<td align=right>{0}</td>\n'
4508         tdlink = '\t<td align=center><a href=    4485         tdlink = '\t<td align=center><a href="{0}">html</a></td>\n'
4509         limit = 1                                4486         limit = 1
4510         for type in sorted(devall, reverse=Tr    4487         for type in sorted(devall, reverse=True):
4511                 num = 0                          4488                 num = 0
4512                 devlist = devall[type]           4489                 devlist = devall[type]
4513                 # table header                   4490                 # table header
4514                 html += '<div class="stamp">%    4491                 html += '<div class="stamp">%s (%s devices > %d ms)</div><table>\n' % \
4515                         (title, type.upper(),    4492                         (title, type.upper(), limit)
4516                 html += '<tr>\n' + '<th align    4493                 html += '<tr>\n' + '<th align=right>Device Name</th>' +\
4517                         th.format('Average Ti    4494                         th.format('Average Time') + th.format('Count') +\
4518                         th.format('Worst Time    4495                         th.format('Worst Time') + th.format('Host (worst time)') +\
4519                         th.format('Link (wors    4496                         th.format('Link (worst time)') + '</tr>\n'
4520                 for name in sorted(devlist, k    4497                 for name in sorted(devlist, key=lambda k:(devlist[k]['worst'], \
4521                         devlist[k]['total'],     4498                         devlist[k]['total'], devlist[k]['name']), reverse=True):
4522                         data = devall[type][n    4499                         data = devall[type][name]
4523                         data['average'] = dat    4500                         data['average'] = data['total'] / data['count']
4524                         if data['average'] <     4501                         if data['average'] < limit:
4525                                 continue         4502                                 continue
4526                         # row classes - alter    4503                         # row classes - alternate row color
4527                         rcls = ['alt'] if num    4504                         rcls = ['alt'] if num % 2 == 1 else []
4528                         html += '<tr class="'    4505                         html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n'
4529                         html += tdr.format(da    4506                         html += tdr.format(data['name'])                                # name
4530                         html += td.format('%.    4507                         html += td.format('%.3f ms' % data['average'])  # average
4531                         html += td.format(dat    4508                         html += td.format(data['count'])                                # count
4532                         html += td.format('%.    4509                         html += td.format('%.3f ms' % data['worst'])    # worst
4533                         html += td.format(dat    4510                         html += td.format(data['host'])                                 # host
4534                         html += tdlink.format    4511                         html += tdlink.format(data['url'])                              # url
4535                         html += '</tr>\n'        4512                         html += '</tr>\n'
4536                         num += 1                 4513                         num += 1
4537                 html += '</table>\n'             4514                 html += '</table>\n'
4538                                                  4515 
4539         # flush the data to file                 4516         # flush the data to file
4540         hf = open(htmlfile, 'w')                 4517         hf = open(htmlfile, 'w')
4541         hf.write(html+'</body>\n</html>\n')      4518         hf.write(html+'</body>\n</html>\n')
4542         hf.close()                               4519         hf.close()
4543         return devall                            4520         return devall
4544                                                  4521 
4545 def createHTMLIssuesSummary(testruns, issues,    4522 def createHTMLIssuesSummary(testruns, issues, htmlfile, title, extra=''):
4546         multihost = len([e for e in issues if    4523         multihost = len([e for e in issues if len(e['urls']) > 1]) > 0
4547         html = summaryCSS('Issues Summary - S    4524         html = summaryCSS('Issues Summary - SleepGraph', False)
4548         total = len(testruns)                    4525         total = len(testruns)
4549                                                  4526 
4550         # generate the html                      4527         # generate the html
4551         th = '\t<th>{0}</th>\n'                  4528         th = '\t<th>{0}</th>\n'
4552         td = '\t<td align={0}>{1}</td>\n'        4529         td = '\t<td align={0}>{1}</td>\n'
4553         tdlink = '<a href="{1}">{0}</a>'         4530         tdlink = '<a href="{1}">{0}</a>'
4554         subtitle = '%d issues' % len(issues)     4531         subtitle = '%d issues' % len(issues) if len(issues) > 0 else 'no issues'
4555         html += '<div class="stamp">%s (%s)</    4532         html += '<div class="stamp">%s (%s)</div><table>\n' % (title, subtitle)
4556         html += '<tr>\n' + th.format('Issue')    4533         html += '<tr>\n' + th.format('Issue') + th.format('Count')
4557         if multihost:                            4534         if multihost:
4558                 html += th.format('Hosts')       4535                 html += th.format('Hosts')
4559         html += th.format('Tests') + th.forma    4536         html += th.format('Tests') + th.format('Fail Rate') +\
4560                 th.format('First Instance') +    4537                 th.format('First Instance') + '</tr>\n'
4561                                                  4538 
4562         num = 0                                  4539         num = 0
4563         for e in sorted(issues, key=lambda v:    4540         for e in sorted(issues, key=lambda v:v['count'], reverse=True):
4564                 testtotal = 0                    4541                 testtotal = 0
4565                 links = []                       4542                 links = []
4566                 for host in sorted(e['urls'])    4543                 for host in sorted(e['urls']):
4567                         links.append(tdlink.f    4544                         links.append(tdlink.format(host, e['urls'][host][0]))
4568                         testtotal += len(e['u    4545                         testtotal += len(e['urls'][host])
4569                 rate = '%d/%d (%.2f%%)' % (te    4546                 rate = '%d/%d (%.2f%%)' % (testtotal, total, 100*float(testtotal)/float(total))
4570                 # row classes - alternate row    4547                 # row classes - alternate row color
4571                 rcls = ['alt'] if num % 2 ==     4548                 rcls = ['alt'] if num % 2 == 1 else []
4572                 html += '<tr class="'+(' '.jo    4549                 html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n'
4573                 html += td.format('left', e['    4550                 html += td.format('left', e['line'])            # issue
4574                 html += td.format('center', e    4551                 html += td.format('center', e['count'])         # count
4575                 if multihost:                    4552                 if multihost:
4576                         html += td.format('ce    4553                         html += td.format('center', len(e['urls']))     # hosts
4577                 html += td.format('center', t    4554                 html += td.format('center', testtotal)          # test count
4578                 html += td.format('center', r    4555                 html += td.format('center', rate)                       # test rate
4579                 html += td.format('center now    4556                 html += td.format('center nowrap', '<br>'.join(links))  # links
4580                 html += '</tr>\n'                4557                 html += '</tr>\n'
4581                 num += 1                         4558                 num += 1
4582                                                  4559 
4583         # flush the data to file                 4560         # flush the data to file
4584         hf = open(htmlfile, 'w')                 4561         hf = open(htmlfile, 'w')
4585         hf.write(html+'</table>\n'+extra+'</b    4562         hf.write(html+'</table>\n'+extra+'</body>\n</html>\n')
4586         hf.close()                               4563         hf.close()
4587         return issues                            4564         return issues
4588                                                  4565 
4589 def ordinal(value):                              4566 def ordinal(value):
4590         suffix = 'th'                            4567         suffix = 'th'
4591         if value < 10 or value > 19:             4568         if value < 10 or value > 19:
4592                 if value % 10 == 1:              4569                 if value % 10 == 1:
4593                         suffix = 'st'            4570                         suffix = 'st'
4594                 elif value % 10 == 2:            4571                 elif value % 10 == 2:
4595                         suffix = 'nd'            4572                         suffix = 'nd'
4596                 elif value % 10 == 3:            4573                 elif value % 10 == 3:
4597                         suffix = 'rd'            4574                         suffix = 'rd'
4598         return '%d%s' % (value, suffix)          4575         return '%d%s' % (value, suffix)
4599                                                  4576 
4600 # Function: createHTML                           4577 # Function: createHTML
4601 # Description:                                   4578 # Description:
4602 #        Create the output html file from the    4579 #        Create the output html file from the resident test data
4603 # Arguments:                                     4580 # Arguments:
4604 #        testruns: array of Data objects from    4581 #        testruns: array of Data objects from parseKernelLog or parseTraceLog
4605 # Output:                                        4582 # Output:
4606 #        True if the html file was created, f    4583 #        True if the html file was created, false if it failed
4607 def createHTML(testruns, testfail):              4584 def createHTML(testruns, testfail):
4608         if len(testruns) < 1:                    4585         if len(testruns) < 1:
4609                 pprint('ERROR: Not enough tes    4586                 pprint('ERROR: Not enough test data to build a timeline')
4610                 return                           4587                 return
4611                                                  4588 
4612         kerror = False                           4589         kerror = False
4613         for data in testruns:                    4590         for data in testruns:
4614                 if data.kerror:                  4591                 if data.kerror:
4615                         kerror = True            4592                         kerror = True
4616                 if(sysvals.suspendmode in ['f    4593                 if(sysvals.suspendmode in ['freeze', 'standby']):
4617                         data.trimFreezeTime(t    4594                         data.trimFreezeTime(testruns[-1].tSuspended)
4618                 else:                            4595                 else:
4619                         data.getMemTime()        4596                         data.getMemTime()
4620                                                  4597 
4621         # html function templates                4598         # html function templates
4622         html_error = '<div id="{1}" title="ke    4599         html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">{2}&rarr;</div>\n'
4623         html_traceevent = '<div title="{0}" c    4600         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    4601         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    4602         html_timetotal = '<table class="time1">\n<tr>'\
4626                 '<td class="green" title="{3}    4603                 '<td class="green" title="{3}">{2} Suspend Time: <b>{0} ms</b></td>'\
4627                 '<td class="yellow" title="{4    4604                 '<td class="yellow" title="{4}">{2} Resume Time: <b>{1} ms</b></td>'\
4628                 '</tr>\n</table>\n'              4605                 '</tr>\n</table>\n'
4629         html_timetotal2 = '<table class="time    4606         html_timetotal2 = '<table class="time1">\n<tr>'\
4630                 '<td class="green" title="{4}    4607                 '<td class="green" title="{4}">{3} Suspend Time: <b>{0} ms</b></td>'\
4631                 '<td class="gray" title="time    4608                 '<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    4609                 '<td class="yellow" title="{5}">{3} Resume Time: <b>{2} ms</b></td>'\
4633                 '</tr>\n</table>\n'              4610                 '</tr>\n</table>\n'
4634         html_timetotal3 = '<table class="time    4611         html_timetotal3 = '<table class="time1">\n<tr>'\
4635                 '<td class="green">Execution     4612                 '<td class="green">Execution Time: <b>{0} ms</b></td>'\
4636                 '<td class="yellow">Command:     4613                 '<td class="yellow">Command: <b>{1}</b></td>'\
4637                 '</tr>\n</table>\n'              4614                 '</tr>\n</table>\n'
4638         html_fail = '<table class="testfail">    4615         html_fail = '<table class="testfail"><tr><td>{0}</td></tr></table>\n'
4639         html_kdesc = '<td class="{3}" title="    4616         html_kdesc = '<td class="{3}" title="time spent in kernel execution">{0}Kernel {2}: {1} ms</td>'
4640         html_fwdesc = '<td class="{3}" title=    4617         html_fwdesc = '<td class="{3}" title="time spent in firmware">{0}Firmware {2}: {1} ms</td>'
4641         html_wifdesc = '<td class="yellow" ti    4618         html_wifdesc = '<td class="yellow" title="time for wifi to reconnect after resume complete ({2})">{0}Wifi Resume: {1}</td>'
4642                                                  4619 
4643         # html format variables                  4620         # html format variables
4644         scaleH = 20                              4621         scaleH = 20
4645         if kerror:                               4622         if kerror:
4646                 scaleH = 40                      4623                 scaleH = 40
4647                                                  4624 
4648         # device timeline                        4625         # device timeline
4649         devtl = Timeline(30, scaleH)             4626         devtl = Timeline(30, scaleH)
4650                                                  4627 
4651         # write the test title and general in    4628         # write the test title and general info header
4652         devtl.createHeader(sysvals, testruns[    4629         devtl.createHeader(sysvals, testruns[0].stamp)
4653                                                  4630 
4654         # Generate the header for this timeli    4631         # Generate the header for this timeline
4655         for data in testruns:                    4632         for data in testruns:
4656                 tTotal = data.end - data.star    4633                 tTotal = data.end - data.start
4657                 if(tTotal == 0):                 4634                 if(tTotal == 0):
4658                         doError('No timeline     4635                         doError('No timeline data')
4659                 if sysvals.suspendmode == 'co    4636                 if sysvals.suspendmode == 'command':
4660                         run_time = '%.0f' % (    4637                         run_time = '%.0f' % (tTotal * 1000)
4661                         if sysvals.testcomman    4638                         if sysvals.testcommand:
4662                                 testdesc = sy    4639                                 testdesc = sysvals.testcommand
4663                         else:                    4640                         else:
4664                                 testdesc = 'u    4641                                 testdesc = 'unknown'
4665                         if(len(testruns) > 1)    4642                         if(len(testruns) > 1):
4666                                 testdesc = or    4643                                 testdesc = ordinal(data.testnumber+1)+' '+testdesc
4667                         thtml = html_timetota    4644                         thtml = html_timetotal3.format(run_time, testdesc)
4668                         devtl.html += thtml      4645                         devtl.html += thtml
4669                         continue                 4646                         continue
4670                 # typical full suspend/resume    4647                 # typical full suspend/resume header
4671                 stot, rtot = sktime, rktime =    4648                 stot, rtot = sktime, rktime = data.getTimeValues()
4672                 ssrc, rsrc, testdesc, testdes    4649                 ssrc, rsrc, testdesc, testdesc2 = ['kernel'], ['kernel'], 'Kernel', ''
4673                 if data.fwValid:                 4650                 if data.fwValid:
4674                         stot += (data.fwSuspe    4651                         stot += (data.fwSuspend/1000000.0)
4675                         rtot += (data.fwResum    4652                         rtot += (data.fwResume/1000000.0)
4676                         ssrc.append('firmware    4653                         ssrc.append('firmware')
4677                         rsrc.append('firmware    4654                         rsrc.append('firmware')
4678                         testdesc = 'Total'       4655                         testdesc = 'Total'
4679                 if 'time' in data.wifi and da    4656                 if 'time' in data.wifi and data.wifi['stat'] != 'timeout':
4680                         rtot += data.end - da    4657                         rtot += data.end - data.tKernRes + (data.wifi['time'] * 1000.0)
4681                         rsrc.append('wifi')      4658                         rsrc.append('wifi')
4682                         testdesc = 'Total'       4659                         testdesc = 'Total'
4683                 suspend_time, resume_time = '    4660                 suspend_time, resume_time = '%.3f' % stot, '%.3f' % rtot
4684                 stitle = 'time from kernel su    4661                 stitle = 'time from kernel suspend start to %s mode [%s time]' % \
4685                         (sysvals.suspendmode,    4662                         (sysvals.suspendmode, ' & '.join(ssrc))
4686                 rtitle = 'time from %s mode t    4663                 rtitle = 'time from %s mode to kernel resume complete [%s time]' % \
4687                         (sysvals.suspendmode,    4664                         (sysvals.suspendmode, ' & '.join(rsrc))
4688                 if(len(testruns) > 1):           4665                 if(len(testruns) > 1):
4689                         testdesc = testdesc2     4666                         testdesc = testdesc2 = ordinal(data.testnumber+1)
4690                         testdesc2 += ' '         4667                         testdesc2 += ' '
4691                 if(len(data.tLow) == 0):         4668                 if(len(data.tLow) == 0):
4692                         thtml = html_timetota    4669                         thtml = html_timetotal.format(suspend_time, \
4693                                 resume_time,     4670                                 resume_time, testdesc, stitle, rtitle)
4694                 else:                            4671                 else:
4695                         low_time = '+'.join(d    4672                         low_time = '+'.join(data.tLow)
4696                         thtml = html_timetota    4673                         thtml = html_timetotal2.format(suspend_time, low_time, \
4697                                 resume_time,     4674                                 resume_time, testdesc, stitle, rtitle)
4698                 devtl.html += thtml              4675                 devtl.html += thtml
4699                 if not data.fwValid and 'dev'    4676                 if not data.fwValid and 'dev' not in data.wifi:
4700                         continue                 4677                         continue
4701                 # extra detail when the times    4678                 # extra detail when the times come from multiple sources
4702                 thtml = '<table class="time2"    4679                 thtml = '<table class="time2">\n<tr>'
4703                 thtml += html_kdesc.format(te    4680                 thtml += html_kdesc.format(testdesc2, '%.3f'%sktime, 'Suspend', 'green')
4704                 if data.fwValid:                 4681                 if data.fwValid:
4705                         sftime = '%.3f'%(data    4682                         sftime = '%.3f'%(data.fwSuspend / 1000000.0)
4706                         rftime = '%.3f'%(data    4683                         rftime = '%.3f'%(data.fwResume / 1000000.0)
4707                         thtml += html_fwdesc.    4684                         thtml += html_fwdesc.format(testdesc2, sftime, 'Suspend', 'green')
4708                         thtml += html_fwdesc.    4685                         thtml += html_fwdesc.format(testdesc2, rftime, 'Resume', 'yellow')
4709                 thtml += html_kdesc.format(te    4686                 thtml += html_kdesc.format(testdesc2, '%.3f'%rktime, 'Resume', 'yellow')
4710                 if 'time' in data.wifi:          4687                 if 'time' in data.wifi:
4711                         if data.wifi['stat']     4688                         if data.wifi['stat'] != 'timeout':
4712                                 wtime = '%.0f    4689                                 wtime = '%.0f ms'%(data.end - data.tKernRes + (data.wifi['time'] * 1000.0))
4713                         else:                    4690                         else:
4714                                 wtime = 'TIME    4691                                 wtime = 'TIMEOUT'
4715                         thtml += html_wifdesc    4692                         thtml += html_wifdesc.format(testdesc2, wtime, data.wifi['dev'])
4716                 thtml += '</tr>\n</table>\n'     4693                 thtml += '</tr>\n</table>\n'
4717                 devtl.html += thtml              4694                 devtl.html += thtml
4718         if testfail:                             4695         if testfail:
4719                 devtl.html += html_fail.forma    4696                 devtl.html += html_fail.format(testfail)
4720                                                  4697 
4721         # time scale for potentially multiple    4698         # time scale for potentially multiple datasets
4722         t0 = testruns[0].start                   4699         t0 = testruns[0].start
4723         tMax = testruns[-1].end                  4700         tMax = testruns[-1].end
4724         tTotal = tMax - t0                       4701         tTotal = tMax - t0
4725                                                  4702 
4726         # determine the maximum number of row    4703         # determine the maximum number of rows we need to draw
4727         fulllist = []                            4704         fulllist = []
4728         threadlist = []                          4705         threadlist = []
4729         pscnt = 0                                4706         pscnt = 0
4730         devcnt = 0                               4707         devcnt = 0
4731         for data in testruns:                    4708         for data in testruns:
4732                 data.selectTimelineDevices('%    4709                 data.selectTimelineDevices('%f', tTotal, sysvals.mindevlen)
4733                 for group in data.devicegroup    4710                 for group in data.devicegroups:
4734                         devlist = []             4711                         devlist = []
4735                         for phase in group:      4712                         for phase in group:
4736                                 for devname i    4713                                 for devname in sorted(data.tdevlist[phase]):
4737                                         d = D    4714                                         d = DevItem(data.testnumber, phase, data.dmesg[phase]['list'][devname])
4738                                         devli    4715                                         devlist.append(d)
4739                                         if d.    4716                                         if d.isa('kth'):
4740                                                  4717                                                 threadlist.append(d)
4741                                         else:    4718                                         else:
4742                                                  4719                                                 if d.isa('ps'):
4743                                                  4720                                                         pscnt += 1
4744                                                  4721                                                 else:
4745                                                  4722                                                         devcnt += 1
4746                                                  4723                                                 fulllist.append(d)
4747                         if sysvals.mixedphase    4724                         if sysvals.mixedphaseheight:
4748                                 devtl.getPhas    4725                                 devtl.getPhaseRows(devlist)
4749         if not sysvals.mixedphaseheight:         4726         if not sysvals.mixedphaseheight:
4750                 if len(threadlist) > 0 and le    4727                 if len(threadlist) > 0 and len(fulllist) > 0:
4751                         if pscnt > 0 and devc    4728                         if pscnt > 0 and devcnt > 0:
4752                                 msg = 'user p    4729                                 msg = 'user processes & device pm callbacks'
4753                         elif pscnt > 0:          4730                         elif pscnt > 0:
4754                                 msg = 'user p    4731                                 msg = 'user processes'
4755                         else:                    4732                         else:
4756                                 msg = 'device    4733                                 msg = 'device pm callbacks'
4757                         d = testruns[0].addHo    4734                         d = testruns[0].addHorizontalDivider(msg, testruns[-1].end)
4758                         fulllist.insert(0, d)    4735                         fulllist.insert(0, d)
4759                 devtl.getPhaseRows(fulllist)     4736                 devtl.getPhaseRows(fulllist)
4760                 if len(threadlist) > 0:          4737                 if len(threadlist) > 0:
4761                         d = testruns[0].addHo    4738                         d = testruns[0].addHorizontalDivider('asynchronous kernel threads', testruns[-1].end)
4762                         threadlist.insert(0,     4739                         threadlist.insert(0, d)
4763                         devtl.getPhaseRows(th    4740                         devtl.getPhaseRows(threadlist, devtl.rows)
4764         devtl.calcTotalRows()                    4741         devtl.calcTotalRows()
4765                                                  4742 
4766         # draw the full timeline                 4743         # draw the full timeline
4767         devtl.createZoomBox(sysvals.suspendmo    4744         devtl.createZoomBox(sysvals.suspendmode, len(testruns))
4768         for data in testruns:                    4745         for data in testruns:
4769                 # draw each test run and bloc    4746                 # draw each test run and block chronologically
4770                 phases = {'suspend':[],'resum    4747                 phases = {'suspend':[],'resume':[]}
4771                 for phase in data.sortedPhase    4748                 for phase in data.sortedPhases():
4772                         if data.dmesg[phase][    4749                         if data.dmesg[phase]['start'] >= data.tSuspended:
4773                                 phases['resum    4750                                 phases['resume'].append(phase)
4774                         else:                    4751                         else:
4775                                 phases['suspe    4752                                 phases['suspend'].append(phase)
4776                 # now draw the actual timelin    4753                 # now draw the actual timeline blocks
4777                 for dir in phases:               4754                 for dir in phases:
4778                         # draw suspend and re    4755                         # draw suspend and resume blocks separately
4779                         bname = '%s%d' % (dir    4756                         bname = '%s%d' % (dir[0], data.testnumber)
4780                         if dir == 'suspend':     4757                         if dir == 'suspend':
4781                                 m0 = data.sta    4758                                 m0 = data.start
4782                                 mMax = data.t    4759                                 mMax = data.tSuspended
4783                                 left = '%f' %    4760                                 left = '%f' % (((m0-t0)*100.0)/tTotal)
4784                         else:                    4761                         else:
4785                                 m0 = data.tSu    4762                                 m0 = data.tSuspended
4786                                 mMax = data.e    4763                                 mMax = data.end
4787                                 # in an x2 ru    4764                                 # in an x2 run, remove any gap between blocks
4788                                 if len(testru    4765                                 if len(testruns) > 1 and data.testnumber == 0:
4789                                         mMax     4766                                         mMax = testruns[1].start
4790                                 left = '%f' %    4767                                 left = '%f' % ((((m0-t0)*100.0)+sysvals.srgap/2)/tTotal)
4791                         mTotal = mMax - m0       4768                         mTotal = mMax - m0
4792                         # if a timeline block    4769                         # if a timeline block is 0 length, skip altogether
4793                         if mTotal == 0:          4770                         if mTotal == 0:
4794                                 continue         4771                                 continue
4795                         width = '%f' % (((mTo    4772                         width = '%f' % (((mTotal*100.0)-sysvals.srgap/2)/tTotal)
4796                         devtl.html += devtl.h    4773                         devtl.html += devtl.html_tblock.format(bname, left, width, devtl.scaleH)
4797                         for b in phases[dir]:    4774                         for b in phases[dir]:
4798                                 # draw the ph    4775                                 # draw the phase color background
4799                                 phase = data.    4776                                 phase = data.dmesg[b]
4800                                 length = phas    4777                                 length = phase['end']-phase['start']
4801                                 left = '%f' %    4778                                 left = '%f' % (((phase['start']-m0)*100.0)/mTotal)
4802                                 width = '%f'     4779                                 width = '%f' % ((length*100.0)/mTotal)
4803                                 devtl.html +=    4780                                 devtl.html += devtl.html_phase.format(left, width, \
4804                                         '%.3f    4781                                         '%.3f'%devtl.scaleH, '%.3f'%devtl.bodyH, \
4805                                         data.    4782                                         data.dmesg[b]['color'], '')
4806                         for e in data.errorin    4783                         for e in data.errorinfo[dir]:
4807                                 # draw red li    4784                                 # draw red lines for any kernel errors found
4808                                 type, t, idx1    4785                                 type, t, idx1, idx2 = e
4809                                 id = '%d_%d'     4786                                 id = '%d_%d' % (idx1, idx2)
4810                                 right = '%f'     4787                                 right = '%f' % (((mMax-t)*100.0)/mTotal)
4811                                 devtl.html +=    4788                                 devtl.html += html_error.format(right, id, type)
4812                         for b in phases[dir]:    4789                         for b in phases[dir]:
4813                                 # draw the de    4790                                 # draw the devices for this phase
4814                                 phaselist = d    4791                                 phaselist = data.dmesg[b]['list']
4815                                 for d in sort    4792                                 for d in sorted(data.tdevlist[b]):
4816                                         dname    4793                                         dname = d if ('[' not in d or 'CPU' in d) else d.split('[')[0]
4817                                         name,    4794                                         name, dev = dname, phaselist[d]
4818                                         drv =    4795                                         drv = xtraclass = xtrainfo = xtrastyle = ''
4819                                         if 'h    4796                                         if 'htmlclass' in dev:
4820                                                  4797                                                 xtraclass = dev['htmlclass']
4821                                         if 'c    4798                                         if 'color' in dev:
4822                                                  4799                                                 xtrastyle = 'background:%s;' % dev['color']
4823                                         if(d     4800                                         if(d in sysvals.devprops):
4824                                                  4801                                                 name = sysvals.devprops[d].altName(d)
4825                                                  4802                                                 xtraclass = sysvals.devprops[d].xtraClass()
4826                                                  4803                                                 xtrainfo = sysvals.devprops[d].xtraInfo()
4827                                         elif     4804                                         elif xtraclass == ' kth':
4828                                                  4805                                                 xtrainfo = ' kernel_thread'
4829                                         if('d    4806                                         if('drv' in dev and dev['drv']):
4830                                                  4807                                                 drv = ' {%s}' % dev['drv']
4831                                         rowhe    4808                                         rowheight = devtl.phaseRowHeight(data.testnumber, b, dev['row'])
4832                                         rowto    4809                                         rowtop = devtl.phaseRowTop(data.testnumber, b, dev['row'])
4833                                         top =    4810                                         top = '%.3f' % (rowtop + devtl.scaleH)
4834                                         left     4811                                         left = '%f' % (((dev['start']-m0)*100)/mTotal)
4835                                         width    4812                                         width = '%f' % (((dev['end']-dev['start'])*100)/mTotal)
4836                                         lengt    4813                                         length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000)
4837                                         title    4814                                         title = name+drv+xtrainfo+length
4838                                         if sy    4815                                         if sysvals.suspendmode == 'command':
4839                                                  4816                                                 title += sysvals.testcommand
4840                                         elif     4817                                         elif xtraclass == ' ps':
4841                                                  4818                                                 if 'suspend' in b:
4842                                                  4819                                                         title += 'pre_suspend_process'
4843                                                  4820                                                 else:
4844                                                  4821                                                         title += 'post_resume_process'
4845                                         else:    4822                                         else:
4846                                                  4823                                                 title += b
4847                                         devtl    4824                                         devtl.html += devtl.html_device.format(dev['id'], \
4848                                                  4825                                                 title, left, top, '%.3f'%rowheight, width, \
4849                                                  4826                                                 dname+drv, xtraclass, xtrastyle)
4850                                         if('c    4827                                         if('cpuexec' in dev):
4851                                                  4828                                                 for t in sorted(dev['cpuexec']):
4852                                                  4829                                                         start, end = t
                                                   >> 4830                                                         j = float(dev['cpuexec'][t]) / 5
                                                   >> 4831                                                         if j > 1.0:
                                                   >> 4832                                                                 j = 1.0
4853                                                  4833                                                         height = '%.3f' % (rowheight/3)
4854                                                  4834                                                         top = '%.3f' % (rowtop + devtl.scaleH + 2*rowheight/3)
4855                                                  4835                                                         left = '%f' % (((start-m0)*100)/mTotal)
4856                                                  4836                                                         width = '%f' % ((end-start)*100/mTotal)
4857                                               !! 4837                                                         color = 'rgba(255, 0, 0, %f)' % j
4858                                                  4838                                                         devtl.html += \
4859                                                  4839                                                                 html_cpuexec.format(left, top, height, width, color)
4860                                         if('s    4840                                         if('src' not in dev):
4861                                                  4841                                                 continue
4862                                         # dra    4842                                         # draw any trace events for this device
4863                                         for e    4843                                         for e in dev['src']:
4864                                                  4844                                                 if e.length == 0:
4865                                                  4845                                                         continue
4866                                                  4846                                                 height = '%.3f' % devtl.rowH
4867                                                  4847                                                 top = '%.3f' % (rowtop + devtl.scaleH + (e.row*devtl.rowH))
4868                                                  4848                                                 left = '%f' % (((e.time-m0)*100)/mTotal)
4869                                                  4849                                                 width = '%f' % (e.length*100/mTotal)
4870                                                  4850                                                 xtrastyle = ''
4871                                                  4851                                                 if e.color:
4872                                                  4852                                                         xtrastyle = 'background:%s;' % e.color
4873                                                  4853                                                 devtl.html += \
4874                                                  4854                                                         html_traceevent.format(e.title(), \
4875                                                  4855                                                                 left, top, height, width, e.text(), '', xtrastyle)
4876                         # draw the time scale    4856                         # draw the time scale, try to make the number of labels readable
4877                         devtl.createTimeScale    4857                         devtl.createTimeScale(m0, mMax, tTotal, dir)
4878                         devtl.html += '</div>    4858                         devtl.html += '</div>\n'
4879                                                  4859 
4880         # timeline is finished                   4860         # timeline is finished
4881         devtl.html += '</div>\n</div>\n'         4861         devtl.html += '</div>\n</div>\n'
4882                                                  4862 
4883         # draw a legend which describes the p    4863         # draw a legend which describes the phases by color
4884         if sysvals.suspendmode != 'command':     4864         if sysvals.suspendmode != 'command':
4885                 phasedef = testruns[-1].phase    4865                 phasedef = testruns[-1].phasedef
4886                 devtl.html += '<div class="le    4866                 devtl.html += '<div class="legend">\n'
4887                 pdelta = 100.0/len(phasedef.k    4867                 pdelta = 100.0/len(phasedef.keys())
4888                 pmargin = pdelta / 4.0           4868                 pmargin = pdelta / 4.0
4889                 for phase in sorted(phasedef,    4869                 for phase in sorted(phasedef, key=lambda k:phasedef[k]['order']):
4890                         id, p = '', phasedef[    4870                         id, p = '', phasedef[phase]
4891                         for word in phase.spl    4871                         for word in phase.split('_'):
4892                                 id += word[0]    4872                                 id += word[0]
4893                         order = '%.2f' % ((p[    4873                         order = '%.2f' % ((p['order'] * pdelta) + pmargin)
4894                         name = phase.replace(    4874                         name = phase.replace('_', ' &nbsp;')
4895                         devtl.html += devtl.h    4875                         devtl.html += devtl.html_legend.format(order, p['color'], name, id)
4896                 devtl.html += '</div>\n'         4876                 devtl.html += '</div>\n'
4897                                                  4877 
4898         hf = open(sysvals.htmlfile, 'w')         4878         hf = open(sysvals.htmlfile, 'w')
4899         addCSS(hf, sysvals, len(testruns), ke    4879         addCSS(hf, sysvals, len(testruns), kerror)
4900                                                  4880 
4901         # write the device timeline              4881         # write the device timeline
4902         hf.write(devtl.html)                     4882         hf.write(devtl.html)
4903         hf.write('<div id="devicedetailtitle"    4883         hf.write('<div id="devicedetailtitle"></div>\n')
4904         hf.write('<div id="devicedetail" styl    4884         hf.write('<div id="devicedetail" style="display:none;">\n')
4905         # draw the colored boxes for the devi    4885         # draw the colored boxes for the device detail section
4906         for data in testruns:                    4886         for data in testruns:
4907                 hf.write('<div id="devicedeta    4887                 hf.write('<div id="devicedetail%d">\n' % data.testnumber)
4908                 pscolor = 'linear-gradient(to    4888                 pscolor = 'linear-gradient(to top left, #ccc, #eee)'
4909                 hf.write(devtl.html_phaselet.    4889                 hf.write(devtl.html_phaselet.format('pre_suspend_process', \
4910                         '0', '0', pscolor))      4890                         '0', '0', pscolor))
4911                 for b in data.sortedPhases():    4891                 for b in data.sortedPhases():
4912                         phase = data.dmesg[b]    4892                         phase = data.dmesg[b]
4913                         length = phase['end']    4893                         length = phase['end']-phase['start']
4914                         left = '%.3f' % (((ph    4894                         left = '%.3f' % (((phase['start']-t0)*100.0)/tTotal)
4915                         width = '%.3f' % ((le    4895                         width = '%.3f' % ((length*100.0)/tTotal)
4916                         hf.write(devtl.html_p    4896                         hf.write(devtl.html_phaselet.format(b, left, width, \
4917                                 data.dmesg[b]    4897                                 data.dmesg[b]['color']))
4918                 hf.write(devtl.html_phaselet.    4898                 hf.write(devtl.html_phaselet.format('post_resume_process', \
4919                         '0', '0', pscolor))      4899                         '0', '0', pscolor))
4920                 if sysvals.suspendmode == 'co    4900                 if sysvals.suspendmode == 'command':
4921                         hf.write(devtl.html_p    4901                         hf.write(devtl.html_phaselet.format('cmdexec', '0', '0', pscolor))
4922                 hf.write('</div>\n')             4902                 hf.write('</div>\n')
4923         hf.write('</div>\n')                     4903         hf.write('</div>\n')
4924                                                  4904 
4925         # write the ftrace data (callgraph)      4905         # write the ftrace data (callgraph)
4926         if sysvals.cgtest >= 0 and len(testru    4906         if sysvals.cgtest >= 0 and len(testruns) > sysvals.cgtest:
4927                 data = testruns[sysvals.cgtes    4907                 data = testruns[sysvals.cgtest]
4928         else:                                    4908         else:
4929                 data = testruns[-1]              4909                 data = testruns[-1]
4930         if sysvals.usecallgraph:                 4910         if sysvals.usecallgraph:
4931                 addCallgraphs(sysvals, hf, da    4911                 addCallgraphs(sysvals, hf, data)
4932                                                  4912 
4933         # add the test log as a hidden div       4913         # add the test log as a hidden div
4934         if sysvals.testlog and sysvals.logmsg    4914         if sysvals.testlog and sysvals.logmsg:
4935                 hf.write('<div id="testlog" s    4915                 hf.write('<div id="testlog" style="display:none;">\n'+sysvals.logmsg+'</div>\n')
4936         # add the dmesg log as a hidden div      4916         # add the dmesg log as a hidden div
4937         if sysvals.dmesglog and sysvals.dmesg    4917         if sysvals.dmesglog and sysvals.dmesgfile:
4938                 hf.write('<div id="dmesglog"     4918                 hf.write('<div id="dmesglog" style="display:none;">\n')
4939                 lf = sysvals.openlog(sysvals.    4919                 lf = sysvals.openlog(sysvals.dmesgfile, 'r')
4940                 for line in lf:                  4920                 for line in lf:
4941                         line = line.replace('    4921                         line = line.replace('<', '&lt').replace('>', '&gt')
4942                         hf.write(line)           4922                         hf.write(line)
4943                 lf.close()                       4923                 lf.close()
4944                 hf.write('</div>\n')             4924                 hf.write('</div>\n')
4945         # add the ftrace log as a hidden div     4925         # add the ftrace log as a hidden div
4946         if sysvals.ftracelog and sysvals.ftra    4926         if sysvals.ftracelog and sysvals.ftracefile:
4947                 hf.write('<div id="ftracelog"    4927                 hf.write('<div id="ftracelog" style="display:none;">\n')
4948                 lf = sysvals.openlog(sysvals.    4928                 lf = sysvals.openlog(sysvals.ftracefile, 'r')
4949                 for line in lf:                  4929                 for line in lf:
4950                         hf.write(line)           4930                         hf.write(line)
4951                 lf.close()                       4931                 lf.close()
4952                 hf.write('</div>\n')             4932                 hf.write('</div>\n')
4953                                                  4933 
4954         # write the footer and close             4934         # write the footer and close
4955         addScriptCode(hf, testruns)              4935         addScriptCode(hf, testruns)
4956         hf.write('</body>\n</html>\n')           4936         hf.write('</body>\n</html>\n')
4957         hf.close()                               4937         hf.close()
4958         return True                              4938         return True
4959                                                  4939 
4960 def addCSS(hf, sv, testcount=1, kerror=False,    4940 def addCSS(hf, sv, testcount=1, kerror=False, extra=''):
4961         kernel = sv.stamp['kernel']              4941         kernel = sv.stamp['kernel']
4962         host = sv.hostname[0].upper()+sv.host    4942         host = sv.hostname[0].upper()+sv.hostname[1:]
4963         mode = sv.suspendmode                    4943         mode = sv.suspendmode
4964         if sv.suspendmode in suspendmodename:    4944         if sv.suspendmode in suspendmodename:
4965                 mode = suspendmodename[sv.sus    4945                 mode = suspendmodename[sv.suspendmode]
4966         title = host+' '+mode+' '+kernel         4946         title = host+' '+mode+' '+kernel
4967                                                  4947 
4968         # various format changes by flags        4948         # various format changes by flags
4969         cgchk = 'checked'                        4949         cgchk = 'checked'
4970         cgnchk = 'not(:checked)'                 4950         cgnchk = 'not(:checked)'
4971         if sv.cgexp:                             4951         if sv.cgexp:
4972                 cgchk = 'not(:checked)'          4952                 cgchk = 'not(:checked)'
4973                 cgnchk = 'checked'               4953                 cgnchk = 'checked'
4974                                                  4954 
4975         hoverZ = 'z-index:8;'                    4955         hoverZ = 'z-index:8;'
4976         if sv.usedevsrc:                         4956         if sv.usedevsrc:
4977                 hoverZ = ''                      4957                 hoverZ = ''
4978                                                  4958 
4979         devlistpos = 'absolute'                  4959         devlistpos = 'absolute'
4980         if testcount > 1:                        4960         if testcount > 1:
4981                 devlistpos = 'relative'          4961                 devlistpos = 'relative'
4982                                                  4962 
4983         scaleTH = 20                             4963         scaleTH = 20
4984         if kerror:                               4964         if kerror:
4985                 scaleTH = 60                     4965                 scaleTH = 60
4986                                                  4966 
4987         # write the html header first (html h    4967         # write the html header first (html head, css code, up to body start)
4988         html_header = '<!DOCTYPE html>\n<html    4968         html_header = '<!DOCTYPE html>\n<html>\n<head>\n\
4989         <meta http-equiv="content-type" conte    4969         <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\
4990         <title>'+title+'</title>\n\              4970         <title>'+title+'</title>\n\
4991         <style type=\'text/css\'>\n\             4971         <style type=\'text/css\'>\n\
4992                 body {overflow-y:scroll;}\n\     4972                 body {overflow-y:scroll;}\n\
4993                 .stamp {width:100%;text-align    4973                 .stamp {width:100%;text-align:center;background:gray;line-height:30px;color:white;font:25px Arial;}\n\
4994                 .stamp.sysinfo {font:10px Ari    4974                 .stamp.sysinfo {font:10px Arial;}\n\
4995                 .callgraph {margin-top:30px;b    4975                 .callgraph {margin-top:30px;box-shadow:5px 5px 20px black;}\n\
4996                 .callgraph article * {padding    4976                 .callgraph article * {padding-left:28px;}\n\
4997                 h1 {color:black;font:bold 30p    4977                 h1 {color:black;font:bold 30px Times;}\n\
4998                 t0 {color:black;font:bold 30p    4978                 t0 {color:black;font:bold 30px Times;}\n\
4999                 t1 {color:black;font:30px Tim    4979                 t1 {color:black;font:30px Times;}\n\
5000                 t2 {color:black;font:25px Tim    4980                 t2 {color:black;font:25px Times;}\n\
5001                 t3 {color:black;font:20px Tim    4981                 t3 {color:black;font:20px Times;white-space:nowrap;}\n\
5002                 t4 {color:black;font:bold 30p    4982                 t4 {color:black;font:bold 30px Times;line-height:60px;white-space:nowrap;}\n\
5003                 cS {font:bold 13px Times;}\n\    4983                 cS {font:bold 13px Times;}\n\
5004                 table {width:100%;}\n\           4984                 table {width:100%;}\n\
5005                 .gray {background:rgba(80,80,    4985                 .gray {background:rgba(80,80,80,0.1);}\n\
5006                 .green {background:rgba(204,2    4986                 .green {background:rgba(204,255,204,0.4);}\n\
5007                 .purple {background:rgba(128,    4987                 .purple {background:rgba(128,0,128,0.2);}\n\
5008                 .yellow {background:rgba(255,    4988                 .yellow {background:rgba(255,255,204,0.4);}\n\
5009                 .blue {background:rgba(169,20    4989                 .blue {background:rgba(169,208,245,0.4);}\n\
5010                 .time1 {font:22px Arial;borde    4990                 .time1 {font:22px Arial;border:1px solid;}\n\
5011                 .time2 {font:15px Arial;borde    4991                 .time2 {font:15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\
5012                 .testfail {font:bold 22px Ari    4992                 .testfail {font:bold 22px Arial;color:red;border:1px dashed;}\n\
5013                 td {text-align:center;}\n\       4993                 td {text-align:center;}\n\
5014                 r {color:#500000;font:15px Ta    4994                 r {color:#500000;font:15px Tahoma;}\n\
5015                 n {color:#505050;font:15px Ta    4995                 n {color:#505050;font:15px Tahoma;}\n\
5016                 .tdhl {color:red;}\n\            4996                 .tdhl {color:red;}\n\
5017                 .hide {display:none;}\n\         4997                 .hide {display:none;}\n\
5018                 .pf {display:none;}\n\           4998                 .pf {display:none;}\n\
5019                 .pf:'+cgchk+' + label {backgr    4999                 .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    5000                 .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    5001                 .pf:'+cgchk+' ~ *:not(:nth-child(2)) {display:none;}\n\
5022                 .zoombox {position:relative;w    5002                 .zoombox {position:relative;width:100%;overflow-x:scroll;-webkit-user-select:none;-moz-user-select:none;user-select:none;}\n\
5023                 .timeline {position:relative;    5003                 .timeline {position:relative;font-size:14px;cursor:pointer;width:100%; overflow:hidden;background:linear-gradient(#cccccc, white);}\n\
5024                 .thread {position:absolute;he    5004                 .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    5005                 .thread.ps {border-radius:3px;background:linear-gradient(to top, #ccc, #eee);}\n\
5026                 .thread:hover {background:whi    5006                 .thread:hover {background:white;border:1px solid red;'+hoverZ+'}\n\
5027                 .thread.sec,.thread.sec:hover    5007                 .thread.sec,.thread.sec:hover {background:black;border:0;color:white;line-height:15px;font-size:10px;}\n\
5028                 .hover {background:white;bord    5008                 .hover {background:white;border:1px solid red;'+hoverZ+'}\n\
5029                 .hover.sync {background:white    5009                 .hover.sync {background:white;}\n\
5030                 .hover.bg,.hover.kth,.hover.s    5010                 .hover.bg,.hover.kth,.hover.sync,.hover.ps {background:white;}\n\
5031                 .jiffie {position:absolute;po    5011                 .jiffie {position:absolute;pointer-events: none;z-index:8;}\n\
5032                 .traceevent {position:absolut    5012                 .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    5013                 .traceevent:hover {color:white;font-weight:bold;border:1px solid white;}\n\
5034                 .phase {position:absolute;ove    5014                 .phase {position:absolute;overflow:hidden;border:0px;text-align:center;}\n\
5035                 .phaselet {float:left;overflo    5015                 .phaselet {float:left;overflow:hidden;border:0px;text-align:center;min-height:100px;font-size:24px;}\n\
5036                 .t {position:absolute;line-he    5016                 .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    5017                 .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    5018                 .legend {position:relative; width:100%; height:40px; text-align:center;margin-bottom:20px}\n\
5039                 .legend .square {position:abs    5019                 .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    5020                 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\
5041                 .btnfmt {position:relative;fl    5021                 .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    5022                 .devlist {position:'+devlistpos+';width:190px;}\n\
5043                 a:link {color:white;text-deco    5023                 a:link {color:white;text-decoration:none;}\n\
5044                 a:visited {color:white;}\n\      5024                 a:visited {color:white;}\n\
5045                 a:hover {color:white;}\n\        5025                 a:hover {color:white;}\n\
5046                 a:active {color:white;}\n\       5026                 a:active {color:white;}\n\
5047                 .version {position:relative;f    5027                 .version {position:relative;float:left;color:white;font-size:10px;line-height:30px;margin-left:10px;}\n\
5048                 #devicedetail {min-height:100    5028                 #devicedetail {min-height:100px;box-shadow:5px 5px 20px black;}\n\
5049                 .tblock {position:absolute;he    5029                 .tblock {position:absolute;height:100%;background:#ddd;}\n\
5050                 .tback {position:absolute;wid    5030                 .tback {position:absolute;width:100%;background:linear-gradient(#ccc, #ddd);}\n\
5051                 .bg {z-index:1;}\n\              5031                 .bg {z-index:1;}\n\
5052 '+extra+'\                                       5032 '+extra+'\
5053         </style>\n</head>\n<body>\n'             5033         </style>\n</head>\n<body>\n'
5054         hf.write(html_header)                    5034         hf.write(html_header)
5055                                                  5035 
5056 # Function: addScriptCode                        5036 # Function: addScriptCode
5057 # Description:                                   5037 # Description:
5058 #        Adds the javascript code to the outp    5038 #        Adds the javascript code to the output html
5059 # Arguments:                                     5039 # Arguments:
5060 #        hf: the open html file pointer          5040 #        hf: the open html file pointer
5061 #        testruns: array of Data objects from    5041 #        testruns: array of Data objects from parseKernelLog or parseTraceLog
5062 def addScriptCode(hf, testruns):                 5042 def addScriptCode(hf, testruns):
5063         t0 = testruns[0].start * 1000            5043         t0 = testruns[0].start * 1000
5064         tMax = testruns[-1].end * 1000           5044         tMax = testruns[-1].end * 1000
5065         hf.write('<script type="text/javascri << 
5066         # create an array in javascript memor    5045         # create an array in javascript memory with the device details
5067         detail = '      var devtable = [];\n'    5046         detail = '      var devtable = [];\n'
5068         for data in testruns:                    5047         for data in testruns:
5069                 topo = data.deviceTopology()     5048                 topo = data.deviceTopology()
5070                 detail += '     devtable[%d]     5049                 detail += '     devtable[%d] = "%s";\n' % (data.testnumber, topo)
5071         detail += '     var bounds = [%f,%f];    5050         detail += '     var bounds = [%f,%f];\n' % (t0, tMax)
5072         # add the code which will manipulate     5051         # add the code which will manipulate the data in the browser
5073         hf.write(detail);                     !! 5052         script_code = \
5074         script_code = r"""      var resolutio !! 5053         '<script type="text/javascript">\n'+detail+\
5075         var dragval = [0, 0];                 !! 5054         '       var resolution = -1;\n'\
5076         function redrawTimescale(t0, tMax, tS !! 5055         '       var dragval = [0, 0];\n'\
5077                 var rline = '<div class="t" s !! 5056         '       function redrawTimescale(t0, tMax, tS) {\n'\
5078                 var tTotal = tMax - t0;       !! 5057         '               var rline = \'<div class="t" style="left:0;border-left:1px solid black;border-right:0;">\';\n'\
5079                 var list = document.getElemen !! 5058         '               var tTotal = tMax - t0;\n'\
5080                 for (var i = 0; i < list.leng !! 5059         '               var list = document.getElementsByClassName("tblock");\n'\
5081                         var timescale = list[ !! 5060         '               for (var i = 0; i < list.length; i++) {\n'\
5082                         var m0 = t0 + (tTotal !! 5061         '                       var timescale = list[i].getElementsByClassName("timescale")[0];\n'\
5083                         var mTotal = tTotal*p !! 5062         '                       var m0 = t0 + (tTotal*parseFloat(list[i].style.left)/100);\n'\
5084                         var mMax = m0 + mTota !! 5063         '                       var mTotal = tTotal*parseFloat(list[i].style.width)/100;\n'\
5085                         var html = "";        !! 5064         '                       var mMax = m0 + mTotal;\n'\
5086                         var divTotal = Math.f !! 5065         '                       var html = "";\n'\
5087                         if(divTotal > 1000) c !! 5066         '                       var divTotal = Math.floor(mTotal/tS) + 1;\n'\
5088                         var divEdge = (mTotal !! 5067         '                       if(divTotal > 1000) continue;\n'\
5089                         var pos = 0.0, val =  !! 5068         '                       var divEdge = (mTotal - tS*(divTotal-1))*100/mTotal;\n'\
5090                         for (var j = 0; j < d !! 5069         '                       var pos = 0.0, val = 0.0;\n'\
5091                                 var htmlline  !! 5070         '                       for (var j = 0; j < divTotal; j++) {\n'\
5092                                 var mode = li !! 5071         '                               var htmlline = "";\n'\
5093                                 if(mode == "s !! 5072         '                               var mode = list[i].id[5];\n'\
5094                                         pos = !! 5073         '                               if(mode == "s") {\n'\
5095                                         val = !! 5074         '                                       pos = 100 - (((j)*tS*100)/mTotal) - divEdge;\n'\
5096                                         if(j  !! 5075         '                                       val = (j-divTotal+1)*tS;\n'\
5097                                               !! 5076         '                                       if(j == divTotal - 1)\n'\
5098                                         else  !! 5077         '                                               htmlline = \'<div class="t" style="right:\'+pos+\'%"><cS>S&rarr;</cS></div>\';\n'\
5099                                               !! 5078         '                                       else\n'\
5100                                 } else {      !! 5079         '                                               htmlline = \'<div class="t" style="right:\'+pos+\'%">\'+val+\'ms</div>\';\n'\
5101                                         pos = !! 5080         '                               } else {\n'\
5102                                         val = !! 5081         '                                       pos = 100 - (((j)*tS*100)/mTotal);\n'\
5103                                         htmll !! 5082         '                                       val = (j)*tS;\n'\
5104                                         if(j  !! 5083         '                                       htmlline = \'<div class="t" style="right:\'+pos+\'%">\'+val+\'ms</div>\';\n'\
5105                                               !! 5084         '                                       if(j == 0)\n'\
5106                                               !! 5085         '                                               if(mode == "r")\n'\
5107                                               !! 5086         '                                                       htmlline = rline+"<cS>&larr;R</cS></div>";\n'\
5108                                               !! 5087         '                                               else\n'\
5109                                 }             !! 5088         '                                                       htmlline = rline+"<cS>0ms</div>";\n'\
5110                                 html += htmll !! 5089         '                               }\n'\
5111                         }                     !! 5090         '                               html += htmlline;\n'\
5112                         timescale.innerHTML = !! 5091         '                       }\n'\
5113                 }                             !! 5092         '                       timescale.innerHTML = html;\n'\
5114         }                                     !! 5093         '               }\n'\
5115         function zoomTimeline() {             !! 5094         '       }\n'\
5116                 var dmesg = document.getEleme !! 5095         '       function zoomTimeline() {\n'\
5117                 var zoombox = document.getEle !! 5096         '               var dmesg = document.getElementById("dmesg");\n'\
5118                 var left = zoombox.scrollLeft !! 5097         '               var zoombox = document.getElementById("dmesgzoombox");\n'\
5119                 var val = parseFloat(dmesg.st !! 5098         '               var left = zoombox.scrollLeft;\n'\
5120                 var newval = 100;             !! 5099         '               var val = parseFloat(dmesg.style.width);\n'\
5121                 var sh = window.outerWidth /  !! 5100         '               var newval = 100;\n'\
5122                 if(this.id == "zoomin") {     !! 5101         '               var sh = window.outerWidth / 2;\n'\
5123                         newval = val * 1.2;   !! 5102         '               if(this.id == "zoomin") {\n'\
5124                         if(newval > 910034) n !! 5103         '                       newval = val * 1.2;\n'\
5125                         dmesg.style.width = n !! 5104         '                       if(newval > 910034) newval = 910034;\n'\
5126                         zoombox.scrollLeft =  !! 5105         '                       dmesg.style.width = newval+"%";\n'\
5127                 } else if (this.id == "zoomou !! 5106         '                       zoombox.scrollLeft = ((left + sh) * newval / val) - sh;\n'\
5128                         newval = val / 1.2;   !! 5107         '               } else if (this.id == "zoomout") {\n'\
5129                         if(newval < 100) newv !! 5108         '                       newval = val / 1.2;\n'\
5130                         dmesg.style.width = n !! 5109         '                       if(newval < 100) newval = 100;\n'\
5131                         zoombox.scrollLeft =  !! 5110         '                       dmesg.style.width = newval+"%";\n'\
5132                 } else {                      !! 5111         '                       zoombox.scrollLeft = ((left + sh) * newval / val) - sh;\n'\
5133                         zoombox.scrollLeft =  !! 5112         '               } else {\n'\
5134                         dmesg.style.width = " !! 5113         '                       zoombox.scrollLeft = 0;\n'\
5135                 }                             !! 5114         '                       dmesg.style.width = "100%";\n'\
5136                 var tS = [10000, 5000, 2000,  !! 5115         '               }\n'\
5137                 var t0 = bounds[0];           !! 5116         '               var tS = [10000, 5000, 2000, 1000, 500, 200, 100, 50, 20, 10, 5, 2, 1];\n'\
5138                 var tMax = bounds[1];         !! 5117         '               var t0 = bounds[0];\n'\
5139                 var tTotal = tMax - t0;       !! 5118         '               var tMax = bounds[1];\n'\
5140                 var wTotal = tTotal * 100.0 / !! 5119         '               var tTotal = tMax - t0;\n'\
5141                 var idx = 7*window.innerWidth !! 5120         '               var wTotal = tTotal * 100.0 / newval;\n'\
5142                 for(var i = 0; (i < tS.length !! 5121         '               var idx = 7*window.innerWidth/1100;\n'\
5143                 if(i >= tS.length) i = tS.len !! 5122         '               for(var i = 0; (i < tS.length)&&((wTotal / tS[i]) < idx); i++);\n'\
5144                 if(tS[i] == resolution) retur !! 5123         '               if(i >= tS.length) i = tS.length - 1;\n'\
5145                 resolution = tS[i];           !! 5124         '               if(tS[i] == resolution) return;\n'\
5146                 redrawTimescale(t0, tMax, tS[ !! 5125         '               resolution = tS[i];\n'\
5147         }                                     !! 5126         '               redrawTimescale(t0, tMax, tS[i]);\n'\
5148         function deviceName(title) {          !! 5127         '       }\n'\
5149                 var name = title.slice(0, tit !! 5128         '       function deviceName(title) {\n'\
5150                 return name;                  !! 5129         '               var name = title.slice(0, title.indexOf(" ("));\n'\
5151         }                                     !! 5130         '               return name;\n'\
5152         function deviceHover() {              !! 5131         '       }\n'\
5153                 var name = deviceName(this.ti !! 5132         '       function deviceHover() {\n'\
5154                 var dmesg = document.getEleme !! 5133         '               var name = deviceName(this.title);\n'\
5155                 var dev = dmesg.getElementsBy !! 5134         '               var dmesg = document.getElementById("dmesg");\n'\
5156                 var cpu = -1;                 !! 5135         '               var dev = dmesg.getElementsByClassName("thread");\n'\
5157                 if(name.match("CPU_ON\[[0-9]* !! 5136         '               var cpu = -1;\n'\
5158                         cpu = parseInt(name.s !! 5137         '               if(name.match("CPU_ON\[[0-9]*\]"))\n'\
5159                 else if(name.match("CPU_OFF\[ !! 5138         '                       cpu = parseInt(name.slice(7));\n'\
5160                         cpu = parseInt(name.s !! 5139         '               else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\
5161                 for (var i = 0; i < dev.lengt !! 5140         '                       cpu = parseInt(name.slice(8));\n'\
5162                         dname = deviceName(de !! 5141         '               for (var i = 0; i < dev.length; i++) {\n'\
5163                         var cname = dev[i].cl !! 5142         '                       dname = deviceName(dev[i].title);\n'\
5164                         if((cpu >= 0 && dname !! 5143         '                       var cname = dev[i].className.slice(dev[i].className.indexOf("thread"));\n'\
5165                                 (name == dnam !! 5144         '                       if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\
5166                         {                     !! 5145         '                               (name == dname))\n'\
5167                                 dev[i].classN !! 5146         '                       {\n'\
5168                         } else {              !! 5147         '                               dev[i].className = "hover "+cname;\n'\
5169                                 dev[i].classN !! 5148         '                       } else {\n'\
5170                         }                     !! 5149         '                               dev[i].className = cname;\n'\
5171                 }                             !! 5150         '                       }\n'\
5172         }                                     !! 5151         '               }\n'\
5173         function deviceUnhover() {            !! 5152         '       }\n'\
5174                 var dmesg = document.getEleme !! 5153         '       function deviceUnhover() {\n'\
5175                 var dev = dmesg.getElementsBy !! 5154         '               var dmesg = document.getElementById("dmesg");\n'\
5176                 for (var i = 0; i < dev.lengt !! 5155         '               var dev = dmesg.getElementsByClassName("thread");\n'\
5177                         dev[i].className = de !! 5156         '               for (var i = 0; i < dev.length; i++) {\n'\
5178                 }                             !! 5157         '                       dev[i].className = dev[i].className.slice(dev[i].className.indexOf("thread"));\n'\
5179         }                                     !! 5158         '               }\n'\
5180         function deviceTitle(title, total, cp !! 5159         '       }\n'\
5181                 var prefix = "Total";         !! 5160         '       function deviceTitle(title, total, cpu) {\n'\
5182                 if(total.length > 3) {        !! 5161         '               var prefix = "Total";\n'\
5183                         prefix = "Average";   !! 5162         '               if(total.length > 3) {\n'\
5184                         total[1] = (total[1]+ !! 5163         '                       prefix = "Average";\n'\
5185                         total[2] = (total[2]+ !! 5164         '                       total[1] = (total[1]+total[3])/2;\n'\
5186                 }                             !! 5165         '                       total[2] = (total[2]+total[4])/2;\n'\
5187                 var devtitle = document.getEl !! 5166         '               }\n'\
5188                 var name = deviceName(title); !! 5167         '               var devtitle = document.getElementById("devicedetailtitle");\n'\
5189                 if(cpu >= 0) name = "CPU"+cpu !! 5168         '               var name = deviceName(title);\n'\
5190                 var driver = "";              !! 5169         '               if(cpu >= 0) name = "CPU"+cpu;\n'\
5191                 var tS = "<t2>(</t2>";        !! 5170         '               var driver = "";\n'\
5192                 var tR = "<t2>)</t2>";        !! 5171         '               var tS = "<t2>(</t2>";\n'\
5193                 if(total[1] > 0)              !! 5172         '               var tR = "<t2>)</t2>";\n'\
5194                         tS = "<t2>("+prefix+" !! 5173         '               if(total[1] > 0)\n'\
5195                 if(total[2] > 0)              !! 5174         '                       tS = "<t2>("+prefix+" Suspend:</t2><t0> "+total[1].toFixed(3)+" ms</t0> ";\n'\
5196                         tR = " <t2>"+prefix+" !! 5175         '               if(total[2] > 0)\n'\
5197                 var s = title.indexOf("{");   !! 5176         '                       tR = " <t2>"+prefix+" Resume:</t2><t0> "+total[2].toFixed(3)+" ms<t2>)</t2></t0>";\n'\
5198                 var e = title.indexOf("}");   !! 5177         '               var s = title.indexOf("{");\n'\
5199                 if((s >= 0) && (e >= 0))      !! 5178         '               var e = title.indexOf("}");\n'\
5200                         driver = title.slice(< !! 5179         '               if((s >= 0) && (e >= 0))\n'\
5201                 if(total[1] > 0 && total[2] > !! 5180         '                       driver = title.slice(s+1, e) + " <t1>@</t1> ";\n'\
5202                         devtitle.innerHTML =  !! 5181         '               if(total[1] > 0 && total[2] > 0)\n'\
5203                 else                          !! 5182         '                       devtitle.innerHTML = "<t0>"+driver+name+"</t0> "+tS+tR;\n'\
5204                         devtitle.innerHTML =  !! 5183         '               else\n'\
5205                 return name;                  !! 5184         '                       devtitle.innerHTML = "<t0>"+title+"</t0>";\n'\
5206         }                                     !! 5185         '               return name;\n'\
5207         function deviceDetail() {             !! 5186         '       }\n'\
5208                 var devinfo = document.getEle !! 5187         '       function deviceDetail() {\n'\
5209                 devinfo.style.display = "bloc !! 5188         '               var devinfo = document.getElementById("devicedetail");\n'\
5210                 var name = deviceName(this.ti !! 5189         '               devinfo.style.display = "block";\n'\
5211                 var cpu = -1;                 !! 5190         '               var name = deviceName(this.title);\n'\
5212                 if(name.match("CPU_ON\[[0-9]* !! 5191         '               var cpu = -1;\n'\
5213                         cpu = parseInt(name.s !! 5192         '               if(name.match("CPU_ON\[[0-9]*\]"))\n'\
5214                 else if(name.match("CPU_OFF\[ !! 5193         '                       cpu = parseInt(name.slice(7));\n'\
5215                         cpu = parseInt(name.s !! 5194         '               else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\
5216                 var dmesg = document.getEleme !! 5195         '                       cpu = parseInt(name.slice(8));\n'\
5217                 var dev = dmesg.getElementsBy !! 5196         '               var dmesg = document.getElementById("dmesg");\n'\
5218                 var idlist = [];              !! 5197         '               var dev = dmesg.getElementsByClassName("thread");\n'\
5219                 var pdata = [[]];             !! 5198         '               var idlist = [];\n'\
5220                 if(document.getElementById("d !! 5199         '               var pdata = [[]];\n'\
5221                         pdata = [[], []];     !! 5200         '               if(document.getElementById("devicedetail1"))\n'\
5222                 var pd = pdata[0];            !! 5201         '                       pdata = [[], []];\n'\
5223                 var total = [0.0, 0.0, 0.0];  !! 5202         '               var pd = pdata[0];\n'\
5224                 for (var i = 0; i < dev.lengt !! 5203         '               var total = [0.0, 0.0, 0.0];\n'\
5225                         dname = deviceName(de !! 5204         '               for (var i = 0; i < dev.length; i++) {\n'\
5226                         if((cpu >= 0 && dname !! 5205         '                       dname = deviceName(dev[i].title);\n'\
5227                                 (name == dnam !! 5206         '                       if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\
5228                         {                     !! 5207         '                               (name == dname))\n'\
5229                                 idlist[idlist !! 5208         '                       {\n'\
5230                                 var tidx = 1; !! 5209         '                               idlist[idlist.length] = dev[i].id;\n'\
5231                                 if(dev[i].id[ !! 5210         '                               var tidx = 1;\n'\
5232                                         pd =  !! 5211         '                               if(dev[i].id[0] == "a") {\n'\
5233                                 } else {      !! 5212         '                                       pd = pdata[0];\n'\
5234                                         if(pd !! 5213         '                               } else {\n'\
5235                                         if(to !! 5214         '                                       if(pdata.length == 1) pdata[1] = [];\n'\
5236                                         pd =  !! 5215         '                                       if(total.length == 3) total[3]=total[4]=0.0;\n'\
5237                                         tidx  !! 5216         '                                       pd = pdata[1];\n'\
5238                                 }             !! 5217         '                                       tidx = 3;\n'\
5239                                 var info = de !! 5218         '                               }\n'\
5240                                 var pname = i !! 5219         '                               var info = dev[i].title.split(" ");\n'\
5241                                 pd[pname] = p !! 5220         '                               var pname = info[info.length-1];\n'\
5242                                 total[0] += p !! 5221         '                               pd[pname] = parseFloat(info[info.length-3].slice(1));\n'\
5243                                 if(pname.inde !! 5222         '                               total[0] += pd[pname];\n'\
5244                                         total !! 5223         '                               if(pname.indexOf("suspend") >= 0)\n'\
5245                                 else          !! 5224         '                                       total[tidx] += pd[pname];\n'\
5246                                         total !! 5225         '                               else\n'\
5247                         }                     !! 5226         '                                       total[tidx+1] += pd[pname];\n'\
5248                 }                             !! 5227         '                       }\n'\
5249                 var devname = deviceTitle(thi !! 5228         '               }\n'\
5250                 var left = 0.0;               !! 5229         '               var devname = deviceTitle(this.title, total, cpu);\n'\
5251                 for (var t = 0; t < pdata.len !! 5230         '               var left = 0.0;\n'\
5252                         pd = pdata[t];        !! 5231         '               for (var t = 0; t < pdata.length; t++) {\n'\
5253                         devinfo = document.ge !! 5232         '                       pd = pdata[t];\n'\
5254                         var phases = devinfo. !! 5233         '                       devinfo = document.getElementById("devicedetail"+t);\n'\
5255                         for (var i = 0; i < p !! 5234         '                       var phases = devinfo.getElementsByClassName("phaselet");\n'\
5256                                 if(phases[i]. !! 5235         '                       for (var i = 0; i < phases.length; i++) {\n'\
5257                                         var w !! 5236         '                               if(phases[i].id in pd) {\n'\
5258                                         var f !! 5237         '                                       var w = 100.0*pd[phases[i].id]/total[0];\n'\
5259                                         if(w  !! 5238         '                                       var fs = 32;\n'\
5260                                         var f !! 5239         '                                       if(w < 8) fs = 4*w | 0;\n'\
5261                                         phase !! 5240         '                                       var fs2 = fs*3/4;\n'\
5262                                         phase !! 5241         '                                       phases[i].style.width = w+"%";\n'\
5263                                         phase !! 5242         '                                       phases[i].style.left = left+"%";\n'\
5264                                         left  !! 5243         '                                       phases[i].title = phases[i].id+" "+pd[phases[i].id]+" ms";\n'\
5265                                         var t !! 5244         '                                       left += w;\n'\
5266                                         var p !! 5245         '                                       var time = "<t4 style=\\"font-size:"+fs+"px\\">"+pd[phases[i].id]+" ms<br></t4>";\n'\
5267                                         phase !! 5246         '                                       var pname = "<t3 style=\\"font-size:"+fs2+"px\\">"+phases[i].id.replace(new RegExp("_", "g"), " ")+"</t3>";\n'\
5268                                 } else {      !! 5247         '                                       phases[i].innerHTML = time+pname;\n'\
5269                                         phase !! 5248         '                               } else {\n'\
5270                                         phase !! 5249         '                                       phases[i].style.width = "0%";\n'\
5271                                 }             !! 5250         '                                       phases[i].style.left = left+"%";\n'\
5272                         }                     !! 5251         '                               }\n'\
5273                 }                             !! 5252         '                       }\n'\
5274                 if(typeof devstats !== 'undef !! 5253         '               }\n'\
5275                         callDetail(this.id, t !! 5254         '               if(typeof devstats !== \'undefined\')\n'\
5276                 var cglist = document.getElem !! 5255         '                       callDetail(this.id, this.title);\n'\
5277                 if(!cglist) return;           !! 5256         '               var cglist = document.getElementById("callgraphs");\n'\
5278                 var cg = cglist.getElementsBy !! 5257         '               if(!cglist) return;\n'\
5279                 if(cg.length < 10) return;    !! 5258         '               var cg = cglist.getElementsByClassName("atop");\n'\
5280                 for (var i = 0; i < cg.length !! 5259         '               if(cg.length < 10) return;\n'\
5281                         cgid = cg[i].id.split !! 5260         '               for (var i = 0; i < cg.length; i++) {\n'\
5282                         if(idlist.indexOf(cgi !! 5261         '                       cgid = cg[i].id.split("x")[0]\n'\
5283                                 cg[i].style.d !! 5262         '                       if(idlist.indexOf(cgid) >= 0) {\n'\
5284                         } else {              !! 5263         '                               cg[i].style.display = "block";\n'\
5285                                 cg[i].style.d !! 5264         '                       } else {\n'\
5286                         }                     !! 5265         '                               cg[i].style.display = "none";\n'\
5287                 }                             !! 5266         '                       }\n'\
5288         }                                     !! 5267         '               }\n'\
5289         function callDetail(devid, devtitle)  !! 5268         '       }\n'\
5290                 if(!(devid in devstats) || de !! 5269         '       function callDetail(devid, devtitle) {\n'\
5291                         return;               !! 5270         '               if(!(devid in devstats) || devstats[devid].length < 1)\n'\
5292                 var list = devstats[devid];   !! 5271         '                       return;\n'\
5293                 var tmp = devtitle.split(" ") !! 5272         '               var list = devstats[devid];\n'\
5294                 var name = tmp[0], phase = tm !! 5273         '               var tmp = devtitle.split(" ");\n'\
5295                 var dd = document.getElementB !! 5274         '               var name = tmp[0], phase = tmp[tmp.length-1];\n'\
5296                 var total = parseFloat(tmp[1] !! 5275         '               var dd = document.getElementById(phase);\n'\
5297                 var mlist = [];               !! 5276         '               var total = parseFloat(tmp[1].slice(1));\n'\
5298                 var maxlen = 0;               !! 5277         '               var mlist = [];\n'\
5299                 var info = []                 !! 5278         '               var maxlen = 0;\n'\
5300                 for(var i in list) {          !! 5279         '               var info = []\n'\
5301                         if(list[i][0] == "@") !! 5280         '               for(var i in list) {\n'\
5302                                 info = list[i !! 5281         '                       if(list[i][0] == "@") {\n'\
5303                                 continue;     !! 5282         '                               info = list[i].split("|");\n'\
5304                         }                     !! 5283         '                               continue;\n'\
5305                         var tmp = list[i].spl !! 5284         '                       }\n'\
5306                         var t = parseFloat(tm !! 5285         '                       var tmp = list[i].split("|");\n'\
5307                         var p = (t*100.0/tota !! 5286         '                       var t = parseFloat(tmp[0]), f = tmp[1], c = parseInt(tmp[2]);\n'\
5308                         mlist[mlist.length] = !! 5287         '                       var p = (t*100.0/total).toFixed(2);\n'\
5309                         if(f.length > maxlen) !! 5288         '                       mlist[mlist.length] = [f, c, t.toFixed(2), p+"%"];\n'\
5310                                 maxlen = f.le !! 5289         '                       if(f.length > maxlen)\n'\
5311                 }                             !! 5290         '                               maxlen = f.length;\n'\
5312                 var pad = 5;                  !! 5291         '               }\n'\
5313                 if(mlist.length == 0) pad = 3 !! 5292         '               var pad = 5;\n'\
5314                 var html = '<div style="paddi !! 5293         '               if(mlist.length == 0) pad = 30;\n'\
5315                 if(info.length > 2)           !! 5294         '               var html = \'<div style="padding-top:\'+pad+\'px"><t3> <b>\'+name+\':</b>\';\n'\
5316                         html += " start=<b>"+ !! 5295         '               if(info.length > 2)\n'\
5317                 if(info.length > 3)           !! 5296         '                       html += " start=<b>"+info[1]+"</b>, end=<b>"+info[2]+"</b>";\n'\
5318                         html += ", length<i>( !! 5297         '               if(info.length > 3)\n'\
5319                 if(info.length > 4)           !! 5298         '                       html += ", length<i>(w/o overhead)</i>=<b>"+info[3]+" ms</b>";\n'\
5320                         html += ", return=<b> !! 5299         '               if(info.length > 4)\n'\
5321                 html += "</t3></div>";        !! 5300         '                       html += ", return=<b>"+info[4]+"</b>";\n'\
5322                 if(mlist.length > 0) {        !! 5301         '               html += "</t3></div>";\n'\
5323                         html += '<table class !! 5302         '               if(mlist.length > 0) {\n'\
5324                         for(var i in mlist)   !! 5303         '                       html += \'<table class=fstat style="padding-top:\'+(maxlen*5)+\'px;"><tr><th>Function</th>\';\n'\
5325                                 html += "<td  !! 5304         '                       for(var i in mlist)\n'\
5326                         html += "</tr><tr><th !! 5305         '                               html += "<td class=vt>"+mlist[i][0]+"</td>";\n'\
5327                         for(var i in mlist)   !! 5306         '                       html += "</tr><tr><th>Calls</th>";\n'\
5328                                 html += "<td> !! 5307         '                       for(var i in mlist)\n'\
5329                         html += "</tr><tr><th !! 5308         '                               html += "<td>"+mlist[i][1]+"</td>";\n'\
5330                         for(var i in mlist)   !! 5309         '                       html += "</tr><tr><th>Time(ms)</th>";\n'\
5331                                 html += "<td> !! 5310         '                       for(var i in mlist)\n'\
5332                         html += "</tr><tr><th !! 5311         '                               html += "<td>"+mlist[i][2]+"</td>";\n'\
5333                         for(var i in mlist)   !! 5312         '                       html += "</tr><tr><th>Percent</th>";\n'\
5334                                 html += "<td> !! 5313         '                       for(var i in mlist)\n'\
5335                         html += "</tr></table !! 5314         '                               html += "<td>"+mlist[i][3]+"</td>";\n'\
5336                 }                             !! 5315         '                       html += "</tr></table>";\n'\
5337                 dd.innerHTML = html;          !! 5316         '               }\n'\
5338                 var height = (maxlen*5)+100;  !! 5317         '               dd.innerHTML = html;\n'\
5339                 dd.style.height = height+"px" !! 5318         '               var height = (maxlen*5)+100;\n'\
5340                 document.getElementById("devi !! 5319         '               dd.style.height = height+"px";\n'\
5341         }                                     !! 5320         '               document.getElementById("devicedetail").style.height = height+"px";\n'\
5342         function callSelect() {               !! 5321         '       }\n'\
5343                 var cglist = document.getElem !! 5322         '       function callSelect() {\n'\
5344                 if(!cglist) return;           !! 5323         '               var cglist = document.getElementById("callgraphs");\n'\
5345                 var cg = cglist.getElementsBy !! 5324         '               if(!cglist) return;\n'\
5346                 for (var i = 0; i < cg.length !! 5325         '               var cg = cglist.getElementsByClassName("atop");\n'\
5347                         if(this.id == cg[i].i !! 5326         '               for (var i = 0; i < cg.length; i++) {\n'\
5348                                 cg[i].style.d !! 5327         '                       if(this.id == cg[i].id) {\n'\
5349                         } else {              !! 5328         '                               cg[i].style.display = "block";\n'\
5350                                 cg[i].style.d !! 5329         '                       } else {\n'\
5351                         }                     !! 5330         '                               cg[i].style.display = "none";\n'\
5352                 }                             !! 5331         '                       }\n'\
5353         }                                     !! 5332         '               }\n'\
5354         function devListWindow(e) {           !! 5333         '       }\n'\
5355                 var win = window.open();      !! 5334         '       function devListWindow(e) {\n'\
5356                 var html = "<title>"+e.target !! 5335         '               var win = window.open();\n'\
5357                         "<style type=\"text/c !! 5336         '               var html = "<title>"+e.target.innerHTML+"</title>"+\n'\
5358                         "   ul {list-style-ty !! 5337         '                       "<style type=\\"text/css\\">"+\n'\
5359                         "</style>"            !! 5338         '                       "   ul {list-style-type:circle;padding-left:10px;margin-left:10px;}"+\n'\
5360                 var dt = devtable[0];         !! 5339         '                       "</style>"\n'\
5361                 if(e.target.id != "devlist1") !! 5340         '               var dt = devtable[0];\n'\
5362                         dt = devtable[1];     !! 5341         '               if(e.target.id != "devlist1")\n'\
5363                 win.document.write(html+dt);  !! 5342         '                       dt = devtable[1];\n'\
5364         }                                     !! 5343         '               win.document.write(html+dt);\n'\
5365         function errWindow() {                !! 5344         '       }\n'\
5366                 var range = this.id.split("_" !! 5345         '       function errWindow() {\n'\
5367                 var idx1 = parseInt(range[0]) !! 5346         '               var range = this.id.split("_");\n'\
5368                 var idx2 = parseInt(range[1]) !! 5347         '               var idx1 = parseInt(range[0]);\n'\
5369                 var win = window.open();      !! 5348         '               var idx2 = parseInt(range[1]);\n'\
5370                 var log = document.getElement !! 5349         '               var win = window.open();\n'\
5371                 var title = "<title>dmesg log !! 5350         '               var log = document.getElementById("dmesglog");\n'\
5372                 var text = log.innerHTML.spli !! 5351         '               var title = "<title>dmesg log</title>";\n'\
5373                 var html = "";                !! 5352         '               var text = log.innerHTML.split("\\n");\n'\
5374                 for(var i = 0; i < text.lengt !! 5353         '               var html = "";\n'\
5375                         if(i == idx1) {       !! 5354         '               for(var i = 0; i < text.length; i++) {\n'\
5376                                 html += "<e i !! 5355         '                       if(i == idx1) {\n'\
5377                         } else if(i > idx1 && !! 5356         '                               html += "<e id=target>"+text[i]+"</e>\\n";\n'\
5378                                 html += "<e>" !! 5357         '                       } else if(i > idx1 && i <= idx2) {\n'\
5379                         } else {              !! 5358         '                               html += "<e>"+text[i]+"</e>\\n";\n'\
5380                                 html += text[ !! 5359         '                       } else {\n'\
5381                         }                     !! 5360         '                               html += text[i]+"\\n";\n'\
5382                 }                             !! 5361         '                       }\n'\
5383                 win.document.write("<style>e{ !! 5362         '               }\n'\
5384                 win.location.hash = "#target" !! 5363         '               win.document.write("<style>e{color:red}</style>"+title+"<pre>"+html+"</pre>");\n'\
5385                 win.document.close();         !! 5364         '               win.location.hash = "#target";\n'\
5386         }                                     !! 5365         '               win.document.close();\n'\
5387         function logWindow(e) {               !! 5366         '       }\n'\
5388                 var name = e.target.id.slice( !! 5367         '       function logWindow(e) {\n'\
5389                 var win = window.open();      !! 5368         '               var name = e.target.id.slice(4);\n'\
5390                 var log = document.getElement !! 5369         '               var win = window.open();\n'\
5391                 var title = "<title>"+documen !! 5370         '               var log = document.getElementById(name+"log");\n'\
5392                 win.document.write(title+"<pr !! 5371         '               var title = "<title>"+document.title.split(" ")[0]+" "+name+" log</title>";\n'\
5393                 win.document.close();         !! 5372         '               win.document.write(title+"<pre>"+log.innerHTML+"</pre>");\n'\
5394         }                                     !! 5373         '               win.document.close();\n'\
5395         function onMouseDown(e) {             !! 5374         '       }\n'\
5396                 dragval[0] = e.clientX;       !! 5375         '       function onMouseDown(e) {\n'\
5397                 dragval[1] = document.getElem !! 5376         '               dragval[0] = e.clientX;\n'\
5398                 document.onmousemove = onMous !! 5377         '               dragval[1] = document.getElementById("dmesgzoombox").scrollLeft;\n'\
5399         }                                     !! 5378         '               document.onmousemove = onMouseMove;\n'\
5400         function onMouseMove(e) {             !! 5379         '       }\n'\
5401                 var zoombox = document.getEle !! 5380         '       function onMouseMove(e) {\n'\
5402                 zoombox.scrollLeft = dragval[ !! 5381         '               var zoombox = document.getElementById("dmesgzoombox");\n'\
5403         }                                     !! 5382         '               zoombox.scrollLeft = dragval[1] + dragval[0] - e.clientX;\n'\
5404         function onMouseUp(e) {               !! 5383         '       }\n'\
5405                 document.onmousemove = null;  !! 5384         '       function onMouseUp(e) {\n'\
5406         }                                     !! 5385         '               document.onmousemove = null;\n'\
5407         function onKeyPress(e) {              !! 5386         '       }\n'\
5408                 var c = e.charCode;           !! 5387         '       function onKeyPress(e) {\n'\
5409                 if(c != 42 && c != 43 && c != !! 5388         '               var c = e.charCode;\n'\
5410                 var click = document.createEv !! 5389         '               if(c != 42 && c != 43 && c != 45) return;\n'\
5411                 click.initEvent("click", true !! 5390         '               var click = document.createEvent("Events");\n'\
5412                 if(c == 43)                   !! 5391         '               click.initEvent("click", true, false);\n'\
5413                         document.getElementBy !! 5392         '               if(c == 43)  \n'\
5414                 else if(c == 45)              !! 5393         '                       document.getElementById("zoomin").dispatchEvent(click);\n'\
5415                         document.getElementBy !! 5394         '               else if(c == 45)\n'\
5416                 else if(c == 42)              !! 5395         '                       document.getElementById("zoomout").dispatchEvent(click);\n'\
5417                         document.getElementBy !! 5396         '               else if(c == 42)\n'\
5418         }                                     !! 5397         '                       document.getElementById("zoomdef").dispatchEvent(click);\n'\
5419         window.addEventListener("resize", fun !! 5398         '       }\n'\
5420         window.addEventListener("load", funct !! 5399         '       window.addEventListener("resize", function () {zoomTimeline();});\n'\
5421                 var dmesg = document.getEleme !! 5400         '       window.addEventListener("load", function () {\n'\
5422                 dmesg.style.width = "100%"    !! 5401         '               var dmesg = document.getElementById("dmesg");\n'\
5423                 dmesg.onmousedown = onMouseDo !! 5402         '               dmesg.style.width = "100%"\n'\
5424                 document.onmouseup = onMouseU !! 5403         '               dmesg.onmousedown = onMouseDown;\n'\
5425                 document.onkeypress = onKeyPr !! 5404         '               document.onmouseup = onMouseUp;\n'\
5426                 document.getElementById("zoom !! 5405         '               document.onkeypress = onKeyPress;\n'\
5427                 document.getElementById("zoom !! 5406         '               document.getElementById("zoomin").onclick = zoomTimeline;\n'\
5428                 document.getElementById("zoom !! 5407         '               document.getElementById("zoomout").onclick = zoomTimeline;\n'\
5429                 var list = document.getElemen !! 5408         '               document.getElementById("zoomdef").onclick = zoomTimeline;\n'\
5430                 for (var i = 0; i < list.leng !! 5409         '               var list = document.getElementsByClassName("err");\n'\
5431                         list[i].onclick = err !! 5410         '               for (var i = 0; i < list.length; i++)\n'\
5432                 var list = document.getElemen !! 5411         '                       list[i].onclick = errWindow;\n'\
5433                 for (var i = 0; i < list.leng !! 5412         '               var list = document.getElementsByClassName("logbtn");\n'\
5434                         list[i].onclick = log !! 5413         '               for (var i = 0; i < list.length; i++)\n'\
5435                 list = document.getElementsBy !! 5414         '                       list[i].onclick = logWindow;\n'\
5436                 for (var i = 0; i < list.leng !! 5415         '               list = document.getElementsByClassName("devlist");\n'\
5437                         list[i].onclick = dev !! 5416         '               for (var i = 0; i < list.length; i++)\n'\
5438                 var dev = dmesg.getElementsBy !! 5417         '                       list[i].onclick = devListWindow;\n'\
5439                 for (var i = 0; i < dev.lengt !! 5418         '               var dev = dmesg.getElementsByClassName("thread");\n'\
5440                         dev[i].onclick = devi !! 5419         '               for (var i = 0; i < dev.length; i++) {\n'\
5441                         dev[i].onmouseover =  !! 5420         '                       dev[i].onclick = deviceDetail;\n'\
5442                         dev[i].onmouseout = d !! 5421         '                       dev[i].onmouseover = deviceHover;\n'\
5443                 }                             !! 5422         '                       dev[i].onmouseout = deviceUnhover;\n'\
5444                 var dev = dmesg.getElementsBy !! 5423         '               }\n'\
5445                 for (var i = 0; i < dev.lengt !! 5424         '               var dev = dmesg.getElementsByClassName("srccall");\n'\
5446                         dev[i].onclick = call !! 5425         '               for (var i = 0; i < dev.length; i++)\n'\
5447                 zoomTimeline();               !! 5426         '                       dev[i].onclick = callSelect;\n'\
5448         });                                   !! 5427         '               zoomTimeline();\n'\
5449 </script> """                                 !! 5428         '       });\n'\
                                                   >> 5429         '</script>\n'
5450         hf.write(script_code);                   5430         hf.write(script_code);
5451                                                  5431 
5452 # Function: executeSuspend                       5432 # Function: executeSuspend
5453 # Description:                                   5433 # Description:
5454 #        Execute system suspend through the s    5434 #        Execute system suspend through the sysfs interface, then copy the output
5455 #        dmesg and ftrace files to the test o    5435 #        dmesg and ftrace files to the test output directory.
5456 def executeSuspend(quiet=False):                 5436 def executeSuspend(quiet=False):
5457         sv, tp, pm = sysvals, sysvals.tpath,     5437         sv, tp, pm = sysvals, sysvals.tpath, ProcessMonitor()
5458         if sv.wifi:                              5438         if sv.wifi:
5459                 wifi = sv.checkWifi()            5439                 wifi = sv.checkWifi()
5460                 sv.dlog('wifi check, connecte    5440                 sv.dlog('wifi check, connected device is "%s"' % wifi)
5461         testdata = []                            5441         testdata = []
5462         # run these commands to prepare the s    5442         # run these commands to prepare the system for suspend
5463         if sv.display:                           5443         if sv.display:
5464                 if not quiet:                    5444                 if not quiet:
5465                         pprint('SET DISPLAY T    5445                         pprint('SET DISPLAY TO %s' % sv.display.upper())
5466                 ret = sv.displayControl(sv.di    5446                 ret = sv.displayControl(sv.display)
5467                 sv.dlog('xset display %s, ret    5447                 sv.dlog('xset display %s, ret = %d' % (sv.display, ret))
5468                 time.sleep(1)                    5448                 time.sleep(1)
5469         if sv.sync:                              5449         if sv.sync:
5470                 if not quiet:                    5450                 if not quiet:
5471                         pprint('SYNCING FILES    5451                         pprint('SYNCING FILESYSTEMS')
5472                 sv.dlog('syncing filesystems'    5452                 sv.dlog('syncing filesystems')
5473                 call('sync', shell=True)         5453                 call('sync', shell=True)
5474         sv.dlog('read dmesg')                    5454         sv.dlog('read dmesg')
5475         sv.initdmesg()                           5455         sv.initdmesg()
5476         sv.dlog('cmdinfo before')             !! 5456         # start ftrace
                                                   >> 5457         if sv.useftrace:
                                                   >> 5458                 if not quiet:
                                                   >> 5459                         pprint('START TRACING')
                                                   >> 5460                 sv.dlog('start ftrace tracing')
                                                   >> 5461                 sv.fsetVal('1', 'tracing_on')
                                                   >> 5462                 if sv.useprocmon:
                                                   >> 5463                         sv.dlog('start the process monitor')
                                                   >> 5464                         pm.start()
                                                   >> 5465         sv.dlog('run the cmdinfo list before')
5477         sv.cmdinfo(True)                         5466         sv.cmdinfo(True)
5478         sv.start(pm)                          << 
5479         # execute however many s/r runs reque    5467         # execute however many s/r runs requested
5480         for count in range(1,sv.execcount+1):    5468         for count in range(1,sv.execcount+1):
5481                 # x2delay in between test run    5469                 # x2delay in between test runs
5482                 if(count > 1 and sv.x2delay >    5470                 if(count > 1 and sv.x2delay > 0):
5483                         sv.fsetVal('WAIT %d'     5471                         sv.fsetVal('WAIT %d' % sv.x2delay, 'trace_marker')
5484                         time.sleep(sv.x2delay    5472                         time.sleep(sv.x2delay/1000.0)
5485                         sv.fsetVal('WAIT END'    5473                         sv.fsetVal('WAIT END', 'trace_marker')
5486                 # start message                  5474                 # start message
5487                 if sv.testcommand != '':         5475                 if sv.testcommand != '':
5488                         pprint('COMMAND START    5476                         pprint('COMMAND START')
5489                 else:                            5477                 else:
5490                         if(sv.rtcwake):          5478                         if(sv.rtcwake):
5491                                 pprint('SUSPE    5479                                 pprint('SUSPEND START')
5492                         else:                    5480                         else:
5493                                 pprint('SUSPE    5481                                 pprint('SUSPEND START (press a key to resume)')
5494                 # set rtcwake                    5482                 # set rtcwake
5495                 if(sv.rtcwake):                  5483                 if(sv.rtcwake):
5496                         if not quiet:            5484                         if not quiet:
5497                                 pprint('will     5485                                 pprint('will issue an rtcwake in %d seconds' % sv.rtcwaketime)
5498                         sv.dlog('enable RTC w    5486                         sv.dlog('enable RTC wake alarm')
5499                         sv.rtcWakeAlarmOn()      5487                         sv.rtcWakeAlarmOn()
5500                 # start of suspend trace mark    5488                 # start of suspend trace marker
5501                 sv.fsetVal(datetime.now().str    5489                 sv.fsetVal(datetime.now().strftime(sv.tmstart), 'trace_marker')
5502                 # predelay delay                 5490                 # predelay delay
5503                 if(count == 1 and sv.predelay    5491                 if(count == 1 and sv.predelay > 0):
5504                         sv.fsetVal('WAIT %d'     5492                         sv.fsetVal('WAIT %d' % sv.predelay, 'trace_marker')
5505                         time.sleep(sv.predela    5493                         time.sleep(sv.predelay/1000.0)
5506                         sv.fsetVal('WAIT END'    5494                         sv.fsetVal('WAIT END', 'trace_marker')
5507                 # initiate suspend or command    5495                 # initiate suspend or command
5508                 sv.dlog('system executing a s    5496                 sv.dlog('system executing a suspend')
5509                 tdata = {'error': ''}            5497                 tdata = {'error': ''}
5510                 if sv.testcommand != '':         5498                 if sv.testcommand != '':
5511                         res = call(sv.testcom    5499                         res = call(sv.testcommand+' 2>&1', shell=True);
5512                         if res != 0:             5500                         if res != 0:
5513                                 tdata['error'    5501                                 tdata['error'] = 'cmd returned %d' % res
5514                 else:                            5502                 else:
5515                         s0ixready = sv.s0ixSu << 
5516                         mode = sv.suspendmode    5503                         mode = sv.suspendmode
5517                         if sv.memmode and os.    5504                         if sv.memmode and os.path.exists(sv.mempowerfile):
5518                                 mode = 'mem'     5505                                 mode = 'mem'
5519                                 sv.testVal(sv    5506                                 sv.testVal(sv.mempowerfile, 'radio', sv.memmode)
5520                         if sv.diskmode and os    5507                         if sv.diskmode and os.path.exists(sv.diskpowerfile):
5521                                 mode = 'disk'    5508                                 mode = 'disk'
5522                                 sv.testVal(sv    5509                                 sv.testVal(sv.diskpowerfile, 'radio', sv.diskmode)
5523                         if sv.acpidebug:         5510                         if sv.acpidebug:
5524                                 sv.testVal(sv    5511                                 sv.testVal(sv.acpipath, 'acpi', '0xe')
5525                         if ((mode == 'freeze' !! 5512                         if mode == 'freeze' and sv.haveTurbostat():
5526                                 and sv.haveTu << 
5527                                 # execution w    5513                                 # execution will pause here
5528                                 retval, turbo !! 5514                                 turbo = sv.turbostat()
5529                                 if retval !=  << 
5530                                         tdata << 
5531                                 if turbo:        5515                                 if turbo:
5532                                         tdata    5516                                         tdata['turbo'] = turbo
5533                         else:                    5517                         else:
5534                                 pf = open(sv.    5518                                 pf = open(sv.powerfile, 'w')
5535                                 pf.write(mode    5519                                 pf.write(mode)
5536                                 # execution w    5520                                 # execution will pause here
5537                                 try:             5521                                 try:
5538                                         pf.fl << 
5539                                         pf.cl    5522                                         pf.close()
5540                                 except Except    5523                                 except Exception as e:
5541                                         tdata    5524                                         tdata['error'] = str(e)
5542                 sv.fsetVal('CMD COMPLETE', 't !! 5525                 sv.dlog('system returned from resume')
5543                 sv.dlog('system returned')    << 
5544                 # reset everything               5526                 # reset everything
5545                 sv.testVal('restoreall')         5527                 sv.testVal('restoreall')
5546                 if(sv.rtcwake):                  5528                 if(sv.rtcwake):
5547                         sv.dlog('disable RTC     5529                         sv.dlog('disable RTC wake alarm')
5548                         sv.rtcWakeAlarmOff()     5530                         sv.rtcWakeAlarmOff()
5549                 # postdelay delay                5531                 # postdelay delay
5550                 if(count == sv.execcount and     5532                 if(count == sv.execcount and sv.postdelay > 0):
5551                         sv.fsetVal('WAIT %d'     5533                         sv.fsetVal('WAIT %d' % sv.postdelay, 'trace_marker')
5552                         time.sleep(sv.postdel    5534                         time.sleep(sv.postdelay/1000.0)
5553                         sv.fsetVal('WAIT END'    5535                         sv.fsetVal('WAIT END', 'trace_marker')
5554                 # return from suspend            5536                 # return from suspend
5555                 pprint('RESUME COMPLETE')        5537                 pprint('RESUME COMPLETE')
5556                 if(count < sv.execcount):     !! 5538                 sv.fsetVal(datetime.now().strftime(sv.tmend), 'trace_marker')
5557                         sv.fsetVal(datetime.n << 
5558                 elif(not sv.wifitrace):       << 
5559                         sv.fsetVal(datetime.n << 
5560                         sv.stop(pm)           << 
5561                 if sv.wifi and wifi:             5539                 if sv.wifi and wifi:
5562                         tdata['wifi'] = sv.po    5540                         tdata['wifi'] = sv.pollWifi(wifi)
5563                         sv.dlog('wifi check,     5541                         sv.dlog('wifi check, %s' % tdata['wifi'])
5564                 if(count == sv.execcount and  !! 5542                         if sv.netfix:
5565                         sv.fsetVal(datetime.n !! 5543                                 netfixout = sv.netfixon('wired')
5566                         sv.stop(pm)           !! 5544                 elif sv.netfix:
5567                 if sv.netfix:                 !! 5545                         netfixout = sv.netfixon()
5568                         tdata['netfix'] = sv. !! 5546                 if sv.netfix and netfixout:
                                                   >> 5547                         tdata['netfix'] = netfixout
5569                         sv.dlog('netfix, %s'     5548                         sv.dlog('netfix, %s' % tdata['netfix'])
5570                 if(sv.suspendmode == 'mem' or    5549                 if(sv.suspendmode == 'mem' or sv.suspendmode == 'command'):
5571                         sv.dlog('read the ACP    5550                         sv.dlog('read the ACPI FPDT')
5572                         tdata['fw'] = getFPDT    5551                         tdata['fw'] = getFPDT(False)
5573                 testdata.append(tdata)           5552                 testdata.append(tdata)
5574         sv.dlog('cmdinfo after')              !! 5553         sv.dlog('run the cmdinfo list after')
5575         cmdafter = sv.cmdinfo(False)             5554         cmdafter = sv.cmdinfo(False)
                                                   >> 5555         # stop ftrace
                                                   >> 5556         if sv.useftrace:
                                                   >> 5557                 if sv.useprocmon:
                                                   >> 5558                         sv.dlog('stop the process monitor')
                                                   >> 5559                         pm.stop()
                                                   >> 5560                 sv.fsetVal('0', 'tracing_on')
5576         # grab a copy of the dmesg output        5561         # grab a copy of the dmesg output
5577         if not quiet:                            5562         if not quiet:
5578                 pprint('CAPTURING DMESG')        5563                 pprint('CAPTURING DMESG')
                                                   >> 5564         sysvals.dlog('EXECUTION TRACE END')
5579         sv.getdmesg(testdata)                    5565         sv.getdmesg(testdata)
5580         # grab a copy of the ftrace output       5566         # grab a copy of the ftrace output
5581         if sv.useftrace:                         5567         if sv.useftrace:
5582                 if not quiet:                    5568                 if not quiet:
5583                         pprint('CAPTURING TRA    5569                         pprint('CAPTURING TRACE')
5584                 op = sv.writeDatafileHeader(s    5570                 op = sv.writeDatafileHeader(sv.ftracefile, testdata)
5585                 fp = open(tp+'trace', 'rb')   !! 5571                 fp = open(tp+'trace', 'r')
5586                 op.write(ascii(fp.read()))    !! 5572                 for line in fp:
                                                   >> 5573                         op.write(line)
5587                 op.close()                       5574                 op.close()
5588                 sv.fsetVal('', 'trace')          5575                 sv.fsetVal('', 'trace')
5589                 sv.platforminfo(cmdafter)        5576                 sv.platforminfo(cmdafter)
5590                                                  5577 
5591 def readFile(file):                              5578 def readFile(file):
5592         if os.path.islink(file):                 5579         if os.path.islink(file):
5593                 return os.readlink(file).spli    5580                 return os.readlink(file).split('/')[-1]
5594         else:                                    5581         else:
5595                 return sysvals.getVal(file).s    5582                 return sysvals.getVal(file).strip()
5596                                                  5583 
5597 # Function: ms2nice                              5584 # Function: ms2nice
5598 # Description:                                   5585 # Description:
5599 #        Print out a very concise time string    5586 #        Print out a very concise time string in minutes and seconds
5600 # Output:                                        5587 # Output:
5601 #        The time string, e.g. "1901m16s"        5588 #        The time string, e.g. "1901m16s"
5602 def ms2nice(val):                                5589 def ms2nice(val):
5603         val = int(val)                           5590         val = int(val)
5604         h = val // 3600000                       5591         h = val // 3600000
5605         m = (val // 60000) % 60                  5592         m = (val // 60000) % 60
5606         s = (val // 1000) % 60                   5593         s = (val // 1000) % 60
5607         if h > 0:                                5594         if h > 0:
5608                 return '%d:%02d:%02d' % (h, m    5595                 return '%d:%02d:%02d' % (h, m, s)
5609         if m > 0:                                5596         if m > 0:
5610                 return '%02d:%02d' % (m, s)      5597                 return '%02d:%02d' % (m, s)
5611         return '%ds' % s                         5598         return '%ds' % s
5612                                                  5599 
5613 def yesno(val):                                  5600 def yesno(val):
5614         list = {'enabled':'A', 'disabled':'S'    5601         list = {'enabled':'A', 'disabled':'S', 'auto':'E', 'on':'D',
5615                 'active':'A', 'suspended':'S'    5602                 'active':'A', 'suspended':'S', 'suspending':'S'}
5616         if val not in list:                      5603         if val not in list:
5617                 return ' '                       5604                 return ' '
5618         return list[val]                         5605         return list[val]
5619                                                  5606 
5620 # Function: deviceInfo                           5607 # Function: deviceInfo
5621 # Description:                                   5608 # Description:
5622 #        Detect all the USB hosts and devices    5609 #        Detect all the USB hosts and devices currently connected and add
5623 #        a list of USB device names to sysval    5610 #        a list of USB device names to sysvals for better timeline readability
5624 def deviceInfo(output=''):                       5611 def deviceInfo(output=''):
5625         if not output:                           5612         if not output:
5626                 pprint('LEGEND\n'\               5613                 pprint('LEGEND\n'\
5627                 '----------------------------    5614                 '---------------------------------------------------------------------------------------------\n'\
5628                 '  A = async/sync PM queue (A    5615                 '  A = async/sync PM queue (A/S)               C = runtime active children\n'\
5629                 '  R = runtime suspend enable    5616                 '  R = runtime suspend enabled/disabled (E/D)  rACTIVE = runtime active (min/sec)\n'\
5630                 '  S = runtime status active/    5617                 '  S = runtime status active/suspended (A/S)   rSUSPEND = runtime suspend (min/sec)\n'\
5631                 '  U = runtime usage count\n'    5618                 '  U = runtime usage count\n'\
5632                 '----------------------------    5619                 '---------------------------------------------------------------------------------------------\n'\
5633                 'DEVICE                     N    5620                 'DEVICE                     NAME                       A R S U C    rACTIVE   rSUSPEND\n'\
5634                 '----------------------------    5621                 '---------------------------------------------------------------------------------------------')
5635                                                  5622 
5636         res = []                                 5623         res = []
5637         tgtval = 'runtime_status'                5624         tgtval = 'runtime_status'
5638         lines = dict()                           5625         lines = dict()
5639         for dirname, dirnames, filenames in o    5626         for dirname, dirnames, filenames in os.walk('/sys/devices'):
5640                 if(not re.match(r'.*/power',  !! 5627                 if(not re.match('.*/power', dirname) or
5641                         'control' not in file    5628                         'control' not in filenames or
5642                         tgtval not in filenam    5629                         tgtval not in filenames):
5643                         continue                 5630                         continue
5644                 name = ''                        5631                 name = ''
5645                 dirname = dirname[:-6]           5632                 dirname = dirname[:-6]
5646                 device = dirname.split('/')[-    5633                 device = dirname.split('/')[-1]
5647                 power = dict()                   5634                 power = dict()
5648                 power[tgtval] = readFile('%s/    5635                 power[tgtval] = readFile('%s/power/%s' % (dirname, tgtval))
5649                 # only list devices which sup    5636                 # only list devices which support runtime suspend
5650                 if power[tgtval] not in ['act    5637                 if power[tgtval] not in ['active', 'suspended', 'suspending']:
5651                         continue                 5638                         continue
5652                 for i in ['product', 'driver'    5639                 for i in ['product', 'driver', 'subsystem']:
5653                         file = '%s/%s' % (dir    5640                         file = '%s/%s' % (dirname, i)
5654                         if os.path.exists(fil    5641                         if os.path.exists(file):
5655                                 name = readFi    5642                                 name = readFile(file)
5656                                 break            5643                                 break
5657                 for i in ['async', 'control',    5644                 for i in ['async', 'control', 'runtime_status', 'runtime_usage',
5658                         'runtime_active_kids'    5645                         'runtime_active_kids', 'runtime_active_time',
5659                         'runtime_suspended_ti    5646                         'runtime_suspended_time']:
5660                         if i in filenames:       5647                         if i in filenames:
5661                                 power[i] = re    5648                                 power[i] = readFile('%s/power/%s' % (dirname, i))
5662                 if output:                       5649                 if output:
5663                         if power['control'] =    5650                         if power['control'] == output:
5664                                 res.append('%    5651                                 res.append('%s/power/control' % dirname)
5665                         continue                 5652                         continue
5666                 lines[dirname] = '%-26s %-26s    5653                 lines[dirname] = '%-26s %-26s %1s %1s %1s %1s %1s %10s %10s' % \
5667                         (device[:26], name[:2    5654                         (device[:26], name[:26],
5668                         yesno(power['async'])    5655                         yesno(power['async']), \
5669                         yesno(power['control'    5656                         yesno(power['control']), \
5670                         yesno(power['runtime_    5657                         yesno(power['runtime_status']), \
5671                         power['runtime_usage'    5658                         power['runtime_usage'], \
5672                         power['runtime_active    5659                         power['runtime_active_kids'], \
5673                         ms2nice(power['runtim    5660                         ms2nice(power['runtime_active_time']), \
5674                         ms2nice(power['runtim    5661                         ms2nice(power['runtime_suspended_time']))
5675         for i in sorted(lines):                  5662         for i in sorted(lines):
5676                 print(lines[i])                  5663                 print(lines[i])
5677         return res                               5664         return res
5678                                                  5665 
5679 # Function: getModes                             5666 # Function: getModes
5680 # Description:                                   5667 # Description:
5681 #        Determine the supported power modes     5668 #        Determine the supported power modes on this system
5682 # Output:                                        5669 # Output:
5683 #        A string list of the available modes    5670 #        A string list of the available modes
5684 def getModes():                                  5671 def getModes():
5685         modes = []                               5672         modes = []
5686         if(os.path.exists(sysvals.powerfile))    5673         if(os.path.exists(sysvals.powerfile)):
5687                 fp = open(sysvals.powerfile,     5674                 fp = open(sysvals.powerfile, 'r')
5688                 modes = fp.read().split()        5675                 modes = fp.read().split()
5689                 fp.close()                       5676                 fp.close()
5690         if(os.path.exists(sysvals.mempowerfil    5677         if(os.path.exists(sysvals.mempowerfile)):
5691                 deep = False                     5678                 deep = False
5692                 fp = open(sysvals.mempowerfil    5679                 fp = open(sysvals.mempowerfile, 'r')
5693                 for m in fp.read().split():      5680                 for m in fp.read().split():
5694                         memmode = m.strip('[]    5681                         memmode = m.strip('[]')
5695                         if memmode == 'deep':    5682                         if memmode == 'deep':
5696                                 deep = True      5683                                 deep = True
5697                         else:                    5684                         else:
5698                                 modes.append(    5685                                 modes.append('mem-%s' % memmode)
5699                 fp.close()                       5686                 fp.close()
5700                 if 'mem' in modes and not dee    5687                 if 'mem' in modes and not deep:
5701                         modes.remove('mem')      5688                         modes.remove('mem')
5702         if('disk' in modes and os.path.exists    5689         if('disk' in modes and os.path.exists(sysvals.diskpowerfile)):
5703                 fp = open(sysvals.diskpowerfi    5690                 fp = open(sysvals.diskpowerfile, 'r')
5704                 for m in fp.read().split():      5691                 for m in fp.read().split():
5705                         modes.append('disk-%s    5692                         modes.append('disk-%s' % m.strip('[]'))
5706                 fp.close()                       5693                 fp.close()
5707         return modes                             5694         return modes
5708                                                  5695 
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                            5696 # Function: dmidecode
5744 # Description:                                   5697 # Description:
5745 #        Read the bios tables and pull out sy    5698 #        Read the bios tables and pull out system info
5746 # Arguments:                                     5699 # Arguments:
5747 #        mempath: /dev/mem or custom mem path    5700 #        mempath: /dev/mem or custom mem path
5748 #        fatal: True to exit on error, False     5701 #        fatal: True to exit on error, False to return empty dict
5749 # Output:                                        5702 # Output:
5750 #        A dict object with all available key    5703 #        A dict object with all available key/values
5751 def dmidecode(mempath, fatal=False):             5704 def dmidecode(mempath, fatal=False):
5752         out = dict()                             5705         out = dict()
5753         if(not (os.path.exists(mempath) and o << 
5754                 return dmidecode_backup(out,  << 
5755                                                  5706 
5756         # the list of values to retrieve, wit    5707         # the list of values to retrieve, with hardcoded (type, idx)
5757         info = {                                 5708         info = {
5758                 'bios-vendor': (0, 4),           5709                 'bios-vendor': (0, 4),
5759                 'bios-version': (0, 5),          5710                 'bios-version': (0, 5),
5760                 'bios-release-date': (0, 8),     5711                 'bios-release-date': (0, 8),
5761                 'system-manufacturer': (1, 4)    5712                 'system-manufacturer': (1, 4),
5762                 'system-product-name': (1, 5)    5713                 'system-product-name': (1, 5),
5763                 'system-version': (1, 6),        5714                 'system-version': (1, 6),
5764                 'system-serial-number': (1, 7    5715                 'system-serial-number': (1, 7),
5765                 'baseboard-manufacturer': (2,    5716                 'baseboard-manufacturer': (2, 4),
5766                 'baseboard-product-name': (2,    5717                 'baseboard-product-name': (2, 5),
5767                 'baseboard-version': (2, 6),     5718                 'baseboard-version': (2, 6),
5768                 'baseboard-serial-number': (2    5719                 'baseboard-serial-number': (2, 7),
5769                 'chassis-manufacturer': (3, 4    5720                 'chassis-manufacturer': (3, 4),
                                                   >> 5721                 'chassis-type': (3, 5),
5770                 'chassis-version': (3, 6),       5722                 'chassis-version': (3, 6),
5771                 'chassis-serial-number': (3,     5723                 'chassis-serial-number': (3, 7),
5772                 'processor-manufacturer': (4,    5724                 'processor-manufacturer': (4, 7),
5773                 'processor-version': (4, 16),    5725                 'processor-version': (4, 16),
5774         }                                        5726         }
                                                   >> 5727         if(not os.path.exists(mempath)):
                                                   >> 5728                 if(fatal):
                                                   >> 5729                         doError('file does not exist: %s' % mempath)
                                                   >> 5730                 return out
                                                   >> 5731         if(not os.access(mempath, os.R_OK)):
                                                   >> 5732                 if(fatal):
                                                   >> 5733                         doError('file is not readable: %s' % mempath)
                                                   >> 5734                 return out
5775                                                  5735 
5776         # by default use legacy scan, but try    5736         # by default use legacy scan, but try to use EFI first
5777         memaddr, memsize = 0xf0000, 0x10000   !! 5737         memaddr = 0xf0000
                                                   >> 5738         memsize = 0x10000
5778         for ep in ['/sys/firmware/efi/systab'    5739         for ep in ['/sys/firmware/efi/systab', '/proc/efi/systab']:
5779                 if not os.path.exists(ep) or     5740                 if not os.path.exists(ep) or not os.access(ep, os.R_OK):
5780                         continue                 5741                         continue
5781                 fp = open(ep, 'r')               5742                 fp = open(ep, 'r')
5782                 buf = fp.read()                  5743                 buf = fp.read()
5783                 fp.close()                       5744                 fp.close()
5784                 i = buf.find('SMBIOS=')          5745                 i = buf.find('SMBIOS=')
5785                 if i >= 0:                       5746                 if i >= 0:
5786                         try:                     5747                         try:
5787                                 memaddr = int    5748                                 memaddr = int(buf[i+7:], 16)
5788                                 memsize = 0x2    5749                                 memsize = 0x20
5789                         except:                  5750                         except:
5790                                 continue         5751                                 continue
5791                                                  5752 
5792         # read in the memory for scanning        5753         # read in the memory for scanning
5793         try:                                     5754         try:
5794                 fp = open(mempath, 'rb')         5755                 fp = open(mempath, 'rb')
5795                 fp.seek(memaddr)                 5756                 fp.seek(memaddr)
5796                 buf = fp.read(memsize)           5757                 buf = fp.read(memsize)
5797         except:                                  5758         except:
5798                 return dmidecode_backup(out,  !! 5759                 if(fatal):
                                                   >> 5760                         doError('DMI table is unreachable, sorry')
                                                   >> 5761                 else:
                                                   >> 5762                         pprint('WARNING: /dev/mem is not readable, ignoring DMI data')
                                                   >> 5763                         return out
5799         fp.close()                               5764         fp.close()
5800                                                  5765 
5801         # search for either an SM table or DM    5766         # search for either an SM table or DMI table
5802         i = base = length = num = 0              5767         i = base = length = num = 0
5803         while(i < memsize):                      5768         while(i < memsize):
5804                 if buf[i:i+4] == b'_SM_' and     5769                 if buf[i:i+4] == b'_SM_' and i < memsize - 16:
5805                         length = struct.unpac    5770                         length = struct.unpack('H', buf[i+22:i+24])[0]
5806                         base, num = struct.un    5771                         base, num = struct.unpack('IH', buf[i+24:i+30])
5807                         break                    5772                         break
5808                 elif buf[i:i+5] == b'_DMI_':     5773                 elif buf[i:i+5] == b'_DMI_':
5809                         length = struct.unpac    5774                         length = struct.unpack('H', buf[i+6:i+8])[0]
5810                         base, num = struct.un    5775                         base, num = struct.unpack('IH', buf[i+8:i+14])
5811                         break                    5776                         break
5812                 i += 16                          5777                 i += 16
5813         if base == 0 and length == 0 and num     5778         if base == 0 and length == 0 and num == 0:
5814                 return dmidecode_backup(out,  !! 5779                 if(fatal):
                                                   >> 5780                         doError('Neither SMBIOS nor DMI were found')
                                                   >> 5781                 else:
                                                   >> 5782                         return out
5815                                                  5783 
5816         # read in the SM or DMI table            5784         # read in the SM or DMI table
5817         try:                                     5785         try:
5818                 fp = open(mempath, 'rb')         5786                 fp = open(mempath, 'rb')
5819                 fp.seek(base)                    5787                 fp.seek(base)
5820                 buf = fp.read(length)            5788                 buf = fp.read(length)
5821         except:                                  5789         except:
5822                 return dmidecode_backup(out,  !! 5790                 if(fatal):
                                                   >> 5791                         doError('DMI table is unreachable, sorry')
                                                   >> 5792                 else:
                                                   >> 5793                         pprint('WARNING: /dev/mem is not readable, ignoring DMI data')
                                                   >> 5794                         return out
5823         fp.close()                               5795         fp.close()
5824                                                  5796 
5825         # scan the table for the values we wa    5797         # scan the table for the values we want
5826         count = i = 0                            5798         count = i = 0
5827         while(count < num and i <= len(buf) -    5799         while(count < num and i <= len(buf) - 4):
5828                 type, size, handle = struct.u    5800                 type, size, handle = struct.unpack('BBH', buf[i:i+4])
5829                 n = i + size                     5801                 n = i + size
5830                 while n < len(buf) - 1:          5802                 while n < len(buf) - 1:
5831                         if 0 == struct.unpack    5803                         if 0 == struct.unpack('H', buf[n:n+2])[0]:
5832                                 break            5804                                 break
5833                         n += 1                   5805                         n += 1
5834                 data = buf[i+size:n+2].split(    5806                 data = buf[i+size:n+2].split(b'\0')
5835                 for name in info:                5807                 for name in info:
5836                         itype, idxadr = info[    5808                         itype, idxadr = info[name]
5837                         if itype == type:        5809                         if itype == type:
5838                                 idx = struct.    5810                                 idx = struct.unpack('B', buf[i+idxadr:i+idxadr+1])[0]
5839                                 if idx > 0 an    5811                                 if idx > 0 and idx < len(data) - 1:
5840                                         s = d    5812                                         s = data[idx-1].decode('utf-8')
5841                                         if s.    5813                                         if s.strip() and s.strip().lower() != 'to be filled by o.e.m.':
5842                                                  5814                                                 out[name] = s
5843                 i = n + 2                        5815                 i = n + 2
5844                 count += 1                       5816                 count += 1
5845         return out                               5817         return out
5846                                                  5818 
5847 # Function: getFPDT                              5819 # Function: getFPDT
5848 # Description:                                   5820 # Description:
5849 #        Read the acpi bios tables and pull o    5821 #        Read the acpi bios tables and pull out FPDT, the firmware data
5850 # Arguments:                                     5822 # Arguments:
5851 #        output: True to output the info to s    5823 #        output: True to output the info to stdout, False otherwise
5852 def getFPDT(output):                             5824 def getFPDT(output):
5853         rectype = {}                             5825         rectype = {}
5854         rectype[0] = 'Firmware Basic Boot Per    5826         rectype[0] = 'Firmware Basic Boot Performance Record'
5855         rectype[1] = 'S3 Performance Table Re    5827         rectype[1] = 'S3 Performance Table Record'
5856         prectype = {}                            5828         prectype = {}
5857         prectype[0] = 'Basic S3 Resume Perfor    5829         prectype[0] = 'Basic S3 Resume Performance Record'
5858         prectype[1] = 'Basic S3 Suspend Perfo    5830         prectype[1] = 'Basic S3 Suspend Performance Record'
5859                                                  5831 
5860         sysvals.rootCheck(True)                  5832         sysvals.rootCheck(True)
5861         if(not os.path.exists(sysvals.fpdtpat    5833         if(not os.path.exists(sysvals.fpdtpath)):
5862                 if(output):                      5834                 if(output):
5863                         doError('file does no    5835                         doError('file does not exist: %s' % sysvals.fpdtpath)
5864                 return False                     5836                 return False
5865         if(not os.access(sysvals.fpdtpath, os    5837         if(not os.access(sysvals.fpdtpath, os.R_OK)):
5866                 if(output):                      5838                 if(output):
5867                         doError('file is not     5839                         doError('file is not readable: %s' % sysvals.fpdtpath)
5868                 return False                     5840                 return False
5869         if(not os.path.exists(sysvals.mempath    5841         if(not os.path.exists(sysvals.mempath)):
5870                 if(output):                      5842                 if(output):
5871                         doError('file does no    5843                         doError('file does not exist: %s' % sysvals.mempath)
5872                 return False                     5844                 return False
5873         if(not os.access(sysvals.mempath, os.    5845         if(not os.access(sysvals.mempath, os.R_OK)):
5874                 if(output):                      5846                 if(output):
5875                         doError('file is not     5847                         doError('file is not readable: %s' % sysvals.mempath)
5876                 return False                     5848                 return False
5877                                                  5849 
5878         fp = open(sysvals.fpdtpath, 'rb')        5850         fp = open(sysvals.fpdtpath, 'rb')
5879         buf = fp.read()                          5851         buf = fp.read()
5880         fp.close()                               5852         fp.close()
5881                                                  5853 
5882         if(len(buf) < 36):                       5854         if(len(buf) < 36):
5883                 if(output):                      5855                 if(output):
5884                         doError('Invalid FPDT    5856                         doError('Invalid FPDT table data, should '+\
5885                                 'be at least     5857                                 'be at least 36 bytes')
5886                 return False                     5858                 return False
5887                                                  5859 
5888         table = struct.unpack('4sIBB6s8sI4sI'    5860         table = struct.unpack('4sIBB6s8sI4sI', buf[0:36])
5889         if(output):                              5861         if(output):
5890                 pprint('\n'\                     5862                 pprint('\n'\
5891                 'Firmware Performance Data Ta    5863                 'Firmware Performance Data Table (%s)\n'\
5892                 '                  Signature     5864                 '                  Signature : %s\n'\
5893                 '               Table Length     5865                 '               Table Length : %u\n'\
5894                 '                   Revision     5866                 '                   Revision : %u\n'\
5895                 '                   Checksum     5867                 '                   Checksum : 0x%x\n'\
5896                 '                     OEM ID     5868                 '                     OEM ID : %s\n'\
5897                 '               OEM Table ID     5869                 '               OEM Table ID : %s\n'\
5898                 '               OEM Revision     5870                 '               OEM Revision : %u\n'\
5899                 '                 Creator ID     5871                 '                 Creator ID : %s\n'\
5900                 '           Creator Revision     5872                 '           Creator Revision : 0x%x\n'\
5901                 '' % (ascii(table[0]), ascii(    5873                 '' % (ascii(table[0]), ascii(table[0]), table[1], table[2],
5902                         table[3], ascii(table    5874                         table[3], ascii(table[4]), ascii(table[5]), table[6],
5903                         ascii(table[7]), tabl    5875                         ascii(table[7]), table[8]))
5904                                                  5876 
5905         if(table[0] != b'FPDT'):                 5877         if(table[0] != b'FPDT'):
5906                 if(output):                      5878                 if(output):
5907                         doError('Invalid FPDT    5879                         doError('Invalid FPDT table')
5908                 return False                     5880                 return False
5909         if(len(buf) <= 36):                      5881         if(len(buf) <= 36):
5910                 return False                     5882                 return False
5911         i = 0                                    5883         i = 0
5912         fwData = [0, 0]                          5884         fwData = [0, 0]
5913         records = buf[36:]                       5885         records = buf[36:]
5914         try:                                     5886         try:
5915                 fp = open(sysvals.mempath, 'r    5887                 fp = open(sysvals.mempath, 'rb')
5916         except:                                  5888         except:
5917                 pprint('WARNING: /dev/mem is     5889                 pprint('WARNING: /dev/mem is not readable, ignoring the FPDT data')
5918                 return False                     5890                 return False
5919         while(i < len(records)):                 5891         while(i < len(records)):
5920                 header = struct.unpack('HBB',    5892                 header = struct.unpack('HBB', records[i:i+4])
5921                 if(header[0] not in rectype):    5893                 if(header[0] not in rectype):
5922                         i += header[1]           5894                         i += header[1]
5923                         continue                 5895                         continue
5924                 if(header[1] != 16):             5896                 if(header[1] != 16):
5925                         i += header[1]           5897                         i += header[1]
5926                         continue                 5898                         continue
5927                 addr = struct.unpack('Q', rec    5899                 addr = struct.unpack('Q', records[i+8:i+16])[0]
5928                 try:                             5900                 try:
5929                         fp.seek(addr)            5901                         fp.seek(addr)
5930                         first = fp.read(8)       5902                         first = fp.read(8)
5931                 except:                          5903                 except:
5932                         if(output):              5904                         if(output):
5933                                 pprint('Bad a    5905                                 pprint('Bad address 0x%x in %s' % (addr, sysvals.mempath))
5934                         return [0, 0]            5906                         return [0, 0]
5935                 rechead = struct.unpack('4sI'    5907                 rechead = struct.unpack('4sI', first)
5936                 recdata = fp.read(rechead[1]-    5908                 recdata = fp.read(rechead[1]-8)
5937                 if(rechead[0] == b'FBPT'):       5909                 if(rechead[0] == b'FBPT'):
5938                         record = struct.unpac    5910                         record = struct.unpack('HBBIQQQQQ', recdata[:48])
5939                         if(output):              5911                         if(output):
5940                                 pprint('%s (%    5912                                 pprint('%s (%s)\n'\
5941                                 '                5913                                 '                  Reset END : %u ns\n'\
5942                                 '  OS Loader     5914                                 '  OS Loader LoadImage Start : %u ns\n'\
5943                                 ' OS Loader S    5915                                 ' OS Loader StartImage Start : %u ns\n'\
5944                                 '     ExitBoo    5916                                 '     ExitBootServices Entry : %u ns\n'\
5945                                 '      ExitBo    5917                                 '      ExitBootServices Exit : %u ns'\
5946                                 '' % (rectype    5918                                 '' % (rectype[header[0]], ascii(rechead[0]), record[4], record[5],
5947                                         recor    5919                                         record[6], record[7], record[8]))
5948                 elif(rechead[0] == b'S3PT'):     5920                 elif(rechead[0] == b'S3PT'):
5949                         if(output):              5921                         if(output):
5950                                 pprint('%s (%    5922                                 pprint('%s (%s)' % (rectype[header[0]], ascii(rechead[0])))
5951                         j = 0                    5923                         j = 0
5952                         while(j < len(recdata    5924                         while(j < len(recdata)):
5953                                 prechead = st    5925                                 prechead = struct.unpack('HBB', recdata[j:j+4])
5954                                 if(prechead[0    5926                                 if(prechead[0] not in prectype):
5955                                         conti    5927                                         continue
5956                                 if(prechead[0    5928                                 if(prechead[0] == 0):
5957                                         recor    5929                                         record = struct.unpack('IIQQ', recdata[j:j+prechead[1]])
5958                                         fwDat    5930                                         fwData[1] = record[2]
5959                                         if(ou    5931                                         if(output):
5960                                                  5932                                                 pprint('    %s\n'\
5961                                                  5933                                                 '               Resume Count : %u\n'\
5962                                                  5934                                                 '                 FullResume : %u ns\n'\
5963                                                  5935                                                 '              AverageResume : %u ns'\
5964                                                  5936                                                 '' % (prectype[prechead[0]], record[1],
5965                                                  5937                                                                 record[2], record[3]))
5966                                 elif(prechead    5938                                 elif(prechead[0] == 1):
5967                                         recor    5939                                         record = struct.unpack('QQ', recdata[j+4:j+prechead[1]])
5968                                         fwDat    5940                                         fwData[0] = record[1] - record[0]
5969                                         if(ou    5941                                         if(output):
5970                                                  5942                                                 pprint('    %s\n'\
5971                                                  5943                                                 '               SuspendStart : %u ns\n'\
5972                                                  5944                                                 '                 SuspendEnd : %u ns\n'\
5973                                                  5945                                                 '                SuspendTime : %u ns'\
5974                                                  5946                                                 '' % (prectype[prechead[0]], record[0],
5975                                                  5947                                                                 record[1], fwData[0]))
5976                                                  5948 
5977                                 j += prechead    5949                                 j += prechead[1]
5978                 if(output):                      5950                 if(output):
5979                         pprint('')               5951                         pprint('')
5980                 i += header[1]                   5952                 i += header[1]
5981         fp.close()                               5953         fp.close()
5982         return fwData                            5954         return fwData
5983                                                  5955 
5984 # Function: statusCheck                          5956 # Function: statusCheck
5985 # Description:                                   5957 # Description:
5986 #        Verify that the requested command an    5958 #        Verify that the requested command and options will work, and
5987 #        print the results to the terminal       5959 #        print the results to the terminal
5988 # Output:                                        5960 # Output:
5989 #        True if the test will work, False if    5961 #        True if the test will work, False if not
5990 def statusCheck(probecheck=False):               5962 def statusCheck(probecheck=False):
5991         status = ''                              5963         status = ''
5992                                                  5964 
5993         pprint('Checking this system (%s)...'    5965         pprint('Checking this system (%s)...' % platform.node())
5994                                                  5966 
5995         # check we have root access              5967         # check we have root access
5996         res = sysvals.colorText('NO (No featu    5968         res = sysvals.colorText('NO (No features of this tool will work!)')
5997         if(sysvals.rootCheck(False)):            5969         if(sysvals.rootCheck(False)):
5998                 res = 'YES'                      5970                 res = 'YES'
5999         pprint('    have root access: %s' % r    5971         pprint('    have root access: %s' % res)
6000         if(res != 'YES'):                        5972         if(res != 'YES'):
6001                 pprint('    Try running this     5973                 pprint('    Try running this script with sudo')
6002                 return 'missing root access'     5974                 return 'missing root access'
6003                                                  5975 
6004         # check sysfs is mounted                 5976         # check sysfs is mounted
6005         res = sysvals.colorText('NO (No featu    5977         res = sysvals.colorText('NO (No features of this tool will work!)')
6006         if(os.path.exists(sysvals.powerfile))    5978         if(os.path.exists(sysvals.powerfile)):
6007                 res = 'YES'                      5979                 res = 'YES'
6008         pprint('    is sysfs mounted: %s' % r    5980         pprint('    is sysfs mounted: %s' % res)
6009         if(res != 'YES'):                        5981         if(res != 'YES'):
6010                 return 'sysfs is missing'        5982                 return 'sysfs is missing'
6011                                                  5983 
6012         # check target mode is a valid mode      5984         # check target mode is a valid mode
6013         if sysvals.suspendmode != 'command':     5985         if sysvals.suspendmode != 'command':
6014                 res = sysvals.colorText('NO')    5986                 res = sysvals.colorText('NO')
6015                 modes = getModes()               5987                 modes = getModes()
6016                 if(sysvals.suspendmode in mod    5988                 if(sysvals.suspendmode in modes):
6017                         res = 'YES'              5989                         res = 'YES'
6018                 else:                            5990                 else:
6019                         status = '%s mode is     5991                         status = '%s mode is not supported' % sysvals.suspendmode
6020                 pprint('    is "%s" a valid p    5992                 pprint('    is "%s" a valid power mode: %s' % (sysvals.suspendmode, res))
6021                 if(res == 'NO'):                 5993                 if(res == 'NO'):
6022                         pprint('      valid p    5994                         pprint('      valid power modes are: %s' % modes)
6023                         pprint('      please     5995                         pprint('      please choose one with -m')
6024                                                  5996 
6025         # check if ftrace is available           5997         # check if ftrace is available
6026         if sysvals.useftrace:                    5998         if sysvals.useftrace:
6027                 res = sysvals.colorText('NO')    5999                 res = sysvals.colorText('NO')
6028                 sysvals.useftrace = sysvals.v    6000                 sysvals.useftrace = sysvals.verifyFtrace()
6029                 efmt = '"{0}" uses ftrace, an    6001                 efmt = '"{0}" uses ftrace, and it is not properly supported'
6030                 if sysvals.useftrace:            6002                 if sysvals.useftrace:
6031                         res = 'YES'              6003                         res = 'YES'
6032                 elif sysvals.usecallgraph:       6004                 elif sysvals.usecallgraph:
6033                         status = efmt.format(    6005                         status = efmt.format('-f')
6034                 elif sysvals.usedevsrc:          6006                 elif sysvals.usedevsrc:
6035                         status = efmt.format(    6007                         status = efmt.format('-dev')
6036                 elif sysvals.useprocmon:         6008                 elif sysvals.useprocmon:
6037                         status = efmt.format(    6009                         status = efmt.format('-proc')
6038                 pprint('    is ftrace support    6010                 pprint('    is ftrace supported: %s' % res)
6039                                                  6011 
6040         # check if kprobes are available         6012         # check if kprobes are available
6041         if sysvals.usekprobes:                   6013         if sysvals.usekprobes:
6042                 res = sysvals.colorText('NO')    6014                 res = sysvals.colorText('NO')
6043                 sysvals.usekprobes = sysvals.    6015                 sysvals.usekprobes = sysvals.verifyKprobes()
6044                 if(sysvals.usekprobes):          6016                 if(sysvals.usekprobes):
6045                         res = 'YES'              6017                         res = 'YES'
6046                 else:                            6018                 else:
6047                         sysvals.usedevsrc = F    6019                         sysvals.usedevsrc = False
6048                 pprint('    are kprobes suppo    6020                 pprint('    are kprobes supported: %s' % res)
6049                                                  6021 
6050         # what data source are we using          6022         # what data source are we using
6051         res = 'DMESG (very limited, ftrace is    6023         res = 'DMESG (very limited, ftrace is preferred)'
6052         if sysvals.useftrace:                    6024         if sysvals.useftrace:
6053                 sysvals.usetraceevents = True    6025                 sysvals.usetraceevents = True
6054                 for e in sysvals.traceevents:    6026                 for e in sysvals.traceevents:
6055                         if not os.path.exists    6027                         if not os.path.exists(sysvals.epath+e):
6056                                 sysvals.usetr    6028                                 sysvals.usetraceevents = False
6057                 if(sysvals.usetraceevents):      6029                 if(sysvals.usetraceevents):
6058                         res = 'FTRACE (all tr    6030                         res = 'FTRACE (all trace events found)'
6059         pprint('    timeline data source: %s'    6031         pprint('    timeline data source: %s' % res)
6060                                                  6032 
6061         # check if rtcwake                       6033         # check if rtcwake
6062         res = sysvals.colorText('NO')            6034         res = sysvals.colorText('NO')
6063         if(sysvals.rtcpath != ''):               6035         if(sysvals.rtcpath != ''):
6064                 res = 'YES'                      6036                 res = 'YES'
6065         elif(sysvals.rtcwake):                   6037         elif(sysvals.rtcwake):
6066                 status = 'rtcwake is not prop    6038                 status = 'rtcwake is not properly supported'
6067         pprint('    is rtcwake supported: %s'    6039         pprint('    is rtcwake supported: %s' % res)
6068                                                  6040 
6069         # check info commands                    6041         # check info commands
6070         pprint('    optional commands this to    6042         pprint('    optional commands this tool may use for info:')
6071         no = sysvals.colorText('MISSING')        6043         no = sysvals.colorText('MISSING')
6072         yes = sysvals.colorText('FOUND', 32)     6044         yes = sysvals.colorText('FOUND', 32)
6073         for c in ['turbostat', 'mcelog', 'lsp    6045         for c in ['turbostat', 'mcelog', 'lspci', 'lsusb', 'netfix']:
6074                 if c == 'turbostat':             6046                 if c == 'turbostat':
6075                         res = yes if sysvals.    6047                         res = yes if sysvals.haveTurbostat() else no
6076                 else:                            6048                 else:
6077                         res = yes if sysvals.    6049                         res = yes if sysvals.getExec(c) else no
6078                 pprint('        %s: %s' % (c,    6050                 pprint('        %s: %s' % (c, res))
6079                                                  6051 
6080         if not probecheck:                       6052         if not probecheck:
6081                 return status                    6053                 return status
6082                                                  6054 
6083         # verify kprobes                         6055         # verify kprobes
6084         if sysvals.usekprobes:                   6056         if sysvals.usekprobes:
6085                 for name in sysvals.tracefunc    6057                 for name in sysvals.tracefuncs:
6086                         sysvals.defaultKprobe    6058                         sysvals.defaultKprobe(name, sysvals.tracefuncs[name])
6087                 if sysvals.usedevsrc:            6059                 if sysvals.usedevsrc:
6088                         for name in sysvals.d    6060                         for name in sysvals.dev_tracefuncs:
6089                                 sysvals.defau    6061                                 sysvals.defaultKprobe(name, sysvals.dev_tracefuncs[name])
6090                 sysvals.addKprobes(True)         6062                 sysvals.addKprobes(True)
6091                                                  6063 
6092         return status                            6064         return status
6093                                                  6065 
6094 # Function: doError                              6066 # Function: doError
6095 # Description:                                   6067 # Description:
6096 #        generic error function for catastrph    6068 #        generic error function for catastrphic failures
6097 # Arguments:                                     6069 # Arguments:
6098 #        msg: the error message to print         6070 #        msg: the error message to print
6099 #        help: True if printHelp should be ca    6071 #        help: True if printHelp should be called after, False otherwise
6100 def doError(msg, help=False):                    6072 def doError(msg, help=False):
6101         if(help == True):                        6073         if(help == True):
6102                 printHelp()                      6074                 printHelp()
6103         pprint('ERROR: %s\n' % msg)              6075         pprint('ERROR: %s\n' % msg)
6104         sysvals.outputResult({'error':msg})      6076         sysvals.outputResult({'error':msg})
6105         sys.exit(1)                              6077         sys.exit(1)
6106                                                  6078 
6107 # Function: getArgInt                            6079 # Function: getArgInt
6108 # Description:                                   6080 # Description:
6109 #        pull out an integer argument from th    6081 #        pull out an integer argument from the command line with checks
6110 def getArgInt(name, args, min, max, main=True    6082 def getArgInt(name, args, min, max, main=True):
6111         if main:                                 6083         if main:
6112                 try:                             6084                 try:
6113                         arg = next(args)         6085                         arg = next(args)
6114                 except:                          6086                 except:
6115                         doError(name+': no ar    6087                         doError(name+': no argument supplied', True)
6116         else:                                    6088         else:
6117                 arg = args                       6089                 arg = args
6118         try:                                     6090         try:
6119                 val = int(arg)                   6091                 val = int(arg)
6120         except:                                  6092         except:
6121                 doError(name+': non-integer v    6093                 doError(name+': non-integer value given', True)
6122         if(val < min or val > max):              6094         if(val < min or val > max):
6123                 doError(name+': value should     6095                 doError(name+': value should be between %d and %d' % (min, max), True)
6124         return val                               6096         return val
6125                                                  6097 
6126 # Function: getArgFloat                          6098 # Function: getArgFloat
6127 # Description:                                   6099 # Description:
6128 #        pull out a float argument from the c    6100 #        pull out a float argument from the command line with checks
6129 def getArgFloat(name, args, min, max, main=Tr    6101 def getArgFloat(name, args, min, max, main=True):
6130         if main:                                 6102         if main:
6131                 try:                             6103                 try:
6132                         arg = next(args)         6104                         arg = next(args)
6133                 except:                          6105                 except:
6134                         doError(name+': no ar    6106                         doError(name+': no argument supplied', True)
6135         else:                                    6107         else:
6136                 arg = args                       6108                 arg = args
6137         try:                                     6109         try:
6138                 val = float(arg)                 6110                 val = float(arg)
6139         except:                                  6111         except:
6140                 doError(name+': non-numerical    6112                 doError(name+': non-numerical value given', True)
6141         if(val < min or val > max):              6113         if(val < min or val > max):
6142                 doError(name+': value should     6114                 doError(name+': value should be between %f and %f' % (min, max), True)
6143         return val                               6115         return val
6144                                                  6116 
6145 def processData(live=False, quiet=False):        6117 def processData(live=False, quiet=False):
6146         if not quiet:                            6118         if not quiet:
6147                 pprint('PROCESSING: %s' % sys    6119                 pprint('PROCESSING: %s' % sysvals.htmlfile)
6148         sysvals.vprint('usetraceevents=%s, us    6120         sysvals.vprint('usetraceevents=%s, usetracemarkers=%s, usekprobes=%s' % \
6149                 (sysvals.usetraceevents, sysv    6121                 (sysvals.usetraceevents, sysvals.usetracemarkers, sysvals.usekprobes))
6150         error = ''                               6122         error = ''
6151         if(sysvals.usetraceevents):              6123         if(sysvals.usetraceevents):
6152                 testruns, error = parseTraceL    6124                 testruns, error = parseTraceLog(live)
6153                 if sysvals.dmesgfile:            6125                 if sysvals.dmesgfile:
6154                         for data in testruns:    6126                         for data in testruns:
6155                                 data.extractE    6127                                 data.extractErrorInfo()
6156         else:                                    6128         else:
6157                 testruns = loadKernelLog()       6129                 testruns = loadKernelLog()
6158                 for data in testruns:            6130                 for data in testruns:
6159                         parseKernelLog(data)     6131                         parseKernelLog(data)
6160                 if(sysvals.ftracefile and (sy    6132                 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)):
6161                         appendIncompleteTrace    6133                         appendIncompleteTraceLog(testruns)
6162         if not sysvals.stamp:                    6134         if not sysvals.stamp:
6163                 pprint('ERROR: data does not     6135                 pprint('ERROR: data does not include the expected stamp')
6164                 return (testruns, {'error': '    6136                 return (testruns, {'error': 'timeline generation failed'})
6165         shown = ['os', 'bios', 'biosdate', 'c    6137         shown = ['os', 'bios', 'biosdate', 'cpu', 'host', 'kernel', 'man', 'memfr',
6166                         'memsz', 'mode', 'num    6138                         'memsz', 'mode', 'numcpu', 'plat', 'time', 'wifi']
6167         sysvals.vprint('System Info:')           6139         sysvals.vprint('System Info:')
6168         for key in sorted(sysvals.stamp):        6140         for key in sorted(sysvals.stamp):
6169                 if key in shown:                 6141                 if key in shown:
6170                         sysvals.vprint('    %    6142                         sysvals.vprint('    %-8s : %s' % (key.upper(), sysvals.stamp[key]))
6171         sysvals.vprint('Command:\n    %s' % s    6143         sysvals.vprint('Command:\n    %s' % sysvals.cmdline)
6172         for data in testruns:                    6144         for data in testruns:
6173                 if data.turbostat:               6145                 if data.turbostat:
6174                         idx, s = 0, 'Turbosta    6146                         idx, s = 0, 'Turbostat:\n    '
6175                         for val in data.turbo    6147                         for val in data.turbostat.split('|'):
6176                                 idx += len(va    6148                                 idx += len(val) + 1
6177                                 if idx >= 80:    6149                                 if idx >= 80:
6178                                         idx =    6150                                         idx = 0
6179                                         s +=     6151                                         s += '\n    '
6180                                 s += val + '     6152                                 s += val + ' '
6181                         sysvals.vprint(s)        6153                         sysvals.vprint(s)
6182                 data.printDetails()              6154                 data.printDetails()
6183         if len(sysvals.platinfo) > 0:            6155         if len(sysvals.platinfo) > 0:
6184                 sysvals.vprint('\nPlatform In    6156                 sysvals.vprint('\nPlatform Info:')
6185                 for info in sysvals.platinfo:    6157                 for info in sysvals.platinfo:
6186                         sysvals.vprint('[%s -    6158                         sysvals.vprint('[%s - %s]' % (info[0], info[1]))
6187                         sysvals.vprint(info[2    6159                         sysvals.vprint(info[2])
6188                 sysvals.vprint('')               6160                 sysvals.vprint('')
6189         if sysvals.cgdump:                       6161         if sysvals.cgdump:
6190                 for data in testruns:            6162                 for data in testruns:
6191                         data.debugPrint()        6163                         data.debugPrint()
6192                 sys.exit(0)                      6164                 sys.exit(0)
6193         if len(testruns) < 1:                    6165         if len(testruns) < 1:
6194                 pprint('ERROR: Not enough tes    6166                 pprint('ERROR: Not enough test data to build a timeline')
6195                 return (testruns, {'error': '    6167                 return (testruns, {'error': 'timeline generation failed'})
6196         sysvals.vprint('Creating the html tim    6168         sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile)
6197         createHTML(testruns, error)              6169         createHTML(testruns, error)
6198         if not quiet:                            6170         if not quiet:
6199                 pprint('DONE:       %s' % sys    6171                 pprint('DONE:       %s' % sysvals.htmlfile)
6200         data = testruns[0]                       6172         data = testruns[0]
6201         stamp = data.stamp                       6173         stamp = data.stamp
6202         stamp['suspend'], stamp['resume'] = d    6174         stamp['suspend'], stamp['resume'] = data.getTimeValues()
6203         if data.fwValid:                         6175         if data.fwValid:
6204                 stamp['fwsuspend'], stamp['fw    6176                 stamp['fwsuspend'], stamp['fwresume'] = data.fwSuspend, data.fwResume
6205         if error:                                6177         if error:
6206                 stamp['error'] = error           6178                 stamp['error'] = error
6207         return (testruns, stamp)                 6179         return (testruns, stamp)
6208                                                  6180 
6209 # Function: rerunTest                            6181 # Function: rerunTest
6210 # Description:                                   6182 # Description:
6211 #        generate an output from an existing     6183 #        generate an output from an existing set of ftrace/dmesg logs
6212 def rerunTest(htmlfile=''):                      6184 def rerunTest(htmlfile=''):
6213         if sysvals.ftracefile:                   6185         if sysvals.ftracefile:
6214                 doesTraceLogHaveTraceEvents()    6186                 doesTraceLogHaveTraceEvents()
6215         if not sysvals.dmesgfile and not sysv    6187         if not sysvals.dmesgfile and not sysvals.usetraceevents:
6216                 doError('recreating this html    6188                 doError('recreating this html output requires a dmesg file')
6217         if htmlfile:                             6189         if htmlfile:
6218                 sysvals.htmlfile = htmlfile      6190                 sysvals.htmlfile = htmlfile
6219         else:                                    6191         else:
6220                 sysvals.setOutputFile()          6192                 sysvals.setOutputFile()
6221         if os.path.exists(sysvals.htmlfile):     6193         if os.path.exists(sysvals.htmlfile):
6222                 if not os.path.isfile(sysvals    6194                 if not os.path.isfile(sysvals.htmlfile):
6223                         doError('a directory     6195                         doError('a directory already exists with this name: %s' % sysvals.htmlfile)
6224                 elif not os.access(sysvals.ht    6196                 elif not os.access(sysvals.htmlfile, os.W_OK):
6225                         doError('missing perm    6197                         doError('missing permission to write to %s' % sysvals.htmlfile)
6226         testruns, stamp = processData()          6198         testruns, stamp = processData()
6227         sysvals.resetlog()                       6199         sysvals.resetlog()
6228         return stamp                             6200         return stamp
6229                                                  6201 
6230 # Function: runTest                              6202 # Function: runTest
6231 # Description:                                   6203 # Description:
6232 #        execute a suspend/resume, gather the    6204 #        execute a suspend/resume, gather the logs, and generate the output
6233 def runTest(n=0, quiet=False):                   6205 def runTest(n=0, quiet=False):
6234         # prepare for the test                   6206         # prepare for the test
6235         sysvals.initTestOutput('suspend')        6207         sysvals.initTestOutput('suspend')
6236         op = sysvals.writeDatafileHeader(sysv    6208         op = sysvals.writeDatafileHeader(sysvals.dmesgfile, [])
6237         op.write('# EXECUTION TRACE START\n')    6209         op.write('# EXECUTION TRACE START\n')
6238         op.close()                               6210         op.close()
6239         if n <= 1:                               6211         if n <= 1:
6240                 if sysvals.rs != 0:              6212                 if sysvals.rs != 0:
6241                         sysvals.dlog('%sablin    6213                         sysvals.dlog('%sabling runtime suspend' % ('en' if sysvals.rs > 0 else 'dis'))
6242                         sysvals.setRuntimeSus    6214                         sysvals.setRuntimeSuspend(True)
6243                 if sysvals.display:              6215                 if sysvals.display:
6244                         ret = sysvals.display    6216                         ret = sysvals.displayControl('init')
6245                         sysvals.dlog('xset di    6217                         sysvals.dlog('xset display init, ret = %d' % ret)
6246         sysvals.testVal(sysvals.pmdpath, 'bas    6218         sysvals.testVal(sysvals.pmdpath, 'basic', '1')
6247         sysvals.testVal(sysvals.s0ixpath, 'ba    6219         sysvals.testVal(sysvals.s0ixpath, 'basic', 'Y')
6248         sysvals.dlog('initialize ftrace')        6220         sysvals.dlog('initialize ftrace')
6249         sysvals.initFtrace(quiet)                6221         sysvals.initFtrace(quiet)
6250                                                  6222 
6251         # execute the test                       6223         # execute the test
6252         executeSuspend(quiet)                    6224         executeSuspend(quiet)
6253         sysvals.cleanupFtrace()                  6225         sysvals.cleanupFtrace()
6254         if sysvals.skiphtml:                     6226         if sysvals.skiphtml:
6255                 sysvals.outputResult({}, n)      6227                 sysvals.outputResult({}, n)
6256                 sysvals.sudoUserchown(sysvals    6228                 sysvals.sudoUserchown(sysvals.testdir)
6257                 return                           6229                 return
6258         testruns, stamp = processData(True, q    6230         testruns, stamp = processData(True, quiet)
6259         for data in testruns:                    6231         for data in testruns:
6260                 del data                         6232                 del data
6261         sysvals.sudoUserchown(sysvals.testdir    6233         sysvals.sudoUserchown(sysvals.testdir)
6262         sysvals.outputResult(stamp, n)           6234         sysvals.outputResult(stamp, n)
6263         if 'error' in stamp:                     6235         if 'error' in stamp:
6264                 return 2                         6236                 return 2
6265         return 0                                 6237         return 0
6266                                                  6238 
6267 def find_in_html(html, start, end, firstonly=    6239 def find_in_html(html, start, end, firstonly=True):
6268         cnt, out, list = len(html), [], []       6240         cnt, out, list = len(html), [], []
6269         if firstonly:                            6241         if firstonly:
6270                 m = re.search(start, html)       6242                 m = re.search(start, html)
6271                 if m:                            6243                 if m:
6272                         list.append(m)           6244                         list.append(m)
6273         else:                                    6245         else:
6274                 list = re.finditer(start, htm    6246                 list = re.finditer(start, html)
6275         for match in list:                       6247         for match in list:
6276                 s = match.end()                  6248                 s = match.end()
6277                 e = cnt if (len(out) < 1 or s    6249                 e = cnt if (len(out) < 1 or s + 10000 > cnt) else s + 10000
6278                 m = re.search(end, html[s:e])    6250                 m = re.search(end, html[s:e])
6279                 if not m:                        6251                 if not m:
6280                         break                    6252                         break
6281                 e = s + m.start()                6253                 e = s + m.start()
6282                 str = html[s:e]                  6254                 str = html[s:e]
6283                 if end == 'ms':                  6255                 if end == 'ms':
6284                         num = re.search(r'[-+    6256                         num = re.search(r'[-+]?\d*\.\d+|\d+', str)
6285                         str = num.group() if     6257                         str = num.group() if num else 'NaN'
6286                 if firstonly:                    6258                 if firstonly:
6287                         return str               6259                         return str
6288                 out.append(str)                  6260                 out.append(str)
6289         if firstonly:                            6261         if firstonly:
6290                 return ''                        6262                 return ''
6291         return out                               6263         return out
6292                                                  6264 
6293 def data_from_html(file, outpath, issues, ful    6265 def data_from_html(file, outpath, issues, fulldetail=False):
6294         try:                                  !! 6266         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    6267         sysvals.htmlfile = os.path.relpath(file, outpath)
6299         # extract general info                   6268         # extract general info
6300         suspend = find_in_html(html, 'Kernel     6269         suspend = find_in_html(html, 'Kernel Suspend', 'ms')
6301         resume = find_in_html(html, 'Kernel R    6270         resume = find_in_html(html, 'Kernel Resume', 'ms')
6302         sysinfo = find_in_html(html, '<div cl    6271         sysinfo = find_in_html(html, '<div class="stamp sysinfo">', '</div>')
6303         line = find_in_html(html, '<div class    6272         line = find_in_html(html, '<div class="stamp">', '</div>')
6304         stmp = line.split()                      6273         stmp = line.split()
6305         if not suspend or not resume or len(s    6274         if not suspend or not resume or len(stmp) != 8:
6306                 return False                     6275                 return False
6307         try:                                     6276         try:
6308                 dt = datetime.strptime(' '.jo    6277                 dt = datetime.strptime(' '.join(stmp[3:]), '%B %d %Y, %I:%M:%S %p')
6309         except:                                  6278         except:
6310                 return False                     6279                 return False
6311         sysvals.hostname = stmp[0]               6280         sysvals.hostname = stmp[0]
6312         tstr = dt.strftime('%Y/%m/%d %H:%M:%S    6281         tstr = dt.strftime('%Y/%m/%d %H:%M:%S')
6313         error = find_in_html(html, '<table cl    6282         error = find_in_html(html, '<table class="testfail"><tr><td>', '</td>')
6314         if error:                                6283         if error:
6315                 m = re.match(r'[a-z0-9]* fail !! 6284                 m = re.match('[a-z0-9]* failed in (?P<p>\S*).*', error)
6316                 if m:                            6285                 if m:
6317                         result = 'fail in %s'    6286                         result = 'fail in %s' % m.group('p')
6318                 else:                            6287                 else:
6319                         result = 'fail'          6288                         result = 'fail'
6320         else:                                    6289         else:
6321                 result = 'pass'                  6290                 result = 'pass'
6322         # extract error info                     6291         # extract error info
6323         tp, ilist = False, []                    6292         tp, ilist = False, []
6324         extra = dict()                           6293         extra = dict()
6325         log = find_in_html(html, '<div id="dm    6294         log = find_in_html(html, '<div id="dmesglog" style="display:none;">',
6326                 '</div>').strip()                6295                 '</div>').strip()
6327         if log:                                  6296         if log:
6328                 d = Data(0)                      6297                 d = Data(0)
6329                 d.end = 999999999                6298                 d.end = 999999999
6330                 d.dmesgtext = log.split('\n')    6299                 d.dmesgtext = log.split('\n')
6331                 tp = d.extractErrorInfo()        6300                 tp = d.extractErrorInfo()
6332                 if len(issues) < 100:         !! 6301                 for msg in tp.msglist:
6333                         for msg in tp.msglist !! 6302                         sysvals.errorSummary(issues, msg)
6334                                 sysvals.error << 
6335                 if stmp[2] == 'freeze':          6303                 if stmp[2] == 'freeze':
6336                         extra = d.turbostatIn    6304                         extra = d.turbostatInfo()
6337                 elist = dict()                   6305                 elist = dict()
6338                 for dir in d.errorinfo:          6306                 for dir in d.errorinfo:
6339                         for err in d.errorinf    6307                         for err in d.errorinfo[dir]:
6340                                 if err[0] not    6308                                 if err[0] not in elist:
6341                                         elist    6309                                         elist[err[0]] = 0
6342                                 elist[err[0]]    6310                                 elist[err[0]] += 1
6343                 for i in elist:                  6311                 for i in elist:
6344                         ilist.append('%sx%d'     6312                         ilist.append('%sx%d' % (i, elist[i]) if elist[i] > 1 else i)
6345                 line = find_in_html(log, '# w    6313                 line = find_in_html(log, '# wifi ', '\n')
6346                 if line:                         6314                 if line:
6347                         extra['wifi'] = line     6315                         extra['wifi'] = line
6348                 line = find_in_html(log, '# n    6316                 line = find_in_html(log, '# netfix ', '\n')
6349                 if line:                         6317                 if line:
6350                         extra['netfix'] = lin    6318                         extra['netfix'] = line
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    6319         low = find_in_html(html, 'freeze time: <b>', ' ms</b>')
6357         for lowstr in ['waking', '+']:           6320         for lowstr in ['waking', '+']:
6358                 if not low:                      6321                 if not low:
6359                         break                    6322                         break
6360                 if lowstr not in low:            6323                 if lowstr not in low:
6361                         continue                 6324                         continue
6362                 if lowstr == '+':                6325                 if lowstr == '+':
6363                         issue = 'S2LOOPx%d' %    6326                         issue = 'S2LOOPx%d' % len(low.split('+'))
6364                 else:                            6327                 else:
6365                         m = re.match(r'.*waki !! 6328                         m = re.match('.*waking *(?P<n>[0-9]*) *times.*', low)
6366                         issue = 'S2WAKEx%s' %    6329                         issue = 'S2WAKEx%s' % m.group('n') if m else 'S2WAKExNaN'
6367                 match = [i for i in issues if    6330                 match = [i for i in issues if i['match'] == issue]
6368                 if len(match) > 0:               6331                 if len(match) > 0:
6369                         match[0]['count'] +=     6332                         match[0]['count'] += 1
6370                         if sysvals.hostname n    6333                         if sysvals.hostname not in match[0]['urls']:
6371                                 match[0]['url    6334                                 match[0]['urls'][sysvals.hostname] = [sysvals.htmlfile]
6372                         elif sysvals.htmlfile    6335                         elif sysvals.htmlfile not in match[0]['urls'][sysvals.hostname]:
6373                                 match[0]['url    6336                                 match[0]['urls'][sysvals.hostname].append(sysvals.htmlfile)
6374                 else:                            6337                 else:
6375                         issues.append({          6338                         issues.append({
6376                                 'match': issu    6339                                 'match': issue, 'count': 1, 'line': issue,
6377                                 'urls': {sysv    6340                                 'urls': {sysvals.hostname: [sysvals.htmlfile]},
6378                         })                       6341                         })
6379                 ilist.append(issue)              6342                 ilist.append(issue)
6380         # extract device info                    6343         # extract device info
6381         devices = dict()                         6344         devices = dict()
6382         for line in html.split('\n'):            6345         for line in html.split('\n'):
6383                 m = re.match(r' *<div id=\"[a !! 6346                 m = re.match(' *<div id=\"[a,0-9]*\" *title=\"(?P<title>.*)\" class=\"thread.*', line)
6384                 if not m or 'thread kth' in l    6347                 if not m or 'thread kth' in line or 'thread sec' in line:
6385                         continue                 6348                         continue
6386                 m = re.match(r'(?P<n>.*) \((? !! 6349                 m = re.match('(?P<n>.*) \((?P<t>[0-9,\.]*) ms\) (?P<p>.*)', m.group('title'))
6387                 if not m:                        6350                 if not m:
6388                         continue                 6351                         continue
6389                 name, time, phase = m.group('    6352                 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    6353                 if ' async' in name or ' sync' in name:
6393                         name = ' '.join(name.    6354                         name = ' '.join(name.split(' ')[:-1])
6394                 if phase.startswith('suspend'    6355                 if phase.startswith('suspend'):
6395                         d = 'suspend'            6356                         d = 'suspend'
6396                 elif phase.startswith('resume    6357                 elif phase.startswith('resume'):
6397                         d = 'resume'             6358                         d = 'resume'
6398                 else:                            6359                 else:
6399                         continue                 6360                         continue
6400                 if d not in devices:             6361                 if d not in devices:
6401                         devices[d] = dict()      6362                         devices[d] = dict()
6402                 if name not in devices[d]:       6363                 if name not in devices[d]:
6403                         devices[d][name] = 0.    6364                         devices[d][name] = 0.0
6404                 devices[d][name] += float(tim    6365                 devices[d][name] += float(time)
6405         # create worst device info               6366         # create worst device info
6406         worst = dict()                           6367         worst = dict()
6407         for d in ['suspend', 'resume']:          6368         for d in ['suspend', 'resume']:
6408                 worst[d] = {'name':'', 'time'    6369                 worst[d] = {'name':'', 'time': 0.0}
6409                 dev = devices[d] if d in devi    6370                 dev = devices[d] if d in devices else 0
6410                 if dev and len(dev.keys()) >     6371                 if dev and len(dev.keys()) > 0:
6411                         n = sorted(dev, key=l    6372                         n = sorted(dev, key=lambda k:(dev[k], k), reverse=True)[0]
6412                         worst[d]['name'], wor    6373                         worst[d]['name'], worst[d]['time'] = n, dev[n]
6413         data = {                                 6374         data = {
6414                 'mode': stmp[2],                 6375                 'mode': stmp[2],
6415                 'host': stmp[0],                 6376                 'host': stmp[0],
6416                 'kernel': stmp[1],               6377                 'kernel': stmp[1],
6417                 'sysinfo': sysinfo,              6378                 'sysinfo': sysinfo,
6418                 'time': tstr,                    6379                 'time': tstr,
6419                 'result': result,                6380                 'result': result,
6420                 'issues': ' '.join(ilist),       6381                 'issues': ' '.join(ilist),
6421                 'suspend': suspend,              6382                 'suspend': suspend,
6422                 'resume': resume,                6383                 'resume': resume,
6423                 'devlist': devices,              6384                 'devlist': devices,
6424                 'sus_worst': worst['suspend']    6385                 'sus_worst': worst['suspend']['name'],
6425                 'sus_worsttime': worst['suspe    6386                 'sus_worsttime': worst['suspend']['time'],
6426                 'res_worst': worst['resume'][    6387                 'res_worst': worst['resume']['name'],
6427                 'res_worsttime': worst['resum    6388                 'res_worsttime': worst['resume']['time'],
6428                 'url': sysvals.htmlfile,         6389                 'url': sysvals.htmlfile,
6429         }                                        6390         }
6430         for key in extra:                        6391         for key in extra:
6431                 data[key] = extra[key]           6392                 data[key] = extra[key]
6432         if fulldetail:                           6393         if fulldetail:
6433                 data['funclist'] = find_in_ht    6394                 data['funclist'] = find_in_html(html, '<div title="', '" class="traceevent"', False)
6434         if tp:                                   6395         if tp:
6435                 for arg in ['-multi ', '-info    6396                 for arg in ['-multi ', '-info ']:
6436                         if arg in tp.cmdline:    6397                         if arg in tp.cmdline:
6437                                 data['target'    6398                                 data['target'] = tp.cmdline[tp.cmdline.find(arg):].split()[1]
6438                                 break            6399                                 break
6439         return data                              6400         return data
6440                                                  6401 
6441 def genHtml(subdir, force=False):                6402 def genHtml(subdir, force=False):
6442         for dirname, dirnames, filenames in o    6403         for dirname, dirnames, filenames in os.walk(subdir):
6443                 sysvals.dmesgfile = sysvals.f    6404                 sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = ''
6444                 for filename in filenames:       6405                 for filename in filenames:
6445                         file = os.path.join(d    6406                         file = os.path.join(dirname, filename)
6446                         if sysvals.usable(fil    6407                         if sysvals.usable(file):
6447                                 if(re.match(r !! 6408                                 if(re.match('.*_dmesg.txt', filename)):
6448                                         sysva    6409                                         sysvals.dmesgfile = file
6449                                 elif(re.match !! 6410                                 elif(re.match('.*_ftrace.txt', filename)):
6450                                         sysva    6411                                         sysvals.ftracefile = file
6451                 sysvals.setOutputFile()          6412                 sysvals.setOutputFile()
6452                 if (sysvals.dmesgfile or sysv    6413                 if (sysvals.dmesgfile or sysvals.ftracefile) and sysvals.htmlfile and \
6453                         (force or not sysvals    6414                         (force or not sysvals.usable(sysvals.htmlfile, True)):
6454                         pprint('FTRACE: %s' %    6415                         pprint('FTRACE: %s' % sysvals.ftracefile)
6455                         if sysvals.dmesgfile:    6416                         if sysvals.dmesgfile:
6456                                 pprint('DMESG    6417                                 pprint('DMESG : %s' % sysvals.dmesgfile)
6457                         rerunTest()              6418                         rerunTest()
6458                                                  6419 
6459 # Function: runSummary                           6420 # Function: runSummary
6460 # Description:                                   6421 # Description:
6461 #        create a summary of tests in a sub-d    6422 #        create a summary of tests in a sub-directory
6462 def runSummary(subdir, local=True, genhtml=Fa    6423 def runSummary(subdir, local=True, genhtml=False):
6463         inpath = os.path.abspath(subdir)         6424         inpath = os.path.abspath(subdir)
6464         outpath = os.path.abspath('.') if loc    6425         outpath = os.path.abspath('.') if local else inpath
6465         pprint('Generating a summary of folde    6426         pprint('Generating a summary of folder:\n   %s' % inpath)
6466         if genhtml:                              6427         if genhtml:
6467                 genHtml(subdir)                  6428                 genHtml(subdir)
6468         target, issues, testruns = '', [], []    6429         target, issues, testruns = '', [], []
6469         desc = {'host':[],'mode':[],'kernel':    6430         desc = {'host':[],'mode':[],'kernel':[]}
6470         for dirname, dirnames, filenames in o    6431         for dirname, dirnames, filenames in os.walk(subdir):
6471                 for filename in filenames:       6432                 for filename in filenames:
6472                         if(not re.match(r'.*. !! 6433                         if(not re.match('.*.html', filename)):
6473                                 continue         6434                                 continue
6474                         data = data_from_html    6435                         data = data_from_html(os.path.join(dirname, filename), outpath, issues)
6475                         if(not data):            6436                         if(not data):
6476                                 continue         6437                                 continue
6477                         if 'target' in data:     6438                         if 'target' in data:
6478                                 target = data    6439                                 target = data['target']
6479                         testruns.append(data)    6440                         testruns.append(data)
6480                         for key in desc:         6441                         for key in desc:
6481                                 if data[key]     6442                                 if data[key] not in desc[key]:
6482                                         desc[    6443                                         desc[key].append(data[key])
6483         pprint('Summary files:')                 6444         pprint('Summary files:')
6484         if len(desc['host']) == len(desc['mod    6445         if len(desc['host']) == len(desc['mode']) == len(desc['kernel']) == 1:
6485                 title = '%s %s %s' % (desc['h    6446                 title = '%s %s %s' % (desc['host'][0], desc['kernel'][0], desc['mode'][0])
6486                 if target:                       6447                 if target:
6487                         title += ' %s' % targ    6448                         title += ' %s' % target
6488         else:                                    6449         else:
6489                 title = inpath                   6450                 title = inpath
6490         createHTMLSummarySimple(testruns, os.    6451         createHTMLSummarySimple(testruns, os.path.join(outpath, 'summary.html'), title)
6491         pprint('   summary.html         - tab    6452         pprint('   summary.html         - tabular list of test data found')
6492         createHTMLDeviceSummary(testruns, os.    6453         createHTMLDeviceSummary(testruns, os.path.join(outpath, 'summary-devices.html'), title)
6493         pprint('   summary-devices.html - ker    6454         pprint('   summary-devices.html - kernel device list sorted by total execution time')
6494         createHTMLIssuesSummary(testruns, iss    6455         createHTMLIssuesSummary(testruns, issues, os.path.join(outpath, 'summary-issues.html'), title)
6495         pprint('   summary-issues.html  - ker    6456         pprint('   summary-issues.html  - kernel issues found sorted by frequency')
6496                                                  6457 
6497 # Function: checkArgBool                         6458 # Function: checkArgBool
6498 # Description:                                   6459 # Description:
6499 #        check if a boolean string value is t    6460 #        check if a boolean string value is true or false
6500 def checkArgBool(name, value):                   6461 def checkArgBool(name, value):
6501         if value in switchvalues:                6462         if value in switchvalues:
6502                 if value in switchoff:           6463                 if value in switchoff:
6503                         return False             6464                         return False
6504                 return True                      6465                 return True
6505         doError('invalid boolean --> (%s: %s)    6466         doError('invalid boolean --> (%s: %s), use "true/false" or "1/0"' % (name, value), True)
6506         return False                             6467         return False
6507                                                  6468 
6508 # Function: configFromFile                       6469 # Function: configFromFile
6509 # Description:                                   6470 # Description:
6510 #        Configure the script via the info in    6471 #        Configure the script via the info in a config file
6511 def configFromFile(file):                        6472 def configFromFile(file):
6512         Config = configparser.ConfigParser()     6473         Config = configparser.ConfigParser()
6513                                                  6474 
6514         Config.read(file)                        6475         Config.read(file)
6515         sections = Config.sections()             6476         sections = Config.sections()
6516         overridekprobes = False                  6477         overridekprobes = False
6517         overridedevkprobes = False               6478         overridedevkprobes = False
6518         if 'Settings' in sections:               6479         if 'Settings' in sections:
6519                 for opt in Config.options('Se    6480                 for opt in Config.options('Settings'):
6520                         value = Config.get('S    6481                         value = Config.get('Settings', opt).lower()
6521                         option = opt.lower()     6482                         option = opt.lower()
6522                         if(option == 'verbose    6483                         if(option == 'verbose'):
6523                                 sysvals.verbo    6484                                 sysvals.verbose = checkArgBool(option, value)
6524                         elif(option == 'addlo    6485                         elif(option == 'addlogs'):
6525                                 sysvals.dmesg    6486                                 sysvals.dmesglog = sysvals.ftracelog = checkArgBool(option, value)
6526                         elif(option == 'dev')    6487                         elif(option == 'dev'):
6527                                 sysvals.usede    6488                                 sysvals.usedevsrc = checkArgBool(option, value)
6528                         elif(option == 'proc'    6489                         elif(option == 'proc'):
6529                                 sysvals.usepr    6490                                 sysvals.useprocmon = checkArgBool(option, value)
6530                         elif(option == 'x2'):    6491                         elif(option == 'x2'):
6531                                 if checkArgBo    6492                                 if checkArgBool(option, value):
6532                                         sysva    6493                                         sysvals.execcount = 2
6533                         elif(option == 'callg    6494                         elif(option == 'callgraph'):
6534                                 sysvals.useca    6495                                 sysvals.usecallgraph = checkArgBool(option, value)
6535                         elif(option == 'overr    6496                         elif(option == 'override-timeline-functions'):
6536                                 overridekprob    6497                                 overridekprobes = checkArgBool(option, value)
6537                         elif(option == 'overr    6498                         elif(option == 'override-dev-timeline-functions'):
6538                                 overridedevkp    6499                                 overridedevkprobes = checkArgBool(option, value)
6539                         elif(option == 'skiph    6500                         elif(option == 'skiphtml'):
6540                                 sysvals.skiph    6501                                 sysvals.skiphtml = checkArgBool(option, value)
6541                         elif(option == 'sync'    6502                         elif(option == 'sync'):
6542                                 sysvals.sync     6503                                 sysvals.sync = checkArgBool(option, value)
6543                         elif(option == 'rs' o    6504                         elif(option == 'rs' or option == 'runtimesuspend'):
6544                                 if value in s    6505                                 if value in switchvalues:
6545                                         if va    6506                                         if value in switchoff:
6546                                                  6507                                                 sysvals.rs = -1
6547                                         else:    6508                                         else:
6548                                                  6509                                                 sysvals.rs = 1
6549                                 else:            6510                                 else:
6550                                         doErr    6511                                         doError('invalid value --> (%s: %s), use "enable/disable"' % (option, value), True)
6551                         elif(option == 'displ    6512                         elif(option == 'display'):
6552                                 disopt = ['on    6513                                 disopt = ['on', 'off', 'standby', 'suspend']
6553                                 if value not     6514                                 if value not in disopt:
6554                                         doErr    6515                                         doError('invalid value --> (%s: %s), use %s' % (option, value, disopt), True)
6555                                 sysvals.displ    6516                                 sysvals.display = value
6556                         elif(option == 'gzip'    6517                         elif(option == 'gzip'):
6557                                 sysvals.gzip     6518                                 sysvals.gzip = checkArgBool(option, value)
6558                         elif(option == 'cgfil    6519                         elif(option == 'cgfilter'):
6559                                 sysvals.setCa    6520                                 sysvals.setCallgraphFilter(value)
6560                         elif(option == 'cgski    6521                         elif(option == 'cgskip'):
6561                                 if value in s    6522                                 if value in switchoff:
6562                                         sysva    6523                                         sysvals.cgskip = ''
6563                                 else:            6524                                 else:
6564                                         sysva    6525                                         sysvals.cgskip = sysvals.configFile(val)
6565                                         if(no    6526                                         if(not sysvals.cgskip):
6566                                                  6527                                                 doError('%s does not exist' % sysvals.cgskip)
6567                         elif(option == 'cgtes    6528                         elif(option == 'cgtest'):
6568                                 sysvals.cgtes    6529                                 sysvals.cgtest = getArgInt('cgtest', value, 0, 1, False)
6569                         elif(option == 'cgpha    6530                         elif(option == 'cgphase'):
6570                                 d = Data(0)      6531                                 d = Data(0)
6571                                 if value not     6532                                 if value not in d.phasedef:
6572                                         doErr    6533                                         doError('invalid phase --> (%s: %s), valid phases are %s'\
6573                                                  6534                                                 % (option, value, d.phasedef.keys()), True)
6574                                 sysvals.cgpha    6535                                 sysvals.cgphase = value
6575                         elif(option == 'fadd'    6536                         elif(option == 'fadd'):
6576                                 file = sysval    6537                                 file = sysvals.configFile(value)
6577                                 if(not file):    6538                                 if(not file):
6578                                         doErr    6539                                         doError('%s does not exist' % value)
6579                                 sysvals.addFt    6540                                 sysvals.addFtraceFilterFunctions(file)
6580                         elif(option == 'resul    6541                         elif(option == 'result'):
6581                                 sysvals.resul    6542                                 sysvals.result = value
6582                         elif(option == 'multi    6543                         elif(option == 'multi'):
6583                                 nums = value.    6544                                 nums = value.split()
6584                                 if len(nums)     6545                                 if len(nums) != 2:
6585                                         doErr    6546                                         doError('multi requires 2 integers (exec_count and delay)', True)
6586                                 sysvals.multi    6547                                 sysvals.multiinit(nums[0], nums[1])
6587                         elif(option == 'devic    6548                         elif(option == 'devicefilter'):
6588                                 sysvals.setDe    6549                                 sysvals.setDeviceFilter(value)
6589                         elif(option == 'expan    6550                         elif(option == 'expandcg'):
6590                                 sysvals.cgexp    6551                                 sysvals.cgexp = checkArgBool(option, value)
6591                         elif(option == 'srgap    6552                         elif(option == 'srgap'):
6592                                 if checkArgBo    6553                                 if checkArgBool(option, value):
6593                                         sysva    6554                                         sysvals.srgap = 5
6594                         elif(option == 'mode'    6555                         elif(option == 'mode'):
6595                                 sysvals.suspe    6556                                 sysvals.suspendmode = value
6596                         elif(option == 'comma    6557                         elif(option == 'command' or option == 'cmd'):
6597                                 sysvals.testc    6558                                 sysvals.testcommand = value
6598                         elif(option == 'x2del    6559                         elif(option == 'x2delay'):
6599                                 sysvals.x2del    6560                                 sysvals.x2delay = getArgInt('x2delay', value, 0, 60000, False)
6600                         elif(option == 'prede    6561                         elif(option == 'predelay'):
6601                                 sysvals.prede    6562                                 sysvals.predelay = getArgInt('predelay', value, 0, 60000, False)
6602                         elif(option == 'postd    6563                         elif(option == 'postdelay'):
6603                                 sysvals.postd    6564                                 sysvals.postdelay = getArgInt('postdelay', value, 0, 60000, False)
6604                         elif(option == 'maxde    6565                         elif(option == 'maxdepth'):
6605                                 sysvals.max_g    6566                                 sysvals.max_graph_depth = getArgInt('maxdepth', value, 0, 1000, False)
6606                         elif(option == 'rtcwa    6567                         elif(option == 'rtcwake'):
6607                                 if value in s    6568                                 if value in switchoff:
6608                                         sysva    6569                                         sysvals.rtcwake = False
6609                                 else:            6570                                 else:
6610                                         sysva    6571                                         sysvals.rtcwake = True
6611                                         sysva    6572                                         sysvals.rtcwaketime = getArgInt('rtcwake', value, 0, 3600, False)
6612                         elif(option == 'timep    6573                         elif(option == 'timeprec'):
6613                                 sysvals.setPr    6574                                 sysvals.setPrecision(getArgInt('timeprec', value, 0, 6, False))
6614                         elif(option == 'minde    6575                         elif(option == 'mindev'):
6615                                 sysvals.minde    6576                                 sysvals.mindevlen = getArgFloat('mindev', value, 0.0, 10000.0, False)
6616                         elif(option == 'calll    6577                         elif(option == 'callloop-maxgap'):
6617                                 sysvals.calll    6578                                 sysvals.callloopmaxgap = getArgFloat('callloop-maxgap', value, 0.0, 1.0, False)
6618                         elif(option == 'calll    6579                         elif(option == 'callloop-maxlen'):
6619                                 sysvals.calll    6580                                 sysvals.callloopmaxgap = getArgFloat('callloop-maxlen', value, 0.0, 1.0, False)
6620                         elif(option == 'mincg    6581                         elif(option == 'mincg'):
6621                                 sysvals.mincg    6582                                 sysvals.mincglen = getArgFloat('mincg', value, 0.0, 10000.0, False)
6622                         elif(option == 'bufsi    6583                         elif(option == 'bufsize'):
6623                                 sysvals.bufsi    6584                                 sysvals.bufsize = getArgInt('bufsize', value, 1, 1024*1024*8, False)
6624                         elif(option == 'outpu    6585                         elif(option == 'output-dir'):
6625                                 sysvals.outdi    6586                                 sysvals.outdir = sysvals.setOutputFolder(value)
6626                                                  6587 
6627         if sysvals.suspendmode == 'command' a    6588         if sysvals.suspendmode == 'command' and not sysvals.testcommand:
6628                 doError('No command supplied     6589                 doError('No command supplied for mode "command"')
6629                                                  6590 
6630         # compatibility errors                   6591         # compatibility errors
6631         if sysvals.usedevsrc and sysvals.usec    6592         if sysvals.usedevsrc and sysvals.usecallgraph:
6632                 doError('-dev is not compatib    6593                 doError('-dev is not compatible with -f')
6633         if sysvals.usecallgraph and sysvals.u    6594         if sysvals.usecallgraph and sysvals.useprocmon:
6634                 doError('-proc is not compati    6595                 doError('-proc is not compatible with -f')
6635                                                  6596 
6636         if overridekprobes:                      6597         if overridekprobes:
6637                 sysvals.tracefuncs = dict()      6598                 sysvals.tracefuncs = dict()
6638         if overridedevkprobes:                   6599         if overridedevkprobes:
6639                 sysvals.dev_tracefuncs = dict    6600                 sysvals.dev_tracefuncs = dict()
6640                                                  6601 
6641         kprobes = dict()                         6602         kprobes = dict()
6642         kprobesec = 'dev_timeline_functions_'    6603         kprobesec = 'dev_timeline_functions_'+platform.machine()
6643         if kprobesec in sections:                6604         if kprobesec in sections:
6644                 for name in Config.options(kp    6605                 for name in Config.options(kprobesec):
6645                         text = Config.get(kpr    6606                         text = Config.get(kprobesec, name)
6646                         kprobes[name] = (text    6607                         kprobes[name] = (text, True)
6647         kprobesec = 'timeline_functions_'+pla    6608         kprobesec = 'timeline_functions_'+platform.machine()
6648         if kprobesec in sections:                6609         if kprobesec in sections:
6649                 for name in Config.options(kp    6610                 for name in Config.options(kprobesec):
6650                         if name in kprobes:      6611                         if name in kprobes:
6651                                 doError('Dupl    6612                                 doError('Duplicate timeline function found "%s"' % (name))
6652                         text = Config.get(kpr    6613                         text = Config.get(kprobesec, name)
6653                         kprobes[name] = (text    6614                         kprobes[name] = (text, False)
6654                                                  6615 
6655         for name in kprobes:                     6616         for name in kprobes:
6656                 function = name                  6617                 function = name
6657                 format = name                    6618                 format = name
6658                 color = ''                       6619                 color = ''
6659                 args = dict()                    6620                 args = dict()
6660                 text, dev = kprobes[name]        6621                 text, dev = kprobes[name]
6661                 data = text.split()              6622                 data = text.split()
6662                 i = 0                            6623                 i = 0
6663                 for val in data:                 6624                 for val in data:
6664                         # bracketted strings     6625                         # bracketted strings are special formatting, read them separately
6665                         if val[0] == '[' and     6626                         if val[0] == '[' and val[-1] == ']':
6666                                 for prop in v    6627                                 for prop in val[1:-1].split(','):
6667                                         p = p    6628                                         p = prop.split('=')
6668                                         if p[    6629                                         if p[0] == 'color':
6669                                                  6630                                                 try:
6670                                                  6631                                                         color = int(p[1], 16)
6671                                                  6632                                                         color = '#'+p[1]
6672                                                  6633                                                 except:
6673                                                  6634                                                         color = p[1]
6674                                 continue         6635                                 continue
6675                         # first real arg shou    6636                         # first real arg should be the format string
6676                         if i == 0:               6637                         if i == 0:
6677                                 format = val     6638                                 format = val
6678                         # all other args are     6639                         # all other args are actual function args
6679                         else:                    6640                         else:
6680                                 d = val.split    6641                                 d = val.split('=')
6681                                 args[d[0]] =     6642                                 args[d[0]] = d[1]
6682                         i += 1                   6643                         i += 1
6683                 if not function or not format    6644                 if not function or not format:
6684                         doError('Invalid kpro    6645                         doError('Invalid kprobe: %s' % name)
6685                 for arg in re.findall('{(?P<n    6646                 for arg in re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', format):
6686                         if arg not in args:      6647                         if arg not in args:
6687                                 doError('Kpro    6648                                 doError('Kprobe "%s" is missing argument "%s"' % (name, arg))
6688                 if (dev and name in sysvals.d    6649                 if (dev and name in sysvals.dev_tracefuncs) or (not dev and name in sysvals.tracefuncs):
6689                         doError('Duplicate ti    6650                         doError('Duplicate timeline function found "%s"' % (name))
6690                                                  6651 
6691                 kp = {                           6652                 kp = {
6692                         'name': name,            6653                         'name': name,
6693                         'func': function,        6654                         'func': function,
6694                         'format': format,        6655                         'format': format,
6695                         sysvals.archargs: arg    6656                         sysvals.archargs: args
6696                 }                                6657                 }
6697                 if color:                        6658                 if color:
6698                         kp['color'] = color      6659                         kp['color'] = color
6699                 if dev:                          6660                 if dev:
6700                         sysvals.dev_tracefunc    6661                         sysvals.dev_tracefuncs[name] = kp
6701                 else:                            6662                 else:
6702                         sysvals.tracefuncs[na    6663                         sysvals.tracefuncs[name] = kp
6703                                                  6664 
6704 # Function: printHelp                            6665 # Function: printHelp
6705 # Description:                                   6666 # Description:
6706 #        print out the help text                 6667 #        print out the help text
6707 def printHelp():                                 6668 def printHelp():
6708         pprint('\n%s v%s\n'\                     6669         pprint('\n%s v%s\n'\
6709         'Usage: sudo sleepgraph <options> <co    6670         'Usage: sudo sleepgraph <options> <commands>\n'\
6710         '\n'\                                    6671         '\n'\
6711         'Description:\n'\                        6672         'Description:\n'\
6712         '  This tool is designed to assist ke    6673         '  This tool is designed to assist kernel and OS developers in optimizing\n'\
6713         '  their linux stack\'s suspend/resum    6674         '  their linux stack\'s suspend/resume time. Using a kernel image built\n'\
6714         '  with a few extra options enabled,     6675         '  with a few extra options enabled, the tool will execute a suspend and\n'\
6715         '  capture dmesg and ftrace data unti    6676         '  capture dmesg and ftrace data until resume is complete. This data is\n'\
6716         '  transformed into a device timeline    6677         '  transformed into a device timeline and an optional callgraph to give\n'\
6717         '  a detailed view of which devices/s    6678         '  a detailed view of which devices/subsystems are taking the most\n'\
6718         '  time in suspend/resume.\n'\           6679         '  time in suspend/resume.\n'\
6719         '\n'\                                    6680         '\n'\
6720         '  If no specific command is given, t    6681         '  If no specific command is given, the default behavior is to initiate\n'\
6721         '  a suspend/resume and capture the d    6682         '  a suspend/resume and capture the dmesg/ftrace output as an html timeline.\n'\
6722         '\n'\                                    6683         '\n'\
6723         '  Generates output files in subdirec    6684         '  Generates output files in subdirectory: suspend-yymmdd-HHMMSS\n'\
6724         '   HTML output:                    <    6685         '   HTML output:                    <hostname>_<mode>.html\n'\
6725         '   raw dmesg output:               <    6686         '   raw dmesg output:               <hostname>_<mode>_dmesg.txt\n'\
6726         '   raw ftrace output:              <    6687         '   raw ftrace output:              <hostname>_<mode>_ftrace.txt\n'\
6727         '\n'\                                    6688         '\n'\
6728         'Options:\n'\                            6689         'Options:\n'\
6729         '   -h           Print this help text    6690         '   -h           Print this help text\n'\
6730         '   -v           Print the current to    6691         '   -v           Print the current tool version\n'\
6731         '   -config fn   Pull arguments and c    6692         '   -config fn   Pull arguments and config options from file fn\n'\
6732         '   -verbose     Print extra informat    6693         '   -verbose     Print extra information during execution and analysis\n'\
6733         '   -m mode      Mode to initiate for    6694         '   -m mode      Mode to initiate for suspend (default: %s)\n'\
6734         '   -o name      Overrides the output    6695         '   -o name      Overrides the output subdirectory name when running a new test\n'\
6735         '                default: suspend-{da    6696         '                default: suspend-{date}-{time}\n'\
6736         '   -rtcwake t   Wakeup t seconds aft    6697         '   -rtcwake t   Wakeup t seconds after suspend, set t to "off" to disable (default: 15)\n'\
6737         '   -addlogs     Add the dmesg and ft    6698         '   -addlogs     Add the dmesg and ftrace logs to the html output\n'\
6738         '   -noturbostat Dont use turbostat i    6699         '   -noturbostat Dont use turbostat in freeze mode (default: disabled)\n'\
6739         '   -srgap       Add a visible gap in    6700         '   -srgap       Add a visible gap in the timeline between sus/res (default: disabled)\n'\
6740         '   -skiphtml    Run the test and cap    6701         '   -skiphtml    Run the test and capture the trace logs, but skip the timeline (default: disabled)\n'\
6741         '   -result fn   Export a results tab    6702         '   -result fn   Export a results table to a text file for parsing.\n'\
6742         '   -wifi        If a wifi connection    6703         '   -wifi        If a wifi connection is available, check that it reconnects after resume.\n'\
6743         '   -wifitrace   Trace kernel executi << 
6744         '   -netfix      Use netfix to reset     6704         '   -netfix      Use netfix to reset the network in the event it fails to resume.\n'\
6745         '  [testprep]\n'\                        6705         '  [testprep]\n'\
6746         '   -sync        Sync the filesystems    6706         '   -sync        Sync the filesystems before starting the test\n'\
6747         '   -rs on/off   Enable/disable runti    6707         '   -rs on/off   Enable/disable runtime suspend for all devices, restore all after test\n'\
6748         '   -display m   Change the display m    6708         '   -display m   Change the display mode to m for the test (on/off/standby/suspend)\n'\
6749         '  [advanced]\n'\                        6709         '  [advanced]\n'\
6750         '   -gzip        Gzip the trace and d    6710         '   -gzip        Gzip the trace and dmesg logs to save space\n'\
6751         '   -cmd {s}     Run the timeline ove    6711         '   -cmd {s}     Run the timeline over a custom command, e.g. "sync -d"\n'\
6752         '   -proc        Add usermode process    6712         '   -proc        Add usermode process info into the timeline (default: disabled)\n'\
6753         '   -dev         Add kernel function     6713         '   -dev         Add kernel function calls and threads to the timeline (default: disabled)\n'\
6754         '   -x2          Run two suspend/resu    6714         '   -x2          Run two suspend/resumes back to back (default: disabled)\n'\
6755         '   -x2delay t   Include t ms delay b    6715         '   -x2delay t   Include t ms delay between multiple test runs (default: 0 ms)\n'\
6756         '   -predelay t  Include t ms delay b    6716         '   -predelay t  Include t ms delay before 1st suspend (default: 0 ms)\n'\
6757         '   -postdelay t Include t ms delay a    6717         '   -postdelay t Include t ms delay after last resume (default: 0 ms)\n'\
6758         '   -mindev ms   Discard all device b    6718         '   -mindev ms   Discard all device blocks shorter than ms milliseconds (e.g. 0.001 for us)\n'\
6759         '   -multi n d   Execute <n> consecut    6719         '   -multi n d   Execute <n> consecutive tests at <d> seconds intervals. If <n> is followed\n'\
6760         '                by a "d", "h", or "m    6720         '                by a "d", "h", or "m" execute for <n> days, hours, or mins instead.\n'\
6761         '                The outputs will be     6721         '                The outputs will be created in a new subdirectory with a summary page.\n'\
6762         '   -maxfail n   Abort a -multi run a    6722         '   -maxfail n   Abort a -multi run after n consecutive fails (default is 0 = never abort)\n'\
6763         '  [debug]\n'\                           6723         '  [debug]\n'\
6764         '   -f           Use ftrace to create    6724         '   -f           Use ftrace to create device callgraphs (default: disabled)\n'\
6765         '   -ftop        Use ftrace on the to    6725         '   -ftop        Use ftrace on the top level call: "%s" (default: disabled)\n'\
6766         '   -maxdepth N  limit the callgraph     6726         '   -maxdepth N  limit the callgraph data to N call levels (default: 0=all)\n'\
6767         '   -expandcg    pre-expand the callg    6727         '   -expandcg    pre-expand the callgraph data in the html output (default: disabled)\n'\
6768         '   -fadd file   Add functions to be     6728         '   -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    6729         '   -filter "d1,d2,..." Filter out all but this comma-delimited list of device names\n'\
6770         '   -mincg  ms   Discard all callgrap    6730         '   -mincg  ms   Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)\n'\
6771         '   -cgphase P   Only show callgraph     6731         '   -cgphase P   Only show callgraph data for phase P (e.g. suspend_late)\n'\
6772         '   -cgtest N    Only show callgraph     6732         '   -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    6733         '   -timeprec N  Number of significant digits in timestamps (0:S, [3:ms], 6:us)\n'\
6774         '   -cgfilter S  Filter the callgraph    6734         '   -cgfilter S  Filter the callgraph output in the timeline\n'\
6775         '   -cgskip file Callgraph functions     6735         '   -cgskip file Callgraph functions to skip, off to disable (default: cgskip.txt)\n'\
6776         '   -bufsize N   Set trace buffer siz    6736         '   -bufsize N   Set trace buffer size to N kilo-bytes (default: all of free memory)\n'\
6777         '   -devdump     Print out all the ra    6737         '   -devdump     Print out all the raw device data for each phase\n'\
6778         '   -cgdump      Print out all the ra    6738         '   -cgdump      Print out all the raw callgraph data\n'\
6779         '\n'\                                    6739         '\n'\
6780         'Other commands:\n'\                     6740         'Other commands:\n'\
6781         '   -modes       List available suspe    6741         '   -modes       List available suspend modes\n'\
6782         '   -status      Test to see if the s    6742         '   -status      Test to see if the system is enabled to run this tool\n'\
6783         '   -fpdt        Print out the conten    6743         '   -fpdt        Print out the contents of the ACPI Firmware Performance Data Table\n'\
6784         '   -wificheck   Print out wifi conne    6744         '   -wificheck   Print out wifi connection info\n'\
6785         '   -x<mode>     Test xset by togglin    6745         '   -x<mode>     Test xset by toggling the given mode (on/off/standby/suspend)\n'\
6786         '   -sysinfo     Print out system inf    6746         '   -sysinfo     Print out system info extracted from BIOS\n'\
6787         '   -devinfo     Print out the pm set    6747         '   -devinfo     Print out the pm settings of all devices which support runtime suspend\n'\
6788         '   -cmdinfo     Print out all the pl    6748         '   -cmdinfo     Print out all the platform info collected before and after suspend/resume\n'\
6789         '   -flist       Print the list of fu    6749         '   -flist       Print the list of functions currently being captured in ftrace\n'\
6790         '   -flistall    Print all functions     6750         '   -flistall    Print all functions capable of being captured in ftrace\n'\
6791         '   -summary dir Create a summary of     6751         '   -summary dir Create a summary of tests in this dir [-genhtml builds missing html]\n'\
6792         '  [redo]\n'\                            6752         '  [redo]\n'\
6793         '   -ftrace ftracefile  Create HTML o    6753         '   -ftrace ftracefile  Create HTML output using ftrace input (used with -dmesg)\n'\
6794         '   -dmesg dmesgfile    Create HTML o    6754         '   -dmesg dmesgfile    Create HTML output using dmesg (used with -ftrace)\n'\
6795         '' % (sysvals.title, sysvals.version,    6755         '' % (sysvals.title, sysvals.version, sysvals.suspendmode, sysvals.ftopfunc))
6796         return True                              6756         return True
6797                                                  6757 
6798 # ----------------- MAIN --------------------    6758 # ----------------- MAIN --------------------
6799 # exec start (skipped if script is loaded as     6759 # exec start (skipped if script is loaded as library)
6800 if __name__ == '__main__':                       6760 if __name__ == '__main__':
6801         genhtml = False                          6761         genhtml = False
6802         cmd = ''                                 6762         cmd = ''
6803         simplecmds = ['-sysinfo', '-modes', '    6763         simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall',
6804                 '-devinfo', '-status', '-xon'    6764                 '-devinfo', '-status', '-xon', '-xoff', '-xstandby', '-xsuspend',
6805                 '-xinit', '-xreset', '-xstat'    6765                 '-xinit', '-xreset', '-xstat', '-wificheck', '-cmdinfo']
6806         if '-f' in sys.argv:                     6766         if '-f' in sys.argv:
6807                 sysvals.cgskip = sysvals.conf    6767                 sysvals.cgskip = sysvals.configFile('cgskip.txt')
6808         # loop through the command line argum    6768         # loop through the command line arguments
6809         args = iter(sys.argv[1:])                6769         args = iter(sys.argv[1:])
6810         for arg in args:                         6770         for arg in args:
6811                 if(arg == '-m'):                 6771                 if(arg == '-m'):
6812                         try:                     6772                         try:
6813                                 val = next(ar    6773                                 val = next(args)
6814                         except:                  6774                         except:
6815                                 doError('No m    6775                                 doError('No mode supplied', True)
6816                         if val == 'command' a    6776                         if val == 'command' and not sysvals.testcommand:
6817                                 doError('No c    6777                                 doError('No command supplied for mode "command"', True)
6818                         sysvals.suspendmode =    6778                         sysvals.suspendmode = val
6819                 elif(arg in simplecmds):         6779                 elif(arg in simplecmds):
6820                         cmd = arg[1:]            6780                         cmd = arg[1:]
6821                 elif(arg == '-h'):               6781                 elif(arg == '-h'):
6822                         printHelp()              6782                         printHelp()
6823                         sys.exit(0)              6783                         sys.exit(0)
6824                 elif(arg == '-v'):               6784                 elif(arg == '-v'):
6825                         pprint("Version %s" %    6785                         pprint("Version %s" % sysvals.version)
6826                         sys.exit(0)              6786                         sys.exit(0)
6827                 elif(arg == '-debugtiming'):     6787                 elif(arg == '-debugtiming'):
6828                         debugtiming = True       6788                         debugtiming = True
6829                 elif(arg == '-x2'):              6789                 elif(arg == '-x2'):
6830                         sysvals.execcount = 2    6790                         sysvals.execcount = 2
6831                 elif(arg == '-x2delay'):         6791                 elif(arg == '-x2delay'):
6832                         sysvals.x2delay = get    6792                         sysvals.x2delay = getArgInt('-x2delay', args, 0, 60000)
6833                 elif(arg == '-predelay'):        6793                 elif(arg == '-predelay'):
6834                         sysvals.predelay = ge    6794                         sysvals.predelay = getArgInt('-predelay', args, 0, 60000)
6835                 elif(arg == '-postdelay'):       6795                 elif(arg == '-postdelay'):
6836                         sysvals.postdelay = g    6796                         sysvals.postdelay = getArgInt('-postdelay', args, 0, 60000)
6837                 elif(arg == '-f'):               6797                 elif(arg == '-f'):
6838                         sysvals.usecallgraph     6798                         sysvals.usecallgraph = True
6839                 elif(arg == '-ftop'):            6799                 elif(arg == '-ftop'):
6840                         sysvals.usecallgraph     6800                         sysvals.usecallgraph = True
6841                         sysvals.ftop = True      6801                         sysvals.ftop = True
6842                         sysvals.usekprobes =     6802                         sysvals.usekprobes = False
6843                 elif(arg == '-skiphtml'):        6803                 elif(arg == '-skiphtml'):
6844                         sysvals.skiphtml = Tr    6804                         sysvals.skiphtml = True
6845                 elif(arg == '-cgdump'):          6805                 elif(arg == '-cgdump'):
6846                         sysvals.cgdump = True    6806                         sysvals.cgdump = True
6847                 elif(arg == '-devdump'):         6807                 elif(arg == '-devdump'):
6848                         sysvals.devdump = Tru    6808                         sysvals.devdump = True
6849                 elif(arg == '-genhtml'):         6809                 elif(arg == '-genhtml'):
6850                         genhtml = True           6810                         genhtml = True
6851                 elif(arg == '-addlogs'):         6811                 elif(arg == '-addlogs'):
6852                         sysvals.dmesglog = sy    6812                         sysvals.dmesglog = sysvals.ftracelog = True
6853                 elif(arg == '-nologs'):          6813                 elif(arg == '-nologs'):
6854                         sysvals.dmesglog = sy    6814                         sysvals.dmesglog = sysvals.ftracelog = False
6855                 elif(arg == '-addlogdmesg'):     6815                 elif(arg == '-addlogdmesg'):
6856                         sysvals.dmesglog = Tr    6816                         sysvals.dmesglog = True
6857                 elif(arg == '-addlogftrace'):    6817                 elif(arg == '-addlogftrace'):
6858                         sysvals.ftracelog = T    6818                         sysvals.ftracelog = True
6859                 elif(arg == '-noturbostat'):     6819                 elif(arg == '-noturbostat'):
6860                         sysvals.tstat = False    6820                         sysvals.tstat = False
6861                 elif(arg == '-verbose'):         6821                 elif(arg == '-verbose'):
6862                         sysvals.verbose = Tru    6822                         sysvals.verbose = True
6863                 elif(arg == '-proc'):            6823                 elif(arg == '-proc'):
6864                         sysvals.useprocmon =     6824                         sysvals.useprocmon = True
6865                 elif(arg == '-dev'):             6825                 elif(arg == '-dev'):
6866                         sysvals.usedevsrc = T    6826                         sysvals.usedevsrc = True
6867                 elif(arg == '-sync'):            6827                 elif(arg == '-sync'):
6868                         sysvals.sync = True      6828                         sysvals.sync = True
6869                 elif(arg == '-wifi'):            6829                 elif(arg == '-wifi'):
6870                         sysvals.wifi = True      6830                         sysvals.wifi = True
6871                 elif(arg == '-wifitrace'):    << 
6872                         sysvals.wifitrace = T << 
6873                 elif(arg == '-netfix'):          6831                 elif(arg == '-netfix'):
6874                         sysvals.netfix = True    6832                         sysvals.netfix = True
6875                 elif(arg == '-gzip'):            6833                 elif(arg == '-gzip'):
6876                         sysvals.gzip = True      6834                         sysvals.gzip = True
6877                 elif(arg == '-info'):            6835                 elif(arg == '-info'):
6878                         try:                     6836                         try:
6879                                 val = next(ar    6837                                 val = next(args)
6880                         except:                  6838                         except:
6881                                 doError('-inf    6839                                 doError('-info requires one string argument', True)
6882                 elif(arg == '-desc'):            6840                 elif(arg == '-desc'):
6883                         try:                     6841                         try:
6884                                 val = next(ar    6842                                 val = next(args)
6885                         except:                  6843                         except:
6886                                 doError('-des    6844                                 doError('-desc requires one string argument', True)
6887                 elif(arg == '-rs'):              6845                 elif(arg == '-rs'):
6888                         try:                     6846                         try:
6889                                 val = next(ar    6847                                 val = next(args)
6890                         except:                  6848                         except:
6891                                 doError('-rs     6849                                 doError('-rs requires "enable" or "disable"', True)
6892                         if val.lower() in swi    6850                         if val.lower() in switchvalues:
6893                                 if val.lower(    6851                                 if val.lower() in switchoff:
6894                                         sysva    6852                                         sysvals.rs = -1
6895                                 else:            6853                                 else:
6896                                         sysva    6854                                         sysvals.rs = 1
6897                         else:                    6855                         else:
6898                                 doError('inva    6856                                 doError('invalid option: %s, use "enable/disable" or "on/off"' % val, True)
6899                 elif(arg == '-display'):         6857                 elif(arg == '-display'):
6900                         try:                     6858                         try:
6901                                 val = next(ar    6859                                 val = next(args)
6902                         except:                  6860                         except:
6903                                 doError('-dis    6861                                 doError('-display requires an mode value', True)
6904                         disopt = ['on', 'off'    6862                         disopt = ['on', 'off', 'standby', 'suspend']
6905                         if val.lower() not in    6863                         if val.lower() not in disopt:
6906                                 doError('vali    6864                                 doError('valid display mode values are %s' % disopt, True)
6907                         sysvals.display = val    6865                         sysvals.display = val.lower()
6908                 elif(arg == '-maxdepth'):        6866                 elif(arg == '-maxdepth'):
6909                         sysvals.max_graph_dep    6867                         sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000)
6910                 elif(arg == '-rtcwake'):         6868                 elif(arg == '-rtcwake'):
6911                         try:                     6869                         try:
6912                                 val = next(ar    6870                                 val = next(args)
6913                         except:                  6871                         except:
6914                                 doError('No r    6872                                 doError('No rtcwake time supplied', True)
6915                         if val.lower() in swi    6873                         if val.lower() in switchoff:
6916                                 sysvals.rtcwa    6874                                 sysvals.rtcwake = False
6917                         else:                    6875                         else:
6918                                 sysvals.rtcwa    6876                                 sysvals.rtcwake = True
6919                                 sysvals.rtcwa    6877                                 sysvals.rtcwaketime = getArgInt('-rtcwake', val, 0, 3600, False)
6920                 elif(arg == '-timeprec'):        6878                 elif(arg == '-timeprec'):
6921                         sysvals.setPrecision(    6879                         sysvals.setPrecision(getArgInt('-timeprec', args, 0, 6))
6922                 elif(arg == '-mindev'):          6880                 elif(arg == '-mindev'):
6923                         sysvals.mindevlen = g    6881                         sysvals.mindevlen = getArgFloat('-mindev', args, 0.0, 10000.0)
6924                 elif(arg == '-mincg'):           6882                 elif(arg == '-mincg'):
6925                         sysvals.mincglen = ge    6883                         sysvals.mincglen = getArgFloat('-mincg', args, 0.0, 10000.0)
6926                 elif(arg == '-bufsize'):         6884                 elif(arg == '-bufsize'):
6927                         sysvals.bufsize = get    6885                         sysvals.bufsize = getArgInt('-bufsize', args, 1, 1024*1024*8)
6928                 elif(arg == '-cgtest'):          6886                 elif(arg == '-cgtest'):
6929                         sysvals.cgtest = getA    6887                         sysvals.cgtest = getArgInt('-cgtest', args, 0, 1)
6930                 elif(arg == '-cgphase'):         6888                 elif(arg == '-cgphase'):
6931                         try:                     6889                         try:
6932                                 val = next(ar    6890                                 val = next(args)
6933                         except:                  6891                         except:
6934                                 doError('No p    6892                                 doError('No phase name supplied', True)
6935                         d = Data(0)              6893                         d = Data(0)
6936                         if val not in d.phase    6894                         if val not in d.phasedef:
6937                                 doError('inva    6895                                 doError('invalid phase --> (%s: %s), valid phases are %s'\
6938                                         % (ar    6896                                         % (arg, val, d.phasedef.keys()), True)
6939                         sysvals.cgphase = val    6897                         sysvals.cgphase = val
6940                 elif(arg == '-cgfilter'):        6898                 elif(arg == '-cgfilter'):
6941                         try:                     6899                         try:
6942                                 val = next(ar    6900                                 val = next(args)
6943                         except:                  6901                         except:
6944                                 doError('No c    6902                                 doError('No callgraph functions supplied', True)
6945                         sysvals.setCallgraphF    6903                         sysvals.setCallgraphFilter(val)
6946                 elif(arg == '-skipkprobe'):      6904                 elif(arg == '-skipkprobe'):
6947                         try:                     6905                         try:
6948                                 val = next(ar    6906                                 val = next(args)
6949                         except:                  6907                         except:
6950                                 doError('No k    6908                                 doError('No kprobe functions supplied', True)
6951                         sysvals.skipKprobes(v    6909                         sysvals.skipKprobes(val)
6952                 elif(arg == '-cgskip'):          6910                 elif(arg == '-cgskip'):
6953                         try:                     6911                         try:
6954                                 val = next(ar    6912                                 val = next(args)
6955                         except:                  6913                         except:
6956                                 doError('No f    6914                                 doError('No file supplied', True)
6957                         if val.lower() in swi    6915                         if val.lower() in switchoff:
6958                                 sysvals.cgski    6916                                 sysvals.cgskip = ''
6959                         else:                    6917                         else:
6960                                 sysvals.cgski    6918                                 sysvals.cgskip = sysvals.configFile(val)
6961                                 if(not sysval    6919                                 if(not sysvals.cgskip):
6962                                         doErr    6920                                         doError('%s does not exist' % sysvals.cgskip)
6963                 elif(arg == '-callloop-maxgap    6921                 elif(arg == '-callloop-maxgap'):
6964                         sysvals.callloopmaxga    6922                         sysvals.callloopmaxgap = getArgFloat('-callloop-maxgap', args, 0.0, 1.0)
6965                 elif(arg == '-callloop-maxlen    6923                 elif(arg == '-callloop-maxlen'):
6966                         sysvals.callloopmaxle    6924                         sysvals.callloopmaxlen = getArgFloat('-callloop-maxlen', args, 0.0, 1.0)
6967                 elif(arg == '-cmd'):             6925                 elif(arg == '-cmd'):
6968                         try:                     6926                         try:
6969                                 val = next(ar    6927                                 val = next(args)
6970                         except:                  6928                         except:
6971                                 doError('No c    6929                                 doError('No command string supplied', True)
6972                         sysvals.testcommand =    6930                         sysvals.testcommand = val
6973                         sysvals.suspendmode =    6931                         sysvals.suspendmode = 'command'
6974                 elif(arg == '-expandcg'):        6932                 elif(arg == '-expandcg'):
6975                         sysvals.cgexp = True     6933                         sysvals.cgexp = True
6976                 elif(arg == '-srgap'):           6934                 elif(arg == '-srgap'):
6977                         sysvals.srgap = 5        6935                         sysvals.srgap = 5
6978                 elif(arg == '-maxfail'):         6936                 elif(arg == '-maxfail'):
6979                         sysvals.maxfail = get    6937                         sysvals.maxfail = getArgInt('-maxfail', args, 0, 1000000)
6980                 elif(arg == '-multi'):           6938                 elif(arg == '-multi'):
6981                         try:                     6939                         try:
6982                                 c, d = next(a    6940                                 c, d = next(args), next(args)
6983                         except:                  6941                         except:
6984                                 doError('-mul    6942                                 doError('-multi requires two values', True)
6985                         sysvals.multiinit(c,     6943                         sysvals.multiinit(c, d)
6986                 elif(arg == '-o'):               6944                 elif(arg == '-o'):
6987                         try:                     6945                         try:
6988                                 val = next(ar    6946                                 val = next(args)
6989                         except:                  6947                         except:
6990                                 doError('No s    6948                                 doError('No subdirectory name supplied', True)
6991                         sysvals.outdir = sysv    6949                         sysvals.outdir = sysvals.setOutputFolder(val)
6992                 elif(arg == '-config'):          6950                 elif(arg == '-config'):
6993                         try:                     6951                         try:
6994                                 val = next(ar    6952                                 val = next(args)
6995                         except:                  6953                         except:
6996                                 doError('No t    6954                                 doError('No text file supplied', True)
6997                         file = sysvals.config    6955                         file = sysvals.configFile(val)
6998                         if(not file):            6956                         if(not file):
6999                                 doError('%s d    6957                                 doError('%s does not exist' % val)
7000                         configFromFile(file)     6958                         configFromFile(file)
7001                 elif(arg == '-fadd'):            6959                 elif(arg == '-fadd'):
7002                         try:                     6960                         try:
7003                                 val = next(ar    6961                                 val = next(args)
7004                         except:                  6962                         except:
7005                                 doError('No t    6963                                 doError('No text file supplied', True)
7006                         file = sysvals.config    6964                         file = sysvals.configFile(val)
7007                         if(not file):            6965                         if(not file):
7008                                 doError('%s d    6966                                 doError('%s does not exist' % val)
7009                         sysvals.addFtraceFilt    6967                         sysvals.addFtraceFilterFunctions(file)
7010                 elif(arg == '-dmesg'):           6968                 elif(arg == '-dmesg'):
7011                         try:                     6969                         try:
7012                                 val = next(ar    6970                                 val = next(args)
7013                         except:                  6971                         except:
7014                                 doError('No d    6972                                 doError('No dmesg file supplied', True)
7015                         sysvals.notestrun = T    6973                         sysvals.notestrun = True
7016                         sysvals.dmesgfile = v    6974                         sysvals.dmesgfile = val
7017                         if(os.path.exists(sys    6975                         if(os.path.exists(sysvals.dmesgfile) == False):
7018                                 doError('%s d    6976                                 doError('%s does not exist' % sysvals.dmesgfile)
7019                 elif(arg == '-ftrace'):          6977                 elif(arg == '-ftrace'):
7020                         try:                     6978                         try:
7021                                 val = next(ar    6979                                 val = next(args)
7022                         except:                  6980                         except:
7023                                 doError('No f    6981                                 doError('No ftrace file supplied', True)
7024                         sysvals.notestrun = T    6982                         sysvals.notestrun = True
7025                         sysvals.ftracefile =     6983                         sysvals.ftracefile = val
7026                         if(os.path.exists(sys    6984                         if(os.path.exists(sysvals.ftracefile) == False):
7027                                 doError('%s d    6985                                 doError('%s does not exist' % sysvals.ftracefile)
7028                 elif(arg == '-summary'):         6986                 elif(arg == '-summary'):
7029                         try:                     6987                         try:
7030                                 val = next(ar    6988                                 val = next(args)
7031                         except:                  6989                         except:
7032                                 doError('No d    6990                                 doError('No directory supplied', True)
7033                         cmd = 'summary'          6991                         cmd = 'summary'
7034                         sysvals.outdir = val     6992                         sysvals.outdir = val
7035                         sysvals.notestrun = T    6993                         sysvals.notestrun = True
7036                         if(os.path.isdir(val)    6994                         if(os.path.isdir(val) == False):
7037                                 doError('%s i    6995                                 doError('%s is not accesible' % val)
7038                 elif(arg == '-filter'):          6996                 elif(arg == '-filter'):
7039                         try:                     6997                         try:
7040                                 val = next(ar    6998                                 val = next(args)
7041                         except:                  6999                         except:
7042                                 doError('No d    7000                                 doError('No devnames supplied', True)
7043                         sysvals.setDeviceFilt    7001                         sysvals.setDeviceFilter(val)
7044                 elif(arg == '-result'):          7002                 elif(arg == '-result'):
7045                         try:                     7003                         try:
7046                                 val = next(ar    7004                                 val = next(args)
7047                         except:                  7005                         except:
7048                                 doError('No r    7006                                 doError('No result file supplied', True)
7049                         sysvals.result = val     7007                         sysvals.result = val
7050                         sysvals.signalHandler    7008                         sysvals.signalHandlerInit()
7051                 else:                            7009                 else:
7052                         doError('Invalid argu    7010                         doError('Invalid argument: '+arg, True)
7053                                                  7011 
7054         # compatibility errors                   7012         # compatibility errors
7055         if(sysvals.usecallgraph and sysvals.u    7013         if(sysvals.usecallgraph and sysvals.usedevsrc):
7056                 doError('-dev is not compatib    7014                 doError('-dev is not compatible with -f')
7057         if(sysvals.usecallgraph and sysvals.u    7015         if(sysvals.usecallgraph and sysvals.useprocmon):
7058                 doError('-proc is not compati    7016                 doError('-proc is not compatible with -f')
7059                                                  7017 
7060         if sysvals.usecallgraph and sysvals.c    7018         if sysvals.usecallgraph and sysvals.cgskip:
7061                 sysvals.vprint('Using cgskip     7019                 sysvals.vprint('Using cgskip file: %s' % sysvals.cgskip)
7062                 sysvals.setCallgraphBlacklist    7020                 sysvals.setCallgraphBlacklist(sysvals.cgskip)
7063                                                  7021 
7064         # callgraph size cannot exceed device    7022         # callgraph size cannot exceed device size
7065         if sysvals.mincglen < sysvals.mindevl    7023         if sysvals.mincglen < sysvals.mindevlen:
7066                 sysvals.mincglen = sysvals.mi    7024                 sysvals.mincglen = sysvals.mindevlen
7067                                                  7025 
7068         # remove existing buffers before calc    7026         # remove existing buffers before calculating memory
7069         if(sysvals.usecallgraph or sysvals.us    7027         if(sysvals.usecallgraph or sysvals.usedevsrc):
7070                 sysvals.fsetVal('16', 'buffer    7028                 sysvals.fsetVal('16', 'buffer_size_kb')
7071         sysvals.cpuInfo()                        7029         sysvals.cpuInfo()
7072                                                  7030 
7073         # just run a utility command and exit    7031         # just run a utility command and exit
7074         if(cmd != ''):                           7032         if(cmd != ''):
7075                 ret = 0                          7033                 ret = 0
7076                 if(cmd == 'status'):             7034                 if(cmd == 'status'):
7077                         if not statusCheck(Tr    7035                         if not statusCheck(True):
7078                                 ret = 1          7036                                 ret = 1
7079                 elif(cmd == 'fpdt'):             7037                 elif(cmd == 'fpdt'):
7080                         if not getFPDT(True):    7038                         if not getFPDT(True):
7081                                 ret = 1          7039                                 ret = 1
7082                 elif(cmd == 'sysinfo'):          7040                 elif(cmd == 'sysinfo'):
7083                         sysvals.printSystemIn    7041                         sysvals.printSystemInfo(True)
7084                 elif(cmd == 'devinfo'):          7042                 elif(cmd == 'devinfo'):
7085                         deviceInfo()             7043                         deviceInfo()
7086                 elif(cmd == 'modes'):            7044                 elif(cmd == 'modes'):
7087                         pprint(getModes())       7045                         pprint(getModes())
7088                 elif(cmd == 'flist'):            7046                 elif(cmd == 'flist'):
7089                         sysvals.getFtraceFilt    7047                         sysvals.getFtraceFilterFunctions(True)
7090                 elif(cmd == 'flistall'):         7048                 elif(cmd == 'flistall'):
7091                         sysvals.getFtraceFilt    7049                         sysvals.getFtraceFilterFunctions(False)
7092                 elif(cmd == 'summary'):          7050                 elif(cmd == 'summary'):
7093                         runSummary(sysvals.ou    7051                         runSummary(sysvals.outdir, True, genhtml)
7094                 elif(cmd in ['xon', 'xoff', '    7052                 elif(cmd in ['xon', 'xoff', 'xstandby', 'xsuspend', 'xinit', 'xreset']):
7095                         sysvals.verbose = Tru    7053                         sysvals.verbose = True
7096                         ret = sysvals.display    7054                         ret = sysvals.displayControl(cmd[1:])
7097                 elif(cmd == 'xstat'):            7055                 elif(cmd == 'xstat'):
7098                         pprint('Display Statu    7056                         pprint('Display Status: %s' % sysvals.displayControl('stat').upper())
7099                 elif(cmd == 'wificheck'):        7057                 elif(cmd == 'wificheck'):
7100                         dev = sysvals.checkWi    7058                         dev = sysvals.checkWifi()
7101                         if dev:                  7059                         if dev:
7102                                 print('%s is     7060                                 print('%s is connected' % sysvals.wifiDetails(dev))
7103                         else:                    7061                         else:
7104                                 print('No wif    7062                                 print('No wifi connection found')
7105                 elif(cmd == 'cmdinfo'):          7063                 elif(cmd == 'cmdinfo'):
7106                         for out in sysvals.cm    7064                         for out in sysvals.cmdinfo(False, True):
7107                                 print('[%s -     7065                                 print('[%s - %s]\n%s\n' % out)
7108                 sys.exit(ret)                    7066                 sys.exit(ret)
7109                                                  7067 
7110         # if instructed, re-analyze existing     7068         # if instructed, re-analyze existing data files
7111         if(sysvals.notestrun):                   7069         if(sysvals.notestrun):
7112                 stamp = rerunTest(sysvals.out    7070                 stamp = rerunTest(sysvals.outdir)
7113                 sysvals.outputResult(stamp)      7071                 sysvals.outputResult(stamp)
7114                 sys.exit(0)                      7072                 sys.exit(0)
7115                                                  7073 
7116         # verify that we can run a test          7074         # verify that we can run a test
7117         error = statusCheck()                    7075         error = statusCheck()
7118         if(error):                               7076         if(error):
7119                 doError(error)                   7077                 doError(error)
7120                                                  7078 
7121         # extract mem/disk extra modes and co    7079         # extract mem/disk extra modes and convert
7122         mode = sysvals.suspendmode               7080         mode = sysvals.suspendmode
7123         if mode.startswith('mem'):               7081         if mode.startswith('mem'):
7124                 memmode = mode.split('-', 1)[    7082                 memmode = mode.split('-', 1)[-1] if '-' in mode else 'deep'
7125                 if memmode == 'shallow':         7083                 if memmode == 'shallow':
7126                         mode = 'standby'         7084                         mode = 'standby'
7127                 elif memmode ==  's2idle':       7085                 elif memmode ==  's2idle':
7128                         mode = 'freeze'          7086                         mode = 'freeze'
7129                 else:                            7087                 else:
7130                         mode = 'mem'             7088                         mode = 'mem'
7131                 sysvals.memmode = memmode        7089                 sysvals.memmode = memmode
7132                 sysvals.suspendmode = mode       7090                 sysvals.suspendmode = mode
7133         if mode.startswith('disk-'):             7091         if mode.startswith('disk-'):
7134                 sysvals.diskmode = mode.split    7092                 sysvals.diskmode = mode.split('-', 1)[-1]
7135                 sysvals.suspendmode = 'disk'     7093                 sysvals.suspendmode = 'disk'
7136         sysvals.systemInfo(dmidecode(sysvals.    7094         sysvals.systemInfo(dmidecode(sysvals.mempath))
7137                                                  7095 
7138         failcnt, ret = 0, 0                      7096         failcnt, ret = 0, 0
7139         if sysvals.multitest['run']:             7097         if sysvals.multitest['run']:
7140                 # run multiple tests in a sep    7098                 # run multiple tests in a separate subdirectory
7141                 if not sysvals.outdir:           7099                 if not sysvals.outdir:
7142                         if 'time' in sysvals.    7100                         if 'time' in sysvals.multitest:
7143                                 s = '-%dm' %     7101                                 s = '-%dm' % sysvals.multitest['time']
7144                         else:                    7102                         else:
7145                                 s = '-x%d' %     7103                                 s = '-x%d' % sysvals.multitest['count']
7146                         sysvals.outdir = date    7104                         sysvals.outdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S'+s)
7147                 if not os.path.isdir(sysvals.    7105                 if not os.path.isdir(sysvals.outdir):
7148                         os.makedirs(sysvals.o    7106                         os.makedirs(sysvals.outdir)
7149                 sysvals.sudoUserchown(sysvals    7107                 sysvals.sudoUserchown(sysvals.outdir)
7150                 finish = datetime.now()          7108                 finish = datetime.now()
7151                 if 'time' in sysvals.multites    7109                 if 'time' in sysvals.multitest:
7152                         finish += timedelta(m    7110                         finish += timedelta(minutes=sysvals.multitest['time'])
7153                 for i in range(sysvals.multit    7111                 for i in range(sysvals.multitest['count']):
7154                         sysvals.multistat(Tru    7112                         sysvals.multistat(True, i, finish)
7155                         if i != 0 and sysvals    7113                         if i != 0 and sysvals.multitest['delay'] > 0:
7156                                 pprint('Waiti    7114                                 pprint('Waiting %d seconds...' % (sysvals.multitest['delay']))
7157                                 time.sleep(sy    7115                                 time.sleep(sysvals.multitest['delay'])
7158                         fmt = 'suspend-%y%m%d    7116                         fmt = 'suspend-%y%m%d-%H%M%S'
7159                         sysvals.testdir = os.    7117                         sysvals.testdir = os.path.join(sysvals.outdir, datetime.now().strftime(fmt))
7160                         ret = runTest(i+1, no    7118                         ret = runTest(i+1, not sysvals.verbose)
7161                         failcnt = 0 if not re    7119                         failcnt = 0 if not ret else failcnt + 1
7162                         if sysvals.maxfail >     7120                         if sysvals.maxfail > 0 and failcnt >= sysvals.maxfail:
7163                                 pprint('Maxim    7121                                 pprint('Maximum fail count of %d reached, aborting multitest' % (sysvals.maxfail))
7164                                 break            7122                                 break
7165                         sysvals.resetlog()       7123                         sysvals.resetlog()
7166                         sysvals.multistat(Fal    7124                         sysvals.multistat(False, i, finish)
7167                         if 'time' in sysvals.    7125                         if 'time' in sysvals.multitest and datetime.now() >= finish:
7168                                 break            7126                                 break
7169                 if not sysvals.skiphtml:         7127                 if not sysvals.skiphtml:
7170                         runSummary(sysvals.ou    7128                         runSummary(sysvals.outdir, False, False)
7171                 sysvals.sudoUserchown(sysvals    7129                 sysvals.sudoUserchown(sysvals.outdir)
7172         else:                                    7130         else:
7173                 if sysvals.outdir:               7131                 if sysvals.outdir:
7174                         sysvals.testdir = sys    7132                         sysvals.testdir = sysvals.outdir
7175                 # run the test in the current    7133                 # run the test in the current directory
7176                 ret = runTest()                  7134                 ret = runTest()
7177                                                  7135 
7178         # reset to default values after testi    7136         # reset to default values after testing
7179         if sysvals.display:                      7137         if sysvals.display:
7180                 sysvals.displayControl('reset    7138                 sysvals.displayControl('reset')
7181         if sysvals.rs != 0:                      7139         if sysvals.rs != 0:
7182                 sysvals.setRuntimeSuspend(Fal    7140                 sysvals.setRuntimeSuspend(False)
7183         sys.exit(ret)                            7141         sys.exit(ret)
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php