~ [ 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-5.3.18)


  1 #!/usr/bin/env python3                         !!   1 #!/usr/bin/python2
  2 # SPDX-License-Identifier: GPL-2.0-only             2 # SPDX-License-Identifier: GPL-2.0-only
  3 #                                                   3 #
  4 # Tool for analyzing suspend/resume timing          4 # Tool for analyzing suspend/resume timing
  5 # Copyright (c) 2013, Intel Corporation.            5 # Copyright (c) 2013, Intel Corporation.
  6 #                                                   6 #
  7 # This program is free software; you can redis << 
  8 # under the terms and conditions of the GNU Ge << 
  9 # version 2, as published by the Free Software << 
 10 #                                              << 
 11 # This program is distributed in the hope it w << 
 12 # ANY WARRANTY; without even the implied warra << 
 13 # FITNESS FOR A PARTICULAR PURPOSE.  See the G << 
 14 # more details.                                << 
 15 #                                              << 
 16 # Authors:                                          7 # Authors:
 17 #        Todd Brandt <todd.e.brandt@linux.intel      8 #        Todd Brandt <todd.e.brandt@linux.intel.com>
 18 #                                                   9 #
 19 # Links:                                           10 # Links:
 20 #        Home Page                                 11 #        Home Page
 21 #          https://01.org/pm-graph                 12 #          https://01.org/pm-graph
 22 #        Source repo                               13 #        Source repo
 23 #          git@github.com:intel/pm-graph           14 #          git@github.com:intel/pm-graph
 24 #                                                  15 #
 25 # Description:                                     16 # Description:
 26 #        This tool is designed to assist kerne     17 #        This tool is designed to assist kernel and OS developers in optimizing
 27 #        their linux stack's suspend/resume ti     18 #        their linux stack's suspend/resume time. Using a kernel image built
 28 #        with a few extra options enabled, the     19 #        with a few extra options enabled, the tool will execute a suspend and
 29 #        will capture dmesg and ftrace data un     20 #        will capture dmesg and ftrace data until resume is complete. This data
 30 #        is transformed into a device timeline     21 #        is transformed into a device timeline and a callgraph to give a quick
 31 #        and detailed view of which devices an     22 #        and detailed view of which devices and callbacks are taking the most
 32 #        time in suspend/resume. The output is     23 #        time in suspend/resume. The output is a single html file which can be
 33 #        viewed in firefox or chrome.              24 #        viewed in firefox or chrome.
 34 #                                                  25 #
 35 #        The following kernel build options ar     26 #        The following kernel build options are required:
 36 #                CONFIG_DEVMEM=y                   27 #                CONFIG_DEVMEM=y
 37 #                CONFIG_PM_DEBUG=y                 28 #                CONFIG_PM_DEBUG=y
 38 #                CONFIG_PM_SLEEP_DEBUG=y           29 #                CONFIG_PM_SLEEP_DEBUG=y
 39 #                CONFIG_FTRACE=y                   30 #                CONFIG_FTRACE=y
 40 #                CONFIG_FUNCTION_TRACER=y          31 #                CONFIG_FUNCTION_TRACER=y
 41 #                CONFIG_FUNCTION_GRAPH_TRACER=     32 #                CONFIG_FUNCTION_GRAPH_TRACER=y
 42 #                CONFIG_KPROBES=y                  33 #                CONFIG_KPROBES=y
 43 #                CONFIG_KPROBES_ON_FTRACE=y        34 #                CONFIG_KPROBES_ON_FTRACE=y
 44 #                                                  35 #
 45 #        For kernel versions older than 3.15:      36 #        For kernel versions older than 3.15:
 46 #        The following additional kernel param     37 #        The following additional kernel parameters are required:
 47 #                (e.g. in file /etc/default/gr     38 #                (e.g. in file /etc/default/grub)
 48 #                GRUB_CMDLINE_LINUX_DEFAULT=".     39 #                GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=16M ..."
 49 #                                                  40 #
 50                                                    41 
 51 # ----------------- LIBRARIES ----------------     42 # ----------------- LIBRARIES --------------------
 52                                                    43 
 53 import sys                                         44 import sys
 54 import time                                        45 import time
 55 import os                                          46 import os
 56 import string                                      47 import string
 57 import re                                          48 import re
 58 import platform                                    49 import platform
 59 import signal                                      50 import signal
 60 import codecs                                  !!  51 from datetime import datetime
 61 from datetime import datetime, timedelta       << 
 62 import struct                                      52 import struct
 63 import configparser                            !!  53 import ConfigParser
 64 import gzip                                        54 import gzip
 65 from threading import Thread                       55 from threading import Thread
 66 from subprocess import call, Popen, PIPE           56 from subprocess import call, Popen, PIPE
 67 import base64                                      57 import base64
 68                                                    58 
 69 debugtiming = False                            << 
 70 mystarttime = time.time()                      << 
 71 def pprint(msg):                                   59 def pprint(msg):
 72         if debugtiming:                        !!  60         print(msg)
 73                 print('[%09.3f] %s' % (time.ti << 
 74         else:                                  << 
 75                 print(msg)                     << 
 76         sys.stdout.flush()                         61         sys.stdout.flush()
 77                                                    62 
 78 def ascii(text):                               << 
 79         return text.decode('ascii', 'ignore')  << 
 80                                                << 
 81 # ----------------- CLASSES ------------------     63 # ----------------- CLASSES --------------------
 82                                                    64 
 83 # Class: SystemValues                              65 # Class: SystemValues
 84 # Description:                                     66 # Description:
 85 #        A global, single-instance container u     67 #        A global, single-instance container used to
 86 #        store system values and test paramete     68 #        store system values and test parameters
 87 class SystemValues:                                69 class SystemValues:
 88         title = 'SleepGraph'                       70         title = 'SleepGraph'
 89         version = '5.12'                       !!  71         version = '5.4'
 90         ansi = False                               72         ansi = False
 91         rs = 0                                     73         rs = 0
 92         display = ''                               74         display = ''
 93         gzip = False                               75         gzip = False
 94         sync = False                               76         sync = False
 95         wifi = False                           << 
 96         netfix = False                         << 
 97         verbose = False                            77         verbose = False
 98         testlog = True                             78         testlog = True
 99         dmesglog = True                            79         dmesglog = True
100         ftracelog = False                          80         ftracelog = False
101         acpidebug = True                       !!  81         tstat = False
102         tstat = True                           !!  82         mindevlen = 0.0
103         wifitrace = False                      << 
104         mindevlen = 0.0001                     << 
105         mincglen = 0.0                             83         mincglen = 0.0
106         cgphase = ''                               84         cgphase = ''
107         cgtest = -1                                85         cgtest = -1
108         cgskip = ''                                86         cgskip = ''
109         maxfail = 0                            !!  87         multitest = {'run': False, 'count': 0, 'delay': 0}
110         multitest = {'run': False, 'count': 10 << 
111         max_graph_depth = 0                        88         max_graph_depth = 0
112         callloopmaxgap = 0.0001                    89         callloopmaxgap = 0.0001
113         callloopmaxlen = 0.005                     90         callloopmaxlen = 0.005
114         bufsize = 0                                91         bufsize = 0
115         cpucount = 0                               92         cpucount = 0
116         memtotal = 204800                          93         memtotal = 204800
117         memfree = 204800                           94         memfree = 204800
118         osversion = ''                         << 
119         srgap = 0                                  95         srgap = 0
120         cgexp = False                              96         cgexp = False
121         testdir = ''                               97         testdir = ''
122         outdir = ''                                98         outdir = ''
123         tpath = '/sys/kernel/tracing/'         !!  99         tpath = '/sys/kernel/debug/tracing/'
124         fpdtpath = '/sys/firmware/acpi/tables/    100         fpdtpath = '/sys/firmware/acpi/tables/FPDT'
125         epath = '/sys/kernel/tracing/events/po !! 101         epath = '/sys/kernel/debug/tracing/events/power/'
126         pmdpath = '/sys/power/pm_debug_message    102         pmdpath = '/sys/power/pm_debug_messages'
127         s0ixpath = '/sys/module/intel_pmc_core << 
128         s0ixres = '/sys/devices/system/cpu/cpu << 
129         acpipath='/sys/module/acpi/parameters/ << 
130         traceevents = [                           103         traceevents = [
131                 'suspend_resume',                 104                 'suspend_resume',
132                 'wakeup_source_activate',         105                 'wakeup_source_activate',
133                 'wakeup_source_deactivate',       106                 'wakeup_source_deactivate',
134                 'device_pm_callback_end',         107                 'device_pm_callback_end',
135                 'device_pm_callback_start'        108                 'device_pm_callback_start'
136         ]                                         109         ]
137         logmsg = ''                               110         logmsg = ''
138         testcommand = ''                          111         testcommand = ''
139         mempath = '/dev/mem'                      112         mempath = '/dev/mem'
140         powerfile = '/sys/power/state'            113         powerfile = '/sys/power/state'
141         mempowerfile = '/sys/power/mem_sleep'     114         mempowerfile = '/sys/power/mem_sleep'
142         diskpowerfile = '/sys/power/disk'         115         diskpowerfile = '/sys/power/disk'
143         suspendmode = 'mem'                       116         suspendmode = 'mem'
144         memmode = ''                              117         memmode = ''
145         diskmode = ''                             118         diskmode = ''
146         hostname = 'localhost'                    119         hostname = 'localhost'
147         prefix = 'test'                           120         prefix = 'test'
148         teststamp = ''                            121         teststamp = ''
149         sysstamp = ''                             122         sysstamp = ''
150         dmesgstart = 0.0                          123         dmesgstart = 0.0
151         dmesgfile = ''                            124         dmesgfile = ''
152         ftracefile = ''                           125         ftracefile = ''
153         htmlfile = 'output.html'                  126         htmlfile = 'output.html'
154         result = ''                               127         result = ''
155         rtcwake = True                            128         rtcwake = True
156         rtcwaketime = 15                          129         rtcwaketime = 15
157         rtcpath = ''                              130         rtcpath = ''
158         devicefilter = []                         131         devicefilter = []
159         cgfilter = []                             132         cgfilter = []
160         stamp = 0                                 133         stamp = 0
161         execcount = 1                             134         execcount = 1
162         x2delay = 0                               135         x2delay = 0
163         skiphtml = False                          136         skiphtml = False
164         usecallgraph = False                      137         usecallgraph = False
165         ftopfunc = 'pm_suspend'                !! 138         ftopfunc = 'suspend_devices_and_enter'
166         ftop = False                              139         ftop = False
167         usetraceevents = False                    140         usetraceevents = False
168         usetracemarkers = True                    141         usetracemarkers = True
169         useftrace = True                       << 
170         usekprobes = True                         142         usekprobes = True
171         usedevsrc = False                         143         usedevsrc = False
172         useprocmon = False                        144         useprocmon = False
173         notestrun = False                         145         notestrun = False
174         cgdump = False                            146         cgdump = False
175         devdump = False                           147         devdump = False
176         mixedphaseheight = True                   148         mixedphaseheight = True
177         devprops = dict()                         149         devprops = dict()
178         cfgdef = dict()                        << 
179         platinfo = []                          << 
180         predelay = 0                              150         predelay = 0
181         postdelay = 0                             151         postdelay = 0
182         tmstart = 'SUSPEND START %Y%m%d-%H:%M: !! 152         pmdebug = ''
183         tmend = 'RESUME COMPLETE %Y%m%d-%H:%M: << 
184         tracefuncs = {                            153         tracefuncs = {
185                 'async_synchronize_full': {},  << 
186                 'sys_sync': {},                   154                 'sys_sync': {},
187                 'ksys_sync': {},                  155                 'ksys_sync': {},
188                 '__pm_notifier_call_chain': {}    156                 '__pm_notifier_call_chain': {},
189                 'pm_prepare_console': {},         157                 'pm_prepare_console': {},
190                 'pm_notifier_call_chain': {},     158                 'pm_notifier_call_chain': {},
191                 'freeze_processes': {},           159                 'freeze_processes': {},
192                 'freeze_kernel_threads': {},      160                 'freeze_kernel_threads': {},
193                 'pm_restrict_gfp_mask': {},       161                 'pm_restrict_gfp_mask': {},
194                 'acpi_suspend_begin': {},         162                 'acpi_suspend_begin': {},
195                 'acpi_hibernation_begin': {},     163                 'acpi_hibernation_begin': {},
196                 'acpi_hibernation_enter': {},     164                 'acpi_hibernation_enter': {},
197                 'acpi_hibernation_leave': {},     165                 'acpi_hibernation_leave': {},
198                 'acpi_pm_freeze': {},             166                 'acpi_pm_freeze': {},
199                 'acpi_pm_thaw': {},               167                 'acpi_pm_thaw': {},
200                 'acpi_s2idle_end': {},            168                 'acpi_s2idle_end': {},
201                 'acpi_s2idle_sync': {},           169                 'acpi_s2idle_sync': {},
202                 'acpi_s2idle_begin': {},          170                 'acpi_s2idle_begin': {},
203                 'acpi_s2idle_prepare': {},        171                 'acpi_s2idle_prepare': {},
204                 'acpi_s2idle_prepare_late': {} << 
205                 'acpi_s2idle_wake': {},           172                 'acpi_s2idle_wake': {},
206                 'acpi_s2idle_wakeup': {},         173                 'acpi_s2idle_wakeup': {},
207                 'acpi_s2idle_restore': {},        174                 'acpi_s2idle_restore': {},
208                 'acpi_s2idle_restore_early': { << 
209                 'hibernate_preallocate_memory'    175                 'hibernate_preallocate_memory': {},
210                 'create_basic_memory_bitmaps':    176                 'create_basic_memory_bitmaps': {},
211                 'swsusp_write': {},               177                 'swsusp_write': {},
212                 'suspend_console': {},            178                 'suspend_console': {},
213                 'acpi_pm_prepare': {},            179                 'acpi_pm_prepare': {},
214                 'syscore_suspend': {},            180                 'syscore_suspend': {},
215                 'arch_enable_nonboot_cpus_end'    181                 'arch_enable_nonboot_cpus_end': {},
216                 'syscore_resume': {},             182                 'syscore_resume': {},
217                 'acpi_pm_finish': {},             183                 'acpi_pm_finish': {},
218                 'resume_console': {},             184                 'resume_console': {},
219                 'acpi_pm_end': {},                185                 'acpi_pm_end': {},
220                 'pm_restore_gfp_mask': {},        186                 'pm_restore_gfp_mask': {},
221                 'thaw_processes': {},             187                 'thaw_processes': {},
222                 'pm_restore_console': {},         188                 'pm_restore_console': {},
223                 'CPU_OFF': {                      189                 'CPU_OFF': {
224                         'func':'_cpu_down',       190                         'func':'_cpu_down',
225                         'args_x86_64': {'cpu':    191                         'args_x86_64': {'cpu':'%di:s32'},
226                         'format': 'CPU_OFF[{cp    192                         'format': 'CPU_OFF[{cpu}]'
227                 },                                193                 },
228                 'CPU_ON': {                       194                 'CPU_ON': {
229                         'func':'_cpu_up',         195                         'func':'_cpu_up',
230                         'args_x86_64': {'cpu':    196                         'args_x86_64': {'cpu':'%di:s32'},
231                         'format': 'CPU_ON[{cpu    197                         'format': 'CPU_ON[{cpu}]'
232                 },                                198                 },
233         }                                         199         }
234         dev_tracefuncs = {                        200         dev_tracefuncs = {
235                 # general wait/delay/sleep        201                 # general wait/delay/sleep
236                 'msleep': { 'args_x86_64': {'t    202                 'msleep': { 'args_x86_64': {'time':'%di:s32'}, 'ub': 1 },
237                 'schedule_timeout': { 'args_x8    203                 'schedule_timeout': { 'args_x86_64': {'timeout':'%di:s32'}, 'ub': 1 },
238                 'udelay': { 'func':'__const_ud    204                 'udelay': { 'func':'__const_udelay', 'args_x86_64': {'loops':'%di:s32'}, 'ub': 1 },
239                 'usleep_range': { 'args_x86_64    205                 'usleep_range': { 'args_x86_64': {'min':'%di:s32', 'max':'%si:s32'}, 'ub': 1 },
240                 'mutex_lock_slowpath': { 'func    206                 'mutex_lock_slowpath': { 'func':'__mutex_lock_slowpath', 'ub': 1 },
241                 'acpi_os_stall': {'ub': 1},       207                 'acpi_os_stall': {'ub': 1},
242                 'rt_mutex_slowlock': {'ub': 1}    208                 'rt_mutex_slowlock': {'ub': 1},
243                 # ACPI                            209                 # ACPI
244                 'acpi_resume_power_resources':    210                 'acpi_resume_power_resources': {},
245                 'acpi_ps_execute_method': { 'a    211                 'acpi_ps_execute_method': { 'args_x86_64': {
246                         'fullpath':'+0(+40(%di    212                         'fullpath':'+0(+40(%di)):string',
247                 }},                               213                 }},
248                 # mei_me                          214                 # mei_me
249                 'mei_reset': {},                  215                 'mei_reset': {},
250                 # filesystem                      216                 # filesystem
251                 'ext4_sync_fs': {},               217                 'ext4_sync_fs': {},
252                 # 80211                           218                 # 80211
253                 'ath10k_bmi_read_memory': { 'a    219                 'ath10k_bmi_read_memory': { 'args_x86_64': {'length':'%cx:s32'} },
254                 'ath10k_bmi_write_memory': { '    220                 'ath10k_bmi_write_memory': { 'args_x86_64': {'length':'%cx:s32'} },
255                 'ath10k_bmi_fast_download': {     221                 'ath10k_bmi_fast_download': { 'args_x86_64': {'length':'%cx:s32'} },
256                 'iwlagn_mac_start': {},           222                 'iwlagn_mac_start': {},
257                 'iwlagn_alloc_bcast_station':     223                 'iwlagn_alloc_bcast_station': {},
258                 'iwl_trans_pcie_start_hw': {},    224                 'iwl_trans_pcie_start_hw': {},
259                 'iwl_trans_pcie_start_fw': {},    225                 'iwl_trans_pcie_start_fw': {},
260                 'iwl_run_init_ucode': {},         226                 'iwl_run_init_ucode': {},
261                 'iwl_load_ucode_wait_alive': {    227                 'iwl_load_ucode_wait_alive': {},
262                 'iwl_alive_start': {},            228                 'iwl_alive_start': {},
263                 'iwlagn_mac_stop': {},            229                 'iwlagn_mac_stop': {},
264                 'iwlagn_mac_suspend': {},         230                 'iwlagn_mac_suspend': {},
265                 'iwlagn_mac_resume': {},          231                 'iwlagn_mac_resume': {},
266                 'iwlagn_mac_add_interface': {}    232                 'iwlagn_mac_add_interface': {},
267                 'iwlagn_mac_remove_interface':    233                 'iwlagn_mac_remove_interface': {},
268                 'iwlagn_mac_change_interface':    234                 'iwlagn_mac_change_interface': {},
269                 'iwlagn_mac_config': {},          235                 'iwlagn_mac_config': {},
270                 'iwlagn_configure_filter': {},    236                 'iwlagn_configure_filter': {},
271                 'iwlagn_mac_hw_scan': {},         237                 'iwlagn_mac_hw_scan': {},
272                 'iwlagn_bss_info_changed': {},    238                 'iwlagn_bss_info_changed': {},
273                 'iwlagn_mac_channel_switch': {    239                 'iwlagn_mac_channel_switch': {},
274                 'iwlagn_mac_flush': {},           240                 'iwlagn_mac_flush': {},
275                 # ATA                             241                 # ATA
276                 'ata_eh_recover': { 'args_x86_    242                 'ata_eh_recover': { 'args_x86_64': {'port':'+36(%di):s32'} },
277                 # i915                            243                 # i915
278                 'i915_gem_resume': {},            244                 'i915_gem_resume': {},
279                 'i915_restore_state': {},         245                 'i915_restore_state': {},
280                 'intel_opregion_setup': {},       246                 'intel_opregion_setup': {},
281                 'g4x_pre_enable_dp': {},          247                 'g4x_pre_enable_dp': {},
282                 'vlv_pre_enable_dp': {},          248                 'vlv_pre_enable_dp': {},
283                 'chv_pre_enable_dp': {},          249                 'chv_pre_enable_dp': {},
284                 'g4x_enable_dp': {},              250                 'g4x_enable_dp': {},
285                 'vlv_enable_dp': {},              251                 'vlv_enable_dp': {},
286                 'intel_hpd_init': {},             252                 'intel_hpd_init': {},
287                 'intel_opregion_register': {},    253                 'intel_opregion_register': {},
288                 'intel_dp_detect': {},            254                 'intel_dp_detect': {},
289                 'intel_hdmi_detect': {},          255                 'intel_hdmi_detect': {},
290                 'intel_opregion_init': {},        256                 'intel_opregion_init': {},
291                 'intel_fbdev_set_suspend': {},    257                 'intel_fbdev_set_suspend': {},
292         }                                         258         }
293         infocmds = [                           << 
294                 [0, 'sysinfo', 'uname', '-a'], << 
295                 [0, 'cpuinfo', 'head', '-7', ' << 
296                 [0, 'kparams', 'cat', '/proc/c << 
297                 [0, 'mcelog', 'mcelog'],       << 
298                 [0, 'pcidevices', 'lspci', '-t << 
299                 [0, 'usbdevices', 'lsusb', '-t << 
300                 [0, 'acpidevices', 'sh', '-c', << 
301                 [0, 's0ix_require', 'cat', '/s << 
302                 [0, 's0ix_debug', 'cat', '/sys << 
303                 [0, 'ethtool', 'ethtool', '{et << 
304                 [1, 's0ix_residency', 'cat', ' << 
305                 [1, 'interrupts', 'cat', '/pro << 
306                 [1, 'wakeups', 'cat', '/sys/ke << 
307                 [2, 'gpecounts', 'sh', '-c', ' << 
308                 [2, 'suspendstats', 'sh', '-c' << 
309                 [2, 'cpuidle', 'sh', '-c', 'gr << 
310                 [2, 'battery', 'sh', '-c', 'gr << 
311                 [2, 'thermal', 'sh', '-c', 'gr << 
312         ]                                      << 
313         cgblacklist = []                          259         cgblacklist = []
314         kprobes = dict()                          260         kprobes = dict()
315         timeformat = '%.3f'                       261         timeformat = '%.3f'
316         cmdline = '%s %s' % \                     262         cmdline = '%s %s' % \
317                         (os.path.basename(sys.    263                         (os.path.basename(sys.argv[0]), ' '.join(sys.argv[1:]))
                                                   >> 264         kparams = ''
318         sudouser = ''                             265         sudouser = ''
319         def __init__(self):                       266         def __init__(self):
320                 self.archargs = 'args_'+platfo    267                 self.archargs = 'args_'+platform.machine()
321                 self.hostname = platform.node(    268                 self.hostname = platform.node()
322                 if(self.hostname == ''):          269                 if(self.hostname == ''):
323                         self.hostname = 'local    270                         self.hostname = 'localhost'
324                 rtc = "rtc0"                      271                 rtc = "rtc0"
325                 if os.path.exists('/dev/rtc'):    272                 if os.path.exists('/dev/rtc'):
326                         rtc = os.readlink('/de    273                         rtc = os.readlink('/dev/rtc')
327                 rtc = '/sys/class/rtc/'+rtc       274                 rtc = '/sys/class/rtc/'+rtc
328                 if os.path.exists(rtc) and os.    275                 if os.path.exists(rtc) and os.path.exists(rtc+'/date') and \
329                         os.path.exists(rtc+'/t    276                         os.path.exists(rtc+'/time') and os.path.exists(rtc+'/wakealarm'):
330                         self.rtcpath = rtc        277                         self.rtcpath = rtc
331                 if (hasattr(sys.stdout, 'isatt    278                 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()):
332                         self.ansi = True          279                         self.ansi = True
333                 self.testdir = datetime.now().    280                 self.testdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S')
334                 if os.getuid() == 0 and 'SUDO_    281                 if os.getuid() == 0 and 'SUDO_USER' in os.environ and \
335                         os.environ['SUDO_USER'    282                         os.environ['SUDO_USER']:
336                         self.sudouser = os.env    283                         self.sudouser = os.environ['SUDO_USER']
337         def resetlog(self):                    << 
338                 self.logmsg = ''               << 
339                 self.platinfo = []             << 
340         def vprint(self, msg):                    284         def vprint(self, msg):
341                 self.logmsg += msg+'\n'           285                 self.logmsg += msg+'\n'
342                 if self.verbose or msg.startsw    286                 if self.verbose or msg.startswith('WARNING:'):
343                         pprint(msg)               287                         pprint(msg)
344         def signalHandler(self, signum, frame)    288         def signalHandler(self, signum, frame):
345                 if not self.result:               289                 if not self.result:
346                         return                    290                         return
347                 signame = self.signames[signum    291                 signame = self.signames[signum] if signum in self.signames else 'UNKNOWN'
348                 msg = 'Signal %s caused a tool    292                 msg = 'Signal %s caused a tool exit, line %d' % (signame, frame.f_lineno)
349                 self.outputResult({'error':msg !! 293                 sysvals.outputResult({'error':msg})
350                 sys.exit(3)                       294                 sys.exit(3)
351         def signalHandlerInit(self):              295         def signalHandlerInit(self):
352                 capture = ['BUS', 'SYS', 'XCPU    296                 capture = ['BUS', 'SYS', 'XCPU', 'XFSZ', 'PWR', 'HUP', 'INT', 'QUIT',
353                         'ILL', 'ABRT', 'FPE',  !! 297                         'ILL', 'ABRT', 'FPE', 'SEGV', 'TERM', 'TSTP']
354                 self.signames = dict()            298                 self.signames = dict()
355                 for i in capture:                 299                 for i in capture:
356                         s = 'SIG'+i               300                         s = 'SIG'+i
357                         try:                      301                         try:
358                                 signum = getat    302                                 signum = getattr(signal, s)
359                                 signal.signal(    303                                 signal.signal(signum, self.signalHandler)
360                         except:                   304                         except:
361                                 continue          305                                 continue
362                         self.signames[signum]     306                         self.signames[signum] = s
363         def rootCheck(self, fatal=True):          307         def rootCheck(self, fatal=True):
364                 if(os.access(self.powerfile, o    308                 if(os.access(self.powerfile, os.W_OK)):
365                         return True               309                         return True
366                 if fatal:                         310                 if fatal:
367                         msg = 'This command re    311                         msg = 'This command requires sysfs mount and root access'
368                         pprint('ERROR: %s\n' %    312                         pprint('ERROR: %s\n' % msg)
369                         self.outputResult({'er    313                         self.outputResult({'error':msg})
370                         sys.exit(1)               314                         sys.exit(1)
371                 return False                      315                 return False
372         def rootUser(self, fatal=False):          316         def rootUser(self, fatal=False):
373                 if 'USER' in os.environ and os    317                 if 'USER' in os.environ and os.environ['USER'] == 'root':
374                         return True               318                         return True
375                 if fatal:                         319                 if fatal:
376                         msg = 'This command mu    320                         msg = 'This command must be run as root'
377                         pprint('ERROR: %s\n' %    321                         pprint('ERROR: %s\n' % msg)
378                         self.outputResult({'er    322                         self.outputResult({'error':msg})
379                         sys.exit(1)               323                         sys.exit(1)
380                 return False                      324                 return False
381         def usable(self, file, ishtml=False):  << 
382                 if not os.path.exists(file) or << 
383                         return False           << 
384                 if ishtml:                     << 
385                         try:                   << 
386                                 fp = open(file << 
387                                 res = fp.read( << 
388                                 fp.close()     << 
389                         except:                << 
390                                 return False   << 
391                         if '<html>' not in res << 
392                                 return False   << 
393                 return True                    << 
394         def getExec(self, cmd):                   325         def getExec(self, cmd):
395                 try:                           !! 326                 dirlist = ['/sbin', '/bin', '/usr/sbin', '/usr/bin',
396                         fp = Popen(['which', c !! 327                         '/usr/local/sbin', '/usr/local/bin']
397                         out = ascii(fp.read()) !! 328                 for path in dirlist:
398                         fp.close()             << 
399                 except:                        << 
400                         out = ''               << 
401                 if out:                        << 
402                         return out             << 
403                 for path in ['/sbin', '/bin',  << 
404                         '/usr/local/sbin', '/u << 
405                         cmdfull = os.path.join    329                         cmdfull = os.path.join(path, cmd)
406                         if os.path.exists(cmdf    330                         if os.path.exists(cmdfull):
407                                 return cmdfull    331                                 return cmdfull
408                 return out                     !! 332                 return ''
409         def setPrecision(self, num):              333         def setPrecision(self, num):
410                 if num < 0 or num > 6:            334                 if num < 0 or num > 6:
411                         return                    335                         return
412                 self.timeformat = '%.{0}f'.for    336                 self.timeformat = '%.{0}f'.format(num)
413         def setOutputFolder(self, value):         337         def setOutputFolder(self, value):
414                 args = dict()                     338                 args = dict()
415                 n = datetime.now()                339                 n = datetime.now()
416                 args['date'] = n.strftime('%y%    340                 args['date'] = n.strftime('%y%m%d')
417                 args['time'] = n.strftime('%H%    341                 args['time'] = n.strftime('%H%M%S')
418                 args['hostname'] = args['host'    342                 args['hostname'] = args['host'] = self.hostname
419                 args['mode'] = self.suspendmod    343                 args['mode'] = self.suspendmode
420                 return value.format(**args)       344                 return value.format(**args)
421         def setOutputFile(self):                  345         def setOutputFile(self):
422                 if self.dmesgfile != '':          346                 if self.dmesgfile != '':
423                         m = re.match(r'(?P<nam !! 347                         m = re.match('(?P<name>.*)_dmesg\.txt.*', self.dmesgfile)
424                         if(m):                    348                         if(m):
425                                 self.htmlfile     349                                 self.htmlfile = m.group('name')+'.html'
426                 if self.ftracefile != '':         350                 if self.ftracefile != '':
427                         m = re.match(r'(?P<nam !! 351                         m = re.match('(?P<name>.*)_ftrace\.txt.*', self.ftracefile)
428                         if(m):                    352                         if(m):
429                                 self.htmlfile     353                                 self.htmlfile = m.group('name')+'.html'
430         def systemInfo(self, info):               354         def systemInfo(self, info):
431                 p = m = ''                        355                 p = m = ''
432                 if 'baseboard-manufacturer' in    356                 if 'baseboard-manufacturer' in info:
433                         m = info['baseboard-ma    357                         m = info['baseboard-manufacturer']
434                 elif 'system-manufacturer' in     358                 elif 'system-manufacturer' in info:
435                         m = info['system-manuf    359                         m = info['system-manufacturer']
436                 if 'system-product-name' in in    360                 if 'system-product-name' in info:
437                         p = info['system-produ    361                         p = info['system-product-name']
438                 elif 'baseboard-product-name'     362                 elif 'baseboard-product-name' in info:
439                         p = info['baseboard-pr    363                         p = info['baseboard-product-name']
440                 if m[:5].lower() == 'intel' an    364                 if m[:5].lower() == 'intel' and 'baseboard-product-name' in info:
441                         p = info['baseboard-pr    365                         p = info['baseboard-product-name']
442                 c = info['processor-version']     366                 c = info['processor-version'] if 'processor-version' in info else ''
443                 b = info['bios-version'] if 'b    367                 b = info['bios-version'] if 'bios-version' in info else ''
444                 r = info['bios-release-date']     368                 r = info['bios-release-date'] if 'bios-release-date' in info else ''
445                 self.sysstamp = '# sysinfo | m    369                 self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | biosdate:%s | numcpu:%d | memsz:%d | memfr:%d' % \
446                         (m, p, c, b, r, self.c    370                         (m, p, c, b, r, self.cpucount, self.memtotal, self.memfree)
447                 if self.osversion:             !! 371                 try:
448                         self.sysstamp += ' | o !! 372                         kcmd = open('/proc/cmdline', 'r').read().strip()
                                                   >> 373                 except:
                                                   >> 374                         kcmd = ''
                                                   >> 375                 if kcmd:
                                                   >> 376                         self.sysstamp += '\n# kparams | %s' % kcmd
449         def printSystemInfo(self, fatal=False)    377         def printSystemInfo(self, fatal=False):
450                 self.rootCheck(True)              378                 self.rootCheck(True)
451                 out = dmidecode(self.mempath,     379                 out = dmidecode(self.mempath, fatal)
452                 if len(out) < 1:                  380                 if len(out) < 1:
453                         return                    381                         return
454                 fmt = '%-24s: %s'                 382                 fmt = '%-24s: %s'
455                 if self.osversion:             << 
456                         print(fmt % ('os-versi << 
457                 for name in sorted(out):          383                 for name in sorted(out):
458                         print(fmt % (name, out    384                         print(fmt % (name, out[name]))
459                 print(fmt % ('cpucount', ('%d'    385                 print(fmt % ('cpucount', ('%d' % self.cpucount)))
460                 print(fmt % ('memtotal', ('%d     386                 print(fmt % ('memtotal', ('%d kB' % self.memtotal)))
461                 print(fmt % ('memfree', ('%d k    387                 print(fmt % ('memfree', ('%d kB' % self.memfree)))
462         def cpuInfo(self):                        388         def cpuInfo(self):
463                 self.cpucount = 0                 389                 self.cpucount = 0
464                 if os.path.exists('/proc/cpuin !! 390                 fp = open('/proc/cpuinfo', 'r')
465                         with open('/proc/cpuin !! 391                 for line in fp:
466                                 for line in fp !! 392                         if re.match('^processor[ \t]*:[ \t]*[0-9]*', line):
467                                         if re. !! 393                                 self.cpucount += 1
468                                                !! 394                 fp.close()
469                 if os.path.exists('/proc/memin !! 395                 fp = open('/proc/meminfo', 'r')
470                         with open('/proc/memin !! 396                 for line in fp:
471                                 for line in fp !! 397                         m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line)
472                                         m = re !! 398                         if m:
473                                         if m:  !! 399                                 self.memtotal = int(m.group('sz'))
474                                                !! 400                         m = re.match('^MemFree:[ \t]*(?P<sz>[0-9]*) *kB', line)
475                                         m = re !! 401                         if m:
476                                         if m:  !! 402                                 self.memfree = int(m.group('sz'))
477                                                !! 403                 fp.close()
478                 if os.path.exists('/etc/os-rel << 
479                         with open('/etc/os-rel << 
480                                 for line in fp << 
481                                         if lin << 
482                                                << 
483         def initTestOutput(self, name):           404         def initTestOutput(self, name):
484                 self.prefix = self.hostname       405                 self.prefix = self.hostname
485                 v = open('/proc/version', 'r')    406                 v = open('/proc/version', 'r').read().strip()
486                 kver = v.split()[2]               407                 kver = v.split()[2]
487                 fmt = name+'-%m%d%y-%H%M%S'       408                 fmt = name+'-%m%d%y-%H%M%S'
488                 testtime = datetime.now().strf    409                 testtime = datetime.now().strftime(fmt)
489                 self.teststamp = \                410                 self.teststamp = \
490                         '# '+testtime+' '+self    411                         '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver
491                 ext = ''                          412                 ext = ''
492                 if self.gzip:                     413                 if self.gzip:
493                         ext = '.gz'               414                         ext = '.gz'
494                 self.dmesgfile = \                415                 self.dmesgfile = \
495                         self.testdir+'/'+self.    416                         self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt'+ext
496                 self.ftracefile = \               417                 self.ftracefile = \
497                         self.testdir+'/'+self.    418                         self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt'+ext
498                 self.htmlfile = \                 419                 self.htmlfile = \
499                         self.testdir+'/'+self.    420                         self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html'
500                 if not os.path.isdir(self.test    421                 if not os.path.isdir(self.testdir):
501                         os.makedirs(self.testd    422                         os.makedirs(self.testdir)
502                 self.sudoUserchown(self.testdi << 
503         def getValueList(self, value):            423         def getValueList(self, value):
504                 out = []                          424                 out = []
505                 for i in value.split(','):        425                 for i in value.split(','):
506                         if i.strip():             426                         if i.strip():
507                                 out.append(i.s    427                                 out.append(i.strip())
508                 return out                        428                 return out
509         def setDeviceFilter(self, value):         429         def setDeviceFilter(self, value):
510                 self.devicefilter = self.getVa    430                 self.devicefilter = self.getValueList(value)
511         def setCallgraphFilter(self, value):      431         def setCallgraphFilter(self, value):
512                 self.cgfilter = self.getValueL    432                 self.cgfilter = self.getValueList(value)
513         def skipKprobes(self, value):             433         def skipKprobes(self, value):
514                 for k in self.getValueList(val    434                 for k in self.getValueList(value):
515                         if k in self.tracefunc    435                         if k in self.tracefuncs:
516                                 del self.trace    436                                 del self.tracefuncs[k]
517                         if k in self.dev_trace    437                         if k in self.dev_tracefuncs:
518                                 del self.dev_t    438                                 del self.dev_tracefuncs[k]
519         def setCallgraphBlacklist(self, file):    439         def setCallgraphBlacklist(self, file):
520                 self.cgblacklist = self.listFr    440                 self.cgblacklist = self.listFromFile(file)
521         def rtcWakeAlarmOn(self):                 441         def rtcWakeAlarmOn(self):
522                 call('echo 0 > '+self.rtcpath+    442                 call('echo 0 > '+self.rtcpath+'/wakealarm', shell=True)
523                 nowtime = open(self.rtcpath+'/    443                 nowtime = open(self.rtcpath+'/since_epoch', 'r').read().strip()
524                 if nowtime:                       444                 if nowtime:
525                         nowtime = int(nowtime)    445                         nowtime = int(nowtime)
526                 else:                             446                 else:
527                         # if hardware time fai    447                         # if hardware time fails, use the software time
528                         nowtime = int(datetime    448                         nowtime = int(datetime.now().strftime('%s'))
529                 alarm = nowtime + self.rtcwake    449                 alarm = nowtime + self.rtcwaketime
530                 call('echo %d > %s/wakealarm'     450                 call('echo %d > %s/wakealarm' % (alarm, self.rtcpath), shell=True)
531         def rtcWakeAlarmOff(self):                451         def rtcWakeAlarmOff(self):
532                 call('echo 0 > %s/wakealarm' %    452                 call('echo 0 > %s/wakealarm' % self.rtcpath, shell=True)
533         def initdmesg(self):                      453         def initdmesg(self):
534                 # get the latest time stamp fr    454                 # get the latest time stamp from the dmesg log
535                 lines = Popen('dmesg', stdout= !! 455                 fp = Popen('dmesg', stdout=PIPE).stdout
536                 ktime = '0'                       456                 ktime = '0'
537                 for line in reversed(lines):   !! 457                 for line in fp:
538                         line = ascii(line).rep !! 458                         line = line.replace('\r\n', '')
539                         idx = line.find('[')      459                         idx = line.find('[')
540                         if idx > 1:               460                         if idx > 1:
541                                 line = line[id    461                                 line = line[idx:]
542                         m = re.match(r'[ \t]*( !! 462                         m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
543                         if(m):                    463                         if(m):
544                                 ktime = m.grou    464                                 ktime = m.group('ktime')
545                                 break          !! 465                 fp.close()
546                 self.dmesgstart = float(ktime)    466                 self.dmesgstart = float(ktime)
547         def getdmesg(self, testdata):             467         def getdmesg(self, testdata):
548                 op = self.writeDatafileHeader( !! 468                 op = self.writeDatafileHeader(sysvals.dmesgfile, testdata)
549                 # store all new dmesg lines si    469                 # store all new dmesg lines since initdmesg was called
550                 fp = Popen('dmesg', stdout=PIP    470                 fp = Popen('dmesg', stdout=PIPE).stdout
551                 for line in fp:                   471                 for line in fp:
552                         line = ascii(line).rep !! 472                         line = line.replace('\r\n', '')
553                         idx = line.find('[')      473                         idx = line.find('[')
554                         if idx > 1:               474                         if idx > 1:
555                                 line = line[id    475                                 line = line[idx:]
556                         m = re.match(r'[ \t]*( !! 476                         m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
557                         if(not m):                477                         if(not m):
558                                 continue          478                                 continue
559                         ktime = float(m.group(    479                         ktime = float(m.group('ktime'))
560                         if ktime > self.dmesgs    480                         if ktime > self.dmesgstart:
561                                 op.write(line)    481                                 op.write(line)
562                 fp.close()                        482                 fp.close()
563                 op.close()                        483                 op.close()
564         def listFromFile(self, file):             484         def listFromFile(self, file):
565                 list = []                         485                 list = []
566                 fp = open(file)                   486                 fp = open(file)
567                 for i in fp.read().split('\n')    487                 for i in fp.read().split('\n'):
568                         i = i.strip()             488                         i = i.strip()
569                         if i and i[0] != '#':     489                         if i and i[0] != '#':
570                                 list.append(i)    490                                 list.append(i)
571                 fp.close()                        491                 fp.close()
572                 return list                       492                 return list
573         def addFtraceFilterFunctions(self, fil    493         def addFtraceFilterFunctions(self, file):
574                 for i in self.listFromFile(fil    494                 for i in self.listFromFile(file):
575                         if len(i) < 2:            495                         if len(i) < 2:
576                                 continue          496                                 continue
577                         self.tracefuncs[i] = d    497                         self.tracefuncs[i] = dict()
578         def getFtraceFilterFunctions(self, cur    498         def getFtraceFilterFunctions(self, current):
579                 self.rootCheck(True)              499                 self.rootCheck(True)
580                 if not current:                   500                 if not current:
581                         call('cat '+self.tpath    501                         call('cat '+self.tpath+'available_filter_functions', shell=True)
582                         return                    502                         return
583                 master = self.listFromFile(sel    503                 master = self.listFromFile(self.tpath+'available_filter_functions')
584                 for i in sorted(self.tracefunc !! 504                 for i in self.tracefuncs:
585                         if 'func' in self.trac    505                         if 'func' in self.tracefuncs[i]:
586                                 i = self.trace    506                                 i = self.tracefuncs[i]['func']
587                         if i in master:           507                         if i in master:
588                                 print(i)          508                                 print(i)
589                         else:                     509                         else:
590                                 print(self.col    510                                 print(self.colorText(i))
591         def setFtraceFilterFunctions(self, lis    511         def setFtraceFilterFunctions(self, list):
592                 master = self.listFromFile(sel    512                 master = self.listFromFile(self.tpath+'available_filter_functions')
593                 flist = ''                        513                 flist = ''
594                 for i in list:                    514                 for i in list:
595                         if i not in master:       515                         if i not in master:
596                                 continue          516                                 continue
597                         if ' [' in i:             517                         if ' [' in i:
598                                 flist += i.spl    518                                 flist += i.split(' ')[0]+'\n'
599                         else:                     519                         else:
600                                 flist += i+'\n    520                                 flist += i+'\n'
601                 fp = open(self.tpath+'set_grap    521                 fp = open(self.tpath+'set_graph_function', 'w')
602                 fp.write(flist)                   522                 fp.write(flist)
603                 fp.close()                        523                 fp.close()
604         def basicKprobe(self, name):              524         def basicKprobe(self, name):
605                 self.kprobes[name] = {'name':     525                 self.kprobes[name] = {'name': name,'func': name,'args': dict(),'format': name}
606         def defaultKprobe(self, name, kdata):     526         def defaultKprobe(self, name, kdata):
607                 k = kdata                         527                 k = kdata
608                 for field in ['name', 'format'    528                 for field in ['name', 'format', 'func']:
609                         if field not in k:        529                         if field not in k:
610                                 k[field] = nam    530                                 k[field] = name
611                 if self.archargs in k:            531                 if self.archargs in k:
612                         k['args'] = k[self.arc    532                         k['args'] = k[self.archargs]
613                 else:                             533                 else:
614                         k['args'] = dict()        534                         k['args'] = dict()
615                         k['format'] = name        535                         k['format'] = name
616                 self.kprobes[name] = k            536                 self.kprobes[name] = k
617         def kprobeColor(self, name):              537         def kprobeColor(self, name):
618                 if name not in self.kprobes or    538                 if name not in self.kprobes or 'color' not in self.kprobes[name]:
619                         return ''                 539                         return ''
620                 return self.kprobes[name]['col    540                 return self.kprobes[name]['color']
621         def kprobeDisplayName(self, name, data    541         def kprobeDisplayName(self, name, dataraw):
622                 if name not in self.kprobes:      542                 if name not in self.kprobes:
623                         self.basicKprobe(name)    543                         self.basicKprobe(name)
624                 data = ''                         544                 data = ''
625                 quote=0                           545                 quote=0
626                 # first remvoe any spaces insi    546                 # first remvoe any spaces inside quotes, and the quotes
627                 for c in dataraw:                 547                 for c in dataraw:
628                         if c == '"':              548                         if c == '"':
629                                 quote = (quote    549                                 quote = (quote + 1) % 2
630                         if quote and c == ' ':    550                         if quote and c == ' ':
631                                 data += '_'       551                                 data += '_'
632                         elif c != '"':            552                         elif c != '"':
633                                 data += c         553                                 data += c
634                 fmt, args = self.kprobes[name]    554                 fmt, args = self.kprobes[name]['format'], self.kprobes[name]['args']
635                 arglist = dict()                  555                 arglist = dict()
636                 # now process the args            556                 # now process the args
637                 for arg in sorted(args):          557                 for arg in sorted(args):
638                         arglist[arg] = ''         558                         arglist[arg] = ''
639                         m = re.match(r'.* '+ar !! 559                         m = re.match('.* '+arg+'=(?P<arg>.*) ', data);
640                         if m:                     560                         if m:
641                                 arglist[arg] =    561                                 arglist[arg] = m.group('arg')
642                         else:                     562                         else:
643                                 m = re.match(r !! 563                                 m = re.match('.* '+arg+'=(?P<arg>.*)', data);
644                                 if m:             564                                 if m:
645                                         arglis    565                                         arglist[arg] = m.group('arg')
646                 out = fmt.format(**arglist)       566                 out = fmt.format(**arglist)
647                 out = out.replace(' ', '_').re    567                 out = out.replace(' ', '_').replace('"', '')
648                 return out                        568                 return out
649         def kprobeText(self, kname, kprobe):      569         def kprobeText(self, kname, kprobe):
650                 name = fmt = func = kname         570                 name = fmt = func = kname
651                 args = dict()                     571                 args = dict()
652                 if 'name' in kprobe:              572                 if 'name' in kprobe:
653                         name = kprobe['name']     573                         name = kprobe['name']
654                 if 'format' in kprobe:            574                 if 'format' in kprobe:
655                         fmt = kprobe['format']    575                         fmt = kprobe['format']
656                 if 'func' in kprobe:              576                 if 'func' in kprobe:
657                         func = kprobe['func']     577                         func = kprobe['func']
658                 if self.archargs in kprobe:       578                 if self.archargs in kprobe:
659                         args = kprobe[self.arc    579                         args = kprobe[self.archargs]
660                 if 'args' in kprobe:              580                 if 'args' in kprobe:
661                         args = kprobe['args']     581                         args = kprobe['args']
662                 if re.findall('{(?P<n>[a-z,A-Z    582                 if re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', func):
663                         doError('Kprobe "%s" h    583                         doError('Kprobe "%s" has format info in the function name "%s"' % (name, func))
664                 for arg in re.findall('{(?P<n>    584                 for arg in re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', fmt):
665                         if arg not in args:       585                         if arg not in args:
666                                 doError('Kprob    586                                 doError('Kprobe "%s" is missing argument "%s"' % (name, arg))
667                 val = 'p:%s_cal %s' % (name, f    587                 val = 'p:%s_cal %s' % (name, func)
668                 for i in sorted(args):            588                 for i in sorted(args):
669                         val += ' %s=%s' % (i,     589                         val += ' %s=%s' % (i, args[i])
670                 val += '\nr:%s_ret %s $retval\    590                 val += '\nr:%s_ret %s $retval\n' % (name, func)
671                 return val                        591                 return val
672         def addKprobes(self, output=False):       592         def addKprobes(self, output=False):
673                 if len(self.kprobes) < 1:         593                 if len(self.kprobes) < 1:
674                         return                    594                         return
675                 if output:                        595                 if output:
676                         pprint('    kprobe fun    596                         pprint('    kprobe functions in this kernel:')
677                 # first test each kprobe          597                 # first test each kprobe
678                 rejects = []                      598                 rejects = []
679                 # sort kprobes: trace, ub-dev,    599                 # sort kprobes: trace, ub-dev, custom, dev
680                 kpl = [[], [], [], []]            600                 kpl = [[], [], [], []]
681                 linesout = len(self.kprobes)      601                 linesout = len(self.kprobes)
682                 for name in sorted(self.kprobe    602                 for name in sorted(self.kprobes):
683                         res = self.colorText('    603                         res = self.colorText('YES', 32)
684                         if not self.testKprobe    604                         if not self.testKprobe(name, self.kprobes[name]):
685                                 res = self.col    605                                 res = self.colorText('NO')
686                                 rejects.append    606                                 rejects.append(name)
687                         else:                     607                         else:
688                                 if name in sel    608                                 if name in self.tracefuncs:
689                                         kpl[0]    609                                         kpl[0].append(name)
690                                 elif name in s    610                                 elif name in self.dev_tracefuncs:
691                                         if 'ub    611                                         if 'ub' in self.dev_tracefuncs[name]:
692                                                   612                                                 kpl[1].append(name)
693                                         else:     613                                         else:
694                                                   614                                                 kpl[3].append(name)
695                                 else:             615                                 else:
696                                         kpl[2]    616                                         kpl[2].append(name)
697                         if output:                617                         if output:
698                                 pprint('          618                                 pprint('         %s: %s' % (name, res))
699                 kplist = kpl[0] + kpl[1] + kpl    619                 kplist = kpl[0] + kpl[1] + kpl[2] + kpl[3]
700                 # remove all failed ones from     620                 # remove all failed ones from the list
701                 for name in rejects:              621                 for name in rejects:
702                         self.kprobes.pop(name)    622                         self.kprobes.pop(name)
703                 # set the kprobes all at once     623                 # set the kprobes all at once
704                 self.fsetVal('', 'kprobe_event    624                 self.fsetVal('', 'kprobe_events')
705                 kprobeevents = ''                 625                 kprobeevents = ''
706                 for kp in kplist:                 626                 for kp in kplist:
707                         kprobeevents += self.k    627                         kprobeevents += self.kprobeText(kp, self.kprobes[kp])
708                 self.fsetVal(kprobeevents, 'kp    628                 self.fsetVal(kprobeevents, 'kprobe_events')
709                 if output:                        629                 if output:
710                         check = self.fgetVal('    630                         check = self.fgetVal('kprobe_events')
711                         linesack = (len(check. !! 631                         linesack = (len(check.split('\n')) - 1) / 2
712                         pprint('    kprobe fun    632                         pprint('    kprobe functions enabled: %d/%d' % (linesack, linesout))
713                 self.fsetVal('1', 'events/kpro    633                 self.fsetVal('1', 'events/kprobes/enable')
714         def testKprobe(self, kname, kprobe):      634         def testKprobe(self, kname, kprobe):
715                 self.fsetVal('0', 'events/kpro    635                 self.fsetVal('0', 'events/kprobes/enable')
716                 kprobeevents = self.kprobeText    636                 kprobeevents = self.kprobeText(kname, kprobe)
717                 if not kprobeevents:              637                 if not kprobeevents:
718                         return False              638                         return False
719                 try:                              639                 try:
720                         self.fsetVal(kprobeeve    640                         self.fsetVal(kprobeevents, 'kprobe_events')
721                         check = self.fgetVal('    641                         check = self.fgetVal('kprobe_events')
722                 except:                           642                 except:
723                         return False              643                         return False
724                 linesout = len(kprobeevents.sp    644                 linesout = len(kprobeevents.split('\n'))
725                 linesack = len(check.split('\n    645                 linesack = len(check.split('\n'))
726                 if linesack < linesout:           646                 if linesack < linesout:
727                         return False              647                         return False
728                 return True                       648                 return True
729         def setVal(self, val, file):           !! 649         def setVal(self, val, file, mode='w'):
730                 if not os.path.exists(file):      650                 if not os.path.exists(file):
731                         return False              651                         return False
732                 try:                              652                 try:
733                         fp = open(file, 'wb',  !! 653                         fp = open(file, mode, 0)
734                         fp.write(val.encode()) !! 654                         fp.write(val)
735                         fp.flush()                655                         fp.flush()
736                         fp.close()                656                         fp.close()
737                 except:                           657                 except:
738                         return False              658                         return False
739                 return True                       659                 return True
740         def fsetVal(self, val, path):          !! 660         def fsetVal(self, val, path, mode='w'):
741                 if not self.useftrace:         !! 661                 return self.setVal(val, self.tpath+path, mode)
742                         return False           << 
743                 return self.setVal(val, self.t << 
744         def getVal(self, file):                   662         def getVal(self, file):
745                 res = ''                          663                 res = ''
746                 if not os.path.exists(file):      664                 if not os.path.exists(file):
747                         return res                665                         return res
748                 try:                              666                 try:
749                         fp = open(file, 'r')      667                         fp = open(file, 'r')
750                         res = fp.read()           668                         res = fp.read()
751                         fp.close()                669                         fp.close()
752                 except:                           670                 except:
753                         pass                      671                         pass
754                 return res                        672                 return res
755         def fgetVal(self, path):                  673         def fgetVal(self, path):
756                 if not self.useftrace:         << 
757                         return ''              << 
758                 return self.getVal(self.tpath+    674                 return self.getVal(self.tpath+path)
759         def cleanupFtrace(self):                  675         def cleanupFtrace(self):
760                 if self.useftrace:             !! 676                 if(self.usecallgraph or self.usetraceevents or self.usedevsrc):
761                         self.fsetVal('0', 'eve    677                         self.fsetVal('0', 'events/kprobes/enable')
762                         self.fsetVal('', 'kpro    678                         self.fsetVal('', 'kprobe_events')
763                         self.fsetVal('1024', '    679                         self.fsetVal('1024', 'buffer_size_kb')
                                                   >> 680                 if self.pmdebug:
                                                   >> 681                         self.setVal(self.pmdebug, self.pmdpath)
764         def setupAllKprobes(self):                682         def setupAllKprobes(self):
765                 for name in self.tracefuncs:      683                 for name in self.tracefuncs:
766                         self.defaultKprobe(nam    684                         self.defaultKprobe(name, self.tracefuncs[name])
767                 for name in self.dev_tracefunc    685                 for name in self.dev_tracefuncs:
768                         self.defaultKprobe(nam    686                         self.defaultKprobe(name, self.dev_tracefuncs[name])
769         def isCallgraphFunc(self, name):          687         def isCallgraphFunc(self, name):
770                 if len(self.tracefuncs) < 1 an    688                 if len(self.tracefuncs) < 1 and self.suspendmode == 'command':
771                         return True               689                         return True
772                 for i in self.tracefuncs:         690                 for i in self.tracefuncs:
773                         if 'func' in self.trac    691                         if 'func' in self.tracefuncs[i]:
774                                 f = self.trace    692                                 f = self.tracefuncs[i]['func']
775                         else:                     693                         else:
776                                 f = i             694                                 f = i
777                         if name == f:             695                         if name == f:
778                                 return True       696                                 return True
779                 return False                      697                 return False
780         def initFtrace(self, quiet=False):     !! 698         def initFtrace(self):
781                 if not self.useftrace:         !! 699                 self.printSystemInfo(False)
782                         return                 !! 700                 pprint('INITIALIZING FTRACE...')
783                 if not quiet:                  << 
784                         sysvals.printSystemInf << 
785                         pprint('INITIALIZING F << 
786                 # turn trace off                  701                 # turn trace off
787                 self.fsetVal('0', 'tracing_on'    702                 self.fsetVal('0', 'tracing_on')
788                 self.cleanupFtrace()              703                 self.cleanupFtrace()
                                                   >> 704                 # pm debug messages
                                                   >> 705                 pv = self.getVal(self.pmdpath)
                                                   >> 706                 if pv != '1':
                                                   >> 707                         self.setVal('1', self.pmdpath)
                                                   >> 708                         self.pmdebug = pv
789                 # set the trace clock to globa    709                 # set the trace clock to global
790                 self.fsetVal('global', 'trace_    710                 self.fsetVal('global', 'trace_clock')
791                 self.fsetVal('nop', 'current_t    711                 self.fsetVal('nop', 'current_tracer')
792                 # set trace buffer to an appro    712                 # set trace buffer to an appropriate value
793                 cpus = max(1, self.cpucount)      713                 cpus = max(1, self.cpucount)
794                 if self.bufsize > 0:              714                 if self.bufsize > 0:
795                         tgtsize = self.bufsize    715                         tgtsize = self.bufsize
796                 elif self.usecallgraph or self    716                 elif self.usecallgraph or self.usedevsrc:
797                         bmax = (1*1024*1024) i    717                         bmax = (1*1024*1024) if self.suspendmode in ['disk', 'command'] \
798                                 else (3*1024*1    718                                 else (3*1024*1024)
799                         tgtsize = min(self.mem    719                         tgtsize = min(self.memfree, bmax)
800                 else:                             720                 else:
801                         tgtsize = 65536           721                         tgtsize = 65536
802                 while not self.fsetVal('%d' %  !! 722                 while not self.fsetVal('%d' % (tgtsize / cpus), 'buffer_size_kb'):
803                         # if the size failed t    723                         # if the size failed to set, lower it and keep trying
804                         tgtsize -= 65536          724                         tgtsize -= 65536
805                         if tgtsize < 65536:       725                         if tgtsize < 65536:
806                                 tgtsize = int(    726                                 tgtsize = int(self.fgetVal('buffer_size_kb')) * cpus
807                                 break             727                                 break
808                 self.vprint('Setting trace buf !! 728                 pprint('Setting trace buffers to %d kB (%d kB per cpu)' % (tgtsize, tgtsize/cpus))
809                 # initialize the callgraph tra    729                 # initialize the callgraph trace
810                 if(self.usecallgraph):            730                 if(self.usecallgraph):
811                         # set trace type          731                         # set trace type
812                         self.fsetVal('function    732                         self.fsetVal('function_graph', 'current_tracer')
813                         self.fsetVal('', 'set_    733                         self.fsetVal('', 'set_ftrace_filter')
814                         # temporary hack to fi << 
815                         fp = open(self.tpath+' << 
816                         fp.write('native_queue << 
817                         fp.close()             << 
818                         # set trace format opt    734                         # set trace format options
819                         self.fsetVal('print-pa    735                         self.fsetVal('print-parent', 'trace_options')
820                         self.fsetVal('funcgrap    736                         self.fsetVal('funcgraph-abstime', 'trace_options')
821                         self.fsetVal('funcgrap    737                         self.fsetVal('funcgraph-cpu', 'trace_options')
822                         self.fsetVal('funcgrap    738                         self.fsetVal('funcgraph-duration', 'trace_options')
823                         self.fsetVal('funcgrap    739                         self.fsetVal('funcgraph-proc', 'trace_options')
824                         self.fsetVal('funcgrap    740                         self.fsetVal('funcgraph-tail', 'trace_options')
825                         self.fsetVal('nofuncgr    741                         self.fsetVal('nofuncgraph-overhead', 'trace_options')
826                         self.fsetVal('context-    742                         self.fsetVal('context-info', 'trace_options')
827                         self.fsetVal('graph-ti    743                         self.fsetVal('graph-time', 'trace_options')
828                         self.fsetVal('%d' % se    744                         self.fsetVal('%d' % self.max_graph_depth, 'max_graph_depth')
829                         cf = ['dpm_run_callbac    745                         cf = ['dpm_run_callback']
830                         if(self.usetraceevents    746                         if(self.usetraceevents):
831                                 cf += ['dpm_pr    747                                 cf += ['dpm_prepare', 'dpm_complete']
832                         for fn in self.tracefu    748                         for fn in self.tracefuncs:
833                                 if 'func' in s    749                                 if 'func' in self.tracefuncs[fn]:
834                                         cf.app    750                                         cf.append(self.tracefuncs[fn]['func'])
835                                 else:             751                                 else:
836                                         cf.app    752                                         cf.append(fn)
837                         if self.ftop:             753                         if self.ftop:
838                                 self.setFtrace    754                                 self.setFtraceFilterFunctions([self.ftopfunc])
839                         else:                     755                         else:
840                                 self.setFtrace    756                                 self.setFtraceFilterFunctions(cf)
841                 # initialize the kprobe trace     757                 # initialize the kprobe trace
842                 elif self.usekprobes:             758                 elif self.usekprobes:
843                         for name in self.trace    759                         for name in self.tracefuncs:
844                                 self.defaultKp    760                                 self.defaultKprobe(name, self.tracefuncs[name])
845                         if self.usedevsrc:        761                         if self.usedevsrc:
846                                 for name in se    762                                 for name in self.dev_tracefuncs:
847                                         self.d    763                                         self.defaultKprobe(name, self.dev_tracefuncs[name])
848                         if not quiet:          !! 764                         pprint('INITIALIZING KPROBES...')
849                                 pprint('INITIA << 
850                         self.addKprobes(self.v    765                         self.addKprobes(self.verbose)
851                 if(self.usetraceevents):          766                 if(self.usetraceevents):
852                         # turn trace events on    767                         # turn trace events on
853                         events = iter(self.tra    768                         events = iter(self.traceevents)
854                         for e in events:          769                         for e in events:
855                                 self.fsetVal('    770                                 self.fsetVal('1', 'events/power/'+e+'/enable')
856                 # clear the trace buffer          771                 # clear the trace buffer
857                 self.fsetVal('', 'trace')         772                 self.fsetVal('', 'trace')
858         def verifyFtrace(self):                   773         def verifyFtrace(self):
859                 # files needed for any trace d    774                 # files needed for any trace data
860                 files = ['buffer_size_kb', 'cu    775                 files = ['buffer_size_kb', 'current_tracer', 'trace', 'trace_clock',
861                                  'trace_marker    776                                  'trace_marker', 'trace_options', 'tracing_on']
862                 # files needed for callgraph t    777                 # files needed for callgraph trace data
863                 tp = self.tpath                   778                 tp = self.tpath
864                 if(self.usecallgraph):            779                 if(self.usecallgraph):
865                         files += [                780                         files += [
866                                 'available_fil    781                                 'available_filter_functions',
867                                 'set_ftrace_fi    782                                 'set_ftrace_filter',
868                                 'set_graph_fun    783                                 'set_graph_function'
869                         ]                         784                         ]
870                 for f in files:                   785                 for f in files:
871                         if(os.path.exists(tp+f    786                         if(os.path.exists(tp+f) == False):
872                                 return False      787                                 return False
873                 return True                       788                 return True
874         def verifyKprobes(self):                  789         def verifyKprobes(self):
875                 # files needed for kprobes to     790                 # files needed for kprobes to work
876                 files = ['kprobe_events', 'eve    791                 files = ['kprobe_events', 'events']
877                 tp = self.tpath                   792                 tp = self.tpath
878                 for f in files:                   793                 for f in files:
879                         if(os.path.exists(tp+f    794                         if(os.path.exists(tp+f) == False):
880                                 return False      795                                 return False
881                 return True                       796                 return True
882         def colorText(self, str, color=31):       797         def colorText(self, str, color=31):
883                 if not self.ansi:                 798                 if not self.ansi:
884                         return str                799                         return str
885                 return '\x1B[%d;40m%s\x1B[m' %    800                 return '\x1B[%d;40m%s\x1B[m' % (color, str)
886         def writeDatafileHeader(self, filename    801         def writeDatafileHeader(self, filename, testdata):
887                 fp = self.openlog(filename, 'w    802                 fp = self.openlog(filename, 'w')
888                 fp.write('%s\n%s\n# command |     803                 fp.write('%s\n%s\n# command | %s\n' % (self.teststamp, self.sysstamp, self.cmdline))
889                 for test in testdata:             804                 for test in testdata:
890                         if 'fw' in test:          805                         if 'fw' in test:
891                                 fw = test['fw'    806                                 fw = test['fw']
892                                 if(fw):           807                                 if(fw):
893                                         fp.wri    808                                         fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1]))
                                                   >> 809                         if 'mcelog' in test:
                                                   >> 810                                 fp.write('# mcelog %s\n' % test['mcelog'])
894                         if 'turbo' in test:       811                         if 'turbo' in test:
895                                 fp.write('# tu    812                                 fp.write('# turbostat %s\n' % test['turbo'])
                                                   >> 813                         if 'bat' in test:
                                                   >> 814                                 (a1, c1), (a2, c2) = test['bat']
                                                   >> 815                                 fp.write('# battery %s %d %s %d\n' % (a1, c1, a2, c2))
896                         if 'wifi' in test:        816                         if 'wifi' in test:
897                                 fp.write('# wi !! 817                                 wstr = []
898                         if 'netfix' in test:   !! 818                                 for wifi in test['wifi']:
899                                 fp.write('# ne !! 819                                         tmp = []
                                                   >> 820                                         for key in sorted(wifi):
                                                   >> 821                                                 tmp.append('%s:%s' % (key, wifi[key]))
                                                   >> 822                                         wstr.append('|'.join(tmp))
                                                   >> 823                                 fp.write('# wifi %s\n' % (','.join(wstr)))
900                         if test['error'] or le    824                         if test['error'] or len(testdata) > 1:
901                                 fp.write('# en    825                                 fp.write('# enter_sleep_error %s\n' % test['error'])
902                 return fp                         826                 return fp
903         def sudoUserchown(self, dir):             827         def sudoUserchown(self, dir):
904                 if os.path.exists(dir) and sel    828                 if os.path.exists(dir) and self.sudouser:
905                         cmd = 'chown -R {0}:{0    829                         cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1'
906                         call(cmd.format(self.s    830                         call(cmd.format(self.sudouser, dir), shell=True)
907         def outputResult(self, testdata, num=0    831         def outputResult(self, testdata, num=0):
908                 if not self.result:               832                 if not self.result:
909                         return                    833                         return
910                 n = ''                            834                 n = ''
911                 if num > 0:                       835                 if num > 0:
912                         n = '%d' % num            836                         n = '%d' % num
913                 fp = open(self.result, 'a')       837                 fp = open(self.result, 'a')
914                 if 'error' in testdata:           838                 if 'error' in testdata:
915                         fp.write('result%s: fa    839                         fp.write('result%s: fail\n' % n)
916                         fp.write('error%s: %s\    840                         fp.write('error%s: %s\n' % (n, testdata['error']))
917                 else:                             841                 else:
918                         fp.write('result%s: pa    842                         fp.write('result%s: pass\n' % n)
919                 if 'mode' in testdata:         << 
920                         fp.write('mode%s: %s\n << 
921                 for v in ['suspend', 'resume',    843                 for v in ['suspend', 'resume', 'boot', 'lastinit']:
922                         if v in testdata:         844                         if v in testdata:
923                                 fp.write('%s%s    845                                 fp.write('%s%s: %.3f\n' % (v, n, testdata[v]))
924                 for v in ['fwsuspend', 'fwresu    846                 for v in ['fwsuspend', 'fwresume']:
925                         if v in testdata:         847                         if v in testdata:
926                                 fp.write('%s%s    848                                 fp.write('%s%s: %.3f\n' % (v, n, testdata[v] / 1000000.0))
927                 if 'bugurl' in testdata:          849                 if 'bugurl' in testdata:
928                         fp.write('url%s: %s\n'    850                         fp.write('url%s: %s\n' % (n, testdata['bugurl']))
929                 fp.close()                        851                 fp.close()
930                 self.sudoUserchown(self.result    852                 self.sudoUserchown(self.result)
931         def configFile(self, file):               853         def configFile(self, file):
932                 dir = os.path.dirname(os.path.    854                 dir = os.path.dirname(os.path.realpath(__file__))
933                 if os.path.exists(file):          855                 if os.path.exists(file):
934                         return file               856                         return file
935                 elif os.path.exists(dir+'/'+fi    857                 elif os.path.exists(dir+'/'+file):
936                         return dir+'/'+file       858                         return dir+'/'+file
937                 elif os.path.exists(dir+'/conf    859                 elif os.path.exists(dir+'/config/'+file):
938                         return dir+'/config/'+    860                         return dir+'/config/'+file
939                 return ''                         861                 return ''
940         def openlog(self, filename, mode):        862         def openlog(self, filename, mode):
941                 isgz = self.gzip                  863                 isgz = self.gzip
942                 if mode == 'r':                   864                 if mode == 'r':
943                         try:                      865                         try:
944                                 with gzip.open !! 866                                 with gzip.open(filename, mode+'b') as fp:
945                                         test =    867                                         test = fp.read(64)
946                                 isgz = True       868                                 isgz = True
947                         except:                   869                         except:
948                                 isgz = False      870                                 isgz = False
949                 if isgz:                          871                 if isgz:
950                         return gzip.open(filen !! 872                         return gzip.open(filename, mode+'b')
951                 return open(filename, mode)       873                 return open(filename, mode)
952         def putlog(self, filename, text):      !! 874         def mcelog(self, clear=False):
953                 with self.openlog(filename, 'a !! 875                 cmd = self.getExec('mcelog')
954                         fp.write(text)         !! 876                 if not cmd:
955                         fp.close()             << 
956         def dlog(self, text):                  << 
957                 if not self.dmesgfile:         << 
958                         return                 << 
959                 self.putlog(self.dmesgfile, '# << 
960         def flog(self, text):                  << 
961                 self.putlog(self.ftracefile, t << 
962         def b64unzip(self, data):              << 
963                 try:                           << 
964                         out = codecs.decode(ba << 
965                 except:                        << 
966                         out = data             << 
967                 return out                     << 
968         def b64zip(self, data):                << 
969                 out = base64.b64encode(codecs. << 
970                 return out                     << 
971         def platforminfo(self, cmdafter):      << 
972                 # add platform info on to a co << 
973                 if not os.path.exists(self.ftr << 
974                         return False           << 
975                 footer = '#\n'                 << 
976                                                << 
977                 # add test command string line << 
978                 if self.suspendmode == 'comman << 
979                         footer += '# platform- << 
980                                                << 
981                 # get a list of target devices << 
982                 props = dict()                 << 
983                 tp = TestProps()               << 
984                 tf = self.openlog(self.ftracef << 
985                 for line in tf:                << 
986                         if tp.stampInfo(line,  << 
987                                 continue       << 
988                         # parse only valid lin << 
989                         m = re.match(tp.ftrace << 
990                         if(not m or 'device_pm << 
991                                 continue       << 
992                         m = re.match(r'.*: (?P << 
993                         if(not m):             << 
994                                 continue       << 
995                         dev = m.group('d')     << 
996                         if dev not in props:   << 
997                                 props[dev] = D << 
998                 tf.close()                     << 
999                                                << 
1000                 # now get the syspath for eac << 
1001                 for dirname, dirnames, filena << 
1002                         if(re.match(r'.*/powe << 
1003                                 dev = dirname << 
1004                                 if dev in pro << 
1005                                         props << 
1006                                               << 
1007                 # now fill in the properties  << 
1008                 for dev in sorted(props):     << 
1009                         dirname = props[dev]. << 
1010                         if not dirname or not << 
1011                                 continue      << 
1012                         props[dev].isasync =  << 
1013                         if os.path.exists(dir << 
1014                                 fp = open(dir << 
1015                                 if 'enabled'  << 
1016                                         props << 
1017                                 fp.close()    << 
1018                         fields = os.listdir(d << 
1019                         for file in ['product << 
1020                                 if file not i << 
1021                                         conti << 
1022                                 try:          << 
1023                                         with  << 
1024                                               << 
1025                                 except:       << 
1026                                         conti << 
1027                                 if file == 'i << 
1028                                         idv,  << 
1029                                         try:  << 
1030                                               << 
1031                                               << 
1032                                         excep << 
1033                                               << 
1034                                               << 
1035                                         props << 
1036                                 break         << 
1037                         if props[dev].altname << 
1038                                 out = props[d << 
1039                                         .repl << 
1040                                 props[dev].al << 
1041                                               << 
1042                 # add a devinfo line to the b << 
1043                 out = ''                      << 
1044                 for dev in sorted(props):     << 
1045                         out += props[dev].out << 
1046                 footer += '# platform-devinfo << 
1047                                               << 
1048                 # add a line for each of thes << 
1049                 for name, cmdline, info in cm << 
1050                         footer += '# platform << 
1051                 self.flog(footer)             << 
1052                 return True                   << 
1053         def commonPrefix(self, list):         << 
1054                 if len(list) < 2:             << 
1055                         return ''                877                         return ''
1056                 prefix = list[0]              !! 878                 if clear:
1057                 for s in list[1:]:            !! 879                         call(cmd+' > /dev/null 2>&1', shell=True)
1058                         while s[:len(prefix)] !! 880                         return ''
1059                                 prefix = pref !! 881                 fp = Popen([cmd], stdout=PIPE, stderr=PIPE).stdout
1060                         if not prefix:        !! 882                 out = fp.read().strip()
1061                                 break         << 
1062                 if '/' in prefix and prefix[- << 
1063                         prefix = prefix[0:pre << 
1064                 return prefix                 << 
1065         def dictify(self, text, format):      << 
1066                 out = dict()                  << 
1067                 header = True if format == 1  << 
1068                 delim = ' ' if format == 1 el << 
1069                 for line in text.split('\n'): << 
1070                         if header:            << 
1071                                 header, out[' << 
1072                                 continue      << 
1073                         line = line.strip()   << 
1074                         if delim in line:     << 
1075                                 data = line.s << 
1076                                 num = re.sear << 
1077                                 if format ==  << 
1078                                         out[d << 
1079                                 else:         << 
1080                                         out[d << 
1081                 return out                    << 
1082         def cmdinfovar(self, arg):            << 
1083                 if arg == 'ethdev':           << 
1084                         try:                  << 
1085                                 cmd = [self.g << 
1086                                 fp = Popen(cm << 
1087                                 info = ascii( << 
1088                                 fp.close()    << 
1089                         except:               << 
1090                                 return 'iptoo << 
1091                         for line in info.spli << 
1092                                 if line[0] == << 
1093                                         retur << 
1094                         return 'nodevicefound << 
1095                 return 'unknown'              << 
1096         def cmdinfo(self, begin, debug=False) << 
1097                 out = []                      << 
1098                 if begin:                     << 
1099                         self.cmd1 = dict()    << 
1100                 for cargs in self.infocmds:   << 
1101                         delta, name, args = c << 
1102                         for i in range(len(ar << 
1103                                 if args[i][0] << 
1104                                         args[ << 
1105                         cmdline, cmdpath = '  << 
1106                         if not cmdpath or (be << 
1107                                 continue      << 
1108                         self.dlog('[%s]' % cm << 
1109                         try:                  << 
1110                                 fp = Popen([c << 
1111                                 info = ascii( << 
1112                                 fp.close()    << 
1113                         except:               << 
1114                                 continue      << 
1115                         if not debug and begi << 
1116                                 self.cmd1[nam << 
1117                         elif not debug and de << 
1118                                 before, after << 
1119                                 dinfo = ('\t% << 
1120                                 prefix = self << 
1121                                 for key in so << 
1122                                         if ke << 
1123                                               << 
1124                                               << 
1125                                               << 
1126                                               << 
1127                                               << 
1128                                               << 
1129                                               << 
1130                                 dinfo = '\tno << 
1131                                 out.append((n << 
1132                         else:                 << 
1133                                 out.append((n << 
1134                 return out                    << 
1135         def testVal(self, file, fmt='basic',  << 
1136                 if file == 'restoreall':      << 
1137                         for f in self.cfgdef: << 
1138                                 if os.path.ex << 
1139                                         fp =  << 
1140                                         fp.wr << 
1141                                         fp.cl << 
1142                         self.cfgdef = dict()  << 
1143                 elif value and os.path.exists << 
1144                         fp = open(file, 'r+') << 
1145                         if fmt == 'radio':    << 
1146                                 m = re.match( << 
1147                                 if m:         << 
1148                                         self. << 
1149                         elif fmt == 'acpi':   << 
1150                                 line = fp.rea << 
1151                                 m = re.match( << 
1152                                 if m:         << 
1153                                         self. << 
1154                         else:                 << 
1155                                 self.cfgdef[f << 
1156                         fp.write(value)       << 
1157                         fp.close()            << 
1158         def s0ixSupport(self):                << 
1159                 if not os.path.exists(self.s0 << 
1160                         return False          << 
1161                 fp = open(sysvals.mempowerfil << 
1162                 data = fp.read().strip()      << 
1163                 fp.close()                       883                 fp.close()
1164                 if '[s2idle]' in data:        !! 884                 if not out:
1165                         return True           !! 885                         return ''
1166                 return False                  !! 886                 return base64.b64encode(out.encode('zlib'))
1167         def haveTurbostat(self):                 887         def haveTurbostat(self):
1168                 if not self.tstat:               888                 if not self.tstat:
1169                         return False             889                         return False
1170                 cmd = self.getExec('turbostat    890                 cmd = self.getExec('turbostat')
1171                 if not cmd:                      891                 if not cmd:
1172                         return False             892                         return False
1173                 fp = Popen([cmd, '-v'], stdou    893                 fp = Popen([cmd, '-v'], stdout=PIPE, stderr=PIPE).stderr
1174                 out = ascii(fp.read()).strip( !! 894                 out = fp.read().strip()
1175                 fp.close()                       895                 fp.close()
1176                 if re.match(r'turbostat versi !! 896                 return re.match('turbostat version [0-9\.]* .*', out)
1177                         self.vprint(out)      !! 897         def turbostat(self):
1178                         return True           << 
1179                 return False                  << 
1180         def turbostat(self, s0ixready):       << 
1181                 cmd = self.getExec('turbostat    898                 cmd = self.getExec('turbostat')
1182                 rawout = keyline = valline =  !! 899                 if not cmd:
                                                   >> 900                         return 'missing turbostat executable'
                                                   >> 901                 text = []
1183                 fullcmd = '%s -q -S echo free    902                 fullcmd = '%s -q -S echo freeze > %s' % (cmd, self.powerfile)
1184                 fp = Popen(['sh', '-c', fullc !! 903                 fp = Popen(['sh', '-c', fullcmd], stdout=PIPE, stderr=PIPE).stderr
1185                 for line in fp.stderr:        !! 904                 for line in fp:
1186                         line = ascii(line)    !! 905                         if re.match('[0-9.]* sec', line):
1187                         rawout += line        << 
1188                         if keyline and vallin << 
1189                                 continue         906                                 continue
1190                         if re.match(r'(?i)Avg !! 907                         text.append(line.split())
1191                                 keyline = lin !! 908                 fp.close()
1192                         elif keyline:         !! 909                 if len(text) < 2:
1193                                 valline = lin !! 910                         return 'turbostat output format error'
1194                 fp.wait()                     << 
1195                 if not keyline or not valline << 
1196                         errmsg = 'unrecognize << 
1197                         self.vprint(errmsg)   << 
1198                         if not self.verbose:  << 
1199                                 pprint(errmsg << 
1200                         return (fp.returncode << 
1201                 if self.verbose:              << 
1202                         pprint(rawout.strip() << 
1203                 out = []                         911                 out = []
1204                 for key in keyline:           !! 912                 for key in text[0]:
1205                         idx = keyline.index(k !! 913                         values = []
1206                         val = valline[idx]    !! 914                         idx = text[0].index(key)
1207                         if key == 'SYS%LPI' a !! 915                         for line in text[1:]:
                                                   >> 916                                 if len(line) > idx:
                                                   >> 917                                         values.append(line[idx])
                                                   >> 918                         out.append('%s=%s' % (key, ','.join(values)))
                                                   >> 919                 return '|'.join(out)
                                                   >> 920         def checkWifi(self):
                                                   >> 921                 out = dict()
                                                   >> 922                 iwcmd, ifcmd = self.getExec('iwconfig'), self.getExec('ifconfig')
                                                   >> 923                 if not iwcmd or not ifcmd:
                                                   >> 924                         return out
                                                   >> 925                 fp = Popen(iwcmd, stdout=PIPE, stderr=PIPE).stdout
                                                   >> 926                 for line in fp:
                                                   >> 927                         m = re.match('(?P<dev>\S*) .* ESSID:(?P<ess>\S*)', line)
                                                   >> 928                         if not m:
1208                                 continue         929                                 continue
1209                         out.append('%s=%s' %  !! 930                         out['device'] = m.group('dev')
1210                 return (fp.returncode, '|'.jo !! 931                         if '"' in m.group('ess'):
1211         def netfixon(self, net='both'):       !! 932                                 out['essid'] = m.group('ess').strip('"')
1212                 cmd = self.getExec('netfix')  !! 933                                 break
1213                 if not cmd:                   << 
1214                         return ''             << 
1215                 fp = Popen([cmd, '-s', net, ' << 
1216                 out = ascii(fp.read()).strip( << 
1217                 fp.close()                       934                 fp.close()
                                                   >> 935                 if 'device' in out:
                                                   >> 936                         fp = Popen([ifcmd, out['device']], stdout=PIPE, stderr=PIPE).stdout
                                                   >> 937                         for line in fp:
                                                   >> 938                                 m = re.match('.* inet (?P<ip>[0-9\.]*)', line)
                                                   >> 939                                 if m:
                                                   >> 940                                         out['ip'] = m.group('ip')
                                                   >> 941                                         break
                                                   >> 942                         fp.close()
1218                 return out                       943                 return out
1219         def wifiDetails(self, dev):           << 
1220                 try:                          << 
1221                         info = open('/sys/cla << 
1222                 except:                       << 
1223                         return dev            << 
1224                 vals = [dev]                  << 
1225                 for prop in info.split('\n'): << 
1226                         if prop.startswith('D << 
1227                                 vals.append(p << 
1228                 return ':'.join(vals)         << 
1229         def checkWifi(self, dev=''):          << 
1230                 try:                          << 
1231                         w = open('/proc/net/w << 
1232                 except:                       << 
1233                         return ''             << 
1234                 for line in reversed(w.split( << 
1235                         m = re.match(r' *(?P< << 
1236                         if not m or (dev and  << 
1237                                 continue      << 
1238                         return m.group('dev') << 
1239                 return ''                     << 
1240         def pollWifi(self, dev, timeout=10):  << 
1241                 start = time.time()           << 
1242                 while (time.time() - start) < << 
1243                         w = self.checkWifi(de << 
1244                         if w:                 << 
1245                                 return '%s re << 
1246                                         (self << 
1247                         time.sleep(0.01)      << 
1248                 return '%s timeout %d' % (sel << 
1249         def errorSummary(self, errinfo, msg):    944         def errorSummary(self, errinfo, msg):
1250                 found = False                    945                 found = False
1251                 for entry in errinfo:            946                 for entry in errinfo:
1252                         if re.match(entry['ma    947                         if re.match(entry['match'], msg):
1253                                 entry['count'    948                                 entry['count'] += 1
1254                                 if self.hostn    949                                 if self.hostname not in entry['urls']:
1255                                         entry    950                                         entry['urls'][self.hostname] = [self.htmlfile]
1256                                 elif self.htm    951                                 elif self.htmlfile not in entry['urls'][self.hostname]:
1257                                         entry    952                                         entry['urls'][self.hostname].append(self.htmlfile)
1258                                 found = True     953                                 found = True
1259                                 break            954                                 break
1260                 if found:                        955                 if found:
1261                         return                   956                         return
1262                 arr = msg.split()                957                 arr = msg.split()
1263                 for j in range(len(arr)):        958                 for j in range(len(arr)):
1264                         if re.match(r'^[0-9,\ !! 959                         if re.match('^[0-9,\-\.]*$', arr[j]):
1265                                 arr[j] = r'[0 !! 960                                 arr[j] = '[0-9,\-\.]*'
1266                         else:                    961                         else:
1267                                 arr[j] = arr[    962                                 arr[j] = arr[j]\
1268                                         .repl !! 963                                         .replace('\\', '\\\\').replace(']', '\]').replace('[', '\[')\
1269                                         .repl !! 964                                         .replace('.', '\.').replace('+', '\+').replace('*', '\*')\
1270                                         .repl !! 965                                         .replace('(', '\(').replace(')', '\)')
1271                                         .repl !! 966                 mstr = ' '.join(arr)
1272                 mstr = ' *'.join(arr)         << 
1273                 entry = {                        967                 entry = {
1274                         'line': msg,             968                         'line': msg,
1275                         'match': mstr,           969                         'match': mstr,
1276                         'count': 1,              970                         'count': 1,
1277                         'urls': {self.hostnam    971                         'urls': {self.hostname: [self.htmlfile]}
1278                 }                                972                 }
1279                 errinfo.append(entry)            973                 errinfo.append(entry)
1280         def multistat(self, start, idx, finis << 
1281                 if 'time' in self.multitest:  << 
1282                         id = '%d Duration=%dm << 
1283                 else:                         << 
1284                         id = '%d/%d' % (idx+1 << 
1285                 t = time.time()               << 
1286                 if 'start' not in self.multit << 
1287                         self.multitest['start << 
1288                         self.multitest['total << 
1289                         pprint('TEST (%s) STA << 
1290                         return                << 
1291                 dt = t - self.multitest['last << 
1292                 if not start:                 << 
1293                         if idx == 0 and self. << 
1294                                 self.multites << 
1295                         pprint('TEST (%s) COM << 
1296                         return                << 
1297                 self.multitest['total'] += dt << 
1298                 self.multitest['last'] = t    << 
1299                 avg = self.multitest['total'] << 
1300                 if 'time' in self.multitest:  << 
1301                         left = finish - datet << 
1302                         left -= timedelta(mic << 
1303                 else:                         << 
1304                         left = timedelta(seco << 
1305                 pprint('TEST (%s) START - Avg << 
1306                         (id, avg, str(left))) << 
1307         def multiinit(self, c, d):            << 
1308                 sz, unit = 'count', 'm'       << 
1309                 if c.endswith('d') or c.endsw << 
1310                         sz, unit, c = 'time', << 
1311                 self.multitest['run'] = True  << 
1312                 self.multitest[sz] = getArgIn << 
1313                 self.multitest['delay'] = get << 
1314                 if unit == 'd':               << 
1315                         self.multitest[sz] *= << 
1316                 elif unit == 'h':             << 
1317                         self.multitest[sz] *= << 
1318         def displayControl(self, cmd):        << 
1319                 xset, ret = 'timeout 10 xset  << 
1320                 if self.sudouser:             << 
1321                         xset = 'sudo -u %s %s << 
1322                 if cmd == 'init':             << 
1323                         ret = call(xset.forma << 
1324                         if not ret:           << 
1325                                 ret = call(xs << 
1326                 elif cmd == 'reset':          << 
1327                         ret = call(xset.forma << 
1328                 elif cmd in ['on', 'off', 'st << 
1329                         b4 = self.displayCont << 
1330                         ret = call(xset.forma << 
1331                         if not ret:           << 
1332                                 curr = self.d << 
1333                                 self.vprint(' << 
1334                                 if curr != cm << 
1335                                         self. << 
1336                         if ret:               << 
1337                                 self.vprint(' << 
1338                                 return ret    << 
1339                 elif cmd == 'stat':           << 
1340                         fp = Popen(xset.forma << 
1341                         ret = 'unknown'       << 
1342                         for line in fp:       << 
1343                                 m = re.match( << 
1344                                 if(m and len( << 
1345                                         out = << 
1346                                         ret = << 
1347                                         break << 
1348                         fp.close()            << 
1349                 return ret                    << 
1350         def setRuntimeSuspend(self, before=Tr << 
1351                 if before:                    << 
1352                         # runtime suspend dis << 
1353                         if self.rs > 0:       << 
1354                                 self.rstgt, s << 
1355                         else:                 << 
1356                                 self.rstgt, s << 
1357                         pprint('CONFIGURING R << 
1358                         self.rslist = deviceI << 
1359                         for i in self.rslist: << 
1360                                 self.setVal(s << 
1361                         pprint('runtime suspe << 
1362                         pprint('waiting 5 sec << 
1363                         time.sleep(5)         << 
1364                 else:                         << 
1365                         # runtime suspend re- << 
1366                         for i in self.rslist: << 
1367                                 self.setVal(s << 
1368                         pprint('runtime suspe << 
1369         def start(self, pm):                  << 
1370                 if self.useftrace:            << 
1371                         self.dlog('start ftra << 
1372                         self.fsetVal('1', 'tr << 
1373                         if self.useprocmon:   << 
1374                                 self.dlog('st << 
1375                                 pm.start()    << 
1376         def stop(self, pm):                   << 
1377                 if self.useftrace:            << 
1378                         if self.useprocmon:   << 
1379                                 self.dlog('st << 
1380                                 pm.stop()     << 
1381                         self.dlog('stop ftrac << 
1382                         self.fsetVal('0', 'tr << 
1383                                                  974 
1384 sysvals = SystemValues()                         975 sysvals = SystemValues()
1385 switchvalues = ['enable', 'disable', 'on', 'o    976 switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0']
1386 switchoff = ['disable', 'off', 'false', '0']     977 switchoff = ['disable', 'off', 'false', '0']
1387 suspendmodename = {                              978 suspendmodename = {
1388         'standby': 'standby (S1)',            !! 979         'freeze': 'Freeze (S0)',
1389         'freeze': 'freeze (S2idle)',          !! 980         'standby': 'Standby (S1)',
1390         'mem': 'suspend (S3)',                !! 981         'mem': 'Suspend (S3)',
1391         'disk': 'hibernate (S4)'              !! 982         'disk': 'Hibernate (S4)'
1392 }                                                983 }
1393                                                  984 
1394 # Class: DevProps                                985 # Class: DevProps
1395 # Description:                                   986 # Description:
1396 #        Simple class which holds property va    987 #        Simple class which holds property values collected
1397 #        for all the devices used in the time    988 #        for all the devices used in the timeline.
1398 class DevProps:                                  989 class DevProps:
1399         def __init__(self):                      990         def __init__(self):
1400                 self.syspath = ''                991                 self.syspath = ''
1401                 self.altname = ''                992                 self.altname = ''
1402                 self.isasync = True           !! 993                 self.async = True
1403                 self.xtraclass = ''              994                 self.xtraclass = ''
1404                 self.xtrainfo = ''               995                 self.xtrainfo = ''
1405         def out(self, dev):                      996         def out(self, dev):
1406                 return '%s,%s,%d;' % (dev, se !! 997                 return '%s,%s,%d;' % (dev, self.altname, self.async)
1407         def debug(self, dev):                    998         def debug(self, dev):
1408                 pprint('%s:\n\taltname = %s\n !! 999                 pprint('%s:\n\taltname = %s\n\t  async = %s' % (dev, self.altname, self.async))
1409         def altName(self, dev):                  1000         def altName(self, dev):
1410                 if not self.altname or self.a    1001                 if not self.altname or self.altname == dev:
1411                         return dev               1002                         return dev
1412                 return '%s [%s]' % (self.altn    1003                 return '%s [%s]' % (self.altname, dev)
1413         def xtraClass(self):                     1004         def xtraClass(self):
1414                 if self.xtraclass:               1005                 if self.xtraclass:
1415                         return ' '+self.xtrac    1006                         return ' '+self.xtraclass
1416                 if not self.isasync:          !! 1007                 if not self.async:
1417                         return ' sync'           1008                         return ' sync'
1418                 return ''                        1009                 return ''
1419         def xtraInfo(self):                      1010         def xtraInfo(self):
1420                 if self.xtraclass:               1011                 if self.xtraclass:
1421                         return ' '+self.xtrac    1012                         return ' '+self.xtraclass
1422                 if self.isasync:              !! 1013                 if self.async:
1423                         return ' (async)'     !! 1014                         return ' async_device'
1424                 return ' (sync)'              !! 1015                 return ' sync_device'
1425                                                  1016 
1426 # Class: DeviceNode                              1017 # Class: DeviceNode
1427 # Description:                                   1018 # Description:
1428 #        A container used to create a device     1019 #        A container used to create a device hierachy, with a single root node
1429 #        and a tree of child nodes. Used by D    1020 #        and a tree of child nodes. Used by Data.deviceTopology()
1430 class DeviceNode:                                1021 class DeviceNode:
1431         def __init__(self, nodename, nodedept    1022         def __init__(self, nodename, nodedepth):
1432                 self.name = nodename             1023                 self.name = nodename
1433                 self.children = []               1024                 self.children = []
1434                 self.depth = nodedepth           1025                 self.depth = nodedepth
1435                                                  1026 
1436 # Class: Data                                    1027 # Class: Data
1437 # Description:                                   1028 # Description:
1438 #        The primary container for suspend/re    1029 #        The primary container for suspend/resume test data. There is one for
1439 #        each test run. The data is organized    1030 #        each test run. The data is organized into a cronological hierarchy:
1440 #        Data.dmesg {                            1031 #        Data.dmesg {
1441 #               phases {                         1032 #               phases {
1442 #                       10 sequential, non-ov    1033 #                       10 sequential, non-overlapping phases of S/R
1443 #                       contents: times for p    1034 #                       contents: times for phase start/end, order/color data for html
1444 #                       devlist {                1035 #                       devlist {
1445 #                               device callba    1036 #                               device callback or action list for this phase
1446 #                               device {         1037 #                               device {
1447 #                                       a sin    1038 #                                       a single device callback or generic action
1448 #                                       conte    1039 #                                       contents: start/stop times, pid/cpu/driver info
1449 #                                                1040 #                                               parents/children, html id for timeline/callgraph
1450 #                                                1041 #                                               optionally includes an ftrace callgraph
1451 #                                                1042 #                                               optionally includes dev/ps data
1452 #                               }                1043 #                               }
1453 #                       }                        1044 #                       }
1454 #               }                                1045 #               }
1455 #       }                                        1046 #       }
1456 #                                                1047 #
1457 class Data:                                      1048 class Data:
1458         phasedef = {                             1049         phasedef = {
1459                 'suspend_prepare': {'order':     1050                 'suspend_prepare': {'order': 0, 'color': '#CCFFCC'},
1460                         'suspend': {'order':     1051                         'suspend': {'order': 1, 'color': '#88FF88'},
1461                    'suspend_late': {'order':     1052                    'suspend_late': {'order': 2, 'color': '#00AA00'},
1462                   'suspend_noirq': {'order':     1053                   'suspend_noirq': {'order': 3, 'color': '#008888'},
1463                 'suspend_machine': {'order':     1054                 'suspend_machine': {'order': 4, 'color': '#0000FF'},
1464                  'resume_machine': {'order':     1055                  'resume_machine': {'order': 5, 'color': '#FF0000'},
1465                    'resume_noirq': {'order':     1056                    'resume_noirq': {'order': 6, 'color': '#FF9900'},
1466                    'resume_early': {'order':     1057                    'resume_early': {'order': 7, 'color': '#FFCC00'},
1467                          'resume': {'order':     1058                          'resume': {'order': 8, 'color': '#FFFF88'},
1468                 'resume_complete': {'order':     1059                 'resume_complete': {'order': 9, 'color': '#FFFFCC'},
1469         }                                        1060         }
1470         errlist = {                              1061         errlist = {
1471                 'HWERROR' : r'.*\[ *Hardware  !! 1062                 'HWERROR' : '.*\[ *Hardware Error *\].*',
1472                 'FWBUG'   : r'.*\[ *Firmware  !! 1063                 'FWBUG'   : '.*\[ *Firmware Bug *\].*',
1473                 'TASKFAIL': r'.*Freezing .*af !! 1064                 'BUG'     : '.*BUG.*',
1474                 'BUG'     : r'(?i).*\bBUG\b.* !! 1065                 'ERROR'   : '.*ERROR.*',
1475                 'ERROR'   : r'(?i).*\bERROR\b !! 1066                 'WARNING' : '.*WARNING.*',
1476                 'WARNING' : r'(?i).*\bWARNING !! 1067                 'IRQ'     : '.*genirq: .*',
1477                 'FAULT'   : r'(?i).*\bFAULT\b !! 1068                 'TASKFAIL': '.*Freezing of tasks *.*',
1478                 'FAIL'    : r'(?i).*\bFAILED\ !! 1069                 'ACPI'    : '.*ACPI *(?P<b>[A-Za-z]*) *Error[: ].*',
1479                 'INVALID' : r'(?i).*\bINVALID !! 1070                 'DEVFAIL' : '.* failed to (?P<b>[a-z]*) async: .*',
1480                 'CRASH'   : r'(?i).*\bCRASHED !! 1071                 'DISKFULL': '.*No space left on device.*',
1481                 'TIMEOUT' : r'(?i).*\bTIMEOUT !! 1072                 'USBERR'  : '.*usb .*device .*, error [0-9-]*',
1482                 'ABORT'   : r'(?i).*\bABORT\b !! 1073                 'ATAERR'  : ' *ata[0-9\.]*: .*failed.*',
1483                 'IRQ'     : r'.*\bgenirq: .*' !! 1074                 'MEIERR'  : ' *mei.*: .*failed.*',
1484                 'ACPI'    : r'.*\bACPI *(?P<b !! 1075                 'TPMERR'  : '(?i) *tpm *tpm[0-9]*: .*error.*',
1485                 'DISKFULL': r'.*\bNo space le << 
1486                 'USBERR'  : r'.*usb .*device  << 
1487                 'ATAERR'  : r' *ata[0-9\.]*:  << 
1488                 'MEIERR'  : r' *mei.*: .*fail << 
1489                 'TPMERR'  : r'(?i) *tpm *tpm[ << 
1490         }                                        1076         }
1491         def __init__(self, num):                 1077         def __init__(self, num):
1492                 idchar = 'abcdefghij'            1078                 idchar = 'abcdefghij'
1493                 self.start = 0.0 # test start    1079                 self.start = 0.0 # test start
1494                 self.end = 0.0   # test end      1080                 self.end = 0.0   # test end
1495                 self.hwstart = 0 # rtc test s << 
1496                 self.hwend = 0   # rtc test e << 
1497                 self.tSuspended = 0.0 # low-l    1081                 self.tSuspended = 0.0 # low-level suspend start
1498                 self.tResumed = 0.0   # low-l    1082                 self.tResumed = 0.0   # low-level resume start
1499                 self.tKernSus = 0.0   # kerne    1083                 self.tKernSus = 0.0   # kernel level suspend start
1500                 self.tKernRes = 0.0   # kerne    1084                 self.tKernRes = 0.0   # kernel level resume end
1501                 self.fwValid = False  # is fi    1085                 self.fwValid = False  # is firmware data available
1502                 self.fwSuspend = 0    # time     1086                 self.fwSuspend = 0    # time spent in firmware suspend
1503                 self.fwResume = 0     # time     1087                 self.fwResume = 0     # time spent in firmware resume
1504                 self.html_device_id = 0          1088                 self.html_device_id = 0
1505                 self.stamp = 0                   1089                 self.stamp = 0
1506                 self.outfile = ''                1090                 self.outfile = ''
1507                 self.kerror = False              1091                 self.kerror = False
1508                 self.wifi = dict()            !! 1092                 self.battery = 0
                                                   >> 1093                 self.wifi = 0
1509                 self.turbostat = 0               1094                 self.turbostat = 0
                                                   >> 1095                 self.mcelog = 0
1510                 self.enterfail = ''              1096                 self.enterfail = ''
1511                 self.currphase = ''              1097                 self.currphase = ''
1512                 self.pstl = dict()    # proce    1098                 self.pstl = dict()    # process timeline
1513                 self.testnumber = num            1099                 self.testnumber = num
1514                 self.idstr = idchar[num]         1100                 self.idstr = idchar[num]
1515                 self.dmesgtext = []   # dmesg    1101                 self.dmesgtext = []   # dmesg text file in memory
1516                 self.dmesg = dict()   # root     1102                 self.dmesg = dict()   # root data structure
1517                 self.errorinfo = {'suspend':[    1103                 self.errorinfo = {'suspend':[],'resume':[]}
1518                 self.tLow = []        # time     1104                 self.tLow = []        # time spent in low-level suspends (standby/freeze)
1519                 self.devpids = []                1105                 self.devpids = []
1520                 self.devicegroups = 0            1106                 self.devicegroups = 0
1521         def sortedPhases(self):                  1107         def sortedPhases(self):
1522                 return sorted(self.dmesg, key    1108                 return sorted(self.dmesg, key=lambda k:self.dmesg[k]['order'])
1523         def initDevicegroups(self):              1109         def initDevicegroups(self):
1524                 # called when phases are all     1110                 # called when phases are all finished being added
1525                 for phase in sorted(self.dmes !! 1111                 for phase in self.dmesg.keys():
1526                         if '*' in phase:         1112                         if '*' in phase:
1527                                 p = phase.spl    1113                                 p = phase.split('*')
1528                                 pnew = '%s%d'    1114                                 pnew = '%s%d' % (p[0], len(p))
1529                                 self.dmesg[pn    1115                                 self.dmesg[pnew] = self.dmesg.pop(phase)
1530                 self.devicegroups = []           1116                 self.devicegroups = []
1531                 for phase in self.sortedPhase    1117                 for phase in self.sortedPhases():
1532                         self.devicegroups.app    1118                         self.devicegroups.append([phase])
1533         def nextPhase(self, phase, offset):      1119         def nextPhase(self, phase, offset):
1534                 order = self.dmesg[phase]['or    1120                 order = self.dmesg[phase]['order'] + offset
1535                 for p in self.dmesg:             1121                 for p in self.dmesg:
1536                         if self.dmesg[p]['ord    1122                         if self.dmesg[p]['order'] == order:
1537                                 return p         1123                                 return p
1538                 return ''                        1124                 return ''
1539         def lastPhase(self, depth=1):         !! 1125         def lastPhase(self):
1540                 plist = self.sortedPhases()      1126                 plist = self.sortedPhases()
1541                 if len(plist) < depth:        !! 1127                 if len(plist) < 1:
1542                         return ''                1128                         return ''
1543                 return plist[-1*depth]        !! 1129                 return plist[-1]
1544         def turbostatInfo(self):                 1130         def turbostatInfo(self):
1545                 tp = TestProps()                 1131                 tp = TestProps()
1546                 out = {'syslpi':'N/A','pkgpc1    1132                 out = {'syslpi':'N/A','pkgpc10':'N/A'}
1547                 for line in self.dmesgtext:      1133                 for line in self.dmesgtext:
1548                         m = re.match(tp.tstat    1134                         m = re.match(tp.tstatfmt, line)
1549                         if not m:                1135                         if not m:
1550                                 continue         1136                                 continue
1551                         for i in m.group('t')    1137                         for i in m.group('t').split('|'):
1552                                 if 'SYS%LPI'     1138                                 if 'SYS%LPI' in i:
1553                                         out['    1139                                         out['syslpi'] = i.split('=')[-1]+'%'
1554                                 elif 'pc10' i    1140                                 elif 'pc10' in i:
1555                                         out['    1141                                         out['pkgpc10'] = i.split('=')[-1]+'%'
1556                         break                    1142                         break
1557                 return out                       1143                 return out
1558         def extractErrorInfo(self):              1144         def extractErrorInfo(self):
1559                 lf = self.dmesgtext              1145                 lf = self.dmesgtext
1560                 if len(self.dmesgtext) < 1 an    1146                 if len(self.dmesgtext) < 1 and sysvals.dmesgfile:
1561                         lf = sysvals.openlog(    1147                         lf = sysvals.openlog(sysvals.dmesgfile, 'r')
1562                 i = 0                            1148                 i = 0
1563                 tp = TestProps()              << 
1564                 list = []                        1149                 list = []
1565                 for line in lf:                  1150                 for line in lf:
1566                         i += 1                   1151                         i += 1
1567                         if tp.stampInfo(line, !! 1152                         m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
1568                                 continue      << 
1569                         m = re.match(r'[ \t]* << 
1570                         if not m:                1153                         if not m:
1571                                 continue         1154                                 continue
1572                         t = float(m.group('kt    1155                         t = float(m.group('ktime'))
1573                         if t < self.start or     1156                         if t < self.start or t > self.end:
1574                                 continue         1157                                 continue
1575                         dir = 'suspend' if t     1158                         dir = 'suspend' if t < self.tSuspended else 'resume'
1576                         msg = m.group('msg')     1159                         msg = m.group('msg')
1577                         if re.match(r'capabil << 
1578                                 continue      << 
1579                         for err in self.errli    1160                         for err in self.errlist:
1580                                 if re.match(s    1161                                 if re.match(self.errlist[err], msg):
1581                                         list.    1162                                         list.append((msg, err, dir, t, i, i))
1582                                         self.    1163                                         self.kerror = True
1583                                         break    1164                                         break
1584                 tp.msglist = []               !! 1165                 msglist = []
1585                 for msg, type, dir, t, idx1,     1166                 for msg, type, dir, t, idx1, idx2 in list:
1586                         tp.msglist.append(msg !! 1167                         msglist.append(msg)
                                                   >> 1168                         sysvals.vprint('kernel %s found in %s at %f' % (type, dir, t))
1587                         self.errorinfo[dir].a    1169                         self.errorinfo[dir].append((type, t, idx1, idx2))
1588                 if self.kerror:                  1170                 if self.kerror:
1589                         sysvals.dmesglog = Tr    1171                         sysvals.dmesglog = True
1590                 if len(self.dmesgtext) < 1 an    1172                 if len(self.dmesgtext) < 1 and sysvals.dmesgfile:
1591                         lf.close()               1173                         lf.close()
1592                 return tp                     !! 1174                 return msglist
1593         def setStart(self, time, msg=''):     !! 1175         def setStart(self, time):
1594                 self.start = time                1176                 self.start = time
1595                 if msg:                       !! 1177         def setEnd(self, time):
1596                         try:                  << 
1597                                 self.hwstart  << 
1598                         except:               << 
1599                                 self.hwstart  << 
1600         def setEnd(self, time, msg=''):       << 
1601                 self.end = time                  1178                 self.end = time
1602                 if msg:                       << 
1603                         try:                  << 
1604                                 self.hwend =  << 
1605                         except:               << 
1606                                 self.hwend =  << 
1607         def isTraceEventOutsideDeviceCalls(se    1179         def isTraceEventOutsideDeviceCalls(self, pid, time):
1608                 for phase in self.sortedPhase    1180                 for phase in self.sortedPhases():
1609                         list = self.dmesg[pha    1181                         list = self.dmesg[phase]['list']
1610                         for dev in list:         1182                         for dev in list:
1611                                 d = list[dev]    1183                                 d = list[dev]
1612                                 if(d['pid'] =    1184                                 if(d['pid'] == pid and time >= d['start'] and
1613                                         time     1185                                         time < d['end']):
1614                                         retur    1186                                         return False
1615                 return True                      1187                 return True
1616         def sourcePhase(self, start):            1188         def sourcePhase(self, start):
1617                 for phase in self.sortedPhase    1189                 for phase in self.sortedPhases():
1618                         if 'machine' in phase    1190                         if 'machine' in phase:
1619                                 continue         1191                                 continue
1620                         pend = self.dmesg[pha    1192                         pend = self.dmesg[phase]['end']
1621                         if start <= pend:        1193                         if start <= pend:
1622                                 return phase     1194                                 return phase
1623                 return 'resume_complete' if ' !! 1195                 return 'resume_complete'
1624         def sourceDevice(self, phaselist, sta    1196         def sourceDevice(self, phaselist, start, end, pid, type):
1625                 tgtdev = ''                      1197                 tgtdev = ''
1626                 for phase in phaselist:          1198                 for phase in phaselist:
1627                         list = self.dmesg[pha    1199                         list = self.dmesg[phase]['list']
1628                         for devname in list:     1200                         for devname in list:
1629                                 dev = list[de    1201                                 dev = list[devname]
1630                                 # pid must ma    1202                                 # pid must match
1631                                 if dev['pid']    1203                                 if dev['pid'] != pid:
1632                                         conti    1204                                         continue
1633                                 devS = dev['s    1205                                 devS = dev['start']
1634                                 devE = dev['e    1206                                 devE = dev['end']
1635                                 if type == 'd    1207                                 if type == 'device':
1636                                         # dev    1208                                         # device target event is entirely inside the source boundary
1637                                         if(st    1209                                         if(start < devS or start >= devE or end <= devS or end > devE):
1638                                                  1210                                                 continue
1639                                 elif type ==     1211                                 elif type == 'thread':
1640                                         # thr    1212                                         # thread target event will expand the source boundary
1641                                         if st    1213                                         if start < devS:
1642                                                  1214                                                 dev['start'] = start
1643                                         if en    1215                                         if end > devE:
1644                                                  1216                                                 dev['end'] = end
1645                                 tgtdev = dev     1217                                 tgtdev = dev
1646                                 break            1218                                 break
1647                 return tgtdev                    1219                 return tgtdev
1648         def addDeviceFunctionCall(self, displ    1220         def addDeviceFunctionCall(self, displayname, kprobename, proc, pid, start, end, cdata, rdata):
1649                 # try to place the call in a     1221                 # try to place the call in a device
1650                 phases = self.sortedPhases()     1222                 phases = self.sortedPhases()
1651                 tgtdev = self.sourceDevice(ph    1223                 tgtdev = self.sourceDevice(phases, start, end, pid, 'device')
1652                 # calls with device pids that    1224                 # calls with device pids that occur outside device bounds are dropped
1653                 # TODO: include these somehow    1225                 # TODO: include these somehow
1654                 if not tgtdev and pid in self    1226                 if not tgtdev and pid in self.devpids:
1655                         return False             1227                         return False
1656                 # try to place the call in a     1228                 # try to place the call in a thread
1657                 if not tgtdev:                   1229                 if not tgtdev:
1658                         tgtdev = self.sourceD    1230                         tgtdev = self.sourceDevice(phases, start, end, pid, 'thread')
1659                 # create new thread blocks, e    1231                 # create new thread blocks, expand as new calls are found
1660                 if not tgtdev:                   1232                 if not tgtdev:
1661                         if proc == '<...>':      1233                         if proc == '<...>':
1662                                 threadname =     1234                                 threadname = 'kthread-%d' % (pid)
1663                         else:                    1235                         else:
1664                                 threadname =     1236                                 threadname = '%s-%d' % (proc, pid)
1665                         tgtphase = self.sourc    1237                         tgtphase = self.sourcePhase(start)
1666                         if not tgtphase:      << 
1667                                 return False  << 
1668                         self.newAction(tgtpha    1238                         self.newAction(tgtphase, threadname, pid, '', start, end, '', ' kth', '')
1669                         return self.addDevice    1239                         return self.addDeviceFunctionCall(displayname, kprobename, proc, pid, start, end, cdata, rdata)
1670                 # this should not happen         1240                 # this should not happen
1671                 if not tgtdev:                   1241                 if not tgtdev:
1672                         sysvals.vprint('[%f -    1242                         sysvals.vprint('[%f - %f] %s-%d %s %s %s' % \
1673                                 (start, end,     1243                                 (start, end, proc, pid, kprobename, cdata, rdata))
1674                         return False             1244                         return False
1675                 # place the call data inside     1245                 # place the call data inside the src element of the tgtdev
1676                 if('src' not in tgtdev):         1246                 if('src' not in tgtdev):
1677                         tgtdev['src'] = []       1247                         tgtdev['src'] = []
1678                 dtf = sysvals.dev_tracefuncs     1248                 dtf = sysvals.dev_tracefuncs
1679                 ubiquitous = False               1249                 ubiquitous = False
1680                 if kprobename in dtf and 'ub'    1250                 if kprobename in dtf and 'ub' in dtf[kprobename]:
1681                         ubiquitous = True        1251                         ubiquitous = True
1682                 mc = re.match(r'\(.*\) *(?P<a !! 1252                 title = cdata+' '+rdata
1683                 mr = re.match(r'\((?P<caller> !! 1253                 mstr = '\(.*\) *(?P<args>.*) *\((?P<caller>.*)\+.* arg1=(?P<ret>.*)'
1684                 if mc and mr:                 !! 1254                 m = re.match(mstr, title)
1685                         c = mr.group('caller' !! 1255                 if m:
1686                         a = mc.group('args'). !! 1256                         c = m.group('caller')
1687                         r = mr.group('ret')   !! 1257                         a = m.group('args').strip()
                                                   >> 1258                         r = m.group('ret')
1688                         if len(r) > 6:           1259                         if len(r) > 6:
1689                                 r = ''           1260                                 r = ''
1690                         else:                    1261                         else:
1691                                 r = 'ret=%s '    1262                                 r = 'ret=%s ' % r
1692                         if ubiquitous and c i    1263                         if ubiquitous and c in dtf and 'ub' in dtf[c]:
1693                                 return False     1264                                 return False
1694                 else:                         << 
1695                         return False          << 
1696                 color = sysvals.kprobeColor(k    1265                 color = sysvals.kprobeColor(kprobename)
1697                 e = DevFunction(displayname,     1266                 e = DevFunction(displayname, a, c, r, start, end, ubiquitous, proc, pid, color)
1698                 tgtdev['src'].append(e)          1267                 tgtdev['src'].append(e)
1699                 return True                      1268                 return True
1700         def overflowDevices(self):               1269         def overflowDevices(self):
1701                 # get a list of devices that     1270                 # get a list of devices that extend beyond the end of this test run
1702                 devlist = []                     1271                 devlist = []
1703                 for phase in self.sortedPhase    1272                 for phase in self.sortedPhases():
1704                         list = self.dmesg[pha    1273                         list = self.dmesg[phase]['list']
1705                         for devname in list:     1274                         for devname in list:
1706                                 dev = list[de    1275                                 dev = list[devname]
1707                                 if dev['end']    1276                                 if dev['end'] > self.end:
1708                                         devli    1277                                         devlist.append(dev)
1709                 return devlist                   1278                 return devlist
1710         def mergeOverlapDevices(self, devlist    1279         def mergeOverlapDevices(self, devlist):
1711                 # merge any devices that over    1280                 # merge any devices that overlap devlist
1712                 for dev in devlist:              1281                 for dev in devlist:
1713                         devname = dev['name']    1282                         devname = dev['name']
1714                         for phase in self.sor    1283                         for phase in self.sortedPhases():
1715                                 list = self.d    1284                                 list = self.dmesg[phase]['list']
1716                                 if devname no    1285                                 if devname not in list:
1717                                         conti    1286                                         continue
1718                                 tdev = list[d    1287                                 tdev = list[devname]
1719                                 o = min(dev['    1288                                 o = min(dev['end'], tdev['end']) - max(dev['start'], tdev['start'])
1720                                 if o <= 0:       1289                                 if o <= 0:
1721                                         conti    1290                                         continue
1722                                 dev['end'] =     1291                                 dev['end'] = tdev['end']
1723                                 if 'src' not     1292                                 if 'src' not in dev or 'src' not in tdev:
1724                                         conti    1293                                         continue
1725                                 dev['src'] +=    1294                                 dev['src'] += tdev['src']
1726                                 del list[devn    1295                                 del list[devname]
1727         def usurpTouchingThread(self, name, d    1296         def usurpTouchingThread(self, name, dev):
1728                 # the caller test has priorit    1297                 # the caller test has priority of this thread, give it to him
1729                 for phase in self.sortedPhase    1298                 for phase in self.sortedPhases():
1730                         list = self.dmesg[pha    1299                         list = self.dmesg[phase]['list']
1731                         if name in list:         1300                         if name in list:
1732                                 tdev = list[n    1301                                 tdev = list[name]
1733                                 if tdev['star    1302                                 if tdev['start'] - dev['end'] < 0.1:
1734                                         dev['    1303                                         dev['end'] = tdev['end']
1735                                         if 's    1304                                         if 'src' not in dev:
1736                                                  1305                                                 dev['src'] = []
1737                                         if 's    1306                                         if 'src' in tdev:
1738                                                  1307                                                 dev['src'] += tdev['src']
1739                                         del l    1308                                         del list[name]
1740                                 break            1309                                 break
1741         def stitchTouchingThreads(self, testl    1310         def stitchTouchingThreads(self, testlist):
1742                 # merge any threads between t    1311                 # merge any threads between tests that touch
1743                 for phase in self.sortedPhase    1312                 for phase in self.sortedPhases():
1744                         list = self.dmesg[pha    1313                         list = self.dmesg[phase]['list']
1745                         for devname in list:     1314                         for devname in list:
1746                                 dev = list[de    1315                                 dev = list[devname]
1747                                 if 'htmlclass    1316                                 if 'htmlclass' not in dev or 'kth' not in dev['htmlclass']:
1748                                         conti    1317                                         continue
1749                                 for data in t    1318                                 for data in testlist:
1750                                         data.    1319                                         data.usurpTouchingThread(devname, dev)
1751         def optimizeDevSrc(self):                1320         def optimizeDevSrc(self):
1752                 # merge any src call loops to    1321                 # merge any src call loops to reduce timeline size
1753                 for phase in self.sortedPhase    1322                 for phase in self.sortedPhases():
1754                         list = self.dmesg[pha    1323                         list = self.dmesg[phase]['list']
1755                         for dev in list:         1324                         for dev in list:
1756                                 if 'src' not     1325                                 if 'src' not in list[dev]:
1757                                         conti    1326                                         continue
1758                                 src = list[de    1327                                 src = list[dev]['src']
1759                                 p = 0            1328                                 p = 0
1760                                 for e in sort    1329                                 for e in sorted(src, key=lambda event: event.time):
1761                                         if no    1330                                         if not p or not e.repeat(p):
1762                                                  1331                                                 p = e
1763                                                  1332                                                 continue
1764                                         # e i    1333                                         # e is another iteration of p, move it into p
1765                                         p.end    1334                                         p.end = e.end
1766                                         p.len    1335                                         p.length = p.end - p.time
1767                                         p.cou    1336                                         p.count += 1
1768                                         src.r    1337                                         src.remove(e)
1769         def trimTimeVal(self, t, t0, dT, left    1338         def trimTimeVal(self, t, t0, dT, left):
1770                 if left:                         1339                 if left:
1771                         if(t > t0):              1340                         if(t > t0):
1772                                 if(t - dT < t    1341                                 if(t - dT < t0):
1773                                         retur    1342                                         return t0
1774                                 return t - dT    1343                                 return t - dT
1775                         else:                    1344                         else:
1776                                 return t         1345                                 return t
1777                 else:                            1346                 else:
1778                         if(t < t0 + dT):         1347                         if(t < t0 + dT):
1779                                 if(t > t0):      1348                                 if(t > t0):
1780                                         retur    1349                                         return t0 + dT
1781                                 return t + dT    1350                                 return t + dT
1782                         else:                    1351                         else:
1783                                 return t         1352                                 return t
1784         def trimTime(self, t0, dT, left):        1353         def trimTime(self, t0, dT, left):
1785                 self.tSuspended = self.trimTi    1354                 self.tSuspended = self.trimTimeVal(self.tSuspended, t0, dT, left)
1786                 self.tResumed = self.trimTime    1355                 self.tResumed = self.trimTimeVal(self.tResumed, t0, dT, left)
1787                 self.start = self.trimTimeVal    1356                 self.start = self.trimTimeVal(self.start, t0, dT, left)
1788                 self.tKernSus = self.trimTime    1357                 self.tKernSus = self.trimTimeVal(self.tKernSus, t0, dT, left)
1789                 self.tKernRes = self.trimTime    1358                 self.tKernRes = self.trimTimeVal(self.tKernRes, t0, dT, left)
1790                 self.end = self.trimTimeVal(s    1359                 self.end = self.trimTimeVal(self.end, t0, dT, left)
1791                 for phase in self.sortedPhase    1360                 for phase in self.sortedPhases():
1792                         p = self.dmesg[phase]    1361                         p = self.dmesg[phase]
1793                         p['start'] = self.tri    1362                         p['start'] = self.trimTimeVal(p['start'], t0, dT, left)
1794                         p['end'] = self.trimT    1363                         p['end'] = self.trimTimeVal(p['end'], t0, dT, left)
1795                         list = p['list']         1364                         list = p['list']
1796                         for name in list:        1365                         for name in list:
1797                                 d = list[name    1366                                 d = list[name]
1798                                 d['start'] =     1367                                 d['start'] = self.trimTimeVal(d['start'], t0, dT, left)
1799                                 d['end'] = se    1368                                 d['end'] = self.trimTimeVal(d['end'], t0, dT, left)
1800                                 d['length'] =    1369                                 d['length'] = d['end'] - d['start']
1801                                 if('ftrace' i    1370                                 if('ftrace' in d):
1802                                         cg =     1371                                         cg = d['ftrace']
1803                                         cg.st    1372                                         cg.start = self.trimTimeVal(cg.start, t0, dT, left)
1804                                         cg.en    1373                                         cg.end = self.trimTimeVal(cg.end, t0, dT, left)
1805                                         for l    1374                                         for line in cg.list:
1806                                                  1375                                                 line.time = self.trimTimeVal(line.time, t0, dT, left)
1807                                 if('src' in d    1376                                 if('src' in d):
1808                                         for e    1377                                         for e in d['src']:
1809                                                  1378                                                 e.time = self.trimTimeVal(e.time, t0, dT, left)
1810                                               << 
1811                                               << 
1812                                 if('cpuexec'  << 
1813                                         cpuex << 
1814                                         for e << 
1815                                               << 
1816                                               << 
1817                                               << 
1818                                               << 
1819                                         d['cp << 
1820                 for dir in ['suspend', 'resum    1379                 for dir in ['suspend', 'resume']:
1821                         list = []                1380                         list = []
1822                         for e in self.errorin    1381                         for e in self.errorinfo[dir]:
1823                                 type, tm, idx    1382                                 type, tm, idx1, idx2 = e
1824                                 tm = self.tri    1383                                 tm = self.trimTimeVal(tm, t0, dT, left)
1825                                 list.append((    1384                                 list.append((type, tm, idx1, idx2))
1826                         self.errorinfo[dir] =    1385                         self.errorinfo[dir] = list
1827         def trimFreezeTime(self, tZero):         1386         def trimFreezeTime(self, tZero):
1828                 # trim out any standby or fre    1387                 # trim out any standby or freeze clock time
1829                 lp = ''                          1388                 lp = ''
1830                 for phase in self.sortedPhase    1389                 for phase in self.sortedPhases():
1831                         if 'resume_machine' i    1390                         if 'resume_machine' in phase and 'suspend_machine' in lp:
1832                                 tS, tR = self    1391                                 tS, tR = self.dmesg[lp]['end'], self.dmesg[phase]['start']
1833                                 tL = tR - tS     1392                                 tL = tR - tS
1834                                 if tL <= 0:   !! 1393                                 if tL > 0:
1835                                         conti !! 1394                                         left = True if tR > tZero else False
1836                                 left = True i !! 1395                                         self.trimTime(tS, tL, left)
1837                                 self.trimTime !! 1396                                         self.tLow.append('%.0f'%(tL*1000))
1838                                 if 'waking' i << 
1839                                         tCnt  << 
1840                                         if se << 
1841                                               << 
1842                                         else: << 
1843                                               << 
1844                                         text  << 
1845                                 else:         << 
1846                                         text  << 
1847                                 self.tLow.app << 
1848                         lp = phase               1397                         lp = phase
1849         def getMemTime(self):                 << 
1850                 if not self.hwstart or not se << 
1851                         return                << 
1852                 stime = (self.tSuspended - se << 
1853                 rtime = (self.end - self.tRes << 
1854                 hws = self.hwstart + timedelt << 
1855                 hwr = self.hwend - timedelta( << 
1856                 self.tLow.append('%.0f'%((hwr << 
1857         def getTimeValues(self):                 1398         def getTimeValues(self):
1858                 s = (self.tSuspended - self.t !! 1399                 sktime = (self.tSuspended - self.tKernSus) * 1000
1859                 r = (self.tKernRes - self.tRe !! 1400                 rktime = (self.tKernRes - self.tResumed) * 1000
1860                 return (max(s, 0), max(r, 0)) !! 1401                 return (sktime, rktime)
1861         def setPhase(self, phase, ktime, isbe    1402         def setPhase(self, phase, ktime, isbegin, order=-1):
1862                 if(isbegin):                     1403                 if(isbegin):
1863                         # phase start over cu    1404                         # phase start over current phase
1864                         if self.currphase:       1405                         if self.currphase:
1865                                 if 'resume_ma    1406                                 if 'resume_machine' not in self.currphase:
1866                                         sysva    1407                                         sysvals.vprint('WARNING: phase %s failed to end' % self.currphase)
1867                                 self.dmesg[se    1408                                 self.dmesg[self.currphase]['end'] = ktime
1868                         phases = self.dmesg.k    1409                         phases = self.dmesg.keys()
1869                         color = self.phasedef    1410                         color = self.phasedef[phase]['color']
1870                         count = len(phases) i    1411                         count = len(phases) if order < 0 else order
1871                         # create unique name     1412                         # create unique name for every new phase
1872                         while phase in phases    1413                         while phase in phases:
1873                                 phase += '*'     1414                                 phase += '*'
1874                         self.dmesg[phase] = {    1415                         self.dmesg[phase] = {'list': dict(), 'start': -1.0, 'end': -1.0,
1875                                 'row': 0, 'co    1416                                 'row': 0, 'color': color, 'order': count}
1876                         self.dmesg[phase]['st    1417                         self.dmesg[phase]['start'] = ktime
1877                         self.currphase = phas    1418                         self.currphase = phase
1878                 else:                            1419                 else:
1879                         # phase end without a    1420                         # phase end without a start
1880                         if phase not in self.    1421                         if phase not in self.currphase:
1881                                 if self.currp    1422                                 if self.currphase:
1882                                         sysva    1423                                         sysvals.vprint('WARNING: %s ended instead of %s, ftrace corruption?' % (phase, self.currphase))
1883                                 else:            1424                                 else:
1884                                         sysva    1425                                         sysvals.vprint('WARNING: %s ended without a start, ftrace corruption?' % phase)
1885                                         retur    1426                                         return phase
1886                         phase = self.currphas    1427                         phase = self.currphase
1887                         self.dmesg[phase]['en    1428                         self.dmesg[phase]['end'] = ktime
1888                         self.currphase = ''      1429                         self.currphase = ''
1889                 return phase                     1430                 return phase
1890         def sortedDevices(self, phase):          1431         def sortedDevices(self, phase):
1891                 list = self.dmesg[phase]['lis    1432                 list = self.dmesg[phase]['list']
1892                 return sorted(list, key=lambd !! 1433                 slist = []
                                                   >> 1434                 tmp = dict()
                                                   >> 1435                 for devname in list:
                                                   >> 1436                         dev = list[devname]
                                                   >> 1437                         if dev['length'] == 0:
                                                   >> 1438                                 continue
                                                   >> 1439                         tmp[dev['start']] = devname
                                                   >> 1440                 for t in sorted(tmp):
                                                   >> 1441                         slist.append(tmp[t])
                                                   >> 1442                 return slist
1893         def fixupInitcalls(self, phase):         1443         def fixupInitcalls(self, phase):
1894                 # if any calls never returned    1444                 # if any calls never returned, clip them at system resume end
1895                 phaselist = self.dmesg[phase]    1445                 phaselist = self.dmesg[phase]['list']
1896                 for devname in phaselist:        1446                 for devname in phaselist:
1897                         dev = phaselist[devna    1447                         dev = phaselist[devname]
1898                         if(dev['end'] < 0):      1448                         if(dev['end'] < 0):
1899                                 for p in self    1449                                 for p in self.sortedPhases():
1900                                         if se    1450                                         if self.dmesg[p]['end'] > dev['start']:
1901                                                  1451                                                 dev['end'] = self.dmesg[p]['end']
1902                                                  1452                                                 break
1903                                 sysvals.vprin    1453                                 sysvals.vprint('%s (%s): callback didnt return' % (devname, phase))
1904         def deviceFilter(self, devicefilter):    1454         def deviceFilter(self, devicefilter):
1905                 for phase in self.sortedPhase    1455                 for phase in self.sortedPhases():
1906                         list = self.dmesg[pha    1456                         list = self.dmesg[phase]['list']
1907                         rmlist = []              1457                         rmlist = []
1908                         for name in list:        1458                         for name in list:
1909                                 keep = False     1459                                 keep = False
1910                                 for filter in    1460                                 for filter in devicefilter:
1911                                         if fi    1461                                         if filter in name or \
1912                                                  1462                                                 ('drv' in list[name] and filter in list[name]['drv']):
1913                                                  1463                                                 keep = True
1914                                 if not keep:     1464                                 if not keep:
1915                                         rmlis    1465                                         rmlist.append(name)
1916                         for name in rmlist:      1466                         for name in rmlist:
1917                                 del list[name    1467                                 del list[name]
1918         def fixupInitcallsThatDidntReturn(sel    1468         def fixupInitcallsThatDidntReturn(self):
1919                 # if any calls never returned    1469                 # if any calls never returned, clip them at system resume end
1920                 for phase in self.sortedPhase    1470                 for phase in self.sortedPhases():
1921                         self.fixupInitcalls(p    1471                         self.fixupInitcalls(phase)
1922         def phaseOverlap(self, phases):          1472         def phaseOverlap(self, phases):
1923                 rmgroups = []                    1473                 rmgroups = []
1924                 newgroup = []                    1474                 newgroup = []
1925                 for group in self.devicegroup    1475                 for group in self.devicegroups:
1926                         for phase in phases:     1476                         for phase in phases:
1927                                 if phase not     1477                                 if phase not in group:
1928                                         conti    1478                                         continue
1929                                 for p in grou    1479                                 for p in group:
1930                                         if p     1480                                         if p not in newgroup:
1931                                                  1481                                                 newgroup.append(p)
1932                                 if group not     1482                                 if group not in rmgroups:
1933                                         rmgro    1483                                         rmgroups.append(group)
1934                 for group in rmgroups:           1484                 for group in rmgroups:
1935                         self.devicegroups.rem    1485                         self.devicegroups.remove(group)
1936                 self.devicegroups.append(newg    1486                 self.devicegroups.append(newgroup)
1937         def newActionGlobal(self, name, start    1487         def newActionGlobal(self, name, start, end, pid=-1, color=''):
1938                 # which phase is this device     1488                 # which phase is this device callback or action in
1939                 phases = self.sortedPhases()     1489                 phases = self.sortedPhases()
1940                 targetphase = 'none'             1490                 targetphase = 'none'
1941                 htmlclass = ''                   1491                 htmlclass = ''
1942                 overlap = 0.0                    1492                 overlap = 0.0
1943                 myphases = []                    1493                 myphases = []
1944                 for phase in phases:             1494                 for phase in phases:
1945                         pstart = self.dmesg[p    1495                         pstart = self.dmesg[phase]['start']
1946                         pend = self.dmesg[pha    1496                         pend = self.dmesg[phase]['end']
1947                         # see if the action o    1497                         # see if the action overlaps this phase
1948                         o = max(0, min(end, p    1498                         o = max(0, min(end, pend) - max(start, pstart))
1949                         if o > 0:                1499                         if o > 0:
1950                                 myphases.appe    1500                                 myphases.append(phase)
1951                         # set the target phas    1501                         # set the target phase to the one that overlaps most
1952                         if o > overlap:          1502                         if o > overlap:
1953                                 if overlap >     1503                                 if overlap > 0 and phase == 'post_resume':
1954                                         conti    1504                                         continue
1955                                 targetphase =    1505                                 targetphase = phase
1956                                 overlap = o      1506                                 overlap = o
1957                 # if no target phase was foun    1507                 # if no target phase was found, pin it to the edge
1958                 if targetphase == 'none':        1508                 if targetphase == 'none':
1959                         p0start = self.dmesg[    1509                         p0start = self.dmesg[phases[0]]['start']
1960                         if start <= p0start:     1510                         if start <= p0start:
1961                                 targetphase =    1511                                 targetphase = phases[0]
1962                         else:                    1512                         else:
1963                                 targetphase =    1513                                 targetphase = phases[-1]
1964                 if pid == -2:                    1514                 if pid == -2:
1965                         htmlclass = ' bg'        1515                         htmlclass = ' bg'
1966                 elif pid == -3:                  1516                 elif pid == -3:
1967                         htmlclass = ' ps'        1517                         htmlclass = ' ps'
1968                 if len(myphases) > 1:            1518                 if len(myphases) > 1:
1969                         htmlclass = ' bg'        1519                         htmlclass = ' bg'
1970                         self.phaseOverlap(myp    1520                         self.phaseOverlap(myphases)
1971                 if targetphase in phases:        1521                 if targetphase in phases:
1972                         newname = self.newAct    1522                         newname = self.newAction(targetphase, name, pid, '', start, end, '', htmlclass, color)
1973                         return (targetphase,     1523                         return (targetphase, newname)
1974                 return False                     1524                 return False
1975         def newAction(self, phase, name, pid,    1525         def newAction(self, phase, name, pid, parent, start, end, drv, htmlclass='', color=''):
1976                 # new device callback for a s    1526                 # new device callback for a specific phase
1977                 self.html_device_id += 1         1527                 self.html_device_id += 1
1978                 devid = '%s%d' % (self.idstr,    1528                 devid = '%s%d' % (self.idstr, self.html_device_id)
1979                 list = self.dmesg[phase]['lis    1529                 list = self.dmesg[phase]['list']
1980                 length = -1.0                    1530                 length = -1.0
1981                 if(start >= 0 and end >= 0):     1531                 if(start >= 0 and end >= 0):
1982                         length = end - start     1532                         length = end - start
1983                 if pid == -2 or name not in s !! 1533                 if pid == -2:
1984                         i = 2                    1534                         i = 2
1985                         origname = name          1535                         origname = name
1986                         while(name in list):     1536                         while(name in list):
1987                                 name = '%s[%d    1537                                 name = '%s[%d]' % (origname, i)
1988                                 i += 1           1538                                 i += 1
1989                 list[name] = {'name': name, '    1539                 list[name] = {'name': name, 'start': start, 'end': end, 'pid': pid,
1990                         'par': parent, 'lengt    1540                         'par': parent, 'length': length, 'row': 0, 'id': devid, 'drv': drv }
1991                 if htmlclass:                    1541                 if htmlclass:
1992                         list[name]['htmlclass    1542                         list[name]['htmlclass'] = htmlclass
1993                 if color:                        1543                 if color:
1994                         list[name]['color'] =    1544                         list[name]['color'] = color
1995                 return name                      1545                 return name
1996         def findDevice(self, phase, name):    << 
1997                 list = self.dmesg[phase]['lis << 
1998                 mydev = ''                    << 
1999                 for devname in sorted(list):  << 
2000                         if name == devname or << 
2001                                 mydev = devna << 
2002                 if mydev:                     << 
2003                         return list[mydev]    << 
2004                 return False                  << 
2005         def deviceChildren(self, devname, pha    1546         def deviceChildren(self, devname, phase):
2006                 devlist = []                     1547                 devlist = []
2007                 list = self.dmesg[phase]['lis    1548                 list = self.dmesg[phase]['list']
2008                 for child in list:               1549                 for child in list:
2009                         if(list[child]['par']    1550                         if(list[child]['par'] == devname):
2010                                 devlist.appen    1551                                 devlist.append(child)
2011                 return devlist                   1552                 return devlist
2012         def maxDeviceNameSize(self, phase):      1553         def maxDeviceNameSize(self, phase):
2013                 size = 0                         1554                 size = 0
2014                 for name in self.dmesg[phase]    1555                 for name in self.dmesg[phase]['list']:
2015                         if len(name) > size:     1556                         if len(name) > size:
2016                                 size = len(na    1557                                 size = len(name)
2017                 return size                      1558                 return size
2018         def printDetails(self):                  1559         def printDetails(self):
2019                 sysvals.vprint('Timeline Deta    1560                 sysvals.vprint('Timeline Details:')
2020                 sysvals.vprint('          tes    1561                 sysvals.vprint('          test start: %f' % self.start)
2021                 sysvals.vprint('kernel suspen    1562                 sysvals.vprint('kernel suspend start: %f' % self.tKernSus)
2022                 tS = tR = False                  1563                 tS = tR = False
2023                 for phase in self.sortedPhase    1564                 for phase in self.sortedPhases():
2024                         devlist = self.dmesg[    1565                         devlist = self.dmesg[phase]['list']
2025                         dc, ps, pe = len(devl    1566                         dc, ps, pe = len(devlist), self.dmesg[phase]['start'], self.dmesg[phase]['end']
2026                         if not tS and ps >= s    1567                         if not tS and ps >= self.tSuspended:
2027                                 sysvals.vprin    1568                                 sysvals.vprint('   machine suspended: %f' % self.tSuspended)
2028                                 tS = True        1569                                 tS = True
2029                         if not tR and ps >= s    1570                         if not tR and ps >= self.tResumed:
2030                                 sysvals.vprin    1571                                 sysvals.vprint('     machine resumed: %f' % self.tResumed)
2031                                 tR = True        1572                                 tR = True
2032                         sysvals.vprint('%20s:    1573                         sysvals.vprint('%20s: %f - %f (%d devices)' % (phase, ps, pe, dc))
2033                         if sysvals.devdump:      1574                         if sysvals.devdump:
2034                                 sysvals.vprin    1575                                 sysvals.vprint(''.join('-' for i in range(80)))
2035                                 maxname = '%d    1576                                 maxname = '%d' % self.maxDeviceNameSize(phase)
2036                                 fmt = '%3d) %    1577                                 fmt = '%3d) %'+maxname+'s - %f - %f'
2037                                 c = 1            1578                                 c = 1
2038                                 for name in s !! 1579                                 for name in devlist:
2039                                         s = d    1580                                         s = devlist[name]['start']
2040                                         e = d    1581                                         e = devlist[name]['end']
2041                                         sysva    1582                                         sysvals.vprint(fmt % (c, name, s, e))
2042                                         c +=     1583                                         c += 1
2043                                 sysvals.vprin    1584                                 sysvals.vprint(''.join('-' for i in range(80)))
2044                 sysvals.vprint('   kernel res    1585                 sysvals.vprint('   kernel resume end: %f' % self.tKernRes)
2045                 sysvals.vprint('            t    1586                 sysvals.vprint('            test end: %f' % self.end)
2046         def deviceChildrenAllPhases(self, dev    1587         def deviceChildrenAllPhases(self, devname):
2047                 devlist = []                     1588                 devlist = []
2048                 for phase in self.sortedPhase    1589                 for phase in self.sortedPhases():
2049                         list = self.deviceChi    1590                         list = self.deviceChildren(devname, phase)
2050                         for dev in sorted(lis !! 1591                         for dev in list:
2051                                 if dev not in    1592                                 if dev not in devlist:
2052                                         devli    1593                                         devlist.append(dev)
2053                 return devlist                   1594                 return devlist
2054         def masterTopology(self, name, list,     1595         def masterTopology(self, name, list, depth):
2055                 node = DeviceNode(name, depth    1596                 node = DeviceNode(name, depth)
2056                 for cname in list:               1597                 for cname in list:
2057                         # avoid recursions       1598                         # avoid recursions
2058                         if name == cname:        1599                         if name == cname:
2059                                 continue         1600                                 continue
2060                         clist = self.deviceCh    1601                         clist = self.deviceChildrenAllPhases(cname)
2061                         cnode = self.masterTo    1602                         cnode = self.masterTopology(cname, clist, depth+1)
2062                         node.children.append(    1603                         node.children.append(cnode)
2063                 return node                      1604                 return node
2064         def printTopology(self, node):           1605         def printTopology(self, node):
2065                 html = ''                        1606                 html = ''
2066                 if node.name:                    1607                 if node.name:
2067                         info = ''                1608                         info = ''
2068                         drv = ''                 1609                         drv = ''
2069                         for phase in self.sor    1610                         for phase in self.sortedPhases():
2070                                 list = self.d    1611                                 list = self.dmesg[phase]['list']
2071                                 if node.name     1612                                 if node.name in list:
2072                                         s = l    1613                                         s = list[node.name]['start']
2073                                         e = l    1614                                         e = list[node.name]['end']
2074                                         if li    1615                                         if list[node.name]['drv']:
2075                                                  1616                                                 drv = ' {'+list[node.name]['drv']+'}'
2076                                         info     1617                                         info += ('<li>%s: %.3fms</li>' % (phase, (e-s)*1000))
2077                         html += '<li><b>'+nod    1618                         html += '<li><b>'+node.name+drv+'</b>'
2078                         if info:                 1619                         if info:
2079                                 html += '<ul>    1620                                 html += '<ul>'+info+'</ul>'
2080                         html += '</li>'          1621                         html += '</li>'
2081                 if len(node.children) > 0:       1622                 if len(node.children) > 0:
2082                         html += '<ul>'           1623                         html += '<ul>'
2083                         for cnode in node.chi    1624                         for cnode in node.children:
2084                                 html += self.    1625                                 html += self.printTopology(cnode)
2085                         html += '</ul>'          1626                         html += '</ul>'
2086                 return html                      1627                 return html
2087         def rootDeviceList(self):                1628         def rootDeviceList(self):
2088                 # list of devices graphed        1629                 # list of devices graphed
2089                 real = []                        1630                 real = []
2090                 for phase in self.sortedPhase !! 1631                 for phase in self.dmesg:
2091                         list = self.dmesg[pha    1632                         list = self.dmesg[phase]['list']
2092                         for dev in sorted(lis !! 1633                         for dev in list:
2093                                 if list[dev][    1634                                 if list[dev]['pid'] >= 0 and dev not in real:
2094                                         real.    1635                                         real.append(dev)
2095                 # list of top-most root devic    1636                 # list of top-most root devices
2096                 rootlist = []                    1637                 rootlist = []
2097                 for phase in self.sortedPhase !! 1638                 for phase in self.dmesg:
2098                         list = self.dmesg[pha    1639                         list = self.dmesg[phase]['list']
2099                         for dev in sorted(lis !! 1640                         for dev in list:
2100                                 pdev = list[d    1641                                 pdev = list[dev]['par']
2101                                 pid = list[de    1642                                 pid = list[dev]['pid']
2102                                 if(pid < 0 or !! 1643                                 if(pid < 0 or re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)):
2103                                         conti    1644                                         continue
2104                                 if pdev and p    1645                                 if pdev and pdev not in real and pdev not in rootlist:
2105                                         rootl    1646                                         rootlist.append(pdev)
2106                 return rootlist                  1647                 return rootlist
2107         def deviceTopology(self):                1648         def deviceTopology(self):
2108                 rootlist = self.rootDeviceLis    1649                 rootlist = self.rootDeviceList()
2109                 master = self.masterTopology(    1650                 master = self.masterTopology('', rootlist, 0)
2110                 return self.printTopology(mas    1651                 return self.printTopology(master)
2111         def selectTimelineDevices(self, widfm    1652         def selectTimelineDevices(self, widfmt, tTotal, mindevlen):
2112                 # only select devices that wi    1653                 # only select devices that will actually show up in html
2113                 self.tdevlist = dict()           1654                 self.tdevlist = dict()
2114                 for phase in self.dmesg:         1655                 for phase in self.dmesg:
2115                         devlist = []             1656                         devlist = []
2116                         list = self.dmesg[pha    1657                         list = self.dmesg[phase]['list']
2117                         for dev in list:         1658                         for dev in list:
2118                                 length = (lis    1659                                 length = (list[dev]['end'] - list[dev]['start']) * 1000
2119                                 width = widfm    1660                                 width = widfmt % (((list[dev]['end']-list[dev]['start'])*100)/tTotal)
2120                                 if length >=  !! 1661                                 if width != '0.000000' and length >= mindevlen:
2121                                         devli    1662                                         devlist.append(dev)
2122                         self.tdevlist[phase]     1663                         self.tdevlist[phase] = devlist
2123         def addHorizontalDivider(self, devnam    1664         def addHorizontalDivider(self, devname, devend):
2124                 phase = 'suspend_prepare'        1665                 phase = 'suspend_prepare'
2125                 self.newAction(phase, devname    1666                 self.newAction(phase, devname, -2, '', \
2126                         self.start, devend, '    1667                         self.start, devend, '', ' sec', '')
2127                 if phase not in self.tdevlist    1668                 if phase not in self.tdevlist:
2128                         self.tdevlist[phase]     1669                         self.tdevlist[phase] = []
2129                 self.tdevlist[phase].append(d    1670                 self.tdevlist[phase].append(devname)
2130                 d = DevItem(0, phase, self.dm    1671                 d = DevItem(0, phase, self.dmesg[phase]['list'][devname])
2131                 return d                         1672                 return d
2132         def addProcessUsageEvent(self, name,     1673         def addProcessUsageEvent(self, name, times):
2133                 # get the start and end times    1674                 # get the start and end times for this process
2134                 cpuexec = dict()              !! 1675                 maxC = 0
2135                 tlast = start = end = -1      !! 1676                 tlast = 0
                                                   >> 1677                 start = -1
                                                   >> 1678                 end = -1
2136                 for t in sorted(times):          1679                 for t in sorted(times):
2137                         if tlast < 0:         !! 1680                         if tlast == 0:
2138                                 tlast = t        1681                                 tlast = t
2139                                 continue         1682                                 continue
2140                         if name in self.pstl[ !! 1683                         if name in self.pstl[t]:
2141                                 if start < 0: !! 1684                                 if start == -1 or tlast < start:
2142                                         start    1685                                         start = tlast
2143                                 end, key = t, !! 1686                                 if end == -1 or t > end:
2144                                 maxj = (t - t !! 1687                                         end = t
2145                                 cpuexec[key]  << 
2146                         tlast = t                1688                         tlast = t
2147                 if start < 0 or end < 0:      !! 1689                 if start == -1 or end == -1:
2148                         return                !! 1690                         return 0
2149                 # add a new action for this p    1691                 # add a new action for this process and get the object
2150                 out = self.newActionGlobal(na    1692                 out = self.newActionGlobal(name, start, end, -3)
2151                 if out:                       !! 1693                 if not out:
2152                         phase, devname = out  !! 1694                         return 0
2153                         dev = self.dmesg[phas !! 1695                 phase, devname = out
2154                         dev['cpuexec'] = cpue !! 1696                 dev = self.dmesg[phase]['list'][devname]
                                                   >> 1697                 # get the cpu exec data
                                                   >> 1698                 tlast = 0
                                                   >> 1699                 clast = 0
                                                   >> 1700                 cpuexec = dict()
                                                   >> 1701                 for t in sorted(times):
                                                   >> 1702                         if tlast == 0 or t <= start or t > end:
                                                   >> 1703                                 tlast = t
                                                   >> 1704                                 continue
                                                   >> 1705                         list = self.pstl[t]
                                                   >> 1706                         c = 0
                                                   >> 1707                         if name in list:
                                                   >> 1708                                 c = list[name]
                                                   >> 1709                         if c > maxC:
                                                   >> 1710                                 maxC = c
                                                   >> 1711                         if c != clast:
                                                   >> 1712                                 key = (tlast, t)
                                                   >> 1713                                 cpuexec[key] = c
                                                   >> 1714                                 tlast = t
                                                   >> 1715                                 clast = c
                                                   >> 1716                 dev['cpuexec'] = cpuexec
                                                   >> 1717                 return maxC
2155         def createProcessUsageEvents(self):      1718         def createProcessUsageEvents(self):
2156                 # get an array of process nam !! 1719                 # get an array of process names
2157                 proclist = {'sus': dict(), 'r !! 1720                 proclist = []
2158                 tdata = {'sus': [], 'res': [] !! 1721                 for t in self.pstl:
                                                   >> 1722                         pslist = self.pstl[t]
                                                   >> 1723                         for ps in pslist:
                                                   >> 1724                                 if ps not in proclist:
                                                   >> 1725                                         proclist.append(ps)
                                                   >> 1726                 # get a list of data points for suspend and resume
                                                   >> 1727                 tsus = []
                                                   >> 1728                 tres = []
2159                 for t in sorted(self.pstl):      1729                 for t in sorted(self.pstl):
2160                         dir = 'sus' if t < se !! 1730                         if t < self.tSuspended:
2161                         for ps in sorted(self !! 1731                                 tsus.append(t)
2162                                 if ps not in  !! 1732                         else:
2163                                         procl !! 1733                                 tres.append(t)
2164                         tdata[dir].append(t)  << 
2165                 # process the events for susp    1734                 # process the events for suspend and resume
2166                 if len(proclist['sus']) > 0 o !! 1735                 if len(proclist) > 0:
2167                         sysvals.vprint('Proce    1736                         sysvals.vprint('Process Execution:')
2168                 for dir in ['sus', 'res']:    !! 1737                 for ps in proclist:
2169                         for ps in sorted(proc !! 1738                         c = self.addProcessUsageEvent(ps, tsus)
2170                                 self.addProce !! 1739                         if c > 0:
2171         def handleEndMarker(self, time, msg=' !! 1740                                 sysvals.vprint('%25s (sus): %d' % (ps, c))
                                                   >> 1741                         c = self.addProcessUsageEvent(ps, tres)
                                                   >> 1742                         if c > 0:
                                                   >> 1743                                 sysvals.vprint('%25s (res): %d' % (ps, c))
                                                   >> 1744         def handleEndMarker(self, time):
2172                 dm = self.dmesg                  1745                 dm = self.dmesg
2173                 self.setEnd(time, msg)        !! 1746                 self.setEnd(time)
2174                 self.initDevicegroups()          1747                 self.initDevicegroups()
2175                 # give suspend_prepare an end    1748                 # give suspend_prepare an end if needed
2176                 if 'suspend_prepare' in dm an    1749                 if 'suspend_prepare' in dm and dm['suspend_prepare']['end'] < 0:
2177                         dm['suspend_prepare']    1750                         dm['suspend_prepare']['end'] = time
2178                 # assume resume machine ends     1751                 # assume resume machine ends at next phase start
2179                 if 'resume_machine' in dm and    1752                 if 'resume_machine' in dm and dm['resume_machine']['end'] < 0:
2180                         np = self.nextPhase('    1753                         np = self.nextPhase('resume_machine', 1)
2181                         if np:                   1754                         if np:
2182                                 dm['resume_ma    1755                                 dm['resume_machine']['end'] = dm[np]['start']
2183                 # if kernel resume end not fo    1756                 # if kernel resume end not found, assume its the end marker
2184                 if self.tKernRes == 0.0:         1757                 if self.tKernRes == 0.0:
2185                         self.tKernRes = time     1758                         self.tKernRes = time
2186                 # if kernel suspend start not    1759                 # if kernel suspend start not found, assume its the end marker
2187                 if self.tKernSus == 0.0:         1760                 if self.tKernSus == 0.0:
2188                         self.tKernSus = time     1761                         self.tKernSus = time
2189                 # set resume complete to end     1762                 # set resume complete to end at end marker
2190                 if 'resume_complete' in dm:      1763                 if 'resume_complete' in dm:
2191                         dm['resume_complete']    1764                         dm['resume_complete']['end'] = time
2192         def initcall_debug_call(self, line, q << 
2193                 m = re.match(r'.*(\[ *)(?P<t> << 
2194                         r'PM: *calling .* @ ( << 
2195                 if not m:                     << 
2196                         m = re.match(r'.*(\[  << 
2197                                 r'calling .*  << 
2198                 if not m:                     << 
2199                         m = re.match(r'.*(\[  << 
2200                                 r'(?P<f>.*)\+  << 
2201                 if m:                         << 
2202                         return True if quick  << 
2203                 return False if quick else (' << 
2204         def initcall_debug_return(self, line, << 
2205                 m = re.match(r'.*(\[ *)(?P<t> << 
2206                         r'.* returned (?P<r>[ << 
2207                 if not m:                     << 
2208                         m = re.match(r'.*(\[  << 
2209                                 r'.* returned << 
2210                 if not m:                     << 
2211                         m = re.match(r'.*(\[  << 
2212                                 r'(?P<f>.*)\+ << 
2213                 if m:                         << 
2214                         return True if quick  << 
2215                 return False if quick else (' << 
2216         def debugPrint(self):                    1765         def debugPrint(self):
2217                 for p in self.sortedPhases():    1766                 for p in self.sortedPhases():
2218                         list = self.dmesg[p][    1767                         list = self.dmesg[p]['list']
2219                         for devname in sorted !! 1768                         for devname in list:
2220                                 dev = list[de    1769                                 dev = list[devname]
2221                                 if 'ftrace' i    1770                                 if 'ftrace' in dev:
2222                                         dev['    1771                                         dev['ftrace'].debugPrint(' [%s]' % devname)
2223                                                  1772 
2224 # Class: DevFunction                             1773 # Class: DevFunction
2225 # Description:                                   1774 # Description:
2226 #        A container for kprobe function data    1775 #        A container for kprobe function data we want in the dev timeline
2227 class DevFunction:                               1776 class DevFunction:
2228         def __init__(self, name, args, caller    1777         def __init__(self, name, args, caller, ret, start, end, u, proc, pid, color):
2229                 self.row = 0                     1778                 self.row = 0
2230                 self.count = 1                   1779                 self.count = 1
2231                 self.name = name                 1780                 self.name = name
2232                 self.args = args                 1781                 self.args = args
2233                 self.caller = caller             1782                 self.caller = caller
2234                 self.ret = ret                   1783                 self.ret = ret
2235                 self.time = start                1784                 self.time = start
2236                 self.length = end - start        1785                 self.length = end - start
2237                 self.end = end                   1786                 self.end = end
2238                 self.ubiquitous = u              1787                 self.ubiquitous = u
2239                 self.proc = proc                 1788                 self.proc = proc
2240                 self.pid = pid                   1789                 self.pid = pid
2241                 self.color = color               1790                 self.color = color
2242         def title(self):                         1791         def title(self):
2243                 cnt = ''                         1792                 cnt = ''
2244                 if self.count > 1:               1793                 if self.count > 1:
2245                         cnt = '(x%d)' % self.    1794                         cnt = '(x%d)' % self.count
2246                 l = '%0.3fms' % (self.length     1795                 l = '%0.3fms' % (self.length * 1000)
2247                 if self.ubiquitous:              1796                 if self.ubiquitous:
2248                         title = '%s(%s)%s <-     1797                         title = '%s(%s)%s <- %s, %s(%s)' % \
2249                                 (self.name, s    1798                                 (self.name, self.args, cnt, self.caller, self.ret, l)
2250                 else:                            1799                 else:
2251                         title = '%s(%s) %s%s(    1800                         title = '%s(%s) %s%s(%s)' % (self.name, self.args, self.ret, cnt, l)
2252                 return title.replace('"', '')    1801                 return title.replace('"', '')
2253         def text(self):                          1802         def text(self):
2254                 if self.count > 1:               1803                 if self.count > 1:
2255                         text = '%s(x%d)' % (s    1804                         text = '%s(x%d)' % (self.name, self.count)
2256                 else:                            1805                 else:
2257                         text = self.name         1806                         text = self.name
2258                 return text                      1807                 return text
2259         def repeat(self, tgt):                   1808         def repeat(self, tgt):
2260                 # is the tgt call just a repe    1809                 # is the tgt call just a repeat of this call (e.g. are we in a loop)
2261                 dt = self.time - tgt.end         1810                 dt = self.time - tgt.end
2262                 # only combine calls if -all-    1811                 # only combine calls if -all- attributes are identical
2263                 if tgt.caller == self.caller     1812                 if tgt.caller == self.caller and \
2264                         tgt.name == self.name    1813                         tgt.name == self.name and tgt.args == self.args and \
2265                         tgt.proc == self.proc    1814                         tgt.proc == self.proc and tgt.pid == self.pid and \
2266                         tgt.ret == self.ret a    1815                         tgt.ret == self.ret and dt >= 0 and \
2267                         dt <= sysvals.callloo    1816                         dt <= sysvals.callloopmaxgap and \
2268                         self.length < sysvals    1817                         self.length < sysvals.callloopmaxlen:
2269                         return True              1818                         return True
2270                 return False                     1819                 return False
2271                                                  1820 
2272 # Class: FTraceLine                              1821 # Class: FTraceLine
2273 # Description:                                   1822 # Description:
2274 #        A container for a single line of ftr    1823 #        A container for a single line of ftrace data. There are six basic types:
2275 #                callgraph line:                 1824 #                callgraph line:
2276 #                         call: "  dpm_run_ca    1825 #                         call: "  dpm_run_callback() {"
2277 #                       return: "  }"            1826 #                       return: "  }"
2278 #                         leaf: " dpm_run_cal    1827 #                         leaf: " dpm_run_callback();"
2279 #                trace event:                    1828 #                trace event:
2280 #                        tracing_mark_write:     1829 #                        tracing_mark_write: SUSPEND START or RESUME COMPLETE
2281 #                        suspend_resume: phas    1830 #                        suspend_resume: phase or custom exec block data
2282 #                        device_pm_callback:     1831 #                        device_pm_callback: device callback info
2283 class FTraceLine:                                1832 class FTraceLine:
2284         def __init__(self, t, m='', d=''):       1833         def __init__(self, t, m='', d=''):
2285                 self.length = 0.0                1834                 self.length = 0.0
2286                 self.fcall = False               1835                 self.fcall = False
2287                 self.freturn = False             1836                 self.freturn = False
2288                 self.fevent = False              1837                 self.fevent = False
2289                 self.fkprobe = False             1838                 self.fkprobe = False
2290                 self.depth = 0                   1839                 self.depth = 0
2291                 self.name = ''                   1840                 self.name = ''
2292                 self.type = ''                   1841                 self.type = ''
2293                 self.time = float(t)             1842                 self.time = float(t)
2294                 if not m and not d:              1843                 if not m and not d:
2295                         return                   1844                         return
2296                 # is this a trace event          1845                 # is this a trace event
2297                 if(d == 'traceevent' or re.ma !! 1846                 if(d == 'traceevent' or re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m)):
2298                         if(d == 'traceevent')    1847                         if(d == 'traceevent'):
2299                                 # nop format     1848                                 # nop format trace event
2300                                 msg = m          1849                                 msg = m
2301                         else:                    1850                         else:
2302                                 # function_gr    1851                                 # function_graph format trace event
2303                                 em = re.match !! 1852                                 em = re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m)
2304                                 msg = em.grou    1853                                 msg = em.group('msg')
2305                                                  1854 
2306                         emm = re.match(r'^(?P !! 1855                         emm = re.match('^(?P<call>.*?): (?P<msg>.*)', msg)
2307                         if(emm):                 1856                         if(emm):
2308                                 self.name = e    1857                                 self.name = emm.group('msg')
2309                                 self.type = e    1858                                 self.type = emm.group('call')
2310                         else:                    1859                         else:
2311                                 self.name = m    1860                                 self.name = msg
2312                         km = re.match(r'^(?P< !! 1861                         km = re.match('^(?P<n>.*)_cal$', self.type)
2313                         if km:                   1862                         if km:
2314                                 self.fcall =     1863                                 self.fcall = True
2315                                 self.fkprobe     1864                                 self.fkprobe = True
2316                                 self.type = k    1865                                 self.type = km.group('n')
2317                                 return           1866                                 return
2318                         km = re.match(r'^(?P< !! 1867                         km = re.match('^(?P<n>.*)_ret$', self.type)
2319                         if km:                   1868                         if km:
2320                                 self.freturn     1869                                 self.freturn = True
2321                                 self.fkprobe     1870                                 self.fkprobe = True
2322                                 self.type = k    1871                                 self.type = km.group('n')
2323                                 return           1872                                 return
2324                         self.fevent = True       1873                         self.fevent = True
2325                         return                   1874                         return
2326                 # convert the duration to sec    1875                 # convert the duration to seconds
2327                 if(d):                           1876                 if(d):
2328                         self.length = float(d    1877                         self.length = float(d)/1000000
2329                 # the indentation determines     1878                 # the indentation determines the depth
2330                 match = re.match(r'^(?P<d> *) !! 1879                 match = re.match('^(?P<d> *)(?P<o>.*)$', m)
2331                 if(not match):                   1880                 if(not match):
2332                         return                   1881                         return
2333                 self.depth = self.getDepth(ma    1882                 self.depth = self.getDepth(match.group('d'))
2334                 m = match.group('o')             1883                 m = match.group('o')
2335                 # function return                1884                 # function return
2336                 if(m[0] == '}'):                 1885                 if(m[0] == '}'):
2337                         self.freturn = True      1886                         self.freturn = True
2338                         if(len(m) > 1):          1887                         if(len(m) > 1):
2339                                 # includes co    1888                                 # includes comment with function name
2340                                 match = re.ma !! 1889                                 match = re.match('^} *\/\* *(?P<n>.*) *\*\/$', m)
2341                                 if(match):       1890                                 if(match):
2342                                         self.    1891                                         self.name = match.group('n').strip()
2343                 # function call                  1892                 # function call
2344                 else:                            1893                 else:
2345                         self.fcall = True        1894                         self.fcall = True
2346                         # function call with     1895                         # function call with children
2347                         if(m[-1] == '{'):        1896                         if(m[-1] == '{'):
2348                                 match = re.ma !! 1897                                 match = re.match('^(?P<n>.*) *\(.*', m)
2349                                 if(match):       1898                                 if(match):
2350                                         self.    1899                                         self.name = match.group('n').strip()
2351                         # function call with     1900                         # function call with no children (leaf)
2352                         elif(m[-1] == ';'):      1901                         elif(m[-1] == ';'):
2353                                 self.freturn     1902                                 self.freturn = True
2354                                 match = re.ma !! 1903                                 match = re.match('^(?P<n>.*) *\(.*', m)
2355                                 if(match):       1904                                 if(match):
2356                                         self.    1905                                         self.name = match.group('n').strip()
2357                         # something else (pos    1906                         # something else (possibly a trace marker)
2358                         else:                    1907                         else:
2359                                 self.name = m    1908                                 self.name = m
2360         def isCall(self):                        1909         def isCall(self):
2361                 return self.fcall and not sel    1910                 return self.fcall and not self.freturn
2362         def isReturn(self):                      1911         def isReturn(self):
2363                 return self.freturn and not s    1912                 return self.freturn and not self.fcall
2364         def isLeaf(self):                        1913         def isLeaf(self):
2365                 return self.fcall and self.fr    1914                 return self.fcall and self.freturn
2366         def getDepth(self, str):                 1915         def getDepth(self, str):
2367                 return len(str)/2                1916                 return len(str)/2
2368         def debugPrint(self, info=''):           1917         def debugPrint(self, info=''):
2369                 if self.isLeaf():                1918                 if self.isLeaf():
2370                         pprint(' -- %12.6f (d    1919                         pprint(' -- %12.6f (depth=%02d): %s(); (%.3f us) %s' % (self.time, \
2371                                 self.depth, s    1920                                 self.depth, self.name, self.length*1000000, info))
2372                 elif self.freturn:               1921                 elif self.freturn:
2373                         pprint(' -- %12.6f (d    1922                         pprint(' -- %12.6f (depth=%02d): %s} (%.3f us) %s' % (self.time, \
2374                                 self.depth, s    1923                                 self.depth, self.name, self.length*1000000, info))
2375                 else:                            1924                 else:
2376                         pprint(' -- %12.6f (d    1925                         pprint(' -- %12.6f (depth=%02d): %s() { (%.3f us) %s' % (self.time, \
2377                                 self.depth, s    1926                                 self.depth, self.name, self.length*1000000, info))
2378         def startMarker(self):                   1927         def startMarker(self):
2379                 # Is this the starting line o    1928                 # Is this the starting line of a suspend?
2380                 if not self.fevent:              1929                 if not self.fevent:
2381                         return False             1930                         return False
2382                 if sysvals.usetracemarkers:      1931                 if sysvals.usetracemarkers:
2383                         if(self.name.startswi !! 1932                         if(self.name == 'SUSPEND START'):
2384                                 return True      1933                                 return True
2385                         return False             1934                         return False
2386                 else:                            1935                 else:
2387                         if(self.type == 'susp    1936                         if(self.type == 'suspend_resume' and
2388                                 re.match(r'su !! 1937                                 re.match('suspend_enter\[.*\] begin', self.name)):
2389                                 return True      1938                                 return True
2390                         return False             1939                         return False
2391         def endMarker(self):                     1940         def endMarker(self):
2392                 # Is this the ending line of     1941                 # Is this the ending line of a resume?
2393                 if not self.fevent:              1942                 if not self.fevent:
2394                         return False             1943                         return False
2395                 if sysvals.usetracemarkers:      1944                 if sysvals.usetracemarkers:
2396                         if(self.name.startswi !! 1945                         if(self.name == 'RESUME COMPLETE'):
2397                                 return True      1946                                 return True
2398                         return False             1947                         return False
2399                 else:                            1948                 else:
2400                         if(self.type == 'susp    1949                         if(self.type == 'suspend_resume' and
2401                                 re.match(r'th !! 1950                                 re.match('thaw_processes\[.*\] end', self.name)):
2402                                 return True      1951                                 return True
2403                         return False             1952                         return False
2404                                                  1953 
2405 # Class: FTraceCallGraph                         1954 # Class: FTraceCallGraph
2406 # Description:                                   1955 # Description:
2407 #        A container for the ftrace callgraph    1956 #        A container for the ftrace callgraph of a single recursive function.
2408 #        This can be a dpm_run_callback, dpm_    1957 #        This can be a dpm_run_callback, dpm_prepare, or dpm_complete callgraph
2409 #        Each instance is tied to a single de    1958 #        Each instance is tied to a single device in a single phase, and is
2410 #        comprised of an ordered list of FTra    1959 #        comprised of an ordered list of FTraceLine objects
2411 class FTraceCallGraph:                           1960 class FTraceCallGraph:
2412         vfname = 'missing_function_name'         1961         vfname = 'missing_function_name'
2413         def __init__(self, pid, sv):             1962         def __init__(self, pid, sv):
2414                 self.id = ''                     1963                 self.id = ''
2415                 self.invalid = False             1964                 self.invalid = False
2416                 self.name = ''                   1965                 self.name = ''
2417                 self.partial = False             1966                 self.partial = False
2418                 self.ignore = False              1967                 self.ignore = False
2419                 self.start = -1.0                1968                 self.start = -1.0
2420                 self.end = -1.0                  1969                 self.end = -1.0
2421                 self.list = []                   1970                 self.list = []
2422                 self.depth = 0                   1971                 self.depth = 0
2423                 self.pid = pid                   1972                 self.pid = pid
2424                 self.sv = sv                     1973                 self.sv = sv
2425         def addLine(self, line):                 1974         def addLine(self, line):
2426                 # if this is already invalid,    1975                 # if this is already invalid, just leave
2427                 if(self.invalid):                1976                 if(self.invalid):
2428                         if(line.depth == 0 an    1977                         if(line.depth == 0 and line.freturn):
2429                                 return 1         1978                                 return 1
2430                         return 0                 1979                         return 0
2431                 # invalidate on bad depth        1980                 # invalidate on bad depth
2432                 if(self.depth < 0):              1981                 if(self.depth < 0):
2433                         self.invalidate(line)    1982                         self.invalidate(line)
2434                         return 0                 1983                         return 0
2435                 # ignore data til we return t    1984                 # ignore data til we return to the current depth
2436                 if self.ignore:                  1985                 if self.ignore:
2437                         if line.depth > self.    1986                         if line.depth > self.depth:
2438                                 return 0         1987                                 return 0
2439                         else:                    1988                         else:
2440                                 self.list[-1]    1989                                 self.list[-1].freturn = True
2441                                 self.list[-1]    1990                                 self.list[-1].length = line.time - self.list[-1].time
2442                                 self.ignore =    1991                                 self.ignore = False
2443                                 # if this is     1992                                 # if this is a return at self.depth, no more work is needed
2444                                 if line.depth    1993                                 if line.depth == self.depth and line.isReturn():
2445                                         if li    1994                                         if line.depth == 0:
2446                                                  1995                                                 self.end = line.time
2447                                                  1996                                                 return 1
2448                                         retur    1997                                         return 0
2449                 # compare current depth with     1998                 # compare current depth with this lines pre-call depth
2450                 prelinedep = line.depth          1999                 prelinedep = line.depth
2451                 if line.isReturn():              2000                 if line.isReturn():
2452                         prelinedep += 1          2001                         prelinedep += 1
2453                 last = 0                         2002                 last = 0
2454                 lasttime = line.time             2003                 lasttime = line.time
2455                 if len(self.list) > 0:           2004                 if len(self.list) > 0:
2456                         last = self.list[-1]     2005                         last = self.list[-1]
2457                         lasttime = last.time     2006                         lasttime = last.time
2458                         if last.isLeaf():        2007                         if last.isLeaf():
2459                                 lasttime += l    2008                                 lasttime += last.length
2460                 # handle low misalignments by    2009                 # handle low misalignments by inserting returns
2461                 mismatch = prelinedep - self.    2010                 mismatch = prelinedep - self.depth
2462                 warning = self.sv.verbose and    2011                 warning = self.sv.verbose and abs(mismatch) > 1
2463                 info = []                        2012                 info = []
2464                 if mismatch < 0:                 2013                 if mismatch < 0:
2465                         idx = 0                  2014                         idx = 0
2466                         # add return calls to    2015                         # add return calls to get the depth down
2467                         while prelinedep < se    2016                         while prelinedep < self.depth:
2468                                 self.depth -=    2017                                 self.depth -= 1
2469                                 if idx == 0 a    2018                                 if idx == 0 and last and last.isCall():
2470                                         # spe    2019                                         # special case, turn last call into a leaf
2471                                         last.    2020                                         last.depth = self.depth
2472                                         last.    2021                                         last.freturn = True
2473                                         last.    2022                                         last.length = line.time - last.time
2474                                         if wa    2023                                         if warning:
2475                                                  2024                                                 info.append(('[make leaf]', last))
2476                                 else:            2025                                 else:
2477                                         vline    2026                                         vline = FTraceLine(lasttime)
2478                                         vline    2027                                         vline.depth = self.depth
2479                                         vline    2028                                         vline.name = self.vfname
2480                                         vline    2029                                         vline.freturn = True
2481                                         self.    2030                                         self.list.append(vline)
2482                                         if wa    2031                                         if warning:
2483                                                  2032                                                 if idx == 0:
2484                                                  2033                                                         info.append(('', last))
2485                                                  2034                                                 info.append(('[add return]', vline))
2486                                 idx += 1         2035                                 idx += 1
2487                         if warning:              2036                         if warning:
2488                                 info.append((    2037                                 info.append(('', line))
2489                 # handle high misalignments b    2038                 # handle high misalignments by inserting calls
2490                 elif mismatch > 0:               2039                 elif mismatch > 0:
2491                         idx = 0                  2040                         idx = 0
2492                         if warning:              2041                         if warning:
2493                                 info.append((    2042                                 info.append(('', last))
2494                         # add calls to get th    2043                         # add calls to get the depth up
2495                         while prelinedep > se    2044                         while prelinedep > self.depth:
2496                                 if idx == 0 a    2045                                 if idx == 0 and line.isReturn():
2497                                         # spe    2046                                         # special case, turn this return into a leaf
2498                                         line.    2047                                         line.fcall = True
2499                                         preli    2048                                         prelinedep -= 1
2500                                         if wa    2049                                         if warning:
2501                                                  2050                                                 info.append(('[make leaf]', line))
2502                                 else:            2051                                 else:
2503                                         vline    2052                                         vline = FTraceLine(lasttime)
2504                                         vline    2053                                         vline.depth = self.depth
2505                                         vline    2054                                         vline.name = self.vfname
2506                                         vline    2055                                         vline.fcall = True
2507                                         self.    2056                                         self.list.append(vline)
2508                                         self.    2057                                         self.depth += 1
2509                                         if no    2058                                         if not last:
2510                                                  2059                                                 self.start = vline.time
2511                                         if wa    2060                                         if warning:
2512                                                  2061                                                 info.append(('[add call]', vline))
2513                                 idx += 1         2062                                 idx += 1
2514                         if warning and ('[mak    2063                         if warning and ('[make leaf]', line) not in info:
2515                                 info.append((    2064                                 info.append(('', line))
2516                 if warning:                      2065                 if warning:
2517                         pprint('WARNING: ftra    2066                         pprint('WARNING: ftrace data missing, corrections made:')
2518                         for i in info:           2067                         for i in info:
2519                                 t, obj = i       2068                                 t, obj = i
2520                                 if obj:          2069                                 if obj:
2521                                         obj.d    2070                                         obj.debugPrint(t)
2522                 # process the call and set th    2071                 # process the call and set the new depth
2523                 skipadd = False                  2072                 skipadd = False
2524                 md = self.sv.max_graph_depth     2073                 md = self.sv.max_graph_depth
2525                 if line.isCall():                2074                 if line.isCall():
2526                         # ignore blacklisted/    2075                         # ignore blacklisted/overdepth funcs
2527                         if (md and self.depth    2076                         if (md and self.depth >= md - 1) or (line.name in self.sv.cgblacklist):
2528                                 self.ignore =    2077                                 self.ignore = True
2529                         else:                    2078                         else:
2530                                 self.depth +=    2079                                 self.depth += 1
2531                 elif line.isReturn():            2080                 elif line.isReturn():
2532                         self.depth -= 1          2081                         self.depth -= 1
2533                         # remove blacklisted/    2082                         # remove blacklisted/overdepth/empty funcs that slipped through
2534                         if (last and last.isC    2083                         if (last and last.isCall() and last.depth == line.depth) or \
2535                                 (md and last     2084                                 (md and last and last.depth >= md) or \
2536                                 (line.name in    2085                                 (line.name in self.sv.cgblacklist):
2537                                 while len(sel    2086                                 while len(self.list) > 0 and self.list[-1].depth > line.depth:
2538                                         self.    2087                                         self.list.pop(-1)
2539                                 if len(self.l    2088                                 if len(self.list) == 0:
2540                                         self.    2089                                         self.invalid = True
2541                                         retur    2090                                         return 1
2542                                 self.list[-1]    2091                                 self.list[-1].freturn = True
2543                                 self.list[-1]    2092                                 self.list[-1].length = line.time - self.list[-1].time
2544                                 self.list[-1]    2093                                 self.list[-1].name = line.name
2545                                 skipadd = Tru    2094                                 skipadd = True
2546                 if len(self.list) < 1:           2095                 if len(self.list) < 1:
2547                         self.start = line.tim    2096                         self.start = line.time
2548                 # check for a mismatch that r    2097                 # check for a mismatch that returned all the way to callgraph end
2549                 res = 1                          2098                 res = 1
2550                 if mismatch < 0 and self.list    2099                 if mismatch < 0 and self.list[-1].depth == 0 and self.list[-1].freturn:
2551                         line = self.list[-1]     2100                         line = self.list[-1]
2552                         skipadd = True           2101                         skipadd = True
2553                         res = -1                 2102                         res = -1
2554                 if not skipadd:                  2103                 if not skipadd:
2555                         self.list.append(line    2104                         self.list.append(line)
2556                 if(line.depth == 0 and line.f    2105                 if(line.depth == 0 and line.freturn):
2557                         if(self.start < 0):      2106                         if(self.start < 0):
2558                                 self.start =     2107                                 self.start = line.time
2559                         self.end = line.time     2108                         self.end = line.time
2560                         if line.fcall:           2109                         if line.fcall:
2561                                 self.end += l    2110                                 self.end += line.length
2562                         if self.list[0].name     2111                         if self.list[0].name == self.vfname:
2563                                 self.invalid     2112                                 self.invalid = True
2564                         if res == -1:            2113                         if res == -1:
2565                                 self.partial     2114                                 self.partial = True
2566                         return res               2115                         return res
2567                 return 0                         2116                 return 0
2568         def invalidate(self, line):              2117         def invalidate(self, line):
2569                 if(len(self.list) > 0):          2118                 if(len(self.list) > 0):
2570                         first = self.list[0]     2119                         first = self.list[0]
2571                         self.list = []           2120                         self.list = []
2572                         self.list.append(firs    2121                         self.list.append(first)
2573                 self.invalid = True              2122                 self.invalid = True
2574                 id = 'task %s' % (self.pid)      2123                 id = 'task %s' % (self.pid)
2575                 window = '(%f - %f)' % (self.    2124                 window = '(%f - %f)' % (self.start, line.time)
2576                 if(self.depth < 0):              2125                 if(self.depth < 0):
2577                         pprint('Data misalign    2126                         pprint('Data misalignment for '+id+\
2578                                 ' (buffer ove    2127                                 ' (buffer overflow), ignoring this callback')
2579                 else:                            2128                 else:
2580                         pprint('Too much data    2129                         pprint('Too much data for '+id+\
2581                                 ' '+window+',    2130                                 ' '+window+', ignoring this callback')
2582         def slice(self, dev):                    2131         def slice(self, dev):
2583                 minicg = FTraceCallGraph(dev[    2132                 minicg = FTraceCallGraph(dev['pid'], self.sv)
2584                 minicg.name = self.name          2133                 minicg.name = self.name
2585                 mydepth = -1                     2134                 mydepth = -1
2586                 good = False                     2135                 good = False
2587                 for l in self.list:              2136                 for l in self.list:
2588                         if(l.time < dev['star    2137                         if(l.time < dev['start'] or l.time > dev['end']):
2589                                 continue         2138                                 continue
2590                         if mydepth < 0:          2139                         if mydepth < 0:
2591                                 if l.name ==     2140                                 if l.name == 'mutex_lock' and l.freturn:
2592                                         mydep    2141                                         mydepth = l.depth
2593                                 continue         2142                                 continue
2594                         elif l.depth == mydep    2143                         elif l.depth == mydepth and l.name == 'mutex_unlock' and l.fcall:
2595                                 good = True      2144                                 good = True
2596                                 break            2145                                 break
2597                         l.depth -= mydepth       2146                         l.depth -= mydepth
2598                         minicg.addLine(l)        2147                         minicg.addLine(l)
2599                 if not good or len(minicg.lis    2148                 if not good or len(minicg.list) < 1:
2600                         return 0                 2149                         return 0
2601                 return minicg                    2150                 return minicg
2602         def repair(self, enddepth):              2151         def repair(self, enddepth):
2603                 # bring the depth back to 0 w    2152                 # bring the depth back to 0 with additional returns
2604                 fixed = False                    2153                 fixed = False
2605                 last = self.list[-1]             2154                 last = self.list[-1]
2606                 for i in reversed(range(endde    2155                 for i in reversed(range(enddepth)):
2607                         t = FTraceLine(last.t    2156                         t = FTraceLine(last.time)
2608                         t.depth = i              2157                         t.depth = i
2609                         t.freturn = True         2158                         t.freturn = True
2610                         fixed = self.addLine(    2159                         fixed = self.addLine(t)
2611                         if fixed != 0:           2160                         if fixed != 0:
2612                                 self.end = la    2161                                 self.end = last.time
2613                                 return True      2162                                 return True
2614                 return False                     2163                 return False
2615         def postProcess(self):                   2164         def postProcess(self):
2616                 if len(self.list) > 0:           2165                 if len(self.list) > 0:
2617                         self.name = self.list    2166                         self.name = self.list[0].name
2618                 stack = dict()                   2167                 stack = dict()
2619                 cnt = 0                          2168                 cnt = 0
2620                 last = 0                         2169                 last = 0
2621                 for l in self.list:              2170                 for l in self.list:
2622                         # ftrace bug: reporte    2171                         # ftrace bug: reported duration is not reliable
2623                         # check each leaf and    2172                         # check each leaf and clip it at max possible length
2624                         if last and last.isLe    2173                         if last and last.isLeaf():
2625                                 if last.lengt    2174                                 if last.length > l.time - last.time:
2626                                         last.    2175                                         last.length = l.time - last.time
2627                         if l.isCall():           2176                         if l.isCall():
2628                                 stack[l.depth    2177                                 stack[l.depth] = l
2629                                 cnt += 1         2178                                 cnt += 1
2630                         elif l.isReturn():       2179                         elif l.isReturn():
2631                                 if(l.depth no    2180                                 if(l.depth not in stack):
2632                                         if se    2181                                         if self.sv.verbose:
2633                                                  2182                                                 pprint('Post Process Error: Depth missing')
2634                                                  2183                                                 l.debugPrint()
2635                                         retur    2184                                         return False
2636                                 # calculate c    2185                                 # calculate call length from call/return lines
2637                                 cl = stack[l.    2186                                 cl = stack[l.depth]
2638                                 cl.length = l    2187                                 cl.length = l.time - cl.time
2639                                 if cl.name ==    2188                                 if cl.name == self.vfname:
2640                                         cl.na    2189                                         cl.name = l.name
2641                                 stack.pop(l.d    2190                                 stack.pop(l.depth)
2642                                 l.length = 0     2191                                 l.length = 0
2643                                 cnt -= 1         2192                                 cnt -= 1
2644                         last = l                 2193                         last = l
2645                 if(cnt == 0):                    2194                 if(cnt == 0):
2646                         # trace caught the wh    2195                         # trace caught the whole call tree
2647                         return True              2196                         return True
2648                 elif(cnt < 0):                   2197                 elif(cnt < 0):
2649                         if self.sv.verbose:      2198                         if self.sv.verbose:
2650                                 pprint('Post     2199                                 pprint('Post Process Error: Depth is less than 0')
2651                         return False             2200                         return False
2652                 # trace ended before call tre    2201                 # trace ended before call tree finished
2653                 return self.repair(cnt)          2202                 return self.repair(cnt)
2654         def deviceMatch(self, pid, data):        2203         def deviceMatch(self, pid, data):
2655                 found = ''                       2204                 found = ''
2656                 # add the callgraph data to t    2205                 # add the callgraph data to the device hierarchy
2657                 borderphase = {                  2206                 borderphase = {
2658                         'dpm_prepare': 'suspe    2207                         'dpm_prepare': 'suspend_prepare',
2659                         'dpm_complete': 'resu    2208                         'dpm_complete': 'resume_complete'
2660                 }                                2209                 }
2661                 if(self.name in borderphase):    2210                 if(self.name in borderphase):
2662                         p = borderphase[self.    2211                         p = borderphase[self.name]
2663                         list = data.dmesg[p][    2212                         list = data.dmesg[p]['list']
2664                         for devname in list:     2213                         for devname in list:
2665                                 dev = list[de    2214                                 dev = list[devname]
2666                                 if(pid == dev    2215                                 if(pid == dev['pid'] and
2667                                         self.    2216                                         self.start <= dev['start'] and
2668                                         self.    2217                                         self.end >= dev['end']):
2669                                         cg =     2218                                         cg = self.slice(dev)
2670                                         if cg    2219                                         if cg:
2671                                                  2220                                                 dev['ftrace'] = cg
2672                                         found    2221                                         found = devname
2673                         return found             2222                         return found
2674                 for p in data.sortedPhases():    2223                 for p in data.sortedPhases():
2675                         if(data.dmesg[p]['sta    2224                         if(data.dmesg[p]['start'] <= self.start and
2676                                 self.start <=    2225                                 self.start <= data.dmesg[p]['end']):
2677                                 list = data.d    2226                                 list = data.dmesg[p]['list']
2678                                 for devname i    2227                                 for devname in sorted(list, key=lambda k:list[k]['start']):
2679                                         dev =    2228                                         dev = list[devname]
2680                                         if(pi    2229                                         if(pid == dev['pid'] and
2681                                                  2230                                                 self.start <= dev['start'] and
2682                                                  2231                                                 self.end >= dev['end']):
2683                                                  2232                                                 dev['ftrace'] = self
2684                                                  2233                                                 found = devname
2685                                                  2234                                                 break
2686                                 break            2235                                 break
2687                 return found                     2236                 return found
2688         def newActionFromFunction(self, data)    2237         def newActionFromFunction(self, data):
2689                 name = self.name                 2238                 name = self.name
2690                 if name in ['dpm_run_callback    2239                 if name in ['dpm_run_callback', 'dpm_prepare', 'dpm_complete']:
2691                         return                   2240                         return
2692                 fs = self.start                  2241                 fs = self.start
2693                 fe = self.end                    2242                 fe = self.end
2694                 if fs < data.start or fe > da    2243                 if fs < data.start or fe > data.end:
2695                         return                   2244                         return
2696                 phase = ''                       2245                 phase = ''
2697                 for p in data.sortedPhases():    2246                 for p in data.sortedPhases():
2698                         if(data.dmesg[p]['sta    2247                         if(data.dmesg[p]['start'] <= self.start and
2699                                 self.start <     2248                                 self.start < data.dmesg[p]['end']):
2700                                 phase = p        2249                                 phase = p
2701                                 break            2250                                 break
2702                 if not phase:                    2251                 if not phase:
2703                         return                   2252                         return
2704                 out = data.newActionGlobal(na    2253                 out = data.newActionGlobal(name, fs, fe, -2)
2705                 if out:                          2254                 if out:
2706                         phase, myname = out      2255                         phase, myname = out
2707                         data.dmesg[phase]['li    2256                         data.dmesg[phase]['list'][myname]['ftrace'] = self
2708         def debugPrint(self, info=''):           2257         def debugPrint(self, info=''):
2709                 pprint('%s pid=%d [%f - %f] %    2258                 pprint('%s pid=%d [%f - %f] %.3f us' % \
2710                         (self.name, self.pid,    2259                         (self.name, self.pid, self.start, self.end,
2711                         (self.end - self.star    2260                         (self.end - self.start)*1000000))
2712                 for l in self.list:              2261                 for l in self.list:
2713                         if l.isLeaf():           2262                         if l.isLeaf():
2714                                 pprint('%f (%    2263                                 pprint('%f (%02d): %s(); (%.3f us)%s' % (l.time, \
2715                                         l.dep    2264                                         l.depth, l.name, l.length*1000000, info))
2716                         elif l.freturn:          2265                         elif l.freturn:
2717                                 pprint('%f (%    2266                                 pprint('%f (%02d): %s} (%.3f us)%s' % (l.time, \
2718                                         l.dep    2267                                         l.depth, l.name, l.length*1000000, info))
2719                         else:                    2268                         else:
2720                                 pprint('%f (%    2269                                 pprint('%f (%02d): %s() { (%.3f us)%s' % (l.time, \
2721                                         l.dep    2270                                         l.depth, l.name, l.length*1000000, info))
2722                 pprint(' ')                      2271                 pprint(' ')
2723                                                  2272 
2724 class DevItem:                                   2273 class DevItem:
2725         def __init__(self, test, phase, dev):    2274         def __init__(self, test, phase, dev):
2726                 self.test = test                 2275                 self.test = test
2727                 self.phase = phase               2276                 self.phase = phase
2728                 self.dev = dev                   2277                 self.dev = dev
2729         def isa(self, cls):                      2278         def isa(self, cls):
2730                 if 'htmlclass' in self.dev an    2279                 if 'htmlclass' in self.dev and cls in self.dev['htmlclass']:
2731                         return True              2280                         return True
2732                 return False                     2281                 return False
2733                                                  2282 
2734 # Class: Timeline                                2283 # Class: Timeline
2735 # Description:                                   2284 # Description:
2736 #        A container for a device timeline wh    2285 #        A container for a device timeline which calculates
2737 #        all the html properties to display i    2286 #        all the html properties to display it correctly
2738 class Timeline:                                  2287 class Timeline:
2739         html_tblock = '<div id="block{0}" cla    2288         html_tblock = '<div id="block{0}" class="tblock" style="left:{1}%;width:{2}%;"><div class="tback" style="height:{3}px"></div>\n'
2740         html_device = '<div id="{0}" title="{    2289         html_device = '<div id="{0}" title="{1}" class="thread{7}" style="left:{2}%;top:{3}px;height:{4}px;width:{5}%;{8}">{6}</div>\n'
2741         html_phase = '<div class="phase" styl    2290         html_phase = '<div class="phase" style="left:{0}%;width:{1}%;top:{2}px;height:{3}px;background:{4}">{5}</div>\n'
2742         html_phaselet = '<div id="{0}" class=    2291         html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background:{3}"></div>\n'
2743         html_legend = '<div id="p{3}" class="    2292         html_legend = '<div id="p{3}" class="square" style="left:{0}%;background:{1}">&nbsp;{2}</div>\n'
2744         def __init__(self, rowheight, scalehe    2293         def __init__(self, rowheight, scaleheight):
2745                 self.html = ''                   2294                 self.html = ''
2746                 self.height = 0  # total time    2295                 self.height = 0  # total timeline height
2747                 self.scaleH = scaleheight # t    2296                 self.scaleH = scaleheight # timescale (top) row height
2748                 self.rowH = rowheight     # d    2297                 self.rowH = rowheight     # device row height
2749                 self.bodyH = 0   # body heigh    2298                 self.bodyH = 0   # body height
2750                 self.rows = 0    # total time    2299                 self.rows = 0    # total timeline rows
2751                 self.rowlines = dict()           2300                 self.rowlines = dict()
2752                 self.rowheight = dict()          2301                 self.rowheight = dict()
2753         def createHeader(self, sv, stamp):       2302         def createHeader(self, sv, stamp):
2754                 if(not stamp['time']):           2303                 if(not stamp['time']):
2755                         return                   2304                         return
2756                 self.html += '<div class="ver !! 2305                 self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \
2757                         % (sv.title, sv.versi    2306                         % (sv.title, sv.version)
2758                 if sv.logmsg and sv.testlog:     2307                 if sv.logmsg and sv.testlog:
2759                         self.html += '<button    2308                         self.html += '<button id="showtest" class="logbtn btnfmt">log</button>'
2760                 if sv.dmesglog:                  2309                 if sv.dmesglog:
2761                         self.html += '<button    2310                         self.html += '<button id="showdmesg" class="logbtn btnfmt">dmesg</button>'
2762                 if sv.ftracelog:                 2311                 if sv.ftracelog:
2763                         self.html += '<button    2312                         self.html += '<button id="showftrace" class="logbtn btnfmt">ftrace</button>'
2764                 headline_stamp = '<div class=    2313                 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n'
2765                 self.html += headline_stamp.f    2314                 self.html += headline_stamp.format(stamp['host'], stamp['kernel'],
2766                         stamp['mode'], stamp[    2315                         stamp['mode'], stamp['time'])
2767                 if 'man' in stamp and 'plat'     2316                 if 'man' in stamp and 'plat' in stamp and 'cpu' in stamp and \
2768                         stamp['man'] and stam    2317                         stamp['man'] and stamp['plat'] and stamp['cpu']:
2769                         headline_sysinfo = '<    2318                         headline_sysinfo = '<div class="stamp sysinfo">{0} {1} <i>with</i> {2}</div>\n'
2770                         self.html += headline    2319                         self.html += headline_sysinfo.format(stamp['man'], stamp['plat'], stamp['cpu'])
2771                                                  2320 
2772         # Function: getDeviceRows                2321         # Function: getDeviceRows
2773         # Description:                           2322         # Description:
2774         #    determine how may rows the devic    2323         #    determine how may rows the device funcs will take
2775         # Arguments:                             2324         # Arguments:
2776         #        rawlist: the list of devices    2325         #        rawlist: the list of devices/actions for a single phase
2777         # Output:                                2326         # Output:
2778         #        The total number of rows nee    2327         #        The total number of rows needed to display this phase of the timeline
2779         def getDeviceRows(self, rawlist):        2328         def getDeviceRows(self, rawlist):
2780                 # clear all rows and set them    2329                 # clear all rows and set them to undefined
2781                 sortdict = dict()                2330                 sortdict = dict()
2782                 for item in rawlist:             2331                 for item in rawlist:
2783                         item.row = -1            2332                         item.row = -1
2784                         sortdict[item] = item    2333                         sortdict[item] = item.length
2785                 sortlist = sorted(sortdict, k    2334                 sortlist = sorted(sortdict, key=sortdict.get, reverse=True)
2786                 remaining = len(sortlist)        2335                 remaining = len(sortlist)
2787                 rowdata = dict()                 2336                 rowdata = dict()
2788                 row = 1                          2337                 row = 1
2789                 # try to pack each row with a    2338                 # try to pack each row with as many ranges as possible
2790                 while(remaining > 0):            2339                 while(remaining > 0):
2791                         if(row not in rowdata    2340                         if(row not in rowdata):
2792                                 rowdata[row]     2341                                 rowdata[row] = []
2793                         for i in sortlist:       2342                         for i in sortlist:
2794                                 if(i.row >= 0    2343                                 if(i.row >= 0):
2795                                         conti    2344                                         continue
2796                                 s = i.time       2345                                 s = i.time
2797                                 e = i.time +     2346                                 e = i.time + i.length
2798                                 valid = True     2347                                 valid = True
2799                                 for ritem in     2348                                 for ritem in rowdata[row]:
2800                                         rs =     2349                                         rs = ritem.time
2801                                         re =     2350                                         re = ritem.time + ritem.length
2802                                         if(no    2351                                         if(not (((s <= rs) and (e <= rs)) or
2803                                                  2352                                                 ((s >= re) and (e >= re)))):
2804                                                  2353                                                 valid = False
2805                                                  2354                                                 break
2806                                 if(valid):       2355                                 if(valid):
2807                                         rowda    2356                                         rowdata[row].append(i)
2808                                         i.row    2357                                         i.row = row
2809                                         remai    2358                                         remaining -= 1
2810                         row += 1                 2359                         row += 1
2811                 return row                       2360                 return row
2812         # Function: getPhaseRows                 2361         # Function: getPhaseRows
2813         # Description:                           2362         # Description:
2814         #        Organize the timeline entrie    2363         #        Organize the timeline entries into the smallest
2815         #        number of rows possible, wit    2364         #        number of rows possible, with no entry overlapping
2816         # Arguments:                             2365         # Arguments:
2817         #        devlist: the list of devices    2366         #        devlist: the list of devices/actions in a group of contiguous phases
2818         # Output:                                2367         # Output:
2819         #        The total number of rows nee    2368         #        The total number of rows needed to display this phase of the timeline
2820         def getPhaseRows(self, devlist, row=0    2369         def getPhaseRows(self, devlist, row=0, sortby='length'):
2821                 # clear all rows and set them    2370                 # clear all rows and set them to undefined
2822                 remaining = len(devlist)         2371                 remaining = len(devlist)
2823                 rowdata = dict()                 2372                 rowdata = dict()
2824                 sortdict = dict()                2373                 sortdict = dict()
2825                 myphases = []                    2374                 myphases = []
2826                 # initialize all device rows     2375                 # initialize all device rows to -1 and calculate devrows
2827                 for item in devlist:             2376                 for item in devlist:
2828                         dev = item.dev           2377                         dev = item.dev
2829                         tp = (item.test, item    2378                         tp = (item.test, item.phase)
2830                         if tp not in myphases    2379                         if tp not in myphases:
2831                                 myphases.appe    2380                                 myphases.append(tp)
2832                         dev['row'] = -1          2381                         dev['row'] = -1
2833                         if sortby == 'start':    2382                         if sortby == 'start':
2834                                 # sort by sta    2383                                 # sort by start 1st, then length 2nd
2835                                 sortdict[item    2384                                 sortdict[item] = (-1*float(dev['start']), float(dev['end']) - float(dev['start']))
2836                         else:                    2385                         else:
2837                                 # sort by len    2386                                 # sort by length 1st, then name 2nd
2838                                 sortdict[item    2387                                 sortdict[item] = (float(dev['end']) - float(dev['start']), item.dev['name'])
2839                         if 'src' in dev:         2388                         if 'src' in dev:
2840                                 dev['devrows'    2389                                 dev['devrows'] = self.getDeviceRows(dev['src'])
2841                 # sort the devlist by length     2390                 # sort the devlist by length so that large items graph on top
2842                 sortlist = sorted(sortdict, k    2391                 sortlist = sorted(sortdict, key=sortdict.get, reverse=True)
2843                 orderedlist = []                 2392                 orderedlist = []
2844                 for item in sortlist:            2393                 for item in sortlist:
2845                         if item.dev['pid'] ==    2394                         if item.dev['pid'] == -2:
2846                                 orderedlist.a    2395                                 orderedlist.append(item)
2847                 for item in sortlist:            2396                 for item in sortlist:
2848                         if item not in ordere    2397                         if item not in orderedlist:
2849                                 orderedlist.a    2398                                 orderedlist.append(item)
2850                 # try to pack each row with a    2399                 # try to pack each row with as many devices as possible
2851                 while(remaining > 0):            2400                 while(remaining > 0):
2852                         rowheight = 1            2401                         rowheight = 1
2853                         if(row not in rowdata    2402                         if(row not in rowdata):
2854                                 rowdata[row]     2403                                 rowdata[row] = []
2855                         for item in orderedli    2404                         for item in orderedlist:
2856                                 dev = item.de    2405                                 dev = item.dev
2857                                 if(dev['row']    2406                                 if(dev['row'] < 0):
2858                                         s = d    2407                                         s = dev['start']
2859                                         e = d    2408                                         e = dev['end']
2860                                         valid    2409                                         valid = True
2861                                         for r    2410                                         for ritem in rowdata[row]:
2862                                                  2411                                                 rs = ritem.dev['start']
2863                                                  2412                                                 re = ritem.dev['end']
2864                                                  2413                                                 if(not (((s <= rs) and (e <= rs)) or
2865                                                  2414                                                         ((s >= re) and (e >= re)))):
2866                                                  2415                                                         valid = False
2867                                                  2416                                                         break
2868                                         if(va    2417                                         if(valid):
2869                                                  2418                                                 rowdata[row].append(item)
2870                                                  2419                                                 dev['row'] = row
2871                                                  2420                                                 remaining -= 1
2872                                                  2421                                                 if 'devrows' in dev and dev['devrows'] > rowheight:
2873                                                  2422                                                         rowheight = dev['devrows']
2874                         for t, p in myphases:    2423                         for t, p in myphases:
2875                                 if t not in s    2424                                 if t not in self.rowlines or t not in self.rowheight:
2876                                         self.    2425                                         self.rowlines[t] = dict()
2877                                         self.    2426                                         self.rowheight[t] = dict()
2878                                 if p not in s    2427                                 if p not in self.rowlines[t] or p not in self.rowheight[t]:
2879                                         self.    2428                                         self.rowlines[t][p] = dict()
2880                                         self.    2429                                         self.rowheight[t][p] = dict()
2881                                 rh = self.row    2430                                 rh = self.rowH
2882                                 # section hea    2431                                 # section headers should use a different row height
2883                                 if len(rowdat    2432                                 if len(rowdata[row]) == 1 and \
2884                                         'html    2433                                         'htmlclass' in rowdata[row][0].dev and \
2885                                         'sec'    2434                                         'sec' in rowdata[row][0].dev['htmlclass']:
2886                                         rh =     2435                                         rh = 15
2887                                 self.rowlines    2436                                 self.rowlines[t][p][row] = rowheight
2888                                 self.rowheigh    2437                                 self.rowheight[t][p][row] = rowheight * rh
2889                         row += 1                 2438                         row += 1
2890                 if(row > self.rows):             2439                 if(row > self.rows):
2891                         self.rows = int(row)     2440                         self.rows = int(row)
2892                 return row                       2441                 return row
2893         def phaseRowHeight(self, test, phase,    2442         def phaseRowHeight(self, test, phase, row):
2894                 return self.rowheight[test][p    2443                 return self.rowheight[test][phase][row]
2895         def phaseRowTop(self, test, phase, ro    2444         def phaseRowTop(self, test, phase, row):
2896                 top = 0                          2445                 top = 0
2897                 for i in sorted(self.rowheigh    2446                 for i in sorted(self.rowheight[test][phase]):
2898                         if i >= row:             2447                         if i >= row:
2899                                 break            2448                                 break
2900                         top += self.rowheight    2449                         top += self.rowheight[test][phase][i]
2901                 return top                       2450                 return top
2902         def calcTotalRows(self):                 2451         def calcTotalRows(self):
2903                 # Calculate the heights and o    2452                 # Calculate the heights and offsets for the header and rows
2904                 maxrows = 0                      2453                 maxrows = 0
2905                 standardphases = []              2454                 standardphases = []
2906                 for t in self.rowlines:          2455                 for t in self.rowlines:
2907                         for p in self.rowline    2456                         for p in self.rowlines[t]:
2908                                 total = 0        2457                                 total = 0
2909                                 for i in sort    2458                                 for i in sorted(self.rowlines[t][p]):
2910                                         total    2459                                         total += self.rowlines[t][p][i]
2911                                 if total > ma    2460                                 if total > maxrows:
2912                                         maxro    2461                                         maxrows = total
2913                                 if total == l    2462                                 if total == len(self.rowlines[t][p]):
2914                                         stand    2463                                         standardphases.append((t, p))
2915                 self.height = self.scaleH + (    2464                 self.height = self.scaleH + (maxrows*self.rowH)
2916                 self.bodyH = self.height - se    2465                 self.bodyH = self.height - self.scaleH
2917                 # if there is 1 line per row,    2466                 # if there is 1 line per row, draw them the standard way
2918                 for t, p in standardphases:      2467                 for t, p in standardphases:
2919                         for i in sorted(self.    2468                         for i in sorted(self.rowheight[t][p]):
2920                                 self.rowheigh !! 2469                                 self.rowheight[t][p][i] = self.bodyH/len(self.rowlines[t][p])
2921         def createZoomBox(self, mode='command    2470         def createZoomBox(self, mode='command', testcount=1):
2922                 # Create bounding box, add bu    2471                 # Create bounding box, add buttons
2923                 html_zoombox = '<center><butt    2472                 html_zoombox = '<center><button id="zoomin">ZOOM IN +</button><button id="zoomout">ZOOM OUT -</button><button id="zoomdef">ZOOM 1:1</button></center>\n'
2924                 html_timeline = '<div id="dme    2473                 html_timeline = '<div id="dmesgzoombox" class="zoombox">\n<div id="{0}" class="timeline" style="height:{1}px">\n'
2925                 html_devlist1 = '<button id="    2474                 html_devlist1 = '<button id="devlist1" class="devlist" style="float:left;">Device Detail{0}</button>'
2926                 html_devlist2 = '<button id="    2475                 html_devlist2 = '<button id="devlist2" class="devlist" style="float:right;">Device Detail2</button>\n'
2927                 if mode != 'command':            2476                 if mode != 'command':
2928                         if testcount > 1:        2477                         if testcount > 1:
2929                                 self.html +=     2478                                 self.html += html_devlist2
2930                                 self.html +=     2479                                 self.html += html_devlist1.format('1')
2931                         else:                    2480                         else:
2932                                 self.html +=     2481                                 self.html += html_devlist1.format('')
2933                 self.html += html_zoombox        2482                 self.html += html_zoombox
2934                 self.html += html_timeline.fo    2483                 self.html += html_timeline.format('dmesg', self.height)
2935         # Function: createTimeScale              2484         # Function: createTimeScale
2936         # Description:                           2485         # Description:
2937         #        Create the timescale for a t    2486         #        Create the timescale for a timeline block
2938         # Arguments:                             2487         # Arguments:
2939         #        m0: start time (mode begin)     2488         #        m0: start time (mode begin)
2940         #        mMax: end time (mode end)       2489         #        mMax: end time (mode end)
2941         #        tTotal: total timeline time     2490         #        tTotal: total timeline time
2942         #        mode: suspend or resume         2491         #        mode: suspend or resume
2943         # Output:                                2492         # Output:
2944         #        The html code needed to disp    2493         #        The html code needed to display the time scale
2945         def createTimeScale(self, m0, mMax, t    2494         def createTimeScale(self, m0, mMax, tTotal, mode):
2946                 timescale = '<div class="t" s    2495                 timescale = '<div class="t" style="right:{0}%">{1}</div>\n'
2947                 rline = '<div class="t" style    2496                 rline = '<div class="t" style="left:0;border-left:1px solid black;border-right:0;">{0}</div>\n'
2948                 output = '<div class="timesca    2497                 output = '<div class="timescale">\n'
2949                 # set scale for timeline         2498                 # set scale for timeline
2950                 mTotal = mMax - m0               2499                 mTotal = mMax - m0
2951                 tS = 0.1                         2500                 tS = 0.1
2952                 if(tTotal <= 0):                 2501                 if(tTotal <= 0):
2953                         return output+'</div>    2502                         return output+'</div>\n'
2954                 if(tTotal > 4):                  2503                 if(tTotal > 4):
2955                         tS = 1                   2504                         tS = 1
2956                 divTotal = int(mTotal/tS) + 1    2505                 divTotal = int(mTotal/tS) + 1
2957                 divEdge = (mTotal - tS*(divTo    2506                 divEdge = (mTotal - tS*(divTotal-1))*100/mTotal
2958                 for i in range(divTotal):        2507                 for i in range(divTotal):
2959                         htmlline = ''            2508                         htmlline = ''
2960                         if(mode == 'suspend')    2509                         if(mode == 'suspend'):
2961                                 pos = '%0.3f'    2510                                 pos = '%0.3f' % (100 - ((float(i)*tS*100)/mTotal) - divEdge)
2962                                 val = '%0.fms    2511                                 val = '%0.fms' % (float(i-divTotal+1)*tS*1000)
2963                                 if(i == divTo    2512                                 if(i == divTotal - 1):
2964                                         val =    2513                                         val = mode
2965                                 htmlline = ti    2514                                 htmlline = timescale.format(pos, val)
2966                         else:                    2515                         else:
2967                                 pos = '%0.3f'    2516                                 pos = '%0.3f' % (100 - ((float(i)*tS*100)/mTotal))
2968                                 val = '%0.fms    2517                                 val = '%0.fms' % (float(i)*tS*1000)
2969                                 htmlline = ti    2518                                 htmlline = timescale.format(pos, val)
2970                                 if(i == 0):      2519                                 if(i == 0):
2971                                         htmll    2520                                         htmlline = rline.format(mode)
2972                         output += htmlline       2521                         output += htmlline
2973                 self.html += output+'</div>\n    2522                 self.html += output+'</div>\n'
2974                                                  2523 
2975 # Class: TestProps                               2524 # Class: TestProps
2976 # Description:                                   2525 # Description:
2977 #        A list of values describing the prop    2526 #        A list of values describing the properties of these test runs
2978 class TestProps:                                 2527 class TestProps:
2979         stampfmt = r'# [a-z]*-(?P<m>[0-9]{2}) !! 2528         stampfmt = '# [a-z]*-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\
2980                                 r'(?P<H>[0-9] !! 2529                                 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\
2981                                 r' (?P<host>. !! 2530                                 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
2982         wififmt    = r'^# wifi *(?P<d>\S*) *( !! 2531         batteryfmt = '^# battery (?P<a1>\w*) (?P<c1>\d*) (?P<a2>\w*) (?P<c2>\d*)'
2983         tstatfmt   = r'^# turbostat (?P<t>\S* !! 2532         wififmt    = '^# wifi (?P<w>.*)'
2984         testerrfmt = r'^# enter_sleep_error ( !! 2533         tstatfmt   = '^# turbostat (?P<t>\S*)'
2985         sysinfofmt = r'^# sysinfo .*'         !! 2534         mcelogfmt  = '^# mcelog (?P<m>\S*)'
2986         cmdlinefmt = r'^# command \| (?P<cmd> !! 2535         testerrfmt = '^# enter_sleep_error (?P<e>.*)'
2987         kparamsfmt = r'^# kparams \| (?P<kp>. !! 2536         sysinfofmt = '^# sysinfo .*'
2988         devpropfmt = r'# Device Properties: . !! 2537         cmdlinefmt = '^# command \| (?P<cmd>.*)'
2989         pinfofmt   = r'# platform-(?P<val>[a- !! 2538         kparamsfmt = '^# kparams \| (?P<kp>.*)'
2990         tracertypefmt = r'# tracer: (?P<t>.*) !! 2539         devpropfmt = '# Device Properties: .*'
2991         firmwarefmt = r'# fwsuspend (?P<s>[0- !! 2540         tracertypefmt = '# tracer: (?P<t>.*)'
2992         procexecfmt = r'ps - (?P<ps>.*)$'     !! 2541         firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$'
2993         procmultifmt = r'@(?P<n>[0-9]*)\|(?P< !! 2542         procexecfmt = 'ps - (?P<ps>.*)$'
2994         ftrace_line_fmt_fg = \                   2543         ftrace_line_fmt_fg = \
2995                 r'^ *(?P<time>[0-9\.]*) *\| * !! 2544                 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\
2996                 r' *(?P<proc>.*)-(?P<pid>[0-9 !! 2545                 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\
2997                 r'[ +!#\*@$]*(?P<dur>[0-9\.]* !! 2546                 '[ +!#\*@$]*(?P<dur>[0-9\.]*) .*\|  (?P<msg>.*)'
2998         ftrace_line_fmt_nop = \                  2547         ftrace_line_fmt_nop = \
2999                 r' *(?P<proc>.*)-(?P<pid>[0-9 !! 2548                 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\[(?P<cpu>[0-9]*)\] *'+\
3000                 r'(?P<flags>\S*) *(?P<time>[0 !! 2549                 '(?P<flags>.{4}) *(?P<time>[0-9\.]*): *'+\
3001                 r'(?P<msg>.*)'                !! 2550                 '(?P<msg>.*)'
3002         machinesuspend = r'machine_suspend\[. << 
3003         multiproclist = dict()                << 
3004         multiproctime = 0.0                   << 
3005         multiproccnt = 0                      << 
3006         def __init__(self):                      2551         def __init__(self):
3007                 self.stamp = ''                  2552                 self.stamp = ''
3008                 self.sysinfo = ''                2553                 self.sysinfo = ''
3009                 self.cmdline = ''                2554                 self.cmdline = ''
                                                   >> 2555                 self.kparams = ''
3010                 self.testerror = []              2556                 self.testerror = []
                                                   >> 2557                 self.mcelog = []
3011                 self.turbostat = []              2558                 self.turbostat = []
                                                   >> 2559                 self.battery = []
3012                 self.wifi = []                   2560                 self.wifi = []
3013                 self.fwdata = []                 2561                 self.fwdata = []
3014                 self.ftrace_line_fmt = self.f    2562                 self.ftrace_line_fmt = self.ftrace_line_fmt_nop
3015                 self.cgformat = False            2563                 self.cgformat = False
3016                 self.data = 0                    2564                 self.data = 0
3017                 self.ktemp = dict()              2565                 self.ktemp = dict()
3018         def setTracerType(self, tracer):         2566         def setTracerType(self, tracer):
3019                 if(tracer == 'function_graph'    2567                 if(tracer == 'function_graph'):
3020                         self.cgformat = True     2568                         self.cgformat = True
3021                         self.ftrace_line_fmt     2569                         self.ftrace_line_fmt = self.ftrace_line_fmt_fg
3022                 elif(tracer == 'nop'):           2570                 elif(tracer == 'nop'):
3023                         self.ftrace_line_fmt     2571                         self.ftrace_line_fmt = self.ftrace_line_fmt_nop
3024                 else:                            2572                 else:
3025                         doError('Invalid trac    2573                         doError('Invalid tracer format: [%s]' % tracer)
3026         def stampInfo(self, line, sv):        !! 2574         def decode(self, data):
                                                   >> 2575                 try:
                                                   >> 2576                         out = base64.b64decode(data).decode('zlib')
                                                   >> 2577                 except:
                                                   >> 2578                         out = data
                                                   >> 2579                 return out
                                                   >> 2580         def stampInfo(self, line):
3027                 if re.match(self.stampfmt, li    2581                 if re.match(self.stampfmt, line):
3028                         self.stamp = line        2582                         self.stamp = line
3029                         return True              2583                         return True
3030                 elif re.match(self.sysinfofmt    2584                 elif re.match(self.sysinfofmt, line):
3031                         self.sysinfo = line      2585                         self.sysinfo = line
3032                         return True              2586                         return True
                                                   >> 2587                 elif re.match(self.kparamsfmt, line):
                                                   >> 2588                         self.kparams = line
                                                   >> 2589                         return True
                                                   >> 2590                 elif re.match(self.cmdlinefmt, line):
                                                   >> 2591                         self.cmdline = line
                                                   >> 2592                         return True
                                                   >> 2593                 elif re.match(self.mcelogfmt, line):
                                                   >> 2594                         self.mcelog.append(line)
                                                   >> 2595                         return True
3033                 elif re.match(self.tstatfmt,     2596                 elif re.match(self.tstatfmt, line):
3034                         self.turbostat.append    2597                         self.turbostat.append(line)
3035                         return True              2598                         return True
                                                   >> 2599                 elif re.match(self.batteryfmt, line):
                                                   >> 2600                         self.battery.append(line)
                                                   >> 2601                         return True
3036                 elif re.match(self.wififmt, l    2602                 elif re.match(self.wififmt, line):
3037                         self.wifi.append(line    2603                         self.wifi.append(line)
3038                         return True              2604                         return True
3039                 elif re.match(self.testerrfmt    2605                 elif re.match(self.testerrfmt, line):
3040                         self.testerror.append    2606                         self.testerror.append(line)
3041                         return True              2607                         return True
3042                 elif re.match(self.firmwarefm    2608                 elif re.match(self.firmwarefmt, line):
3043                         self.fwdata.append(li    2609                         self.fwdata.append(line)
3044                         return True              2610                         return True
3045                 elif(re.match(self.devpropfmt << 
3046                         self.parseDevprops(li << 
3047                         return True           << 
3048                 elif(re.match(self.pinfofmt,  << 
3049                         self.parsePlatformInf << 
3050                         return True           << 
3051                 m = re.match(self.cmdlinefmt, << 
3052                 if m:                         << 
3053                         self.cmdline = m.grou << 
3054                         return True           << 
3055                 m = re.match(self.tracertypef << 
3056                 if(m):                        << 
3057                         self.setTracerType(m. << 
3058                         return True           << 
3059                 return False                     2611                 return False
3060         def parseStamp(self, data, sv):          2612         def parseStamp(self, data, sv):
3061                 # global test data               2613                 # global test data
3062                 m = re.match(self.stampfmt, s    2614                 m = re.match(self.stampfmt, self.stamp)
3063                 if not self.stamp or not m:   << 
3064                         doError('data does no << 
3065                 data.stamp = {'time': '', 'ho    2615                 data.stamp = {'time': '', 'host': '', 'mode': ''}
3066                 dt = datetime(int(m.group('y'    2616                 dt = datetime(int(m.group('y'))+2000, int(m.group('m')),
3067                         int(m.group('d')), in    2617                         int(m.group('d')), int(m.group('H')), int(m.group('M')),
3068                         int(m.group('S')))       2618                         int(m.group('S')))
3069                 data.stamp['time'] = dt.strft    2619                 data.stamp['time'] = dt.strftime('%B %d %Y, %I:%M:%S %p')
3070                 data.stamp['host'] = m.group(    2620                 data.stamp['host'] = m.group('host')
3071                 data.stamp['mode'] = m.group(    2621                 data.stamp['mode'] = m.group('mode')
3072                 data.stamp['kernel'] = m.grou    2622                 data.stamp['kernel'] = m.group('kernel')
3073                 if re.match(self.sysinfofmt,     2623                 if re.match(self.sysinfofmt, self.sysinfo):
3074                         for f in self.sysinfo    2624                         for f in self.sysinfo.split('|'):
3075                                 if '#' in f:     2625                                 if '#' in f:
3076                                         conti    2626                                         continue
3077                                 tmp = f.strip    2627                                 tmp = f.strip().split(':', 1)
3078                                 key = tmp[0]     2628                                 key = tmp[0]
3079                                 val = tmp[1]     2629                                 val = tmp[1]
3080                                 data.stamp[ke    2630                                 data.stamp[key] = val
3081                 sv.hostname = data.stamp['hos    2631                 sv.hostname = data.stamp['host']
3082                 sv.suspendmode = data.stamp['    2632                 sv.suspendmode = data.stamp['mode']
3083                 if sv.suspendmode == 'freeze' << 
3084                         self.machinesuspend = << 
3085                 else:                         << 
3086                         self.machinesuspend = << 
3087                 if sv.suspendmode == 'command    2633                 if sv.suspendmode == 'command' and sv.ftracefile != '':
3088                         modes = ['on', 'freez    2634                         modes = ['on', 'freeze', 'standby', 'mem', 'disk']
3089                         fp = sv.openlog(sv.ft !! 2635                         fp = sysvals.openlog(sv.ftracefile, 'r')
3090                         for line in fp:          2636                         for line in fp:
3091                                 m = re.match( !! 2637                                 m = re.match('.* machine_suspend\[(?P<mode>.*)\]', line)
3092                                 if m and m.gr    2638                                 if m and m.group('mode') in ['1', '2', '3', '4']:
3093                                         sv.su    2639                                         sv.suspendmode = modes[int(m.group('mode'))]
3094                                         data.    2640                                         data.stamp['mode'] = sv.suspendmode
3095                                         break    2641                                         break
3096                         fp.close()               2642                         fp.close()
3097                 sv.cmdline = self.cmdline     !! 2643                 m = re.match(self.cmdlinefmt, self.cmdline)
                                                   >> 2644                 if m:
                                                   >> 2645                         sv.cmdline = m.group('cmd')
                                                   >> 2646                 if self.kparams:
                                                   >> 2647                         m = re.match(self.kparamsfmt, self.kparams)
                                                   >> 2648                         if m:
                                                   >> 2649                                 sv.kparams = m.group('kp')
3098                 if not sv.stamp:                 2650                 if not sv.stamp:
3099                         sv.stamp = data.stamp    2651                         sv.stamp = data.stamp
3100                 # firmware data                  2652                 # firmware data
3101                 if sv.suspendmode == 'mem' an    2653                 if sv.suspendmode == 'mem' and len(self.fwdata) > data.testnumber:
3102                         m = re.match(self.fir    2654                         m = re.match(self.firmwarefmt, self.fwdata[data.testnumber])
3103                         if m:                    2655                         if m:
3104                                 data.fwSuspen    2656                                 data.fwSuspend, data.fwResume = int(m.group('s')), int(m.group('r'))
3105                                 if(data.fwSus    2657                                 if(data.fwSuspend > 0 or data.fwResume > 0):
3106                                         data.    2658                                         data.fwValid = True
                                                   >> 2659                 # mcelog data
                                                   >> 2660                 if len(self.mcelog) > data.testnumber:
                                                   >> 2661                         m = re.match(self.mcelogfmt, self.mcelog[data.testnumber])
                                                   >> 2662                         if m:
                                                   >> 2663                                 data.mcelog = self.decode(m.group('m'))
3107                 # turbostat data                 2664                 # turbostat data
3108                 if len(self.turbostat) > data    2665                 if len(self.turbostat) > data.testnumber:
3109                         m = re.match(self.tst    2666                         m = re.match(self.tstatfmt, self.turbostat[data.testnumber])
3110                         if m:                    2667                         if m:
3111                                 data.turbosta    2668                                 data.turbostat = m.group('t')
                                                   >> 2669                 # battery data
                                                   >> 2670                 if len(self.battery) > data.testnumber:
                                                   >> 2671                         m = re.match(self.batteryfmt, self.battery[data.testnumber])
                                                   >> 2672                         if m:
                                                   >> 2673                                 data.battery = m.groups()
3112                 # wifi data                      2674                 # wifi data
3113                 if len(self.wifi) > data.test    2675                 if len(self.wifi) > data.testnumber:
3114                         m = re.match(self.wif    2676                         m = re.match(self.wififmt, self.wifi[data.testnumber])
3115                         if m:                    2677                         if m:
3116                                 data.wifi = { !! 2678                                 data.wifi = m.group('w')
3117                                         'time << 
3118                                 data.stamp['w << 
3119                 # sleep mode enter errors        2679                 # sleep mode enter errors
3120                 if len(self.testerror) > data    2680                 if len(self.testerror) > data.testnumber:
3121                         m = re.match(self.tes    2681                         m = re.match(self.testerrfmt, self.testerror[data.testnumber])
3122                         if m:                    2682                         if m:
3123                                 data.enterfai    2683                                 data.enterfail = m.group('e')
3124         def devprops(self, data):             << 
3125                 props = dict()                << 
3126                 devlist = data.split(';')     << 
3127                 for dev in devlist:           << 
3128                         f = dev.split(',')    << 
3129                         if len(f) < 3:        << 
3130                                 continue      << 
3131                         dev = f[0]            << 
3132                         props[dev] = DevProps << 
3133                         props[dev].altname =  << 
3134                         if int(f[2]):         << 
3135                                 props[dev].is << 
3136                         else:                 << 
3137                                 props[dev].is << 
3138                 return props                  << 
3139         def parseDevprops(self, line, sv):    << 
3140                 idx = line.index(': ') + 2    << 
3141                 if idx >= len(line):          << 
3142                         return                << 
3143                 props = self.devprops(line[id << 
3144                 if sv.suspendmode == 'command << 
3145                         sv.testcommand = prop << 
3146                 sv.devprops = props           << 
3147         def parsePlatformInfo(self, line, sv) << 
3148                 m = re.match(self.pinfofmt, l << 
3149                 if not m:                     << 
3150                         return                << 
3151                 name, info = m.group('val'),  << 
3152                 if name == 'devinfo':         << 
3153                         sv.devprops = self.de << 
3154                         return                << 
3155                 elif name == 'testcmd':       << 
3156                         sv.testcommand = info << 
3157                         return                << 
3158                 field = info.split('|')       << 
3159                 if len(field) < 2:            << 
3160                         return                << 
3161                 cmdline = field[0].strip()    << 
3162                 output = sv.b64unzip(field[1] << 
3163                 sv.platinfo.append([name, cmd << 
3164                                                  2684 
3165 # Class: TestRun                                 2685 # Class: TestRun
3166 # Description:                                   2686 # Description:
3167 #        A container for a suspend/resume tes    2687 #        A container for a suspend/resume test run. This is necessary as
3168 #        there could be more than one, and th    2688 #        there could be more than one, and they need to be separate.
3169 class TestRun:                                   2689 class TestRun:
3170         def __init__(self, dataobj):             2690         def __init__(self, dataobj):
3171                 self.data = dataobj              2691                 self.data = dataobj
3172                 self.ftemp = dict()              2692                 self.ftemp = dict()
3173                 self.ttemp = dict()              2693                 self.ttemp = dict()
3174                                                  2694 
3175 class ProcessMonitor:                            2695 class ProcessMonitor:
3176         maxchars = 512                        << 
3177         def __init__(self):                      2696         def __init__(self):
3178                 self.proclist = dict()           2697                 self.proclist = dict()
3179                 self.running = False             2698                 self.running = False
3180         def procstat(self):                      2699         def procstat(self):
3181                 c = ['cat /proc/[1-9]*/stat 2    2700                 c = ['cat /proc/[1-9]*/stat 2>/dev/null']
3182                 process = Popen(c, shell=True    2701                 process = Popen(c, shell=True, stdout=PIPE)
3183                 running = dict()                 2702                 running = dict()
3184                 for line in process.stdout:      2703                 for line in process.stdout:
3185                         data = ascii(line).sp !! 2704                         data = line.split()
3186                         pid = data[0]            2705                         pid = data[0]
3187                         name = re.sub('[()]',    2706                         name = re.sub('[()]', '', data[1])
3188                         user = int(data[13])     2707                         user = int(data[13])
3189                         kern = int(data[14])     2708                         kern = int(data[14])
3190                         kjiff = ujiff = 0        2709                         kjiff = ujiff = 0
3191                         if pid not in self.pr    2710                         if pid not in self.proclist:
3192                                 self.proclist    2711                                 self.proclist[pid] = {'name' : name, 'user' : user, 'kern' : kern}
3193                         else:                    2712                         else:
3194                                 val = self.pr    2713                                 val = self.proclist[pid]
3195                                 ujiff = user     2714                                 ujiff = user - val['user']
3196                                 kjiff = kern     2715                                 kjiff = kern - val['kern']
3197                                 val['user'] =    2716                                 val['user'] = user
3198                                 val['kern'] =    2717                                 val['kern'] = kern
3199                         if ujiff > 0 or kjiff    2718                         if ujiff > 0 or kjiff > 0:
3200                                 running[pid]     2719                                 running[pid] = ujiff + kjiff
3201                 process.wait()                   2720                 process.wait()
3202                 out = ['']                    !! 2721                 out = ''
3203                 for pid in running:              2722                 for pid in running:
3204                         jiffies = running[pid    2723                         jiffies = running[pid]
3205                         val = self.proclist[p    2724                         val = self.proclist[pid]
3206                         if len(out[-1]) > sel !! 2725                         if out:
3207                                 out.append('' !! 2726                                 out += ','
3208                         elif len(out[-1]) > 0 !! 2727                         out += '%s-%s %d' % (val['name'], pid, jiffies)
3209                                 out[-1] += ', !! 2728                 return 'ps - '+out
3210                         out[-1] += '%s-%s %d' << 
3211                 if len(out) > 1:              << 
3212                         for line in out:      << 
3213                                 sysvals.fsetV << 
3214                 else:                         << 
3215                         sysvals.fsetVal('ps - << 
3216         def processMonitor(self, tid):           2729         def processMonitor(self, tid):
3217                 while self.running:              2730                 while self.running:
3218                         self.procstat()       !! 2731                         out = self.procstat()
                                                   >> 2732                         if out:
                                                   >> 2733                                 sysvals.fsetVal(out, 'trace_marker')
3219         def start(self):                         2734         def start(self):
3220                 self.thread = Thread(target=s    2735                 self.thread = Thread(target=self.processMonitor, args=(0,))
3221                 self.running = True              2736                 self.running = True
3222                 self.thread.start()              2737                 self.thread.start()
3223         def stop(self):                          2738         def stop(self):
3224                 self.running = False             2739                 self.running = False
3225                                                  2740 
3226 # ----------------- FUNCTIONS ---------------    2741 # ----------------- FUNCTIONS --------------------
3227                                                  2742 
3228 # Function: doesTraceLogHaveTraceEvents          2743 # Function: doesTraceLogHaveTraceEvents
3229 # Description:                                   2744 # Description:
3230 #        Quickly determine if the ftrace log     2745 #        Quickly determine if the ftrace log has all of the trace events,
3231 #        markers, and/or kprobes required for    2746 #        markers, and/or kprobes required for primary parsing.
3232 def doesTraceLogHaveTraceEvents():               2747 def doesTraceLogHaveTraceEvents():
3233         kpcheck = ['_cal: (', '_ret: (']         2748         kpcheck = ['_cal: (', '_ret: (']
3234         techeck = ['suspend_resume', 'device_ !! 2749         techeck = ['suspend_resume', 'device_pm_callback']
3235         tmcheck = ['SUSPEND START', 'RESUME C    2750         tmcheck = ['SUSPEND START', 'RESUME COMPLETE']
3236         sysvals.usekprobes = False               2751         sysvals.usekprobes = False
3237         fp = sysvals.openlog(sysvals.ftracefi    2752         fp = sysvals.openlog(sysvals.ftracefile, 'r')
3238         for line in fp:                          2753         for line in fp:
3239                 # check for kprobes              2754                 # check for kprobes
3240                 if not sysvals.usekprobes:       2755                 if not sysvals.usekprobes:
3241                         for i in kpcheck:        2756                         for i in kpcheck:
3242                                 if i in line:    2757                                 if i in line:
3243                                         sysva    2758                                         sysvals.usekprobes = True
3244                 # check for all necessary tra    2759                 # check for all necessary trace events
3245                 check = techeck[:]               2760                 check = techeck[:]
3246                 for i in techeck:                2761                 for i in techeck:
3247                         if i in line:            2762                         if i in line:
3248                                 check.remove(    2763                                 check.remove(i)
3249                 techeck = check                  2764                 techeck = check
3250                 # check for all necessary tra    2765                 # check for all necessary trace markers
3251                 check = tmcheck[:]               2766                 check = tmcheck[:]
3252                 for i in tmcheck:                2767                 for i in tmcheck:
3253                         if i in line:            2768                         if i in line:
3254                                 check.remove(    2769                                 check.remove(i)
3255                 tmcheck = check                  2770                 tmcheck = check
3256         fp.close()                               2771         fp.close()
3257         sysvals.usetraceevents = True if len( !! 2772         sysvals.usetraceevents = True if len(techeck) < 2 else False
3258         sysvals.usetracemarkers = True if len    2773         sysvals.usetracemarkers = True if len(tmcheck) == 0 else False
3259                                                  2774 
3260 # Function: appendIncompleteTraceLog             2775 # Function: appendIncompleteTraceLog
3261 # Description:                                   2776 # Description:
                                                   >> 2777 #        [deprecated for kernel 3.15 or newer]
3262 #        Adds callgraph data which lacks trac    2778 #        Adds callgraph data which lacks trace event data. This is only
3263 #        for timelines generated from 3.15 or    2779 #        for timelines generated from 3.15 or older
3264 # Arguments:                                     2780 # Arguments:
3265 #        testruns: the array of Data objects     2781 #        testruns: the array of Data objects obtained from parseKernelLog
3266 def appendIncompleteTraceLog(testruns):          2782 def appendIncompleteTraceLog(testruns):
3267         # create TestRun vessels for ftrace p    2783         # create TestRun vessels for ftrace parsing
3268         testcnt = len(testruns)                  2784         testcnt = len(testruns)
3269         testidx = 0                              2785         testidx = 0
3270         testrun = []                             2786         testrun = []
3271         for data in testruns:                    2787         for data in testruns:
3272                 testrun.append(TestRun(data))    2788                 testrun.append(TestRun(data))
3273                                                  2789 
3274         # extract the callgraph and traceeven    2790         # extract the callgraph and traceevent data
3275         sysvals.vprint('Analyzing the ftrace     2791         sysvals.vprint('Analyzing the ftrace data (%s)...' % \
3276                 os.path.basename(sysvals.ftra    2792                 os.path.basename(sysvals.ftracefile))
3277         tp = TestProps()                         2793         tp = TestProps()
3278         tf = sysvals.openlog(sysvals.ftracefi    2794         tf = sysvals.openlog(sysvals.ftracefile, 'r')
3279         data = 0                                 2795         data = 0
3280         for line in tf:                          2796         for line in tf:
3281                 # remove any latent carriage     2797                 # remove any latent carriage returns
3282                 line = line.replace('\r\n', '    2798                 line = line.replace('\r\n', '')
3283                 if tp.stampInfo(line, sysvals !! 2799                 if tp.stampInfo(line):
                                                   >> 2800                         continue
                                                   >> 2801                 # determine the trace data type (required for further parsing)
                                                   >> 2802                 m = re.match(tp.tracertypefmt, line)
                                                   >> 2803                 if(m):
                                                   >> 2804                         tp.setTracerType(m.group('t'))
                                                   >> 2805                         continue
                                                   >> 2806                 # device properties line
                                                   >> 2807                 if(re.match(tp.devpropfmt, line)):
                                                   >> 2808                         devProps(line)
3284                         continue                 2809                         continue
3285                 # parse only valid lines, if     2810                 # parse only valid lines, if this is not one move on
3286                 m = re.match(tp.ftrace_line_f    2811                 m = re.match(tp.ftrace_line_fmt, line)
3287                 if(not m):                       2812                 if(not m):
3288                         continue                 2813                         continue
3289                 # gather the basic message da    2814                 # gather the basic message data from the line
3290                 m_time = m.group('time')         2815                 m_time = m.group('time')
3291                 m_pid = m.group('pid')           2816                 m_pid = m.group('pid')
3292                 m_msg = m.group('msg')           2817                 m_msg = m.group('msg')
3293                 if(tp.cgformat):                 2818                 if(tp.cgformat):
3294                         m_param3 = m.group('d    2819                         m_param3 = m.group('dur')
3295                 else:                            2820                 else:
3296                         m_param3 = 'traceeven    2821                         m_param3 = 'traceevent'
3297                 if(m_time and m_pid and m_msg    2822                 if(m_time and m_pid and m_msg):
3298                         t = FTraceLine(m_time    2823                         t = FTraceLine(m_time, m_msg, m_param3)
3299                         pid = int(m_pid)         2824                         pid = int(m_pid)
3300                 else:                            2825                 else:
3301                         continue                 2826                         continue
3302                 # the line should be a call,     2827                 # the line should be a call, return, or event
3303                 if(not t.fcall and not t.fret    2828                 if(not t.fcall and not t.freturn and not t.fevent):
3304                         continue                 2829                         continue
3305                 # look for the suspend start     2830                 # look for the suspend start marker
3306                 if(t.startMarker()):             2831                 if(t.startMarker()):
3307                         data = testrun[testid    2832                         data = testrun[testidx].data
3308                         tp.parseStamp(data, s    2833                         tp.parseStamp(data, sysvals)
3309                         data.setStart(t.time, !! 2834                         data.setStart(t.time)
3310                         continue                 2835                         continue
3311                 if(not data):                    2836                 if(not data):
3312                         continue                 2837                         continue
3313                 # find the end of resume         2838                 # find the end of resume
3314                 if(t.endMarker()):               2839                 if(t.endMarker()):
3315                         data.setEnd(t.time, t !! 2840                         data.setEnd(t.time)
3316                         testidx += 1             2841                         testidx += 1
3317                         if(testidx >= testcnt    2842                         if(testidx >= testcnt):
3318                                 break            2843                                 break
3319                         continue                 2844                         continue
3320                 # trace event processing         2845                 # trace event processing
3321                 if(t.fevent):                    2846                 if(t.fevent):
3322                         continue                 2847                         continue
3323                 # call/return processing         2848                 # call/return processing
3324                 elif sysvals.usecallgraph:       2849                 elif sysvals.usecallgraph:
3325                         # create a callgraph     2850                         # create a callgraph object for the data
3326                         if(pid not in testrun    2851                         if(pid not in testrun[testidx].ftemp):
3327                                 testrun[testi    2852                                 testrun[testidx].ftemp[pid] = []
3328                                 testrun[testi    2853                                 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals))
3329                         # when the call is fi    2854                         # when the call is finished, see which device matches it
3330                         cg = testrun[testidx]    2855                         cg = testrun[testidx].ftemp[pid][-1]
3331                         res = cg.addLine(t)      2856                         res = cg.addLine(t)
3332                         if(res != 0):            2857                         if(res != 0):
3333                                 testrun[testi    2858                                 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals))
3334                         if(res == -1):           2859                         if(res == -1):
3335                                 testrun[testi    2860                                 testrun[testidx].ftemp[pid][-1].addLine(t)
3336         tf.close()                               2861         tf.close()
3337                                                  2862 
3338         for test in testrun:                     2863         for test in testrun:
3339                 # add the callgraph data to t    2864                 # add the callgraph data to the device hierarchy
3340                 for pid in test.ftemp:           2865                 for pid in test.ftemp:
3341                         for cg in test.ftemp[    2866                         for cg in test.ftemp[pid]:
3342                                 if len(cg.lis    2867                                 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0):
3343                                         conti    2868                                         continue
3344                                 if(not cg.pos    2869                                 if(not cg.postProcess()):
3345                                         id =     2870                                         id = 'task %s cpu %s' % (pid, m.group('cpu'))
3346                                         sysva    2871                                         sysvals.vprint('Sanity check failed for '+\
3347                                                  2872                                                 id+', ignoring this callback')
3348                                         conti    2873                                         continue
3349                                 callstart = c    2874                                 callstart = cg.start
3350                                 callend = cg.    2875                                 callend = cg.end
3351                                 for p in test    2876                                 for p in test.data.sortedPhases():
3352                                         if(te    2877                                         if(test.data.dmesg[p]['start'] <= callstart and
3353                                                  2878                                                 callstart <= test.data.dmesg[p]['end']):
3354                                                  2879                                                 list = test.data.dmesg[p]['list']
3355                                                  2880                                                 for devname in list:
3356                                                  2881                                                         dev = list[devname]
3357                                                  2882                                                         if(pid == dev['pid'] and
3358                                                  2883                                                                 callstart <= dev['start'] and
3359                                                  2884                                                                 callend >= dev['end']):
3360                                                  2885                                                                 dev['ftrace'] = cg
3361                                                  2886                                                 break
3362                                                  2887 
3363 # Function: loadTraceLog                      << 
3364 # Description:                                << 
3365 #        load the ftrace file into memory and << 
3366 # Output:                                     << 
3367 #        TestProps instance and an array of l << 
3368 def loadTraceLog():                           << 
3369         tp, data, lines, trace = TestProps(), << 
3370         tf = sysvals.openlog(sysvals.ftracefi << 
3371         for line in tf:                       << 
3372                 # remove any latent carriage  << 
3373                 line = line.replace('\r\n', ' << 
3374                 if tp.stampInfo(line, sysvals << 
3375                         continue              << 
3376                 # ignore all other commented  << 
3377                 if line[0] == '#':            << 
3378                         continue              << 
3379                 # ftrace line: parse only val << 
3380                 m = re.match(tp.ftrace_line_f << 
3381                 if(not m):                    << 
3382                         continue              << 
3383                 dur = m.group('dur') if tp.cg << 
3384                 info = (m.group('time'), m.gr << 
3385                         m.group('msg'), dur)  << 
3386                 # group the data by timestamp << 
3387                 t = float(info[0])            << 
3388                 if t in data:                 << 
3389                         data[t].append(info)  << 
3390                 else:                         << 
3391                         data[t] = [info]      << 
3392                 # we only care about trace ev << 
3393                 if (info[3].startswith('suspe << 
3394                         info[3].startswith('t << 
3395                                 trace.append( << 
3396         tf.close()                            << 
3397         for t in sorted(data):                << 
3398                 first, last, blk = [], [], da << 
3399                 if len(blk) > 1 and t in trac << 
3400                         # move certain lines  << 
3401                         for i in range(len(bl << 
3402                                 if 'SUSPEND S << 
3403                                         first << 
3404                                 elif re.match << 
3405                                         last. << 
3406                                 elif re.match << 
3407                                         first << 
3408                                 elif 'RESUME  << 
3409                                         last. << 
3410                         if len(first) == 1 an << 
3411                                 blk.insert(0, << 
3412                         elif len(last) == 1 a << 
3413                                 blk.append(bl << 
3414                 for info in blk:              << 
3415                         lines.append(info)    << 
3416         return (tp, lines)                    << 
3417                                               << 
3418 # Function: parseTraceLog                        2888 # Function: parseTraceLog
3419 # Description:                                   2889 # Description:
3420 #        Analyze an ftrace log output file ge    2890 #        Analyze an ftrace log output file generated from this app during
3421 #        the execution phase. Used when the f    2891 #        the execution phase. Used when the ftrace log is the primary data source
3422 #        and includes the suspend_resume and     2892 #        and includes the suspend_resume and device_pm_callback trace events
3423 #        The ftrace filename is taken from sy    2893 #        The ftrace filename is taken from sysvals
3424 # Output:                                        2894 # Output:
3425 #        An array of Data objects                2895 #        An array of Data objects
3426 def parseTraceLog(live=False):                   2896 def parseTraceLog(live=False):
3427         sysvals.vprint('Analyzing the ftrace     2897         sysvals.vprint('Analyzing the ftrace data (%s)...' % \
3428                 os.path.basename(sysvals.ftra    2898                 os.path.basename(sysvals.ftracefile))
3429         if(os.path.exists(sysvals.ftracefile)    2899         if(os.path.exists(sysvals.ftracefile) == False):
3430                 doError('%s does not exist' %    2900                 doError('%s does not exist' % sysvals.ftracefile)
3431         if not live:                             2901         if not live:
3432                 sysvals.setupAllKprobes()        2902                 sysvals.setupAllKprobes()
3433         ksuscalls = ['ksys_sync', 'pm_prepare !! 2903         ksuscalls = ['pm_prepare_console']
3434         krescalls = ['pm_restore_console']       2904         krescalls = ['pm_restore_console']
3435         tracewatch = ['irq_wakeup']           !! 2905         tracewatch = []
3436         if sysvals.usekprobes:                   2906         if sysvals.usekprobes:
3437                 tracewatch += ['sync_filesyst    2907                 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend',
3438                         'syscore_resume', 're    2908                         'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON',
3439                         'CPU_OFF', 'acpi_susp !! 2909                         'CPU_OFF', 'timekeeping_freeze', 'acpi_suspend']
3440                                                  2910 
3441         # extract the callgraph and traceeven    2911         # extract the callgraph and traceevent data
3442         s2idle_enter = hwsus = False          !! 2912         tp = TestProps()
3443         testruns, testdata = [], []           !! 2913         testruns = []
3444         testrun, data, limbo = 0, 0, True     !! 2914         testdata = []
                                                   >> 2915         testrun = 0
                                                   >> 2916         data = 0
                                                   >> 2917         tf = sysvals.openlog(sysvals.ftracefile, 'r')
3445         phase = 'suspend_prepare'                2918         phase = 'suspend_prepare'
3446         tp, tf = loadTraceLog()               !! 2919         for line in tf:
3447         for m_time, m_proc, m_pid, m_msg, m_p !! 2920                 # remove any latent carriage returns
                                                   >> 2921                 line = line.replace('\r\n', '')
                                                   >> 2922                 if tp.stampInfo(line):
                                                   >> 2923                         continue
                                                   >> 2924                 # tracer type line: determine the trace data type
                                                   >> 2925                 m = re.match(tp.tracertypefmt, line)
                                                   >> 2926                 if(m):
                                                   >> 2927                         tp.setTracerType(m.group('t'))
                                                   >> 2928                         continue
                                                   >> 2929                 # device properties line
                                                   >> 2930                 if(re.match(tp.devpropfmt, line)):
                                                   >> 2931                         devProps(line)
                                                   >> 2932                         continue
                                                   >> 2933                 # ignore all other commented lines
                                                   >> 2934                 if line[0] == '#':
                                                   >> 2935                         continue
                                                   >> 2936                 # ftrace line: parse only valid lines
                                                   >> 2937                 m = re.match(tp.ftrace_line_fmt, line)
                                                   >> 2938                 if(not m):
                                                   >> 2939                         continue
3448                 # gather the basic message da    2940                 # gather the basic message data from the line
                                                   >> 2941                 m_time = m.group('time')
                                                   >> 2942                 m_proc = m.group('proc')
                                                   >> 2943                 m_pid = m.group('pid')
                                                   >> 2944                 m_msg = m.group('msg')
                                                   >> 2945                 if(tp.cgformat):
                                                   >> 2946                         m_param3 = m.group('dur')
                                                   >> 2947                 else:
                                                   >> 2948                         m_param3 = 'traceevent'
3449                 if(m_time and m_pid and m_msg    2949                 if(m_time and m_pid and m_msg):
3450                         t = FTraceLine(m_time    2950                         t = FTraceLine(m_time, m_msg, m_param3)
3451                         pid = int(m_pid)         2951                         pid = int(m_pid)
3452                 else:                            2952                 else:
3453                         continue                 2953                         continue
3454                 # the line should be a call,     2954                 # the line should be a call, return, or event
3455                 if(not t.fcall and not t.fret    2955                 if(not t.fcall and not t.freturn and not t.fevent):
3456                         continue                 2956                         continue
3457                 # find the start of suspend      2957                 # find the start of suspend
3458                 if(t.startMarker()):             2958                 if(t.startMarker()):
3459                         data, limbo = Data(le !! 2959                         data = Data(len(testdata))
3460                         testdata.append(data)    2960                         testdata.append(data)
3461                         testrun = TestRun(dat    2961                         testrun = TestRun(data)
3462                         testruns.append(testr    2962                         testruns.append(testrun)
3463                         tp.parseStamp(data, s    2963                         tp.parseStamp(data, sysvals)
3464                         data.setStart(t.time, !! 2964                         data.setStart(t.time)
3465                         data.first_suspend_pr    2965                         data.first_suspend_prepare = True
3466                         phase = data.setPhase    2966                         phase = data.setPhase('suspend_prepare', t.time, True)
3467                         continue                 2967                         continue
3468                 if(not data or limbo):        !! 2968                 if(not data):
3469                         continue                 2969                         continue
3470                 # process cpu exec line          2970                 # process cpu exec line
3471                 if t.type == 'tracing_mark_wr    2971                 if t.type == 'tracing_mark_write':
3472                         if t.name == 'CMD COM << 
3473                                 data.tKernRes << 
3474                         m = re.match(tp.proce    2972                         m = re.match(tp.procexecfmt, t.name)
3475                         if(m):                   2973                         if(m):
3476                                 parts, msg =  !! 2974                                 proclist = dict()
3477                                 m = re.match( !! 2975                                 for ps in m.group('ps').split(','):
3478                                 if(m):        << 
3479                                         parts << 
3480                                         if tp << 
3481                                               << 
3482                                               << 
3483                                         procl << 
3484                                         tp.mu << 
3485                                 else:         << 
3486                                         procl << 
3487                                         tp.mu << 
3488                                 for ps in msg << 
3489                                         val =    2976                                         val = ps.split()
3490                                         if no !! 2977                                         if not val:
3491                                                  2978                                                 continue
3492                                         name     2979                                         name = val[0].replace('--', '-')
3493                                         procl    2980                                         proclist[name] = int(val[1])
3494                                 if parts == 1 !! 2981                                 data.pstl[t.time] = proclist
3495                                         data. << 
3496                                 elif parts == << 
3497                                         data. << 
3498                                         tp.mu << 
3499                                 continue         2982                                 continue
3500                 # find the end of resume         2983                 # find the end of resume
3501                 if(t.endMarker()):               2984                 if(t.endMarker()):
3502                         if data.tKernRes == 0 !! 2985                         data.handleEndMarker(t.time)
3503                                 data.tKernRes << 
3504                         data.handleEndMarker( << 
3505                         if(not sysvals.usetra    2986                         if(not sysvals.usetracemarkers):
3506                                 # no trace ma    2987                                 # no trace markers? then quit and be sure to finish recording
3507                                 # the event w    2988                                 # the event we used to trigger resume end
3508                                 if('thaw_proc    2989                                 if('thaw_processes' in testrun.ttemp and len(testrun.ttemp['thaw_processes']) > 0):
3509                                         # if     2990                                         # if an entry exists, assume this is its end
3510                                         testr    2991                                         testrun.ttemp['thaw_processes'][-1]['end'] = t.time
3511                         limbo = True          !! 2992                                 break
3512                         continue                 2993                         continue
3513                 # trace event processing         2994                 # trace event processing
3514                 if(t.fevent):                    2995                 if(t.fevent):
3515                         if(t.type == 'suspend    2996                         if(t.type == 'suspend_resume'):
3516                                 # suspend_res    2997                                 # suspend_resume trace events have two types, begin and end
3517                                 if(re.match(r !! 2998                                 if(re.match('(?P<name>.*) begin$', t.name)):
3518                                         isbeg    2999                                         isbegin = True
3519                                 elif(re.match !! 3000                                 elif(re.match('(?P<name>.*) end$', t.name)):
3520                                         isbeg    3001                                         isbegin = False
3521                                 else:            3002                                 else:
3522                                         conti    3003                                         continue
3523                                 if '[' in t.n !! 3004                                 m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name)
3524                                         m = r !! 3005                                 if(m):
                                                   >> 3006                                         val = m.group('val')
                                                   >> 3007                                         if val == '0':
                                                   >> 3008                                                 name = m.group('name')
                                                   >> 3009                                         else:
                                                   >> 3010                                                 name = m.group('name')+'['+val+']'
3525                                 else:            3011                                 else:
3526                                         m = r !! 3012                                         m = re.match('(?P<name>.*) .*', t.name)
3527                                 name = m.grou !! 3013                                         name = m.group('name')
3528                                 # ignore thes    3014                                 # ignore these events
3529                                 if(name.split    3015                                 if(name.split('[')[0] in tracewatch):
3530                                         conti    3016                                         continue
3531                                 # -- phase ch    3017                                 # -- phase changes --
3532                                 # start of ke    3018                                 # start of kernel suspend
3533                                 if(re.match(r !! 3019                                 if(re.match('suspend_enter\[.*', t.name)):
3534                                         if(is !! 3020                                         if(isbegin):
3535                                                  3021                                                 data.tKernSus = t.time
3536                                         conti    3022                                         continue
3537                                 # suspend_pre    3023                                 # suspend_prepare start
3538                                 elif(re.match !! 3024                                 elif(re.match('dpm_prepare\[.*', t.name)):
3539                                         if is    3025                                         if isbegin and data.first_suspend_prepare:
3540                                                  3026                                                 data.first_suspend_prepare = False
3541                                                  3027                                                 if data.tKernSus == 0:
3542                                                  3028                                                         data.tKernSus = t.time
3543                                                  3029                                                 continue
3544                                         phase    3030                                         phase = data.setPhase('suspend_prepare', t.time, isbegin)
3545                                         conti    3031                                         continue
3546                                 # suspend sta    3032                                 # suspend start
3547                                 elif(re.match !! 3033                                 elif(re.match('dpm_suspend\[.*', t.name)):
3548                                         phase    3034                                         phase = data.setPhase('suspend', t.time, isbegin)
3549                                         conti    3035                                         continue
3550                                 # suspend_lat    3036                                 # suspend_late start
3551                                 elif(re.match !! 3037                                 elif(re.match('dpm_suspend_late\[.*', t.name)):
3552                                         phase    3038                                         phase = data.setPhase('suspend_late', t.time, isbegin)
3553                                         conti    3039                                         continue
3554                                 # suspend_noi    3040                                 # suspend_noirq start
3555                                 elif(re.match !! 3041                                 elif(re.match('dpm_suspend_noirq\[.*', t.name)):
3556                                         phase    3042                                         phase = data.setPhase('suspend_noirq', t.time, isbegin)
3557                                         conti    3043                                         continue
3558                                 # suspend_mac    3044                                 # suspend_machine/resume_machine
3559                                 elif(re.match !! 3045                                 elif(re.match('machine_suspend\[.*', t.name)):
3560                                         lp =  << 
3561                                         if(is    3046                                         if(isbegin):
3562                                               !! 3047                                                 lp = data.lastPhase()
3563                                               << 
3564                                               << 
3565                                               << 
3566                                               << 
3567                                               << 
3568                                               << 
3569                                               << 
3570                                               << 
3571                                               << 
3572                                               << 
3573                                               << 
3574                                               << 
3575                                                  3048                                                 phase = data.setPhase('suspend_machine', data.dmesg[lp]['end'], True)
3576                                                  3049                                                 data.setPhase(phase, t.time, False)
3577                                                  3050                                                 if data.tSuspended == 0:
3578                                                  3051                                                         data.tSuspended = t.time
3579                                         else:    3052                                         else:
3580                                               << 
3581                                               << 
3582                                               << 
3583                                                  3053                                                 phase = data.setPhase('resume_machine', t.time, True)
3584                                                  3054                                                 if(sysvals.suspendmode in ['mem', 'disk']):
3585                                                  3055                                                         susp = phase.replace('resume', 'suspend')
3586                                                  3056                                                         if susp in data.dmesg:
3587                                                  3057                                                                 data.dmesg[susp]['end'] = t.time
3588                                                  3058                                                         data.tSuspended = t.time
3589                                                  3059                                                 data.tResumed = t.time
3590                                         conti    3060                                         continue
3591                                 # resume_noir    3061                                 # resume_noirq start
3592                                 elif(re.match !! 3062                                 elif(re.match('dpm_resume_noirq\[.*', t.name)):
3593                                         phase    3063                                         phase = data.setPhase('resume_noirq', t.time, isbegin)
3594                                         conti    3064                                         continue
3595                                 # resume_earl    3065                                 # resume_early start
3596                                 elif(re.match !! 3066                                 elif(re.match('dpm_resume_early\[.*', t.name)):
3597                                         phase    3067                                         phase = data.setPhase('resume_early', t.time, isbegin)
3598                                         conti    3068                                         continue
3599                                 # resume star    3069                                 # resume start
3600                                 elif(re.match !! 3070                                 elif(re.match('dpm_resume\[.*', t.name)):
3601                                         phase    3071                                         phase = data.setPhase('resume', t.time, isbegin)
3602                                         conti    3072                                         continue
3603                                 # resume comp    3073                                 # resume complete start
3604                                 elif(re.match !! 3074                                 elif(re.match('dpm_complete\[.*', t.name)):
3605                                         phase    3075                                         phase = data.setPhase('resume_complete', t.time, isbegin)
3606                                         conti    3076                                         continue
3607                                 # skip trace     3077                                 # skip trace events inside devices calls
3608                                 if(not data.i    3078                                 if(not data.isTraceEventOutsideDeviceCalls(pid, t.time)):
3609                                         conti    3079                                         continue
3610                                 # global even    3080                                 # global events (outside device calls) are graphed
3611                                 if(name not i    3081                                 if(name not in testrun.ttemp):
3612                                         testr    3082                                         testrun.ttemp[name] = []
3613                                 # special han << 
3614                                 if name == 'm << 
3615                                         if hw << 
3616                                               << 
3617                                         elif  << 
3618                                               << 
3619                                               << 
3620                                               << 
3621                                         elif  << 
3622                                               << 
3623                                               << 
3624                                               << 
3625                                         conti << 
3626                                 if(isbegin):     3083                                 if(isbegin):
3627                                         # cre    3084                                         # create a new list entry
3628                                         testr    3085                                         testrun.ttemp[name].append(\
3629                                                  3086                                                 {'begin': t.time, 'end': t.time, 'pid': pid})
3630                                 else:            3087                                 else:
3631                                         if(le    3088                                         if(len(testrun.ttemp[name]) > 0):
3632                                                  3089                                                 # if an entry exists, assume this is its end
3633                                                  3090                                                 testrun.ttemp[name][-1]['end'] = t.time
3634                         # device callback sta    3091                         # device callback start
3635                         elif(t.type == 'devic    3092                         elif(t.type == 'device_pm_callback_start'):
3636                                 if phase not     3093                                 if phase not in data.dmesg:
3637                                         conti    3094                                         continue
3638                                 m = re.match( !! 3095                                 m = re.match('(?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*',\
3639                                         t.nam    3096                                         t.name);
3640                                 if(not m):       3097                                 if(not m):
3641                                         conti    3098                                         continue
3642                                 drv = m.group    3099                                 drv = m.group('drv')
3643                                 n = m.group('    3100                                 n = m.group('d')
3644                                 p = m.group('    3101                                 p = m.group('p')
3645                                 if(n and p):     3102                                 if(n and p):
3646                                         data.    3103                                         data.newAction(phase, n, pid, p, t.time, -1, drv)
3647                                         if pi    3104                                         if pid not in data.devpids:
3648                                                  3105                                                 data.devpids.append(pid)
3649                         # device callback fin    3106                         # device callback finish
3650                         elif(t.type == 'devic    3107                         elif(t.type == 'device_pm_callback_end'):
3651                                 if phase not     3108                                 if phase not in data.dmesg:
3652                                         conti    3109                                         continue
3653                                 m = re.match( !! 3110                                 m = re.match('(?P<drv>.*) (?P<d>.*), err.*', t.name);
3654                                 if(not m):       3111                                 if(not m):
3655                                         conti    3112                                         continue
3656                                 n = m.group('    3113                                 n = m.group('d')
3657                                 dev = data.fi !! 3114                                 list = data.dmesg[phase]['list']
3658                                 if dev:       !! 3115                                 if(n in list):
                                                   >> 3116                                         dev = list[n]
3659                                         dev['    3117                                         dev['length'] = t.time - dev['start']
3660                                         dev['    3118                                         dev['end'] = t.time
3661                 # kprobe event processing        3119                 # kprobe event processing
3662                 elif(t.fkprobe):                 3120                 elif(t.fkprobe):
3663                         kprobename = t.type      3121                         kprobename = t.type
3664                         kprobedata = t.name      3122                         kprobedata = t.name
3665                         key = (kprobename, pi    3123                         key = (kprobename, pid)
3666                         # displayname is gene    3124                         # displayname is generated from kprobe data
3667                         displayname = ''         3125                         displayname = ''
3668                         if(t.fcall):             3126                         if(t.fcall):
3669                                 displayname =    3127                                 displayname = sysvals.kprobeDisplayName(kprobename, kprobedata)
3670                                 if not displa    3128                                 if not displayname:
3671                                         conti    3129                                         continue
3672                                 if(key not in    3130                                 if(key not in tp.ktemp):
3673                                         tp.kt    3131                                         tp.ktemp[key] = []
3674                                 tp.ktemp[key]    3132                                 tp.ktemp[key].append({
3675                                         'pid'    3133                                         'pid': pid,
3676                                         'begi    3134                                         'begin': t.time,
3677                                         'end'    3135                                         'end': -1,
3678                                         'name    3136                                         'name': displayname,
3679                                         'cdat    3137                                         'cdata': kprobedata,
3680                                         'proc    3138                                         'proc': m_proc,
3681                                 })               3139                                 })
3682                                 # start of ke    3140                                 # start of kernel resume
3683                                 if(data.tKern !! 3141                                 if(phase == 'suspend_prepare' and kprobename in ksuscalls):
3684                                         and k << 
3685                                         data.    3142                                         data.tKernSus = t.time
3686                         elif(t.freturn):         3143                         elif(t.freturn):
3687                                 if(key not in    3144                                 if(key not in tp.ktemp) or len(tp.ktemp[key]) < 1:
3688                                         conti    3145                                         continue
3689                                 e = next((x f    3146                                 e = next((x for x in reversed(tp.ktemp[key]) if x['end'] < 0), 0)
3690                                 if not e:        3147                                 if not e:
3691                                         conti    3148                                         continue
3692                                 if (t.time -  << 
3693                                         tp.kt << 
3694                                         conti << 
3695                                 e['end'] = t.    3149                                 e['end'] = t.time
3696                                 e['rdata'] =     3150                                 e['rdata'] = kprobedata
3697                                 # end of kern    3151                                 # end of kernel resume
3698                                 if(phase != '    3152                                 if(phase != 'suspend_prepare' and kprobename in krescalls):
3699                                         if ph    3153                                         if phase in data.dmesg:
3700                                                  3154                                                 data.dmesg[phase]['end'] = t.time
3701                                         data.    3155                                         data.tKernRes = t.time
3702                                                  3156 
3703                 # callgraph processing           3157                 # callgraph processing
3704                 elif sysvals.usecallgraph:       3158                 elif sysvals.usecallgraph:
3705                         # create a callgraph     3159                         # create a callgraph object for the data
3706                         key = (m_proc, pid)      3160                         key = (m_proc, pid)
3707                         if(key not in testrun    3161                         if(key not in testrun.ftemp):
3708                                 testrun.ftemp    3162                                 testrun.ftemp[key] = []
3709                                 testrun.ftemp    3163                                 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals))
3710                         # when the call is fi    3164                         # when the call is finished, see which device matches it
3711                         cg = testrun.ftemp[ke    3165                         cg = testrun.ftemp[key][-1]
3712                         res = cg.addLine(t)      3166                         res = cg.addLine(t)
3713                         if(res != 0):            3167                         if(res != 0):
3714                                 testrun.ftemp    3168                                 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals))
3715                         if(res == -1):           3169                         if(res == -1):
3716                                 testrun.ftemp    3170                                 testrun.ftemp[key][-1].addLine(t)
                                                   >> 3171         tf.close()
3717         if len(testdata) < 1:                    3172         if len(testdata) < 1:
3718                 sysvals.vprint('WARNING: ftra    3173                 sysvals.vprint('WARNING: ftrace start marker is missing')
3719         if data and not data.devicegroups:       3174         if data and not data.devicegroups:
3720                 sysvals.vprint('WARNING: ftra    3175                 sysvals.vprint('WARNING: ftrace end marker is missing')
3721                 data.handleEndMarker(t.time,  !! 3176                 data.handleEndMarker(t.time)
3722                                                  3177 
3723         if sysvals.suspendmode == 'command':     3178         if sysvals.suspendmode == 'command':
3724                 for test in testruns:            3179                 for test in testruns:
3725                         for p in test.data.so    3180                         for p in test.data.sortedPhases():
3726                                 if p == 'susp    3181                                 if p == 'suspend_prepare':
3727                                         test.    3182                                         test.data.dmesg[p]['start'] = test.data.start
3728                                         test.    3183                                         test.data.dmesg[p]['end'] = test.data.end
3729                                 else:            3184                                 else:
3730                                         test.    3185                                         test.data.dmesg[p]['start'] = test.data.end
3731                                         test.    3186                                         test.data.dmesg[p]['end'] = test.data.end
3732                         test.data.tSuspended     3187                         test.data.tSuspended = test.data.end
3733                         test.data.tResumed =     3188                         test.data.tResumed = test.data.end
3734                         test.data.fwValid = F    3189                         test.data.fwValid = False
3735                                                  3190 
3736         # dev source and procmon events can b    3191         # dev source and procmon events can be unreadable with mixed phase height
3737         if sysvals.usedevsrc or sysvals.usepr    3192         if sysvals.usedevsrc or sysvals.useprocmon:
3738                 sysvals.mixedphaseheight = Fa    3193                 sysvals.mixedphaseheight = False
3739                                                  3194 
3740         # expand phase boundaries so there ar    3195         # expand phase boundaries so there are no gaps
3741         for data in testdata:                    3196         for data in testdata:
3742                 lp = data.sortedPhases()[0]      3197                 lp = data.sortedPhases()[0]
3743                 for p in data.sortedPhases():    3198                 for p in data.sortedPhases():
3744                         if(p != lp and not ('    3199                         if(p != lp and not ('machine' in p and 'machine' in lp)):
3745                                 data.dmesg[lp    3200                                 data.dmesg[lp]['end'] = data.dmesg[p]['start']
3746                         lp = p                   3201                         lp = p
3747                                                  3202 
3748         for i in range(len(testruns)):           3203         for i in range(len(testruns)):
3749                 test = testruns[i]               3204                 test = testruns[i]
3750                 data = test.data                 3205                 data = test.data
3751                 # find the total time range f    3206                 # find the total time range for this test (begin, end)
3752                 tlb, tle = data.start, data.e    3207                 tlb, tle = data.start, data.end
3753                 if i < len(testruns) - 1:        3208                 if i < len(testruns) - 1:
3754                         tle = testruns[i+1].d    3209                         tle = testruns[i+1].data.start
3755                 # add the process usage data     3210                 # add the process usage data to the timeline
3756                 if sysvals.useprocmon:           3211                 if sysvals.useprocmon:
3757                         data.createProcessUsa    3212                         data.createProcessUsageEvents()
3758                 # add the traceevent data to     3213                 # add the traceevent data to the device hierarchy
3759                 if(sysvals.usetraceevents):      3214                 if(sysvals.usetraceevents):
3760                         # add actual trace fu    3215                         # add actual trace funcs
3761                         for name in sorted(te !! 3216                         for name in test.ttemp:
3762                                 for event in     3217                                 for event in test.ttemp[name]:
3763                                         if ev !! 3218                                         data.newActionGlobal(name, event['begin'], event['end'], event['pid'])
3764                                               << 
3765                                         title << 
3766                                         if na << 
3767                                               << 
3768                                         data. << 
3769                         # add the kprobe base    3219                         # add the kprobe based virtual tracefuncs as actual devices
3770                         for key in sorted(tp. !! 3220                         for key in tp.ktemp:
3771                                 name, pid = k    3221                                 name, pid = key
3772                                 if name not i    3222                                 if name not in sysvals.tracefuncs:
3773                                         conti    3223                                         continue
3774                                 if pid not in    3224                                 if pid not in data.devpids:
3775                                         data.    3225                                         data.devpids.append(pid)
3776                                 for e in tp.k    3226                                 for e in tp.ktemp[key]:
3777                                         kb, k    3227                                         kb, ke = e['begin'], e['end']
3778                                         if ke    3228                                         if ke - kb < 0.000001 or tlb > kb or tle <= kb:
3779                                                  3229                                                 continue
3780                                         color    3230                                         color = sysvals.kprobeColor(name)
3781                                         data.    3231                                         data.newActionGlobal(e['name'], kb, ke, pid, color)
3782                         # add config base kpr    3232                         # add config base kprobes and dev kprobes
3783                         if sysvals.usedevsrc:    3233                         if sysvals.usedevsrc:
3784                                 for key in so !! 3234                                 for key in tp.ktemp:
3785                                         name,    3235                                         name, pid = key
3786                                         if na    3236                                         if name in sysvals.tracefuncs or name not in sysvals.dev_tracefuncs:
3787                                                  3237                                                 continue
3788                                         for e    3238                                         for e in tp.ktemp[key]:
3789                                                  3239                                                 kb, ke = e['begin'], e['end']
3790                                                  3240                                                 if ke - kb < 0.000001 or tlb > kb or tle <= kb:
3791                                                  3241                                                         continue
3792                                                  3242                                                 data.addDeviceFunctionCall(e['name'], name, e['proc'], pid, kb,
3793                                                  3243                                                         ke, e['cdata'], e['rdata'])
3794                 if sysvals.usecallgraph:         3244                 if sysvals.usecallgraph:
3795                         # add the callgraph d    3245                         # add the callgraph data to the device hierarchy
3796                         sortlist = dict()        3246                         sortlist = dict()
3797                         for key in sorted(tes !! 3247                         for key in test.ftemp:
3798                                 proc, pid = k    3248                                 proc, pid = key
3799                                 for cg in tes    3249                                 for cg in test.ftemp[key]:
3800                                         if le    3250                                         if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0):
3801                                                  3251                                                 continue
3802                                         if(no    3252                                         if(not cg.postProcess()):
3803                                                  3253                                                 id = 'task %s' % (pid)
3804                                                  3254                                                 sysvals.vprint('Sanity check failed for '+\
3805                                                  3255                                                         id+', ignoring this callback')
3806                                                  3256                                                 continue
3807                                         # mat    3257                                         # match cg data to devices
3808                                         devna    3258                                         devname = ''
3809                                         if sy    3259                                         if sysvals.suspendmode != 'command':
3810                                                  3260                                                 devname = cg.deviceMatch(pid, data)
3811                                         if no    3261                                         if not devname:
3812                                                  3262                                                 sortkey = '%f%f%d' % (cg.start, cg.end, pid)
3813                                                  3263                                                 sortlist[sortkey] = cg
3814                                         elif     3264                                         elif len(cg.list) > 1000000 and cg.name != sysvals.ftopfunc:
3815                                                  3265                                                 sysvals.vprint('WARNING: the callgraph for %s is massive (%d lines)' %\
3816                                                  3266                                                         (devname, len(cg.list)))
3817                         # create blocks for o    3267                         # create blocks for orphan cg data
3818                         for sortkey in sorted    3268                         for sortkey in sorted(sortlist):
3819                                 cg = sortlist    3269                                 cg = sortlist[sortkey]
3820                                 name = cg.nam    3270                                 name = cg.name
3821                                 if sysvals.is    3271                                 if sysvals.isCallgraphFunc(name):
3822                                         sysva    3272                                         sysvals.vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name))
3823                                         cg.ne    3273                                         cg.newActionFromFunction(data)
3824         if sysvals.suspendmode == 'command':     3274         if sysvals.suspendmode == 'command':
3825                 return (testdata, '')            3275                 return (testdata, '')
3826                                                  3276 
3827         # fill in any missing phases             3277         # fill in any missing phases
3828         error = []                               3278         error = []
3829         for data in testdata:                    3279         for data in testdata:
3830                 tn = '' if len(testdata) == 1    3280                 tn = '' if len(testdata) == 1 else ('%d' % (data.testnumber + 1))
3831                 terr = ''                        3281                 terr = ''
3832                 phasedef = data.phasedef         3282                 phasedef = data.phasedef
3833                 lp = 'suspend_prepare'           3283                 lp = 'suspend_prepare'
3834                 for p in sorted(phasedef, key    3284                 for p in sorted(phasedef, key=lambda k:phasedef[k]['order']):
3835                         if p not in data.dmes    3285                         if p not in data.dmesg:
3836                                 if not terr:     3286                                 if not terr:
3837                                         ph =  !! 3287                                         pprint('TEST%s FAILED: %s failed in %s phase' % (tn, sysvals.suspendmode, lp))
3838                                         if p  !! 3288                                         terr = '%s%s failed in %s phase' % (sysvals.suspendmode, tn, lp)
3839                                               << 
3840                                               << 
3841                                               << 
3842                                               << 
3843                                         else: << 
3844                                               << 
3845                                         pprin << 
3846                                         error    3289                                         error.append(terr)
3847                                         if da    3290                                         if data.tSuspended == 0:
3848                                                  3291                                                 data.tSuspended = data.dmesg[lp]['end']
3849                                         if da    3292                                         if data.tResumed == 0:
3850                                                  3293                                                 data.tResumed = data.dmesg[lp]['end']
3851                                         data.    3294                                         data.fwValid = False
3852                                 sysvals.vprin    3295                                 sysvals.vprint('WARNING: phase "%s" is missing!' % p)
3853                         lp = p                   3296                         lp = p
3854                 if not terr and 'dev' in data << 
3855                         terr = '%s%s failed i << 
3856                                 (sysvals.susp << 
3857                         error.append(terr)    << 
3858                 if not terr and data.enterfai    3297                 if not terr and data.enterfail:
3859                         pprint('test%s FAILED    3298                         pprint('test%s FAILED: enter %s failed with %s' % (tn, sysvals.suspendmode, data.enterfail))
3860                         terr = 'test%s failed    3299                         terr = 'test%s failed to enter %s mode' % (tn, sysvals.suspendmode)
3861                         error.append(terr)       3300                         error.append(terr)
3862                 if data.tSuspended == 0:         3301                 if data.tSuspended == 0:
3863                         data.tSuspended = dat    3302                         data.tSuspended = data.tKernRes
3864                 if data.tResumed == 0:           3303                 if data.tResumed == 0:
3865                         data.tResumed = data.    3304                         data.tResumed = data.tSuspended
3866                                                  3305 
3867                 if(len(sysvals.devicefilter)     3306                 if(len(sysvals.devicefilter) > 0):
3868                         data.deviceFilter(sys    3307                         data.deviceFilter(sysvals.devicefilter)
3869                 data.fixupInitcallsThatDidntR    3308                 data.fixupInitcallsThatDidntReturn()
3870                 if sysvals.usedevsrc:            3309                 if sysvals.usedevsrc:
3871                         data.optimizeDevSrc()    3310                         data.optimizeDevSrc()
3872                                                  3311 
3873         # x2: merge any overlapping devices b    3312         # x2: merge any overlapping devices between test runs
3874         if sysvals.usedevsrc and len(testdata    3313         if sysvals.usedevsrc and len(testdata) > 1:
3875                 tc = len(testdata)               3314                 tc = len(testdata)
3876                 for i in range(tc - 1):          3315                 for i in range(tc - 1):
3877                         devlist = testdata[i]    3316                         devlist = testdata[i].overflowDevices()
3878                         for j in range(i + 1,    3317                         for j in range(i + 1, tc):
3879                                 testdata[j].m    3318                                 testdata[j].mergeOverlapDevices(devlist)
3880                 testdata[0].stitchTouchingThr    3319                 testdata[0].stitchTouchingThreads(testdata[1:])
3881         return (testdata, ', '.join(error))      3320         return (testdata, ', '.join(error))
3882                                                  3321 
3883 # Function: loadKernelLog                        3322 # Function: loadKernelLog
3884 # Description:                                   3323 # Description:
                                                   >> 3324 #        [deprecated for kernel 3.15.0 or newer]
3885 #        load the dmesg file into memory and     3325 #        load the dmesg file into memory and fix up any ordering issues
                                                   >> 3326 #        The dmesg filename is taken from sysvals
3886 # Output:                                        3327 # Output:
3887 #        An array of empty Data objects with     3328 #        An array of empty Data objects with only their dmesgtext attributes set
3888 def loadKernelLog():                             3329 def loadKernelLog():
3889         sysvals.vprint('Analyzing the dmesg d    3330         sysvals.vprint('Analyzing the dmesg data (%s)...' % \
3890                 os.path.basename(sysvals.dmes    3331                 os.path.basename(sysvals.dmesgfile))
3891         if(os.path.exists(sysvals.dmesgfile)     3332         if(os.path.exists(sysvals.dmesgfile) == False):
3892                 doError('%s does not exist' %    3333                 doError('%s does not exist' % sysvals.dmesgfile)
3893                                                  3334 
3894         # there can be multiple test runs in     3335         # there can be multiple test runs in a single file
3895         tp = TestProps()                         3336         tp = TestProps()
3896         tp.stamp = datetime.now().strftime('#    3337         tp.stamp = datetime.now().strftime('# suspend-%m%d%y-%H%M%S localhost mem unknown')
3897         testruns = []                            3338         testruns = []
3898         data = 0                                 3339         data = 0
3899         lf = sysvals.openlog(sysvals.dmesgfil    3340         lf = sysvals.openlog(sysvals.dmesgfile, 'r')
3900         for line in lf:                          3341         for line in lf:
3901                 line = line.replace('\r\n', '    3342                 line = line.replace('\r\n', '')
3902                 idx = line.find('[')             3343                 idx = line.find('[')
3903                 if idx > 1:                      3344                 if idx > 1:
3904                         line = line[idx:]        3345                         line = line[idx:]
3905                 if tp.stampInfo(line, sysvals !! 3346                 if tp.stampInfo(line):
3906                         continue                 3347                         continue
3907                 m = re.match(r'[ \t]*(\[ *)(? !! 3348                 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
3908                 if(not m):                       3349                 if(not m):
3909                         continue                 3350                         continue
3910                 msg = m.group("msg")             3351                 msg = m.group("msg")
3911                 if re.match(r'PM: Syncing fil !! 3352                 if(re.match('PM: Syncing filesystems.*', msg)):
3912                         re.match(r'PM: suspen << 
3913                         if(data):                3353                         if(data):
3914                                 testruns.appe    3354                                 testruns.append(data)
3915                         data = Data(len(testr    3355                         data = Data(len(testruns))
3916                         tp.parseStamp(data, s    3356                         tp.parseStamp(data, sysvals)
3917                 if(not data):                    3357                 if(not data):
3918                         continue                 3358                         continue
3919                 m = re.match(r'.* *(?P<k>[0-9 !! 3359                 m = re.match('.* *(?P<k>[0-9]\.[0-9]{2}\.[0-9]-.*) .*', msg)
3920                 if(m):                           3360                 if(m):
3921                         sysvals.stamp['kernel    3361                         sysvals.stamp['kernel'] = m.group('k')
3922                 m = re.match(r'PM: Preparing  !! 3362                 m = re.match('PM: Preparing system for (?P<m>.*) sleep', msg)
3923                 if not m:                     !! 3363                 if(m):
3924                         m = re.match(r'PM: Pr << 
3925                 if m:                         << 
3926                         sysvals.stamp['mode']    3364                         sysvals.stamp['mode'] = sysvals.suspendmode = m.group('m')
3927                 data.dmesgtext.append(line)      3365                 data.dmesgtext.append(line)
3928         lf.close()                               3366         lf.close()
3929                                                  3367 
3930         if sysvals.suspendmode == 's2idle':   << 
3931                 sysvals.suspendmode = 'freeze << 
3932         elif sysvals.suspendmode == 'deep':   << 
3933                 sysvals.suspendmode = 'mem'   << 
3934         if data:                                 3368         if data:
3935                 testruns.append(data)            3369                 testruns.append(data)
3936         if len(testruns) < 1:                    3370         if len(testruns) < 1:
3937                 doError('dmesg log has no sus    3371                 doError('dmesg log has no suspend/resume data: %s' \
3938                         % sysvals.dmesgfile)     3372                         % sysvals.dmesgfile)
3939                                                  3373 
3940         # fix lines with same timestamp/funct    3374         # fix lines with same timestamp/function with the call and return swapped
3941         for data in testruns:                    3375         for data in testruns:
3942                 last = ''                        3376                 last = ''
3943                 for line in data.dmesgtext:      3377                 for line in data.dmesgtext:
3944                         ct, cf, n, p = data.i !! 3378                         mc = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) calling  '+\
3945                         rt, rf, l = data.init !! 3379                                 '(?P<f>.*)\+ @ .*, parent: .*', line)
3946                         if ct and rt and ct = !! 3380                         mr = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) call '+\
                                                   >> 3381                                 '(?P<f>.*)\+ returned .* after (?P<dt>.*) usecs', last)
                                                   >> 3382                         if(mc and mr and (mc.group('t') == mr.group('t')) and
                                                   >> 3383                                 (mc.group('f') == mr.group('f'))):
3947                                 i = data.dmes    3384                                 i = data.dmesgtext.index(last)
3948                                 j = data.dmes    3385                                 j = data.dmesgtext.index(line)
3949                                 data.dmesgtex    3386                                 data.dmesgtext[i] = line
3950                                 data.dmesgtex    3387                                 data.dmesgtext[j] = last
3951                         last = line              3388                         last = line
3952         return testruns                          3389         return testruns
3953                                                  3390 
3954 # Function: parseKernelLog                       3391 # Function: parseKernelLog
3955 # Description:                                   3392 # Description:
                                                   >> 3393 #        [deprecated for kernel 3.15.0 or newer]
3956 #        Analyse a dmesg log output file gene    3394 #        Analyse a dmesg log output file generated from this app during
3957 #        the execution phase. Create a set of    3395 #        the execution phase. Create a set of device structures in memory
3958 #        for subsequent formatting in the htm    3396 #        for subsequent formatting in the html output file
3959 #        This call is only for legacy support    3397 #        This call is only for legacy support on kernels where the ftrace
3960 #        data lacks the suspend_resume or dev    3398 #        data lacks the suspend_resume or device_pm_callbacks trace events.
3961 # Arguments:                                     3399 # Arguments:
3962 #        data: an empty Data object (with dme    3400 #        data: an empty Data object (with dmesgtext) obtained from loadKernelLog
3963 # Output:                                        3401 # Output:
3964 #        The filled Data object                  3402 #        The filled Data object
3965 def parseKernelLog(data):                        3403 def parseKernelLog(data):
3966         phase = 'suspend_runtime'                3404         phase = 'suspend_runtime'
3967                                                  3405 
3968         if(data.fwValid):                        3406         if(data.fwValid):
3969                 sysvals.vprint('Firmware Susp    3407                 sysvals.vprint('Firmware Suspend = %u ns, Firmware Resume = %u ns' % \
3970                         (data.fwSuspend, data    3408                         (data.fwSuspend, data.fwResume))
3971                                                  3409 
3972         # dmesg phase match table                3410         # dmesg phase match table
3973         dm = {                                   3411         dm = {
3974                 'suspend_prepare': ['PM: Sync !! 3412                 'suspend_prepare': ['PM: Syncing filesystems.*'],
3975                         'suspend': ['PM: Ente !! 3413                         'suspend': ['PM: Entering [a-z]* sleep.*', 'Suspending console.*'],
3976                                     'PM: Susp !! 3414                    'suspend_late': ['PM: suspend of devices complete after.*'],
3977                    'suspend_late': ['PM: susp !! 3415                   'suspend_noirq': ['PM: late suspend of devices complete after.*'],
3978                                               !! 3416                 'suspend_machine': ['PM: noirq suspend of devices complete after.*'],
3979                   'suspend_noirq': ['PM: late !! 3417                  'resume_machine': ['ACPI: Low-level resume complete.*'],
3980                                               !! 3418                    'resume_noirq': ['ACPI: Waking up from system sleep state.*'],
3981                 'suspend_machine': ['PM: susp !! 3419                    'resume_early': ['PM: noirq resume of devices complete after.*'],
3982                                               !! 3420                          'resume': ['PM: early resume of devices complete after.*'],
3983                                               !! 3421                 'resume_complete': ['PM: resume of devices complete after.*'],
3984                  'resume_machine': ['[PM: ]*T !! 3422                     'post_resume': ['.*Restarting tasks \.\.\..*'],
3985                                               << 
3986                                               << 
3987                                               << 
3988                    'resume_noirq': ['PM: resu << 
3989                                               << 
3990                    'resume_early': ['PM: noir << 
3991                                               << 
3992                          'resume': ['PM: earl << 
3993                                               << 
3994                 'resume_complete': ['PM: resu << 
3995                                               << 
3996                     'post_resume': [r'.*Resta << 
3997         }                                        3423         }
                                                   >> 3424         if(sysvals.suspendmode == 'standby'):
                                                   >> 3425                 dm['resume_machine'] = ['PM: Restoring platform NVS memory']
                                                   >> 3426         elif(sysvals.suspendmode == 'disk'):
                                                   >> 3427                 dm['suspend_late'] = ['PM: freeze of devices complete after.*']
                                                   >> 3428                 dm['suspend_noirq'] = ['PM: late freeze of devices complete after.*']
                                                   >> 3429                 dm['suspend_machine'] = ['PM: noirq freeze of devices complete after.*']
                                                   >> 3430                 dm['resume_machine'] = ['PM: Restoring platform NVS memory']
                                                   >> 3431                 dm['resume_early'] = ['PM: noirq restore of devices complete after.*']
                                                   >> 3432                 dm['resume'] = ['PM: early restore of devices complete after.*']
                                                   >> 3433                 dm['resume_complete'] = ['PM: restore of devices complete after.*']
                                                   >> 3434         elif(sysvals.suspendmode == 'freeze'):
                                                   >> 3435                 dm['resume_machine'] = ['ACPI: resume from mwait']
3998                                                  3436 
3999         # action table (expected events that     3437         # action table (expected events that occur and show up in dmesg)
4000         at = {                                   3438         at = {
4001                 'sync_filesystems': {            3439                 'sync_filesystems': {
4002                         'smsg': '.*[Ff]+ilesy !! 3440                         'smsg': 'PM: Syncing filesystems.*',
4003                         'emsg': 'PM: Preparin !! 3441                         'emsg': 'PM: Preparing system for mem sleep.*' },
4004                 'freeze_user_processes': {       3442                 'freeze_user_processes': {
4005                         'smsg': 'Freezing use !! 3443                         'smsg': 'Freezing user space processes .*',
4006                         'emsg': 'Freezing rem    3444                         'emsg': 'Freezing remaining freezable tasks.*' },
4007                 'freeze_tasks': {                3445                 'freeze_tasks': {
4008                         'smsg': 'Freezing rem    3446                         'smsg': 'Freezing remaining freezable tasks.*',
4009                         'emsg': 'PM: Suspendi !! 3447                         'emsg': 'PM: Entering (?P<mode>[a-z,A-Z]*) sleep.*' },
4010                 'ACPI prepare': {                3448                 'ACPI prepare': {
4011                         'smsg': 'ACPI: Prepar    3449                         'smsg': 'ACPI: Preparing to enter system sleep state.*',
4012                         'emsg': 'PM: Saving p    3450                         'emsg': 'PM: Saving platform NVS memory.*' },
4013                 'PM vns': {                      3451                 'PM vns': {
4014                         'smsg': 'PM: Saving p    3452                         'smsg': 'PM: Saving platform NVS memory.*',
4015                         'emsg': 'Disabling no    3453                         'emsg': 'Disabling non-boot CPUs .*' },
4016         }                                        3454         }
4017                                                  3455 
4018         t0 = -1.0                                3456         t0 = -1.0
4019         cpu_start = -1.0                         3457         cpu_start = -1.0
4020         prevktime = -1.0                         3458         prevktime = -1.0
4021         actions = dict()                         3459         actions = dict()
4022         for line in data.dmesgtext:              3460         for line in data.dmesgtext:
4023                 # parse each dmesg line into     3461                 # parse each dmesg line into the time and message
4024                 m = re.match(r'[ \t]*(\[ *)(? !! 3462                 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
4025                 if(m):                           3463                 if(m):
4026                         val = m.group('ktime'    3464                         val = m.group('ktime')
4027                         try:                     3465                         try:
4028                                 ktime = float    3466                                 ktime = float(val)
4029                         except:                  3467                         except:
4030                                 continue         3468                                 continue
4031                         msg = m.group('msg')     3469                         msg = m.group('msg')
4032                         # initialize data sta    3470                         # initialize data start to first line time
4033                         if t0 < 0:               3471                         if t0 < 0:
4034                                 data.setStart    3472                                 data.setStart(ktime)
4035                                 t0 = ktime       3473                                 t0 = ktime
4036                 else:                            3474                 else:
4037                         continue                 3475                         continue
4038                                                  3476 
4039                 # check for a phase change li    3477                 # check for a phase change line
4040                 phasechange = False              3478                 phasechange = False
4041                 for p in dm:                     3479                 for p in dm:
4042                         for s in dm[p]:          3480                         for s in dm[p]:
4043                                 if(re.match(s    3481                                 if(re.match(s, msg)):
4044                                         phase    3482                                         phasechange, phase = True, p
4045                                         dm[p] << 
4046                                         break    3483                                         break
4047                                                  3484 
4048                 # hack for determining resume    3485                 # hack for determining resume_machine end for freeze
4049                 if(not sysvals.usetraceevents    3486                 if(not sysvals.usetraceevents and sysvals.suspendmode == 'freeze' \
4050                         and phase == 'resume_    3487                         and phase == 'resume_machine' and \
4051                         data.initcall_debug_c !! 3488                         re.match('calling  (?P<f>.*)\+ @ .*, parent: .*', msg)):
4052                         data.setPhase(phase,     3489                         data.setPhase(phase, ktime, False)
4053                         phase = 'resume_noirq    3490                         phase = 'resume_noirq'
4054                         data.setPhase(phase,     3491                         data.setPhase(phase, ktime, True)
4055                                                  3492 
4056                 if phasechange:                  3493                 if phasechange:
4057                         if phase == 'suspend_    3494                         if phase == 'suspend_prepare':
4058                                 data.setPhase    3495                                 data.setPhase(phase, ktime, True)
4059                                 data.setStart    3496                                 data.setStart(ktime)
4060                                 data.tKernSus    3497                                 data.tKernSus = ktime
4061                         elif phase == 'suspen    3498                         elif phase == 'suspend':
4062                                 lp = data.las    3499                                 lp = data.lastPhase()
4063                                 if lp:           3500                                 if lp:
4064                                         data.    3501                                         data.setPhase(lp, ktime, False)
4065                                 data.setPhase    3502                                 data.setPhase(phase, ktime, True)
4066                         elif phase == 'suspen    3503                         elif phase == 'suspend_late':
4067                                 lp = data.las    3504                                 lp = data.lastPhase()
4068                                 if lp:           3505                                 if lp:
4069                                         data.    3506                                         data.setPhase(lp, ktime, False)
4070                                 data.setPhase    3507                                 data.setPhase(phase, ktime, True)
4071                         elif phase == 'suspen    3508                         elif phase == 'suspend_noirq':
4072                                 lp = data.las    3509                                 lp = data.lastPhase()
4073                                 if lp:           3510                                 if lp:
4074                                         data.    3511                                         data.setPhase(lp, ktime, False)
4075                                 data.setPhase    3512                                 data.setPhase(phase, ktime, True)
4076                         elif phase == 'suspen    3513                         elif phase == 'suspend_machine':
4077                                 lp = data.las    3514                                 lp = data.lastPhase()
4078                                 if lp:           3515                                 if lp:
4079                                         data.    3516                                         data.setPhase(lp, ktime, False)
4080                                 data.setPhase    3517                                 data.setPhase(phase, ktime, True)
4081                         elif phase == 'resume    3518                         elif phase == 'resume_machine':
4082                                 lp = data.las    3519                                 lp = data.lastPhase()
4083                                 if(sysvals.su    3520                                 if(sysvals.suspendmode in ['freeze', 'standby']):
4084                                         data.    3521                                         data.tSuspended = prevktime
4085                                         if lp    3522                                         if lp:
4086                                                  3523                                                 data.setPhase(lp, prevktime, False)
4087                                 else:            3524                                 else:
4088                                         data.    3525                                         data.tSuspended = ktime
4089                                         if lp    3526                                         if lp:
4090                                                  3527                                                 data.setPhase(lp, prevktime, False)
4091                                 data.tResumed    3528                                 data.tResumed = ktime
4092                                 data.setPhase    3529                                 data.setPhase(phase, ktime, True)
4093                         elif phase == 'resume    3530                         elif phase == 'resume_noirq':
4094                                 lp = data.las    3531                                 lp = data.lastPhase()
4095                                 if lp:           3532                                 if lp:
4096                                         data.    3533                                         data.setPhase(lp, ktime, False)
4097                                 data.setPhase    3534                                 data.setPhase(phase, ktime, True)
4098                         elif phase == 'resume    3535                         elif phase == 'resume_early':
4099                                 lp = data.las    3536                                 lp = data.lastPhase()
4100                                 if lp:           3537                                 if lp:
4101                                         data.    3538                                         data.setPhase(lp, ktime, False)
4102                                 data.setPhase    3539                                 data.setPhase(phase, ktime, True)
4103                         elif phase == 'resume    3540                         elif phase == 'resume':
4104                                 lp = data.las    3541                                 lp = data.lastPhase()
4105                                 if lp:           3542                                 if lp:
4106                                         data.    3543                                         data.setPhase(lp, ktime, False)
4107                                 data.setPhase    3544                                 data.setPhase(phase, ktime, True)
4108                         elif phase == 'resume    3545                         elif phase == 'resume_complete':
4109                                 lp = data.las    3546                                 lp = data.lastPhase()
4110                                 if lp:           3547                                 if lp:
4111                                         data.    3548                                         data.setPhase(lp, ktime, False)
4112                                 data.setPhase    3549                                 data.setPhase(phase, ktime, True)
4113                         elif phase == 'post_r    3550                         elif phase == 'post_resume':
4114                                 lp = data.las    3551                                 lp = data.lastPhase()
4115                                 if lp:           3552                                 if lp:
4116                                         data.    3553                                         data.setPhase(lp, ktime, False)
4117                                 data.setEnd(k    3554                                 data.setEnd(ktime)
4118                                 data.tKernRes    3555                                 data.tKernRes = ktime
4119                                 break            3556                                 break
4120                                                  3557 
4121                 # -- device callbacks --         3558                 # -- device callbacks --
4122                 if(phase in data.sortedPhases    3559                 if(phase in data.sortedPhases()):
4123                         # device init call       3560                         # device init call
4124                         t, f, n, p = data.ini !! 3561                         if(re.match('calling  (?P<f>.*)\+ @ .*, parent: .*', msg)):
4125                         if t and f and n and  !! 3562                                 sm = re.match('calling  (?P<f>.*)\+ @ '+\
4126                                 data.newActio !! 3563                                         '(?P<n>.*), parent: (?P<p>.*)', msg);
4127                         else:                 !! 3564                                 f = sm.group('f')
4128                                 # device init !! 3565                                 n = sm.group('n')
4129                                 t, f, l = dat !! 3566                                 p = sm.group('p')
4130                                 if t and f an !! 3567                                 if(f and n and p):
4131                                         list  !! 3568                                         data.newAction(phase, f, int(n), p, ktime, -1, '')
4132                                         if(f  !! 3569                         # device init return
4133                                               !! 3570                         elif(re.match('call (?P<f>.*)\+ returned .* after '+\
4134                                               !! 3571                                 '(?P<t>.*) usecs', msg)):
4135                                               !! 3572                                 sm = re.match('call (?P<f>.*)\+ returned .* after '+\
                                                   >> 3573                                         '(?P<t>.*) usecs(?P<a>.*)', msg);
                                                   >> 3574                                 f = sm.group('f')
                                                   >> 3575                                 t = sm.group('t')
                                                   >> 3576                                 list = data.dmesg[phase]['list']
                                                   >> 3577                                 if(f in list):
                                                   >> 3578                                         dev = list[f]
                                                   >> 3579                                         dev['length'] = int(t)
                                                   >> 3580                                         dev['end'] = ktime
4136                                                  3581 
4137                 # if trace events are not ava    3582                 # if trace events are not available, these are better than nothing
4138                 if(not sysvals.usetraceevents    3583                 if(not sysvals.usetraceevents):
4139                         # look for known acti    3584                         # look for known actions
4140                         for a in sorted(at):  !! 3585                         for a in at:
4141                                 if(re.match(a    3586                                 if(re.match(at[a]['smsg'], msg)):
4142                                         if(a     3587                                         if(a not in actions):
4143                                               !! 3588                                                 actions[a] = []
                                                   >> 3589                                         actions[a].append({'begin': ktime, 'end': ktime})
4144                                 if(re.match(a    3590                                 if(re.match(at[a]['emsg'], msg)):
4145                                         if(a  !! 3591                                         if(a in actions):
4146                                                  3592                                                 actions[a][-1]['end'] = ktime
4147                         # now look for CPU on    3593                         # now look for CPU on/off events
4148                         if(re.match(r'Disabli !! 3594                         if(re.match('Disabling non-boot CPUs .*', msg)):
4149                                 # start of fi    3595                                 # start of first cpu suspend
4150                                 cpu_start = k    3596                                 cpu_start = ktime
4151                         elif(re.match(r'Enabl !! 3597                         elif(re.match('Enabling non-boot CPUs .*', msg)):
4152                                 # start of fi    3598                                 # start of first cpu resume
4153                                 cpu_start = k    3599                                 cpu_start = ktime
4154                         elif(re.match(r'smpbo !! 3600                         elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)):
4155                                 or re.match(r << 
4156                                 # end of a cp    3601                                 # end of a cpu suspend, start of the next
4157                                 m = re.match( !! 3602                                 m = re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)
4158                                 if(not m):    << 
4159                                         m = r << 
4160                                 cpu = 'CPU'+m    3603                                 cpu = 'CPU'+m.group('cpu')
4161                                 if(cpu not in    3604                                 if(cpu not in actions):
4162                                         actio    3605                                         actions[cpu] = []
4163                                 actions[cpu].    3606                                 actions[cpu].append({'begin': cpu_start, 'end': ktime})
4164                                 cpu_start = k    3607                                 cpu_start = ktime
4165                         elif(re.match(r'CPU(? !! 3608                         elif(re.match('CPU(?P<cpu>[0-9]*) is up', msg)):
4166                                 # end of a cp    3609                                 # end of a cpu resume, start of the next
4167                                 m = re.match( !! 3610                                 m = re.match('CPU(?P<cpu>[0-9]*) is up', msg)
4168                                 cpu = 'CPU'+m    3611                                 cpu = 'CPU'+m.group('cpu')
4169                                 if(cpu not in    3612                                 if(cpu not in actions):
4170                                         actio    3613                                         actions[cpu] = []
4171                                 actions[cpu].    3614                                 actions[cpu].append({'begin': cpu_start, 'end': ktime})
4172                                 cpu_start = k    3615                                 cpu_start = ktime
4173                 prevktime = ktime                3616                 prevktime = ktime
4174         data.initDevicegroups()                  3617         data.initDevicegroups()
4175                                                  3618 
4176         # fill in any missing phases             3619         # fill in any missing phases
4177         phasedef = data.phasedef                 3620         phasedef = data.phasedef
4178         terr, lp = '', 'suspend_prepare'         3621         terr, lp = '', 'suspend_prepare'
4179         if lp not in data.dmesg:              << 
4180                 doError('dmesg log format has << 
4181         for p in sorted(phasedef, key=lambda     3622         for p in sorted(phasedef, key=lambda k:phasedef[k]['order']):
4182                 if p not in data.dmesg:          3623                 if p not in data.dmesg:
4183                         if not terr:             3624                         if not terr:
4184                                 pprint('TEST     3625                                 pprint('TEST FAILED: %s failed in %s phase' % (sysvals.suspendmode, lp))
4185                                 terr = '%s fa    3626                                 terr = '%s failed in %s phase' % (sysvals.suspendmode, lp)
4186                                 if data.tSusp    3627                                 if data.tSuspended == 0:
4187                                         data.    3628                                         data.tSuspended = data.dmesg[lp]['end']
4188                                 if data.tResu    3629                                 if data.tResumed == 0:
4189                                         data.    3630                                         data.tResumed = data.dmesg[lp]['end']
4190                         sysvals.vprint('WARNI    3631                         sysvals.vprint('WARNING: phase "%s" is missing!' % p)
4191                 lp = p                           3632                 lp = p
4192         lp = data.sortedPhases()[0]              3633         lp = data.sortedPhases()[0]
4193         for p in data.sortedPhases():            3634         for p in data.sortedPhases():
4194                 if(p != lp and not ('machine'    3635                 if(p != lp and not ('machine' in p and 'machine' in lp)):
4195                         data.dmesg[lp]['end']    3636                         data.dmesg[lp]['end'] = data.dmesg[p]['start']
4196                 lp = p                           3637                 lp = p
4197         if data.tSuspended == 0:                 3638         if data.tSuspended == 0:
4198                 data.tSuspended = data.tKernR    3639                 data.tSuspended = data.tKernRes
4199         if data.tResumed == 0:                   3640         if data.tResumed == 0:
4200                 data.tResumed = data.tSuspend    3641                 data.tResumed = data.tSuspended
4201                                                  3642 
4202         # fill in any actions we've found        3643         # fill in any actions we've found
4203         for name in sorted(actions):          !! 3644         for name in actions:
4204                 for event in actions[name]:      3645                 for event in actions[name]:
4205                         data.newActionGlobal(    3646                         data.newActionGlobal(name, event['begin'], event['end'])
4206                                                  3647 
4207         if(len(sysvals.devicefilter) > 0):       3648         if(len(sysvals.devicefilter) > 0):
4208                 data.deviceFilter(sysvals.dev    3649                 data.deviceFilter(sysvals.devicefilter)
4209         data.fixupInitcallsThatDidntReturn()     3650         data.fixupInitcallsThatDidntReturn()
4210         return True                              3651         return True
4211                                                  3652 
4212 def callgraphHTML(sv, hf, num, cg, title, col    3653 def callgraphHTML(sv, hf, num, cg, title, color, devid):
4213         html_func_top = '<article id="{0}" cl    3654         html_func_top = '<article id="{0}" class="atop" style="background:{1}">\n<input type="checkbox" class="pf" id="f{2}" checked/><label for="f{2}">{3} {4}</label>\n'
4214         html_func_start = '<article>\n<input     3655         html_func_start = '<article>\n<input type="checkbox" class="pf" id="f{0}" checked/><label for="f{0}">{1} {2}</label>\n'
4215         html_func_end = '</article>\n'           3656         html_func_end = '</article>\n'
4216         html_func_leaf = '<article>{0} {1}</a    3657         html_func_leaf = '<article>{0} {1}</article>\n'
4217                                                  3658 
4218         cgid = devid                             3659         cgid = devid
4219         if cg.id:                                3660         if cg.id:
4220                 cgid += cg.id                    3661                 cgid += cg.id
4221         cglen = (cg.end - cg.start) * 1000       3662         cglen = (cg.end - cg.start) * 1000
4222         if cglen < sv.mincglen:                  3663         if cglen < sv.mincglen:
4223                 return num                       3664                 return num
4224                                                  3665 
4225         fmt = '<r>(%.3f ms @ '+sv.timeformat+'    3666         fmt = '<r>(%.3f ms @ '+sv.timeformat+' to '+sv.timeformat+')</r>'
4226         flen = fmt % (cglen, cg.start, cg.end    3667         flen = fmt % (cglen, cg.start, cg.end)
4227         hf.write(html_func_top.format(cgid, c    3668         hf.write(html_func_top.format(cgid, color, num, title, flen))
4228         num += 1                                 3669         num += 1
4229         for line in cg.list:                     3670         for line in cg.list:
4230                 if(line.length < 0.000000001)    3671                 if(line.length < 0.000000001):
4231                         flen = ''                3672                         flen = ''
4232                 else:                            3673                 else:
4233                         fmt = '<n>(%.3f ms @ '    3674                         fmt = '<n>(%.3f ms @ '+sv.timeformat+')</n>'
4234                         flen = fmt % (line.le    3675                         flen = fmt % (line.length*1000, line.time)
4235                 if line.isLeaf():                3676                 if line.isLeaf():
4236                         if line.length * 1000 << 
4237                                 continue      << 
4238                         hf.write(html_func_le    3677                         hf.write(html_func_leaf.format(line.name, flen))
4239                 elif line.freturn:               3678                 elif line.freturn:
4240                         hf.write(html_func_en    3679                         hf.write(html_func_end)
4241                 else:                            3680                 else:
4242                         hf.write(html_func_st    3681                         hf.write(html_func_start.format(num, line.name, flen))
4243                         num += 1                 3682                         num += 1
4244         hf.write(html_func_end)                  3683         hf.write(html_func_end)
4245         return num                               3684         return num
4246                                                  3685 
4247 def addCallgraphs(sv, hf, data):                 3686 def addCallgraphs(sv, hf, data):
4248         hf.write('<section id="callgraphs" cl    3687         hf.write('<section id="callgraphs" class="callgraph">\n')
4249         # write out the ftrace data converted    3688         # write out the ftrace data converted to html
4250         num = 0                                  3689         num = 0
4251         for p in data.sortedPhases():            3690         for p in data.sortedPhases():
4252                 if sv.cgphase and p != sv.cgp    3691                 if sv.cgphase and p != sv.cgphase:
4253                         continue                 3692                         continue
4254                 list = data.dmesg[p]['list']     3693                 list = data.dmesg[p]['list']
4255                 for d in data.sortedDevices(p !! 3694                 for devname in data.sortedDevices(p):
4256                         if len(sv.cgfilter) > !! 3695                         if len(sv.cgfilter) > 0 and devname not in sv.cgfilter:
4257                                 continue         3696                                 continue
4258                         dev = list[d]         !! 3697                         dev = list[devname]
4259                         color = 'white'          3698                         color = 'white'
4260                         if 'color' in data.dm    3699                         if 'color' in data.dmesg[p]:
4261                                 color = data.    3700                                 color = data.dmesg[p]['color']
4262                         if 'color' in dev:       3701                         if 'color' in dev:
4263                                 color = dev['    3702                                 color = dev['color']
4264                         name = d if '[' not i !! 3703                         name = devname
4265                         if(d in sv.devprops): !! 3704                         if(devname in sv.devprops):
4266                                 name = sv.dev !! 3705                                 name = sv.devprops[devname].altName(devname)
4267                         if 'drv' in dev and d << 
4268                                 name += ' {%s << 
4269                         if sv.suspendmode in     3706                         if sv.suspendmode in suspendmodename:
4270                                 name += ' '+p    3707                                 name += ' '+p
4271                         if('ftrace' in dev):     3708                         if('ftrace' in dev):
4272                                 cg = dev['ftr    3709                                 cg = dev['ftrace']
4273                                 if cg.name ==    3710                                 if cg.name == sv.ftopfunc:
4274                                         name     3711                                         name = 'top level suspend/resume call'
4275                                 num = callgra    3712                                 num = callgraphHTML(sv, hf, num, cg,
4276                                         name,    3713                                         name, color, dev['id'])
4277                         if('ftraces' in dev):    3714                         if('ftraces' in dev):
4278                                 for cg in dev    3715                                 for cg in dev['ftraces']:
4279                                         num =    3716                                         num = callgraphHTML(sv, hf, num, cg,
4280                                                  3717                                                 name+' &rarr; '+cg.name, color, dev['id'])
4281         hf.write('\n\n    </section>\n')         3718         hf.write('\n\n    </section>\n')
4282                                                  3719 
4283 def summaryCSS(title, center=True):              3720 def summaryCSS(title, center=True):
4284         tdcenter = 'text-align:center;' if ce    3721         tdcenter = 'text-align:center;' if center else ''
4285         out = '<!DOCTYPE html>\n<html>\n<head    3722         out = '<!DOCTYPE html>\n<html>\n<head>\n\
4286         <meta http-equiv="content-type" conte    3723         <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\
4287         <title>'+title+'</title>\n\              3724         <title>'+title+'</title>\n\
4288         <style type=\'text/css\'>\n\             3725         <style type=\'text/css\'>\n\
4289                 .stamp {width: 100%;text-alig    3726                 .stamp {width: 100%;text-align:center;background:#888;line-height:30px;color:white;font: 25px Arial;}\n\
4290                 table {width:100%;border-coll    3727                 table {width:100%;border-collapse: collapse;border:1px solid;}\n\
4291                 th {border: 1px solid black;b    3728                 th {border: 1px solid black;background:#222;color:white;}\n\
4292                 td {font: 14px "Times New Rom    3729                 td {font: 14px "Times New Roman";'+tdcenter+'}\n\
4293                 tr.head td {border: 1px solid    3730                 tr.head td {border: 1px solid black;background:#aaa;}\n\
4294                 tr.alt {background-color:#ddd    3731                 tr.alt {background-color:#ddd;}\n\
4295                 tr.notice {color:red;}\n\        3732                 tr.notice {color:red;}\n\
4296                 .minval {background-color:#BB    3733                 .minval {background-color:#BBFFBB;}\n\
4297                 .medval {background-color:#BB    3734                 .medval {background-color:#BBBBFF;}\n\
4298                 .maxval {background-color:#FF    3735                 .maxval {background-color:#FFBBBB;}\n\
4299                 .head a {color:#000;text-deco    3736                 .head a {color:#000;text-decoration: none;}\n\
4300         </style>\n</head>\n<body>\n'             3737         </style>\n</head>\n<body>\n'
4301         return out                               3738         return out
4302                                                  3739 
4303 # Function: createHTMLSummarySimple              3740 # Function: createHTMLSummarySimple
4304 # Description:                                   3741 # Description:
4305 #        Create summary html file for a serie    3742 #        Create summary html file for a series of tests
4306 # Arguments:                                     3743 # Arguments:
4307 #        testruns: array of Data objects from    3744 #        testruns: array of Data objects from parseTraceLog
4308 def createHTMLSummarySimple(testruns, htmlfil    3745 def createHTMLSummarySimple(testruns, htmlfile, title):
4309         # write the html header first (html h    3746         # write the html header first (html head, css code, up to body start)
4310         html = summaryCSS('Summary - SleepGra    3747         html = summaryCSS('Summary - SleepGraph')
4311                                                  3748 
4312         # extract the test data into list        3749         # extract the test data into list
4313         list = dict()                            3750         list = dict()
4314         tAvg, tMin, tMax, tMed = [0.0, 0.0],     3751         tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [dict(), dict()]
4315         iMin, iMed, iMax = [0, 0], [0, 0], [0    3752         iMin, iMed, iMax = [0, 0], [0, 0], [0, 0]
4316         num = 0                                  3753         num = 0
4317         useturbo = usewifi = False            !! 3754         useturbo = False
4318         lastmode = ''                            3755         lastmode = ''
4319         cnt = dict()                             3756         cnt = dict()
4320         for data in sorted(testruns, key=lamb    3757         for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])):
4321                 mode = data['mode']              3758                 mode = data['mode']
4322                 if mode not in list:             3759                 if mode not in list:
4323                         list[mode] = {'data':    3760                         list[mode] = {'data': [], 'avg': [0,0], 'min': [0,0], 'max': [0,0], 'med': [0,0]}
4324                 if lastmode and lastmode != m    3761                 if lastmode and lastmode != mode and num > 0:
4325                         for i in range(2):       3762                         for i in range(2):
4326                                 s = sorted(tM    3763                                 s = sorted(tMed[i])
4327                                 list[lastmode !! 3764                                 list[lastmode]['med'][i] = s[int(len(s)/2)]
4328                                 iMed[i] = tMe    3765                                 iMed[i] = tMed[i][list[lastmode]['med'][i]]
4329                         list[lastmode]['avg']    3766                         list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num]
4330                         list[lastmode]['min']    3767                         list[lastmode]['min'] = tMin
4331                         list[lastmode]['max']    3768                         list[lastmode]['max'] = tMax
4332                         list[lastmode]['idx']    3769                         list[lastmode]['idx'] = (iMin, iMed, iMax)
4333                         tAvg, tMin, tMax, tMe    3770                         tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [dict(), dict()]
4334                         iMin, iMed, iMax = [0    3771                         iMin, iMed, iMax = [0, 0], [0, 0], [0, 0]
4335                         num = 0                  3772                         num = 0
4336                 pkgpc10 = syslpi = wifi = ''  !! 3773                 pkgpc10 = syslpi = ''
4337                 if 'pkgpc10' in data and 'sys    3774                 if 'pkgpc10' in data and 'syslpi' in data:
4338                         pkgpc10, syslpi, uset !! 3775                         pkgpc10 = data['pkgpc10']
4339                 if 'wifi' in data:            !! 3776                         syslpi = data['syslpi']
4340                         wifi, usewifi = data[ !! 3777                         useturbo = True
4341                 res = data['result']             3778                 res = data['result']
4342                 tVal = [float(data['suspend']    3779                 tVal = [float(data['suspend']), float(data['resume'])]
4343                 list[mode]['data'].append([da    3780                 list[mode]['data'].append([data['host'], data['kernel'],
4344                         data['time'], tVal[0]    3781                         data['time'], tVal[0], tVal[1], data['url'], res,
4345                         data['issues'], data[    3782                         data['issues'], data['sus_worst'], data['sus_worsttime'],
4346                         data['res_worst'], da !! 3783                         data['res_worst'], data['res_worsttime'], pkgpc10, syslpi])
4347                         (data['fullmode'] if  << 
4348                 idx = len(list[mode]['data'])    3784                 idx = len(list[mode]['data']) - 1
4349                 if res.startswith('fail in'):    3785                 if res.startswith('fail in'):
4350                         res = 'fail'             3786                         res = 'fail'
4351                 if res not in cnt:               3787                 if res not in cnt:
4352                         cnt[res] = 1             3788                         cnt[res] = 1
4353                 else:                            3789                 else:
4354                         cnt[res] += 1            3790                         cnt[res] += 1
4355                 if res == 'pass':                3791                 if res == 'pass':
4356                         for i in range(2):       3792                         for i in range(2):
4357                                 tMed[i][tVal[    3793                                 tMed[i][tVal[i]] = idx
4358                                 tAvg[i] += tV    3794                                 tAvg[i] += tVal[i]
4359                                 if tMin[i] ==    3795                                 if tMin[i] == 0 or tVal[i] < tMin[i]:
4360                                         iMin[    3796                                         iMin[i] = idx
4361                                         tMin[    3797                                         tMin[i] = tVal[i]
4362                                 if tMax[i] ==    3798                                 if tMax[i] == 0 or tVal[i] > tMax[i]:
4363                                         iMax[    3799                                         iMax[i] = idx
4364                                         tMax[    3800                                         tMax[i] = tVal[i]
4365                         num += 1                 3801                         num += 1
4366                 lastmode = mode                  3802                 lastmode = mode
4367         if lastmode and num > 0:                 3803         if lastmode and num > 0:
4368                 for i in range(2):               3804                 for i in range(2):
4369                         s = sorted(tMed[i])      3805                         s = sorted(tMed[i])
4370                         list[lastmode]['med'] !! 3806                         list[lastmode]['med'][i] = s[int(len(s)/2)]
4371                         iMed[i] = tMed[i][lis    3807                         iMed[i] = tMed[i][list[lastmode]['med'][i]]
4372                 list[lastmode]['avg'] = [tAvg    3808                 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num]
4373                 list[lastmode]['min'] = tMin     3809                 list[lastmode]['min'] = tMin
4374                 list[lastmode]['max'] = tMax     3810                 list[lastmode]['max'] = tMax
4375                 list[lastmode]['idx'] = (iMin    3811                 list[lastmode]['idx'] = (iMin, iMed, iMax)
4376                                                  3812 
4377         # group test header                      3813         # group test header
4378         desc = []                                3814         desc = []
4379         for ilk in sorted(cnt, reverse=True):    3815         for ilk in sorted(cnt, reverse=True):
4380                 if cnt[ilk] > 0:                 3816                 if cnt[ilk] > 0:
4381                         desc.append('%d %s' %    3817                         desc.append('%d %s' % (cnt[ilk], ilk))
4382         html += '<div class="stamp">%s (%d te    3818         html += '<div class="stamp">%s (%d tests: %s)</div>\n' % (title, len(testruns), ', '.join(desc))
4383         th = '\t<th>{0}</th>\n'                  3819         th = '\t<th>{0}</th>\n'
4384         td = '\t<td>{0}</td>\n'                  3820         td = '\t<td>{0}</td>\n'
4385         tdh = '\t<td{1}>{0}</td>\n'              3821         tdh = '\t<td{1}>{0}</td>\n'
4386         tdlink = '\t<td><a href="{0}">html</a    3822         tdlink = '\t<td><a href="{0}">html</a></td>\n'
4387         cols = 12                             !! 3823         colspan = '14' if useturbo else '12'
4388         if useturbo:                          << 
4389                 cols += 2                     << 
4390         if usewifi:                           << 
4391                 cols += 1                     << 
4392         colspan = '%d' % cols                 << 
4393                                                  3824 
4394         # table header                           3825         # table header
4395         html += '<table>\n<tr>\n' + th.format    3826         html += '<table>\n<tr>\n' + th.format('#') +\
4396                 th.format('Mode') + th.format    3827                 th.format('Mode') + th.format('Host') + th.format('Kernel') +\
4397                 th.format('Test Time') + th.f    3828                 th.format('Test Time') + th.format('Result') + th.format('Issues') +\
4398                 th.format('Suspend') + th.for    3829                 th.format('Suspend') + th.format('Resume') +\
4399                 th.format('Worst Suspend Devi    3830                 th.format('Worst Suspend Device') + th.format('SD Time') +\
4400                 th.format('Worst Resume Devic    3831                 th.format('Worst Resume Device') + th.format('RD Time')
4401         if useturbo:                             3832         if useturbo:
4402                 html += th.format('PkgPC10')     3833                 html += th.format('PkgPC10') + th.format('SysLPI')
4403         if usewifi:                           << 
4404                 html += th.format('Wifi')     << 
4405         html += th.format('Detail')+'</tr>\n'    3834         html += th.format('Detail')+'</tr>\n'
4406         # export list into html                  3835         # export list into html
4407         head = '<tr class="head"><td>{0}</td>    3836         head = '<tr class="head"><td>{0}</td><td>{1}</td>'+\
4408                 '<td colspan='+colspan+' clas    3837                 '<td colspan='+colspan+' class="sus">Suspend Avg={2} '+\
4409                 '<span class=minval><a href="    3838                 '<span class=minval><a href="#s{10}min">Min={3}</a></span> '+\
4410                 '<span class=medval><a href="    3839                 '<span class=medval><a href="#s{10}med">Med={4}</a></span> '+\
4411                 '<span class=maxval><a href="    3840                 '<span class=maxval><a href="#s{10}max">Max={5}</a></span> '+\
4412                 'Resume Avg={6} '+\              3841                 'Resume Avg={6} '+\
4413                 '<span class=minval><a href="    3842                 '<span class=minval><a href="#r{10}min">Min={7}</a></span> '+\
4414                 '<span class=medval><a href="    3843                 '<span class=medval><a href="#r{10}med">Med={8}</a></span> '+\
4415                 '<span class=maxval><a href="    3844                 '<span class=maxval><a href="#r{10}max">Max={9}</a></span></td>'+\
4416                 '</tr>\n'                        3845                 '</tr>\n'
4417         headnone = '<tr class="head"><td>{0}<    3846         headnone = '<tr class="head"><td>{0}</td><td>{1}</td><td colspan='+\
4418                 colspan+'></td></tr>\n'          3847                 colspan+'></td></tr>\n'
4419         for mode in sorted(list):             !! 3848         for mode in list:
4420                 # header line for each suspen    3849                 # header line for each suspend mode
4421                 num = 0                          3850                 num = 0
4422                 tAvg, tMin, tMax, tMed = list    3851                 tAvg, tMin, tMax, tMed = list[mode]['avg'], list[mode]['min'],\
4423                         list[mode]['max'], li    3852                         list[mode]['max'], list[mode]['med']
4424                 count = len(list[mode]['data'    3853                 count = len(list[mode]['data'])
4425                 if 'idx' in list[mode]:          3854                 if 'idx' in list[mode]:
4426                         iMin, iMed, iMax = li    3855                         iMin, iMed, iMax = list[mode]['idx']
4427                         html += head.format('    3856                         html += head.format('%d' % count, mode.upper(),
4428                                 '%.3f' % tAvg    3857                                 '%.3f' % tAvg[0], '%.3f' % tMin[0], '%.3f' % tMed[0], '%.3f' % tMax[0],
4429                                 '%.3f' % tAvg    3858                                 '%.3f' % tAvg[1], '%.3f' % tMin[1], '%.3f' % tMed[1], '%.3f' % tMax[1],
4430                                 mode.lower()     3859                                 mode.lower()
4431                         )                        3860                         )
4432                 else:                            3861                 else:
4433                         iMin = iMed = iMax =     3862                         iMin = iMed = iMax = [-1, -1, -1]
4434                         html += headnone.form    3863                         html += headnone.format('%d' % count, mode.upper())
4435                 for d in list[mode]['data']:     3864                 for d in list[mode]['data']:
4436                         # row classes - alter    3865                         # row classes - alternate row color
4437                         rcls = ['alt'] if num    3866                         rcls = ['alt'] if num % 2 == 1 else []
4438                         if d[6] != 'pass':       3867                         if d[6] != 'pass':
4439                                 rcls.append('    3868                                 rcls.append('notice')
4440                         html += '<tr class="'    3869                         html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n'
4441                         # figure out if the l    3870                         # figure out if the line has sus or res highlighted
4442                         idx = list[mode]['dat    3871                         idx = list[mode]['data'].index(d)
4443                         tHigh = ['', '']         3872                         tHigh = ['', '']
4444                         for i in range(2):       3873                         for i in range(2):
4445                                 tag = 's%s' %    3874                                 tag = 's%s' % mode if i == 0 else 'r%s' % mode
4446                                 if idx == iMi    3875                                 if idx == iMin[i]:
4447                                         tHigh    3876                                         tHigh[i] = ' id="%smin" class=minval title="Minimum"' % tag
4448                                 elif idx == i    3877                                 elif idx == iMax[i]:
4449                                         tHigh    3878                                         tHigh[i] = ' id="%smax" class=maxval title="Maximum"' % tag
4450                                 elif idx == i    3879                                 elif idx == iMed[i]:
4451                                         tHigh    3880                                         tHigh[i] = ' id="%smed" class=medval title="Median"' % tag
4452                         html += td.format("%d    3881                         html += td.format("%d" % (list[mode]['data'].index(d) + 1)) # row
4453                         html += td.format(d[1 !! 3882                         html += td.format(mode)                                                                         # mode
4454                         html += td.format(d[0    3883                         html += td.format(d[0])                                                                         # host
4455                         html += td.format(d[1    3884                         html += td.format(d[1])                                                                         # kernel
4456                         html += td.format(d[2    3885                         html += td.format(d[2])                                                                         # time
4457                         html += td.format(d[6    3886                         html += td.format(d[6])                                                                         # result
4458                         html += td.format(d[7    3887                         html += td.format(d[7])                                                                         # issues
4459                         html += tdh.format('%    3888                         html += tdh.format('%.3f ms' % d[3], tHigh[0]) if d[3] else td.format('')       # suspend
4460                         html += tdh.format('%    3889                         html += tdh.format('%.3f ms' % d[4], tHigh[1]) if d[4] else td.format('')       # resume
4461                         html += td.format(d[8    3890                         html += td.format(d[8])                                                                         # sus_worst
4462                         html += td.format('%.    3891                         html += td.format('%.3f ms' % d[9])     if d[9] else td.format('')              # sus_worst time
4463                         html += td.format(d[1    3892                         html += td.format(d[10])                                                                        # res_worst
4464                         html += td.format('%.    3893                         html += td.format('%.3f ms' % d[11]) if d[11] else td.format('')        # res_worst time
4465                         if useturbo:             3894                         if useturbo:
4466                                 html += td.fo    3895                                 html += td.format(d[12])                                                                # pkg_pc10
4467                                 html += td.fo    3896                                 html += td.format(d[13])                                                                # syslpi
4468                         if usewifi:           << 
4469                                 html += td.fo << 
4470                         html += tdlink.format    3897                         html += tdlink.format(d[5]) if d[5] else td.format('')          # url
4471                         html += '</tr>\n'        3898                         html += '</tr>\n'
4472                         num += 1                 3899                         num += 1
4473                                                  3900 
4474         # flush the data to file                 3901         # flush the data to file
4475         hf = open(htmlfile, 'w')                 3902         hf = open(htmlfile, 'w')
4476         hf.write(html+'</table>\n</body>\n</h    3903         hf.write(html+'</table>\n</body>\n</html>\n')
4477         hf.close()                               3904         hf.close()
4478                                                  3905 
4479 def createHTMLDeviceSummary(testruns, htmlfil    3906 def createHTMLDeviceSummary(testruns, htmlfile, title):
4480         html = summaryCSS('Device Summary - S    3907         html = summaryCSS('Device Summary - SleepGraph', False)
4481                                                  3908 
4482         # create global device list from all     3909         # create global device list from all tests
4483         devall = dict()                          3910         devall = dict()
4484         for data in testruns:                    3911         for data in testruns:
4485                 host, url, devlist = data['ho    3912                 host, url, devlist = data['host'], data['url'], data['devlist']
4486                 for type in devlist:             3913                 for type in devlist:
4487                         if type not in devall    3914                         if type not in devall:
4488                                 devall[type]     3915                                 devall[type] = dict()
4489                         mdevlist, devlist = d    3916                         mdevlist, devlist = devall[type], data['devlist'][type]
4490                         for name in devlist:     3917                         for name in devlist:
4491                                 length = devl    3918                                 length = devlist[name]
4492                                 if name not i    3919                                 if name not in mdevlist:
4493                                         mdevl    3920                                         mdevlist[name] = {'name': name, 'host': host,
4494                                                  3921                                                 'worst': length, 'total': length, 'count': 1,
4495                                                  3922                                                 'url': url}
4496                                 else:            3923                                 else:
4497                                         if le    3924                                         if length > mdevlist[name]['worst']:
4498                                                  3925                                                 mdevlist[name]['worst'] = length
4499                                                  3926                                                 mdevlist[name]['url'] = url
4500                                                  3927                                                 mdevlist[name]['host'] = host
4501                                         mdevl    3928                                         mdevlist[name]['total'] += length
4502                                         mdevl    3929                                         mdevlist[name]['count'] += 1
4503                                                  3930 
4504         # generate the html                      3931         # generate the html
4505         th = '\t<th>{0}</th>\n'                  3932         th = '\t<th>{0}</th>\n'
4506         td = '\t<td align=center>{0}</td>\n'     3933         td = '\t<td align=center>{0}</td>\n'
4507         tdr = '\t<td align=right>{0}</td>\n'     3934         tdr = '\t<td align=right>{0}</td>\n'
4508         tdlink = '\t<td align=center><a href=    3935         tdlink = '\t<td align=center><a href="{0}">html</a></td>\n'
4509         limit = 1                                3936         limit = 1
4510         for type in sorted(devall, reverse=Tr    3937         for type in sorted(devall, reverse=True):
4511                 num = 0                          3938                 num = 0
4512                 devlist = devall[type]           3939                 devlist = devall[type]
4513                 # table header                   3940                 # table header
4514                 html += '<div class="stamp">%    3941                 html += '<div class="stamp">%s (%s devices > %d ms)</div><table>\n' % \
4515                         (title, type.upper(),    3942                         (title, type.upper(), limit)
4516                 html += '<tr>\n' + '<th align    3943                 html += '<tr>\n' + '<th align=right>Device Name</th>' +\
4517                         th.format('Average Ti    3944                         th.format('Average Time') + th.format('Count') +\
4518                         th.format('Worst Time    3945                         th.format('Worst Time') + th.format('Host (worst time)') +\
4519                         th.format('Link (wors    3946                         th.format('Link (worst time)') + '</tr>\n'
4520                 for name in sorted(devlist, k !! 3947                 for name in sorted(devlist, key=lambda k:devlist[k]['worst'], reverse=True):
4521                         devlist[k]['total'],  << 
4522                         data = devall[type][n    3948                         data = devall[type][name]
4523                         data['average'] = dat    3949                         data['average'] = data['total'] / data['count']
4524                         if data['average'] <     3950                         if data['average'] < limit:
4525                                 continue         3951                                 continue
4526                         # row classes - alter    3952                         # row classes - alternate row color
4527                         rcls = ['alt'] if num    3953                         rcls = ['alt'] if num % 2 == 1 else []
4528                         html += '<tr class="'    3954                         html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n'
4529                         html += tdr.format(da    3955                         html += tdr.format(data['name'])                                # name
4530                         html += td.format('%.    3956                         html += td.format('%.3f ms' % data['average'])  # average
4531                         html += td.format(dat    3957                         html += td.format(data['count'])                                # count
4532                         html += td.format('%.    3958                         html += td.format('%.3f ms' % data['worst'])    # worst
4533                         html += td.format(dat    3959                         html += td.format(data['host'])                                 # host
4534                         html += tdlink.format    3960                         html += tdlink.format(data['url'])                              # url
4535                         html += '</tr>\n'        3961                         html += '</tr>\n'
4536                         num += 1                 3962                         num += 1
4537                 html += '</table>\n'             3963                 html += '</table>\n'
4538                                                  3964 
4539         # flush the data to file                 3965         # flush the data to file
4540         hf = open(htmlfile, 'w')                 3966         hf = open(htmlfile, 'w')
4541         hf.write(html+'</body>\n</html>\n')      3967         hf.write(html+'</body>\n</html>\n')
4542         hf.close()                               3968         hf.close()
4543         return devall                            3969         return devall
4544                                                  3970 
4545 def createHTMLIssuesSummary(testruns, issues,    3971 def createHTMLIssuesSummary(testruns, issues, htmlfile, title, extra=''):
4546         multihost = len([e for e in issues if    3972         multihost = len([e for e in issues if len(e['urls']) > 1]) > 0
4547         html = summaryCSS('Issues Summary - S    3973         html = summaryCSS('Issues Summary - SleepGraph', False)
4548         total = len(testruns)                    3974         total = len(testruns)
4549                                                  3975 
4550         # generate the html                      3976         # generate the html
4551         th = '\t<th>{0}</th>\n'                  3977         th = '\t<th>{0}</th>\n'
4552         td = '\t<td align={0}>{1}</td>\n'        3978         td = '\t<td align={0}>{1}</td>\n'
4553         tdlink = '<a href="{1}">{0}</a>'         3979         tdlink = '<a href="{1}">{0}</a>'
4554         subtitle = '%d issues' % len(issues)     3980         subtitle = '%d issues' % len(issues) if len(issues) > 0 else 'no issues'
4555         html += '<div class="stamp">%s (%s)</    3981         html += '<div class="stamp">%s (%s)</div><table>\n' % (title, subtitle)
4556         html += '<tr>\n' + th.format('Issue')    3982         html += '<tr>\n' + th.format('Issue') + th.format('Count')
4557         if multihost:                            3983         if multihost:
4558                 html += th.format('Hosts')       3984                 html += th.format('Hosts')
4559         html += th.format('Tests') + th.forma    3985         html += th.format('Tests') + th.format('Fail Rate') +\
4560                 th.format('First Instance') +    3986                 th.format('First Instance') + '</tr>\n'
4561                                                  3987 
4562         num = 0                                  3988         num = 0
4563         for e in sorted(issues, key=lambda v:    3989         for e in sorted(issues, key=lambda v:v['count'], reverse=True):
4564                 testtotal = 0                    3990                 testtotal = 0
4565                 links = []                       3991                 links = []
4566                 for host in sorted(e['urls'])    3992                 for host in sorted(e['urls']):
4567                         links.append(tdlink.f    3993                         links.append(tdlink.format(host, e['urls'][host][0]))
4568                         testtotal += len(e['u    3994                         testtotal += len(e['urls'][host])
4569                 rate = '%d/%d (%.2f%%)' % (te    3995                 rate = '%d/%d (%.2f%%)' % (testtotal, total, 100*float(testtotal)/float(total))
4570                 # row classes - alternate row    3996                 # row classes - alternate row color
4571                 rcls = ['alt'] if num % 2 ==     3997                 rcls = ['alt'] if num % 2 == 1 else []
4572                 html += '<tr class="'+(' '.jo    3998                 html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n'
4573                 html += td.format('left', e['    3999                 html += td.format('left', e['line'])            # issue
4574                 html += td.format('center', e    4000                 html += td.format('center', e['count'])         # count
4575                 if multihost:                    4001                 if multihost:
4576                         html += td.format('ce    4002                         html += td.format('center', len(e['urls']))     # hosts
4577                 html += td.format('center', t    4003                 html += td.format('center', testtotal)          # test count
4578                 html += td.format('center', r    4004                 html += td.format('center', rate)                       # test rate
4579                 html += td.format('center now    4005                 html += td.format('center nowrap', '<br>'.join(links))  # links
4580                 html += '</tr>\n'                4006                 html += '</tr>\n'
4581                 num += 1                         4007                 num += 1
4582                                                  4008 
4583         # flush the data to file                 4009         # flush the data to file
4584         hf = open(htmlfile, 'w')                 4010         hf = open(htmlfile, 'w')
4585         hf.write(html+'</table>\n'+extra+'</b    4011         hf.write(html+'</table>\n'+extra+'</body>\n</html>\n')
4586         hf.close()                               4012         hf.close()
4587         return issues                            4013         return issues
4588                                                  4014 
4589 def ordinal(value):                              4015 def ordinal(value):
4590         suffix = 'th'                            4016         suffix = 'th'
4591         if value < 10 or value > 19:             4017         if value < 10 or value > 19:
4592                 if value % 10 == 1:              4018                 if value % 10 == 1:
4593                         suffix = 'st'            4019                         suffix = 'st'
4594                 elif value % 10 == 2:            4020                 elif value % 10 == 2:
4595                         suffix = 'nd'            4021                         suffix = 'nd'
4596                 elif value % 10 == 3:            4022                 elif value % 10 == 3:
4597                         suffix = 'rd'            4023                         suffix = 'rd'
4598         return '%d%s' % (value, suffix)          4024         return '%d%s' % (value, suffix)
4599                                                  4025 
4600 # Function: createHTML                           4026 # Function: createHTML
4601 # Description:                                   4027 # Description:
4602 #        Create the output html file from the    4028 #        Create the output html file from the resident test data
4603 # Arguments:                                     4029 # Arguments:
4604 #        testruns: array of Data objects from    4030 #        testruns: array of Data objects from parseKernelLog or parseTraceLog
4605 # Output:                                        4031 # Output:
4606 #        True if the html file was created, f    4032 #        True if the html file was created, false if it failed
4607 def createHTML(testruns, testfail):              4033 def createHTML(testruns, testfail):
4608         if len(testruns) < 1:                    4034         if len(testruns) < 1:
4609                 pprint('ERROR: Not enough tes    4035                 pprint('ERROR: Not enough test data to build a timeline')
4610                 return                           4036                 return
4611                                                  4037 
4612         kerror = False                           4038         kerror = False
4613         for data in testruns:                    4039         for data in testruns:
4614                 if data.kerror:                  4040                 if data.kerror:
4615                         kerror = True            4041                         kerror = True
4616                 if(sysvals.suspendmode in ['f    4042                 if(sysvals.suspendmode in ['freeze', 'standby']):
4617                         data.trimFreezeTime(t    4043                         data.trimFreezeTime(testruns[-1].tSuspended)
4618                 else:                         << 
4619                         data.getMemTime()     << 
4620                                                  4044 
4621         # html function templates                4045         # html function templates
4622         html_error = '<div id="{1}" title="ke    4046         html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">{2}&rarr;</div>\n'
4623         html_traceevent = '<div title="{0}" c    4047         html_traceevent = '<div title="{0}" class="traceevent{6}" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;{7}">{5}</div>\n'
4624         html_cpuexec = '<div class="jiffie" s    4048         html_cpuexec = '<div class="jiffie" style="left:{0}%;top:{1}px;height:{2}px;width:{3}%;background:{4};"></div>\n'
4625         html_timetotal = '<table class="time1    4049         html_timetotal = '<table class="time1">\n<tr>'\
4626                 '<td class="green" title="{3}    4050                 '<td class="green" title="{3}">{2} Suspend Time: <b>{0} ms</b></td>'\
4627                 '<td class="yellow" title="{4    4051                 '<td class="yellow" title="{4}">{2} Resume Time: <b>{1} ms</b></td>'\
4628                 '</tr>\n</table>\n'              4052                 '</tr>\n</table>\n'
4629         html_timetotal2 = '<table class="time    4053         html_timetotal2 = '<table class="time1">\n<tr>'\
4630                 '<td class="green" title="{4}    4054                 '<td class="green" title="{4}">{3} Suspend Time: <b>{0} ms</b></td>'\
4631                 '<td class="gray" title="time    4055                 '<td class="gray" title="time spent in low-power mode with clock running">'+sysvals.suspendmode+' time: <b>{1} ms</b></td>'\
4632                 '<td class="yellow" title="{5    4056                 '<td class="yellow" title="{5}">{3} Resume Time: <b>{2} ms</b></td>'\
4633                 '</tr>\n</table>\n'              4057                 '</tr>\n</table>\n'
4634         html_timetotal3 = '<table class="time    4058         html_timetotal3 = '<table class="time1">\n<tr>'\
4635                 '<td class="green">Execution     4059                 '<td class="green">Execution Time: <b>{0} ms</b></td>'\
4636                 '<td class="yellow">Command:     4060                 '<td class="yellow">Command: <b>{1}</b></td>'\
4637                 '</tr>\n</table>\n'              4061                 '</tr>\n</table>\n'
                                                   >> 4062         html_timegroups = '<table class="time2">\n<tr>'\
                                                   >> 4063                 '<td class="green" title="time from kernel enter_state({5}) to firmware mode [kernel time only]">{4}Kernel Suspend: {0} ms</td>'\
                                                   >> 4064                 '<td class="purple">{4}Firmware Suspend: {1} ms</td>'\
                                                   >> 4065                 '<td class="purple">{4}Firmware Resume: {2} ms</td>'\
                                                   >> 4066                 '<td class="yellow" title="time from firmware mode to return from kernel enter_state({5}) [kernel time only]">{4}Kernel Resume: {3} ms</td>'\
                                                   >> 4067                 '</tr>\n</table>\n'
4638         html_fail = '<table class="testfail">    4068         html_fail = '<table class="testfail"><tr><td>{0}</td></tr></table>\n'
4639         html_kdesc = '<td class="{3}" title=" << 
4640         html_fwdesc = '<td class="{3}" title= << 
4641         html_wifdesc = '<td class="yellow" ti << 
4642                                                  4069 
4643         # html format variables                  4070         # html format variables
4644         scaleH = 20                              4071         scaleH = 20
4645         if kerror:                               4072         if kerror:
4646                 scaleH = 40                      4073                 scaleH = 40
4647                                                  4074 
4648         # device timeline                        4075         # device timeline
4649         devtl = Timeline(30, scaleH)             4076         devtl = Timeline(30, scaleH)
4650                                                  4077 
4651         # write the test title and general in    4078         # write the test title and general info header
4652         devtl.createHeader(sysvals, testruns[    4079         devtl.createHeader(sysvals, testruns[0].stamp)
4653                                                  4080 
4654         # Generate the header for this timeli    4081         # Generate the header for this timeline
4655         for data in testruns:                    4082         for data in testruns:
4656                 tTotal = data.end - data.star    4083                 tTotal = data.end - data.start
                                                   >> 4084                 sktime, rktime = data.getTimeValues()
4657                 if(tTotal == 0):                 4085                 if(tTotal == 0):
4658                         doError('No timeline     4086                         doError('No timeline data')
                                                   >> 4087                 if(len(data.tLow) > 0):
                                                   >> 4088                         low_time = '|'.join(data.tLow)
4659                 if sysvals.suspendmode == 'co    4089                 if sysvals.suspendmode == 'command':
4660                         run_time = '%.0f' % ( !! 4090                         run_time = '%.0f'%((data.end-data.start)*1000)
4661                         if sysvals.testcomman    4091                         if sysvals.testcommand:
4662                                 testdesc = sy    4092                                 testdesc = sysvals.testcommand
4663                         else:                    4093                         else:
4664                                 testdesc = 'u    4094                                 testdesc = 'unknown'
4665                         if(len(testruns) > 1)    4095                         if(len(testruns) > 1):
4666                                 testdesc = or    4096                                 testdesc = ordinal(data.testnumber+1)+' '+testdesc
4667                         thtml = html_timetota    4097                         thtml = html_timetotal3.format(run_time, testdesc)
4668                         devtl.html += thtml      4098                         devtl.html += thtml
4669                         continue              !! 4099                 elif data.fwValid:
4670                 # typical full suspend/resume !! 4100                         suspend_time = '%.0f'%(sktime + (data.fwSuspend/1000000.0))
4671                 stot, rtot = sktime, rktime = !! 4101                         resume_time = '%.0f'%(rktime + (data.fwResume/1000000.0))
4672                 ssrc, rsrc, testdesc, testdes !! 4102                         testdesc1 = 'Total'
4673                 if data.fwValid:              !! 4103                         testdesc2 = ''
4674                         stot += (data.fwSuspe !! 4104                         stitle = 'time from kernel enter_state(%s) to low-power mode [kernel & firmware time]' % sysvals.suspendmode
4675                         rtot += (data.fwResum !! 4105                         rtitle = 'time from low-power mode to return from kernel enter_state(%s) [firmware & kernel time]' % sysvals.suspendmode
4676                         ssrc.append('firmware !! 4106                         if(len(testruns) > 1):
4677                         rsrc.append('firmware !! 4107                                 testdesc1 = testdesc2 = ordinal(data.testnumber+1)
4678                         testdesc = 'Total'    !! 4108                                 testdesc2 += ' '
4679                 if 'time' in data.wifi and da !! 4109                         if(len(data.tLow) == 0):
4680                         rtot += data.end - da !! 4110                                 thtml = html_timetotal.format(suspend_time, \
4681                         rsrc.append('wifi')   !! 4111                                         resume_time, testdesc1, stitle, rtitle)
4682                         testdesc = 'Total'    !! 4112                         else:
4683                 suspend_time, resume_time = ' !! 4113                                 thtml = html_timetotal2.format(suspend_time, low_time, \
4684                 stitle = 'time from kernel su !! 4114                                         resume_time, testdesc1, stitle, rtitle)
4685                         (sysvals.suspendmode, !! 4115                         devtl.html += thtml
4686                 rtitle = 'time from %s mode t << 
4687                         (sysvals.suspendmode, << 
4688                 if(len(testruns) > 1):        << 
4689                         testdesc = testdesc2  << 
4690                         testdesc2 += ' '      << 
4691                 if(len(data.tLow) == 0):      << 
4692                         thtml = html_timetota << 
4693                                 resume_time,  << 
4694                 else:                         << 
4695                         low_time = '+'.join(d << 
4696                         thtml = html_timetota << 
4697                                 resume_time,  << 
4698                 devtl.html += thtml           << 
4699                 if not data.fwValid and 'dev' << 
4700                         continue              << 
4701                 # extra detail when the times << 
4702                 thtml = '<table class="time2" << 
4703                 thtml += html_kdesc.format(te << 
4704                 if data.fwValid:              << 
4705                         sftime = '%.3f'%(data    4116                         sftime = '%.3f'%(data.fwSuspend / 1000000.0)
4706                         rftime = '%.3f'%(data    4117                         rftime = '%.3f'%(data.fwResume / 1000000.0)
4707                         thtml += html_fwdesc. !! 4118                         devtl.html += html_timegroups.format('%.3f'%sktime, \
4708                         thtml += html_fwdesc. !! 4119                                 sftime, rftime, '%.3f'%rktime, testdesc2, sysvals.suspendmode)
4709                 thtml += html_kdesc.format(te !! 4120                 else:
4710                 if 'time' in data.wifi:       !! 4121                         suspend_time = '%.3f' % sktime
4711                         if data.wifi['stat']  !! 4122                         resume_time = '%.3f' % rktime
4712                                 wtime = '%.0f !! 4123                         testdesc = 'Kernel'
                                                   >> 4124                         stitle = 'time from kernel enter_state(%s) to firmware mode [kernel time only]' % sysvals.suspendmode
                                                   >> 4125                         rtitle = 'time from firmware mode to return from kernel enter_state(%s) [kernel time only]' % sysvals.suspendmode
                                                   >> 4126                         if(len(testruns) > 1):
                                                   >> 4127                                 testdesc = ordinal(data.testnumber+1)+' '+testdesc
                                                   >> 4128                         if(len(data.tLow) == 0):
                                                   >> 4129                                 thtml = html_timetotal.format(suspend_time, \
                                                   >> 4130                                         resume_time, testdesc, stitle, rtitle)
4713                         else:                    4131                         else:
4714                                 wtime = 'TIME !! 4132                                 thtml = html_timetotal2.format(suspend_time, low_time, \
4715                         thtml += html_wifdesc !! 4133                                         resume_time, testdesc, stitle, rtitle)
4716                 thtml += '</tr>\n</table>\n'  !! 4134                         devtl.html += thtml
4717                 devtl.html += thtml           !! 4135 
4718         if testfail:                             4136         if testfail:
4719                 devtl.html += html_fail.forma    4137                 devtl.html += html_fail.format(testfail)
4720                                                  4138 
4721         # time scale for potentially multiple    4139         # time scale for potentially multiple datasets
4722         t0 = testruns[0].start                   4140         t0 = testruns[0].start
4723         tMax = testruns[-1].end                  4141         tMax = testruns[-1].end
4724         tTotal = tMax - t0                       4142         tTotal = tMax - t0
4725                                                  4143 
4726         # determine the maximum number of row    4144         # determine the maximum number of rows we need to draw
4727         fulllist = []                            4145         fulllist = []
4728         threadlist = []                          4146         threadlist = []
4729         pscnt = 0                                4147         pscnt = 0
4730         devcnt = 0                               4148         devcnt = 0
4731         for data in testruns:                    4149         for data in testruns:
4732                 data.selectTimelineDevices('%    4150                 data.selectTimelineDevices('%f', tTotal, sysvals.mindevlen)
4733                 for group in data.devicegroup    4151                 for group in data.devicegroups:
4734                         devlist = []             4152                         devlist = []
4735                         for phase in group:      4153                         for phase in group:
4736                                 for devname i !! 4154                                 for devname in data.tdevlist[phase]:
4737                                         d = D    4155                                         d = DevItem(data.testnumber, phase, data.dmesg[phase]['list'][devname])
4738                                         devli    4156                                         devlist.append(d)
4739                                         if d.    4157                                         if d.isa('kth'):
4740                                                  4158                                                 threadlist.append(d)
4741                                         else:    4159                                         else:
4742                                                  4160                                                 if d.isa('ps'):
4743                                                  4161                                                         pscnt += 1
4744                                                  4162                                                 else:
4745                                                  4163                                                         devcnt += 1
4746                                                  4164                                                 fulllist.append(d)
4747                         if sysvals.mixedphase    4165                         if sysvals.mixedphaseheight:
4748                                 devtl.getPhas    4166                                 devtl.getPhaseRows(devlist)
4749         if not sysvals.mixedphaseheight:         4167         if not sysvals.mixedphaseheight:
4750                 if len(threadlist) > 0 and le    4168                 if len(threadlist) > 0 and len(fulllist) > 0:
4751                         if pscnt > 0 and devc    4169                         if pscnt > 0 and devcnt > 0:
4752                                 msg = 'user p    4170                                 msg = 'user processes & device pm callbacks'
4753                         elif pscnt > 0:          4171                         elif pscnt > 0:
4754                                 msg = 'user p    4172                                 msg = 'user processes'
4755                         else:                    4173                         else:
4756                                 msg = 'device    4174                                 msg = 'device pm callbacks'
4757                         d = testruns[0].addHo    4175                         d = testruns[0].addHorizontalDivider(msg, testruns[-1].end)
4758                         fulllist.insert(0, d)    4176                         fulllist.insert(0, d)
4759                 devtl.getPhaseRows(fulllist)     4177                 devtl.getPhaseRows(fulllist)
4760                 if len(threadlist) > 0:          4178                 if len(threadlist) > 0:
4761                         d = testruns[0].addHo    4179                         d = testruns[0].addHorizontalDivider('asynchronous kernel threads', testruns[-1].end)
4762                         threadlist.insert(0,     4180                         threadlist.insert(0, d)
4763                         devtl.getPhaseRows(th    4181                         devtl.getPhaseRows(threadlist, devtl.rows)
4764         devtl.calcTotalRows()                    4182         devtl.calcTotalRows()
4765                                                  4183 
4766         # draw the full timeline                 4184         # draw the full timeline
4767         devtl.createZoomBox(sysvals.suspendmo    4185         devtl.createZoomBox(sysvals.suspendmode, len(testruns))
4768         for data in testruns:                    4186         for data in testruns:
4769                 # draw each test run and bloc    4187                 # draw each test run and block chronologically
4770                 phases = {'suspend':[],'resum    4188                 phases = {'suspend':[],'resume':[]}
4771                 for phase in data.sortedPhase    4189                 for phase in data.sortedPhases():
4772                         if data.dmesg[phase][    4190                         if data.dmesg[phase]['start'] >= data.tSuspended:
4773                                 phases['resum    4191                                 phases['resume'].append(phase)
4774                         else:                    4192                         else:
4775                                 phases['suspe    4193                                 phases['suspend'].append(phase)
4776                 # now draw the actual timelin    4194                 # now draw the actual timeline blocks
4777                 for dir in phases:               4195                 for dir in phases:
4778                         # draw suspend and re    4196                         # draw suspend and resume blocks separately
4779                         bname = '%s%d' % (dir    4197                         bname = '%s%d' % (dir[0], data.testnumber)
4780                         if dir == 'suspend':     4198                         if dir == 'suspend':
4781                                 m0 = data.sta    4199                                 m0 = data.start
4782                                 mMax = data.t    4200                                 mMax = data.tSuspended
4783                                 left = '%f' %    4201                                 left = '%f' % (((m0-t0)*100.0)/tTotal)
4784                         else:                    4202                         else:
4785                                 m0 = data.tSu    4203                                 m0 = data.tSuspended
4786                                 mMax = data.e    4204                                 mMax = data.end
4787                                 # in an x2 ru    4205                                 # in an x2 run, remove any gap between blocks
4788                                 if len(testru    4206                                 if len(testruns) > 1 and data.testnumber == 0:
4789                                         mMax     4207                                         mMax = testruns[1].start
4790                                 left = '%f' %    4208                                 left = '%f' % ((((m0-t0)*100.0)+sysvals.srgap/2)/tTotal)
4791                         mTotal = mMax - m0       4209                         mTotal = mMax - m0
4792                         # if a timeline block    4210                         # if a timeline block is 0 length, skip altogether
4793                         if mTotal == 0:          4211                         if mTotal == 0:
4794                                 continue         4212                                 continue
4795                         width = '%f' % (((mTo    4213                         width = '%f' % (((mTotal*100.0)-sysvals.srgap/2)/tTotal)
4796                         devtl.html += devtl.h    4214                         devtl.html += devtl.html_tblock.format(bname, left, width, devtl.scaleH)
4797                         for b in phases[dir]:    4215                         for b in phases[dir]:
4798                                 # draw the ph    4216                                 # draw the phase color background
4799                                 phase = data.    4217                                 phase = data.dmesg[b]
4800                                 length = phas    4218                                 length = phase['end']-phase['start']
4801                                 left = '%f' %    4219                                 left = '%f' % (((phase['start']-m0)*100.0)/mTotal)
4802                                 width = '%f'     4220                                 width = '%f' % ((length*100.0)/mTotal)
4803                                 devtl.html +=    4221                                 devtl.html += devtl.html_phase.format(left, width, \
4804                                         '%.3f    4222                                         '%.3f'%devtl.scaleH, '%.3f'%devtl.bodyH, \
4805                                         data.    4223                                         data.dmesg[b]['color'], '')
4806                         for e in data.errorin    4224                         for e in data.errorinfo[dir]:
4807                                 # draw red li    4225                                 # draw red lines for any kernel errors found
4808                                 type, t, idx1    4226                                 type, t, idx1, idx2 = e
4809                                 id = '%d_%d'     4227                                 id = '%d_%d' % (idx1, idx2)
4810                                 right = '%f'     4228                                 right = '%f' % (((mMax-t)*100.0)/mTotal)
4811                                 devtl.html +=    4229                                 devtl.html += html_error.format(right, id, type)
4812                         for b in phases[dir]:    4230                         for b in phases[dir]:
4813                                 # draw the de    4231                                 # draw the devices for this phase
4814                                 phaselist = d    4232                                 phaselist = data.dmesg[b]['list']
4815                                 for d in sort !! 4233                                 for d in data.tdevlist[b]:
4816                                         dname !! 4234                                         name = d
4817                                         name, !! 4235                                         drv = ''
4818                                         drv = !! 4236                                         dev = phaselist[d]
                                                   >> 4237                                         xtraclass = ''
                                                   >> 4238                                         xtrainfo = ''
                                                   >> 4239                                         xtrastyle = ''
4819                                         if 'h    4240                                         if 'htmlclass' in dev:
4820                                                  4241                                                 xtraclass = dev['htmlclass']
4821                                         if 'c    4242                                         if 'color' in dev:
4822                                                  4243                                                 xtrastyle = 'background:%s;' % dev['color']
4823                                         if(d     4244                                         if(d in sysvals.devprops):
4824                                                  4245                                                 name = sysvals.devprops[d].altName(d)
4825                                                  4246                                                 xtraclass = sysvals.devprops[d].xtraClass()
4826                                                  4247                                                 xtrainfo = sysvals.devprops[d].xtraInfo()
4827                                         elif     4248                                         elif xtraclass == ' kth':
4828                                                  4249                                                 xtrainfo = ' kernel_thread'
4829                                         if('d    4250                                         if('drv' in dev and dev['drv']):
4830                                                  4251                                                 drv = ' {%s}' % dev['drv']
4831                                         rowhe    4252                                         rowheight = devtl.phaseRowHeight(data.testnumber, b, dev['row'])
4832                                         rowto    4253                                         rowtop = devtl.phaseRowTop(data.testnumber, b, dev['row'])
4833                                         top =    4254                                         top = '%.3f' % (rowtop + devtl.scaleH)
4834                                         left     4255                                         left = '%f' % (((dev['start']-m0)*100)/mTotal)
4835                                         width    4256                                         width = '%f' % (((dev['end']-dev['start'])*100)/mTotal)
4836                                         lengt    4257                                         length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000)
4837                                         title    4258                                         title = name+drv+xtrainfo+length
4838                                         if sy    4259                                         if sysvals.suspendmode == 'command':
4839                                                  4260                                                 title += sysvals.testcommand
4840                                         elif     4261                                         elif xtraclass == ' ps':
4841                                                  4262                                                 if 'suspend' in b:
4842                                                  4263                                                         title += 'pre_suspend_process'
4843                                                  4264                                                 else:
4844                                                  4265                                                         title += 'post_resume_process'
4845                                         else:    4266                                         else:
4846                                                  4267                                                 title += b
4847                                         devtl    4268                                         devtl.html += devtl.html_device.format(dev['id'], \
4848                                                  4269                                                 title, left, top, '%.3f'%rowheight, width, \
4849                                               !! 4270                                                 d+drv, xtraclass, xtrastyle)
4850                                         if('c    4271                                         if('cpuexec' in dev):
4851                                                  4272                                                 for t in sorted(dev['cpuexec']):
4852                                                  4273                                                         start, end = t
                                                   >> 4274                                                         j = float(dev['cpuexec'][t]) / 5
                                                   >> 4275                                                         if j > 1.0:
                                                   >> 4276                                                                 j = 1.0
4853                                                  4277                                                         height = '%.3f' % (rowheight/3)
4854                                                  4278                                                         top = '%.3f' % (rowtop + devtl.scaleH + 2*rowheight/3)
4855                                                  4279                                                         left = '%f' % (((start-m0)*100)/mTotal)
4856                                                  4280                                                         width = '%f' % ((end-start)*100/mTotal)
4857                                               !! 4281                                                         color = 'rgba(255, 0, 0, %f)' % j
4858                                                  4282                                                         devtl.html += \
4859                                                  4283                                                                 html_cpuexec.format(left, top, height, width, color)
4860                                         if('s    4284                                         if('src' not in dev):
4861                                                  4285                                                 continue
4862                                         # dra    4286                                         # draw any trace events for this device
4863                                         for e    4287                                         for e in dev['src']:
4864                                               << 
4865                                               << 
4866                                                  4288                                                 height = '%.3f' % devtl.rowH
4867                                                  4289                                                 top = '%.3f' % (rowtop + devtl.scaleH + (e.row*devtl.rowH))
4868                                                  4290                                                 left = '%f' % (((e.time-m0)*100)/mTotal)
4869                                                  4291                                                 width = '%f' % (e.length*100/mTotal)
4870                                                  4292                                                 xtrastyle = ''
4871                                                  4293                                                 if e.color:
4872                                                  4294                                                         xtrastyle = 'background:%s;' % e.color
4873                                                  4295                                                 devtl.html += \
4874                                                  4296                                                         html_traceevent.format(e.title(), \
4875                                                  4297                                                                 left, top, height, width, e.text(), '', xtrastyle)
4876                         # draw the time scale    4298                         # draw the time scale, try to make the number of labels readable
4877                         devtl.createTimeScale    4299                         devtl.createTimeScale(m0, mMax, tTotal, dir)
4878                         devtl.html += '</div>    4300                         devtl.html += '</div>\n'
4879                                                  4301 
4880         # timeline is finished                   4302         # timeline is finished
4881         devtl.html += '</div>\n</div>\n'         4303         devtl.html += '</div>\n</div>\n'
4882                                                  4304 
4883         # draw a legend which describes the p    4305         # draw a legend which describes the phases by color
4884         if sysvals.suspendmode != 'command':     4306         if sysvals.suspendmode != 'command':
4885                 phasedef = testruns[-1].phase    4307                 phasedef = testruns[-1].phasedef
4886                 devtl.html += '<div class="le    4308                 devtl.html += '<div class="legend">\n'
4887                 pdelta = 100.0/len(phasedef.k    4309                 pdelta = 100.0/len(phasedef.keys())
4888                 pmargin = pdelta / 4.0           4310                 pmargin = pdelta / 4.0
4889                 for phase in sorted(phasedef,    4311                 for phase in sorted(phasedef, key=lambda k:phasedef[k]['order']):
4890                         id, p = '', phasedef[    4312                         id, p = '', phasedef[phase]
4891                         for word in phase.spl    4313                         for word in phase.split('_'):
4892                                 id += word[0]    4314                                 id += word[0]
4893                         order = '%.2f' % ((p[    4315                         order = '%.2f' % ((p['order'] * pdelta) + pmargin)
4894                         name = phase.replace(    4316                         name = phase.replace('_', ' &nbsp;')
4895                         devtl.html += devtl.h    4317                         devtl.html += devtl.html_legend.format(order, p['color'], name, id)
4896                 devtl.html += '</div>\n'         4318                 devtl.html += '</div>\n'
4897                                                  4319 
4898         hf = open(sysvals.htmlfile, 'w')         4320         hf = open(sysvals.htmlfile, 'w')
4899         addCSS(hf, sysvals, len(testruns), ke    4321         addCSS(hf, sysvals, len(testruns), kerror)
4900                                                  4322 
4901         # write the device timeline              4323         # write the device timeline
4902         hf.write(devtl.html)                     4324         hf.write(devtl.html)
4903         hf.write('<div id="devicedetailtitle"    4325         hf.write('<div id="devicedetailtitle"></div>\n')
4904         hf.write('<div id="devicedetail" styl    4326         hf.write('<div id="devicedetail" style="display:none;">\n')
4905         # draw the colored boxes for the devi    4327         # draw the colored boxes for the device detail section
4906         for data in testruns:                    4328         for data in testruns:
4907                 hf.write('<div id="devicedeta    4329                 hf.write('<div id="devicedetail%d">\n' % data.testnumber)
4908                 pscolor = 'linear-gradient(to    4330                 pscolor = 'linear-gradient(to top left, #ccc, #eee)'
4909                 hf.write(devtl.html_phaselet.    4331                 hf.write(devtl.html_phaselet.format('pre_suspend_process', \
4910                         '0', '0', pscolor))      4332                         '0', '0', pscolor))
4911                 for b in data.sortedPhases():    4333                 for b in data.sortedPhases():
4912                         phase = data.dmesg[b]    4334                         phase = data.dmesg[b]
4913                         length = phase['end']    4335                         length = phase['end']-phase['start']
4914                         left = '%.3f' % (((ph    4336                         left = '%.3f' % (((phase['start']-t0)*100.0)/tTotal)
4915                         width = '%.3f' % ((le    4337                         width = '%.3f' % ((length*100.0)/tTotal)
4916                         hf.write(devtl.html_p    4338                         hf.write(devtl.html_phaselet.format(b, left, width, \
4917                                 data.dmesg[b]    4339                                 data.dmesg[b]['color']))
4918                 hf.write(devtl.html_phaselet.    4340                 hf.write(devtl.html_phaselet.format('post_resume_process', \
4919                         '0', '0', pscolor))      4341                         '0', '0', pscolor))
4920                 if sysvals.suspendmode == 'co    4342                 if sysvals.suspendmode == 'command':
4921                         hf.write(devtl.html_p    4343                         hf.write(devtl.html_phaselet.format('cmdexec', '0', '0', pscolor))
4922                 hf.write('</div>\n')             4344                 hf.write('</div>\n')
4923         hf.write('</div>\n')                     4345         hf.write('</div>\n')
4924                                                  4346 
4925         # write the ftrace data (callgraph)      4347         # write the ftrace data (callgraph)
4926         if sysvals.cgtest >= 0 and len(testru    4348         if sysvals.cgtest >= 0 and len(testruns) > sysvals.cgtest:
4927                 data = testruns[sysvals.cgtes    4349                 data = testruns[sysvals.cgtest]
4928         else:                                    4350         else:
4929                 data = testruns[-1]              4351                 data = testruns[-1]
4930         if sysvals.usecallgraph:                 4352         if sysvals.usecallgraph:
4931                 addCallgraphs(sysvals, hf, da    4353                 addCallgraphs(sysvals, hf, data)
4932                                                  4354 
4933         # add the test log as a hidden div       4355         # add the test log as a hidden div
4934         if sysvals.testlog and sysvals.logmsg    4356         if sysvals.testlog and sysvals.logmsg:
4935                 hf.write('<div id="testlog" s    4357                 hf.write('<div id="testlog" style="display:none;">\n'+sysvals.logmsg+'</div>\n')
4936         # add the dmesg log as a hidden div      4358         # add the dmesg log as a hidden div
4937         if sysvals.dmesglog and sysvals.dmesg    4359         if sysvals.dmesglog and sysvals.dmesgfile:
4938                 hf.write('<div id="dmesglog"     4360                 hf.write('<div id="dmesglog" style="display:none;">\n')
4939                 lf = sysvals.openlog(sysvals.    4361                 lf = sysvals.openlog(sysvals.dmesgfile, 'r')
4940                 for line in lf:                  4362                 for line in lf:
4941                         line = line.replace('    4363                         line = line.replace('<', '&lt').replace('>', '&gt')
4942                         hf.write(line)           4364                         hf.write(line)
4943                 lf.close()                       4365                 lf.close()
4944                 hf.write('</div>\n')             4366                 hf.write('</div>\n')
4945         # add the ftrace log as a hidden div     4367         # add the ftrace log as a hidden div
4946         if sysvals.ftracelog and sysvals.ftra    4368         if sysvals.ftracelog and sysvals.ftracefile:
4947                 hf.write('<div id="ftracelog"    4369                 hf.write('<div id="ftracelog" style="display:none;">\n')
4948                 lf = sysvals.openlog(sysvals.    4370                 lf = sysvals.openlog(sysvals.ftracefile, 'r')
4949                 for line in lf:                  4371                 for line in lf:
4950                         hf.write(line)           4372                         hf.write(line)
4951                 lf.close()                       4373                 lf.close()
4952                 hf.write('</div>\n')             4374                 hf.write('</div>\n')
4953                                                  4375 
4954         # write the footer and close             4376         # write the footer and close
4955         addScriptCode(hf, testruns)              4377         addScriptCode(hf, testruns)
4956         hf.write('</body>\n</html>\n')           4378         hf.write('</body>\n</html>\n')
4957         hf.close()                               4379         hf.close()
4958         return True                              4380         return True
4959                                                  4381 
4960 def addCSS(hf, sv, testcount=1, kerror=False,    4382 def addCSS(hf, sv, testcount=1, kerror=False, extra=''):
4961         kernel = sv.stamp['kernel']              4383         kernel = sv.stamp['kernel']
4962         host = sv.hostname[0].upper()+sv.host    4384         host = sv.hostname[0].upper()+sv.hostname[1:]
4963         mode = sv.suspendmode                    4385         mode = sv.suspendmode
4964         if sv.suspendmode in suspendmodename:    4386         if sv.suspendmode in suspendmodename:
4965                 mode = suspendmodename[sv.sus    4387                 mode = suspendmodename[sv.suspendmode]
4966         title = host+' '+mode+' '+kernel         4388         title = host+' '+mode+' '+kernel
4967                                                  4389 
4968         # various format changes by flags        4390         # various format changes by flags
4969         cgchk = 'checked'                        4391         cgchk = 'checked'
4970         cgnchk = 'not(:checked)'                 4392         cgnchk = 'not(:checked)'
4971         if sv.cgexp:                             4393         if sv.cgexp:
4972                 cgchk = 'not(:checked)'          4394                 cgchk = 'not(:checked)'
4973                 cgnchk = 'checked'               4395                 cgnchk = 'checked'
4974                                                  4396 
4975         hoverZ = 'z-index:8;'                    4397         hoverZ = 'z-index:8;'
4976         if sv.usedevsrc:                         4398         if sv.usedevsrc:
4977                 hoverZ = ''                      4399                 hoverZ = ''
4978                                                  4400 
4979         devlistpos = 'absolute'                  4401         devlistpos = 'absolute'
4980         if testcount > 1:                        4402         if testcount > 1:
4981                 devlistpos = 'relative'          4403                 devlistpos = 'relative'
4982                                                  4404 
4983         scaleTH = 20                             4405         scaleTH = 20
4984         if kerror:                               4406         if kerror:
4985                 scaleTH = 60                     4407                 scaleTH = 60
4986                                                  4408 
4987         # write the html header first (html h    4409         # write the html header first (html head, css code, up to body start)
4988         html_header = '<!DOCTYPE html>\n<html    4410         html_header = '<!DOCTYPE html>\n<html>\n<head>\n\
4989         <meta http-equiv="content-type" conte    4411         <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\
4990         <title>'+title+'</title>\n\              4412         <title>'+title+'</title>\n\
4991         <style type=\'text/css\'>\n\             4413         <style type=\'text/css\'>\n\
4992                 body {overflow-y:scroll;}\n\     4414                 body {overflow-y:scroll;}\n\
4993                 .stamp {width:100%;text-align    4415                 .stamp {width:100%;text-align:center;background:gray;line-height:30px;color:white;font:25px Arial;}\n\
4994                 .stamp.sysinfo {font:10px Ari    4416                 .stamp.sysinfo {font:10px Arial;}\n\
4995                 .callgraph {margin-top:30px;b    4417                 .callgraph {margin-top:30px;box-shadow:5px 5px 20px black;}\n\
4996                 .callgraph article * {padding    4418                 .callgraph article * {padding-left:28px;}\n\
4997                 h1 {color:black;font:bold 30p    4419                 h1 {color:black;font:bold 30px Times;}\n\
4998                 t0 {color:black;font:bold 30p    4420                 t0 {color:black;font:bold 30px Times;}\n\
4999                 t1 {color:black;font:30px Tim    4421                 t1 {color:black;font:30px Times;}\n\
5000                 t2 {color:black;font:25px Tim    4422                 t2 {color:black;font:25px Times;}\n\
5001                 t3 {color:black;font:20px Tim    4423                 t3 {color:black;font:20px Times;white-space:nowrap;}\n\
5002                 t4 {color:black;font:bold 30p    4424                 t4 {color:black;font:bold 30px Times;line-height:60px;white-space:nowrap;}\n\
5003                 cS {font:bold 13px Times;}\n\    4425                 cS {font:bold 13px Times;}\n\
5004                 table {width:100%;}\n\           4426                 table {width:100%;}\n\
5005                 .gray {background:rgba(80,80,    4427                 .gray {background:rgba(80,80,80,0.1);}\n\
5006                 .green {background:rgba(204,2    4428                 .green {background:rgba(204,255,204,0.4);}\n\
5007                 .purple {background:rgba(128,    4429                 .purple {background:rgba(128,0,128,0.2);}\n\
5008                 .yellow {background:rgba(255,    4430                 .yellow {background:rgba(255,255,204,0.4);}\n\
5009                 .blue {background:rgba(169,20    4431                 .blue {background:rgba(169,208,245,0.4);}\n\
5010                 .time1 {font:22px Arial;borde    4432                 .time1 {font:22px Arial;border:1px solid;}\n\
5011                 .time2 {font:15px Arial;borde    4433                 .time2 {font:15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\
5012                 .testfail {font:bold 22px Ari    4434                 .testfail {font:bold 22px Arial;color:red;border:1px dashed;}\n\
5013                 td {text-align:center;}\n\       4435                 td {text-align:center;}\n\
5014                 r {color:#500000;font:15px Ta    4436                 r {color:#500000;font:15px Tahoma;}\n\
5015                 n {color:#505050;font:15px Ta    4437                 n {color:#505050;font:15px Tahoma;}\n\
5016                 .tdhl {color:red;}\n\            4438                 .tdhl {color:red;}\n\
5017                 .hide {display:none;}\n\         4439                 .hide {display:none;}\n\
5018                 .pf {display:none;}\n\           4440                 .pf {display:none;}\n\
5019                 .pf:'+cgchk+' + label {backgr    4441                 .pf:'+cgchk+' + label {background:url(\'data:image/svg+xml;utf,<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" version="1.1"><circle cx="9" cy="9" r="8" stroke="black" stroke-width="1" fill="white"/><rect x="4" y="8" width="10" height="2" style="fill:black;stroke-width:0"/><rect x="8" y="4" width="2" height="10" style="fill:black;stroke-width:0"/></svg>\') no-repeat left center;}\n\
5020                 .pf:'+cgnchk+' ~ label {backg    4442                 .pf:'+cgnchk+' ~ label {background:url(\'data:image/svg+xml;utf,<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" version="1.1"><circle cx="9" cy="9" r="8" stroke="black" stroke-width="1" fill="white"/><rect x="4" y="8" width="10" height="2" style="fill:black;stroke-width:0"/></svg>\') no-repeat left center;}\n\
5021                 .pf:'+cgchk+' ~ *:not(:nth-ch    4443                 .pf:'+cgchk+' ~ *:not(:nth-child(2)) {display:none;}\n\
5022                 .zoombox {position:relative;w    4444                 .zoombox {position:relative;width:100%;overflow-x:scroll;-webkit-user-select:none;-moz-user-select:none;user-select:none;}\n\
5023                 .timeline {position:relative;    4445                 .timeline {position:relative;font-size:14px;cursor:pointer;width:100%; overflow:hidden;background:linear-gradient(#cccccc, white);}\n\
5024                 .thread {position:absolute;he    4446                 .thread {position:absolute;height:0%;overflow:hidden;z-index:7;line-height:30px;font-size:14px;border:1px solid;text-align:center;white-space:nowrap;}\n\
5025                 .thread.ps {border-radius:3px    4447                 .thread.ps {border-radius:3px;background:linear-gradient(to top, #ccc, #eee);}\n\
5026                 .thread:hover {background:whi    4448                 .thread:hover {background:white;border:1px solid red;'+hoverZ+'}\n\
5027                 .thread.sec,.thread.sec:hover    4449                 .thread.sec,.thread.sec:hover {background:black;border:0;color:white;line-height:15px;font-size:10px;}\n\
5028                 .hover {background:white;bord    4450                 .hover {background:white;border:1px solid red;'+hoverZ+'}\n\
5029                 .hover.sync {background:white    4451                 .hover.sync {background:white;}\n\
5030                 .hover.bg,.hover.kth,.hover.s    4452                 .hover.bg,.hover.kth,.hover.sync,.hover.ps {background:white;}\n\
5031                 .jiffie {position:absolute;po    4453                 .jiffie {position:absolute;pointer-events: none;z-index:8;}\n\
5032                 .traceevent {position:absolut    4454                 .traceevent {position:absolute;font-size:10px;z-index:7;overflow:hidden;color:black;text-align:center;white-space:nowrap;border-radius:5px;border:1px solid black;background:linear-gradient(to bottom right,#CCC,#969696);}\n\
5033                 .traceevent:hover {color:whit    4455                 .traceevent:hover {color:white;font-weight:bold;border:1px solid white;}\n\
5034                 .phase {position:absolute;ove    4456                 .phase {position:absolute;overflow:hidden;border:0px;text-align:center;}\n\
5035                 .phaselet {float:left;overflo    4457                 .phaselet {float:left;overflow:hidden;border:0px;text-align:center;min-height:100px;font-size:24px;}\n\
5036                 .t {position:absolute;line-he    4458                 .t {position:absolute;line-height:'+('%d'%scaleTH)+'px;pointer-events:none;top:0;height:100%;border-right:1px solid black;z-index:6;}\n\
5037                 .err {position:absolute;top:0    4459                 .err {position:absolute;top:0%;height:100%;border-right:3px solid red;color:red;font:bold 14px Times;line-height:18px;}\n\
5038                 .legend {position:relative; w    4460                 .legend {position:relative; width:100%; height:40px; text-align:center;margin-bottom:20px}\n\
5039                 .legend .square {position:abs    4461                 .legend .square {position:absolute;cursor:pointer;top:10px; width:0px;height:20px;border:1px solid;padding-left:20px;}\n\
5040                 button {height:40px;width:200    4462                 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\
5041                 .btnfmt {position:relative;fl    4463                 .btnfmt {position:relative;float:right;height:25px;width:auto;margin-top:3px;margin-bottom:0;font-size:10px;text-align:center;}\n\
5042                 .devlist {position:'+devlistp    4464                 .devlist {position:'+devlistpos+';width:190px;}\n\
5043                 a:link {color:white;text-deco    4465                 a:link {color:white;text-decoration:none;}\n\
5044                 a:visited {color:white;}\n\      4466                 a:visited {color:white;}\n\
5045                 a:hover {color:white;}\n\        4467                 a:hover {color:white;}\n\
5046                 a:active {color:white;}\n\       4468                 a:active {color:white;}\n\
5047                 .version {position:relative;f    4469                 .version {position:relative;float:left;color:white;font-size:10px;line-height:30px;margin-left:10px;}\n\
5048                 #devicedetail {min-height:100    4470                 #devicedetail {min-height:100px;box-shadow:5px 5px 20px black;}\n\
5049                 .tblock {position:absolute;he    4471                 .tblock {position:absolute;height:100%;background:#ddd;}\n\
5050                 .tback {position:absolute;wid    4472                 .tback {position:absolute;width:100%;background:linear-gradient(#ccc, #ddd);}\n\
5051                 .bg {z-index:1;}\n\              4473                 .bg {z-index:1;}\n\
5052 '+extra+'\                                       4474 '+extra+'\
5053         </style>\n</head>\n<body>\n'             4475         </style>\n</head>\n<body>\n'
5054         hf.write(html_header)                    4476         hf.write(html_header)
5055                                                  4477 
5056 # Function: addScriptCode                        4478 # Function: addScriptCode
5057 # Description:                                   4479 # Description:
5058 #        Adds the javascript code to the outp    4480 #        Adds the javascript code to the output html
5059 # Arguments:                                     4481 # Arguments:
5060 #        hf: the open html file pointer          4482 #        hf: the open html file pointer
5061 #        testruns: array of Data objects from    4483 #        testruns: array of Data objects from parseKernelLog or parseTraceLog
5062 def addScriptCode(hf, testruns):                 4484 def addScriptCode(hf, testruns):
5063         t0 = testruns[0].start * 1000            4485         t0 = testruns[0].start * 1000
5064         tMax = testruns[-1].end * 1000           4486         tMax = testruns[-1].end * 1000
5065         hf.write('<script type="text/javascri << 
5066         # create an array in javascript memor    4487         # create an array in javascript memory with the device details
5067         detail = '      var devtable = [];\n'    4488         detail = '      var devtable = [];\n'
5068         for data in testruns:                    4489         for data in testruns:
5069                 topo = data.deviceTopology()     4490                 topo = data.deviceTopology()
5070                 detail += '     devtable[%d]     4491                 detail += '     devtable[%d] = "%s";\n' % (data.testnumber, topo)
5071         detail += '     var bounds = [%f,%f];    4492         detail += '     var bounds = [%f,%f];\n' % (t0, tMax)
5072         # add the code which will manipulate     4493         # add the code which will manipulate the data in the browser
5073         hf.write(detail);                     !! 4494         script_code = \
5074         script_code = r"""      var resolutio !! 4495         '<script type="text/javascript">\n'+detail+\
5075         var dragval = [0, 0];                 !! 4496         '       var resolution = -1;\n'\
5076         function redrawTimescale(t0, tMax, tS !! 4497         '       var dragval = [0, 0];\n'\
5077                 var rline = '<div class="t" s !! 4498         '       function redrawTimescale(t0, tMax, tS) {\n'\
5078                 var tTotal = tMax - t0;       !! 4499         '               var rline = \'<div class="t" style="left:0;border-left:1px solid black;border-right:0;">\';\n'\
5079                 var list = document.getElemen !! 4500         '               var tTotal = tMax - t0;\n'\
5080                 for (var i = 0; i < list.leng !! 4501         '               var list = document.getElementsByClassName("tblock");\n'\
5081                         var timescale = list[ !! 4502         '               for (var i = 0; i < list.length; i++) {\n'\
5082                         var m0 = t0 + (tTotal !! 4503         '                       var timescale = list[i].getElementsByClassName("timescale")[0];\n'\
5083                         var mTotal = tTotal*p !! 4504         '                       var m0 = t0 + (tTotal*parseFloat(list[i].style.left)/100);\n'\
5084                         var mMax = m0 + mTota !! 4505         '                       var mTotal = tTotal*parseFloat(list[i].style.width)/100;\n'\
5085                         var html = "";        !! 4506         '                       var mMax = m0 + mTotal;\n'\
5086                         var divTotal = Math.f !! 4507         '                       var html = "";\n'\
5087                         if(divTotal > 1000) c !! 4508         '                       var divTotal = Math.floor(mTotal/tS) + 1;\n'\
5088                         var divEdge = (mTotal !! 4509         '                       if(divTotal > 1000) continue;\n'\
5089                         var pos = 0.0, val =  !! 4510         '                       var divEdge = (mTotal - tS*(divTotal-1))*100/mTotal;\n'\
5090                         for (var j = 0; j < d !! 4511         '                       var pos = 0.0, val = 0.0;\n'\
5091                                 var htmlline  !! 4512         '                       for (var j = 0; j < divTotal; j++) {\n'\
5092                                 var mode = li !! 4513         '                               var htmlline = "";\n'\
5093                                 if(mode == "s !! 4514         '                               var mode = list[i].id[5];\n'\
5094                                         pos = !! 4515         '                               if(mode == "s") {\n'\
5095                                         val = !! 4516         '                                       pos = 100 - (((j)*tS*100)/mTotal) - divEdge;\n'\
5096                                         if(j  !! 4517         '                                       val = (j-divTotal+1)*tS;\n'\
5097                                               !! 4518         '                                       if(j == divTotal - 1)\n'\
5098                                         else  !! 4519         '                                               htmlline = \'<div class="t" style="right:\'+pos+\'%"><cS>S&rarr;</cS></div>\';\n'\
5099                                               !! 4520         '                                       else\n'\
5100                                 } else {      !! 4521         '                                               htmlline = \'<div class="t" style="right:\'+pos+\'%">\'+val+\'ms</div>\';\n'\
5101                                         pos = !! 4522         '                               } else {\n'\
5102                                         val = !! 4523         '                                       pos = 100 - (((j)*tS*100)/mTotal);\n'\
5103                                         htmll !! 4524         '                                       val = (j)*tS;\n'\
5104                                         if(j  !! 4525         '                                       htmlline = \'<div class="t" style="right:\'+pos+\'%">\'+val+\'ms</div>\';\n'\
5105                                               !! 4526         '                                       if(j == 0)\n'\
5106                                               !! 4527         '                                               if(mode == "r")\n'\
5107                                               !! 4528         '                                                       htmlline = rline+"<cS>&larr;R</cS></div>";\n'\
5108                                               !! 4529         '                                               else\n'\
5109                                 }             !! 4530         '                                                       htmlline = rline+"<cS>0ms</div>";\n'\
5110                                 html += htmll !! 4531         '                               }\n'\
5111                         }                     !! 4532         '                               html += htmlline;\n'\
5112                         timescale.innerHTML = !! 4533         '                       }\n'\
5113                 }                             !! 4534         '                       timescale.innerHTML = html;\n'\
5114         }                                     !! 4535         '               }\n'\
5115         function zoomTimeline() {             !! 4536         '       }\n'\
5116                 var dmesg = document.getEleme !! 4537         '       function zoomTimeline() {\n'\
5117                 var zoombox = document.getEle !! 4538         '               var dmesg = document.getElementById("dmesg");\n'\
5118                 var left = zoombox.scrollLeft !! 4539         '               var zoombox = document.getElementById("dmesgzoombox");\n'\
5119                 var val = parseFloat(dmesg.st !! 4540         '               var left = zoombox.scrollLeft;\n'\
5120                 var newval = 100;             !! 4541         '               var val = parseFloat(dmesg.style.width);\n'\
5121                 var sh = window.outerWidth /  !! 4542         '               var newval = 100;\n'\
5122                 if(this.id == "zoomin") {     !! 4543         '               var sh = window.outerWidth / 2;\n'\
5123                         newval = val * 1.2;   !! 4544         '               if(this.id == "zoomin") {\n'\
5124                         if(newval > 910034) n !! 4545         '                       newval = val * 1.2;\n'\
5125                         dmesg.style.width = n !! 4546         '                       if(newval > 910034) newval = 910034;\n'\
5126                         zoombox.scrollLeft =  !! 4547         '                       dmesg.style.width = newval+"%";\n'\
5127                 } else if (this.id == "zoomou !! 4548         '                       zoombox.scrollLeft = ((left + sh) * newval / val) - sh;\n'\
5128                         newval = val / 1.2;   !! 4549         '               } else if (this.id == "zoomout") {\n'\
5129                         if(newval < 100) newv !! 4550         '                       newval = val / 1.2;\n'\
5130                         dmesg.style.width = n !! 4551         '                       if(newval < 100) newval = 100;\n'\
5131                         zoombox.scrollLeft =  !! 4552         '                       dmesg.style.width = newval+"%";\n'\
5132                 } else {                      !! 4553         '                       zoombox.scrollLeft = ((left + sh) * newval / val) - sh;\n'\
5133                         zoombox.scrollLeft =  !! 4554         '               } else {\n'\
5134                         dmesg.style.width = " !! 4555         '                       zoombox.scrollLeft = 0;\n'\
5135                 }                             !! 4556         '                       dmesg.style.width = "100%";\n'\
5136                 var tS = [10000, 5000, 2000,  !! 4557         '               }\n'\
5137                 var t0 = bounds[0];           !! 4558         '               var tS = [10000, 5000, 2000, 1000, 500, 200, 100, 50, 20, 10, 5, 2, 1];\n'\
5138                 var tMax = bounds[1];         !! 4559         '               var t0 = bounds[0];\n'\
5139                 var tTotal = tMax - t0;       !! 4560         '               var tMax = bounds[1];\n'\
5140                 var wTotal = tTotal * 100.0 / !! 4561         '               var tTotal = tMax - t0;\n'\
5141                 var idx = 7*window.innerWidth !! 4562         '               var wTotal = tTotal * 100.0 / newval;\n'\
5142                 for(var i = 0; (i < tS.length !! 4563         '               var idx = 7*window.innerWidth/1100;\n'\
5143                 if(i >= tS.length) i = tS.len !! 4564         '               for(var i = 0; (i < tS.length)&&((wTotal / tS[i]) < idx); i++);\n'\
5144                 if(tS[i] == resolution) retur !! 4565         '               if(i >= tS.length) i = tS.length - 1;\n'\
5145                 resolution = tS[i];           !! 4566         '               if(tS[i] == resolution) return;\n'\
5146                 redrawTimescale(t0, tMax, tS[ !! 4567         '               resolution = tS[i];\n'\
5147         }                                     !! 4568         '               redrawTimescale(t0, tMax, tS[i]);\n'\
5148         function deviceName(title) {          !! 4569         '       }\n'\
5149                 var name = title.slice(0, tit !! 4570         '       function deviceName(title) {\n'\
5150                 return name;                  !! 4571         '               var name = title.slice(0, title.indexOf(" ("));\n'\
5151         }                                     !! 4572         '               return name;\n'\
5152         function deviceHover() {              !! 4573         '       }\n'\
5153                 var name = deviceName(this.ti !! 4574         '       function deviceHover() {\n'\
5154                 var dmesg = document.getEleme !! 4575         '               var name = deviceName(this.title);\n'\
5155                 var dev = dmesg.getElementsBy !! 4576         '               var dmesg = document.getElementById("dmesg");\n'\
5156                 var cpu = -1;                 !! 4577         '               var dev = dmesg.getElementsByClassName("thread");\n'\
5157                 if(name.match("CPU_ON\[[0-9]* !! 4578         '               var cpu = -1;\n'\
5158                         cpu = parseInt(name.s !! 4579         '               if(name.match("CPU_ON\[[0-9]*\]"))\n'\
5159                 else if(name.match("CPU_OFF\[ !! 4580         '                       cpu = parseInt(name.slice(7));\n'\
5160                         cpu = parseInt(name.s !! 4581         '               else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\
5161                 for (var i = 0; i < dev.lengt !! 4582         '                       cpu = parseInt(name.slice(8));\n'\
5162                         dname = deviceName(de !! 4583         '               for (var i = 0; i < dev.length; i++) {\n'\
5163                         var cname = dev[i].cl !! 4584         '                       dname = deviceName(dev[i].title);\n'\
5164                         if((cpu >= 0 && dname !! 4585         '                       var cname = dev[i].className.slice(dev[i].className.indexOf("thread"));\n'\
5165                                 (name == dnam !! 4586         '                       if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\
5166                         {                     !! 4587         '                               (name == dname))\n'\
5167                                 dev[i].classN !! 4588         '                       {\n'\
5168                         } else {              !! 4589         '                               dev[i].className = "hover "+cname;\n'\
5169                                 dev[i].classN !! 4590         '                       } else {\n'\
5170                         }                     !! 4591         '                               dev[i].className = cname;\n'\
5171                 }                             !! 4592         '                       }\n'\
5172         }                                     !! 4593         '               }\n'\
5173         function deviceUnhover() {            !! 4594         '       }\n'\
5174                 var dmesg = document.getEleme !! 4595         '       function deviceUnhover() {\n'\
5175                 var dev = dmesg.getElementsBy !! 4596         '               var dmesg = document.getElementById("dmesg");\n'\
5176                 for (var i = 0; i < dev.lengt !! 4597         '               var dev = dmesg.getElementsByClassName("thread");\n'\
5177                         dev[i].className = de !! 4598         '               for (var i = 0; i < dev.length; i++) {\n'\
5178                 }                             !! 4599         '                       dev[i].className = dev[i].className.slice(dev[i].className.indexOf("thread"));\n'\
5179         }                                     !! 4600         '               }\n'\
5180         function deviceTitle(title, total, cp !! 4601         '       }\n'\
5181                 var prefix = "Total";         !! 4602         '       function deviceTitle(title, total, cpu) {\n'\
5182                 if(total.length > 3) {        !! 4603         '               var prefix = "Total";\n'\
5183                         prefix = "Average";   !! 4604         '               if(total.length > 3) {\n'\
5184                         total[1] = (total[1]+ !! 4605         '                       prefix = "Average";\n'\
5185                         total[2] = (total[2]+ !! 4606         '                       total[1] = (total[1]+total[3])/2;\n'\
5186                 }                             !! 4607         '                       total[2] = (total[2]+total[4])/2;\n'\
5187                 var devtitle = document.getEl !! 4608         '               }\n'\
5188                 var name = deviceName(title); !! 4609         '               var devtitle = document.getElementById("devicedetailtitle");\n'\
5189                 if(cpu >= 0) name = "CPU"+cpu !! 4610         '               var name = deviceName(title);\n'\
5190                 var driver = "";              !! 4611         '               if(cpu >= 0) name = "CPU"+cpu;\n'\
5191                 var tS = "<t2>(</t2>";        !! 4612         '               var driver = "";\n'\
5192                 var tR = "<t2>)</t2>";        !! 4613         '               var tS = "<t2>(</t2>";\n'\
5193                 if(total[1] > 0)              !! 4614         '               var tR = "<t2>)</t2>";\n'\
5194                         tS = "<t2>("+prefix+" !! 4615         '               if(total[1] > 0)\n'\
5195                 if(total[2] > 0)              !! 4616         '                       tS = "<t2>("+prefix+" Suspend:</t2><t0> "+total[1].toFixed(3)+" ms</t0> ";\n'\
5196                         tR = " <t2>"+prefix+" !! 4617         '               if(total[2] > 0)\n'\
5197                 var s = title.indexOf("{");   !! 4618         '                       tR = " <t2>"+prefix+" Resume:</t2><t0> "+total[2].toFixed(3)+" ms<t2>)</t2></t0>";\n'\
5198                 var e = title.indexOf("}");   !! 4619         '               var s = title.indexOf("{");\n'\
5199                 if((s >= 0) && (e >= 0))      !! 4620         '               var e = title.indexOf("}");\n'\
5200                         driver = title.slice(< !! 4621         '               if((s >= 0) && (e >= 0))\n'\
5201                 if(total[1] > 0 && total[2] > !! 4622         '                       driver = title.slice(s+1, e) + " <t1>@</t1> ";\n'\
5202                         devtitle.innerHTML =  !! 4623         '               if(total[1] > 0 && total[2] > 0)\n'\
5203                 else                          !! 4624         '                       devtitle.innerHTML = "<t0>"+driver+name+"</t0> "+tS+tR;\n'\
5204                         devtitle.innerHTML =  !! 4625         '               else\n'\
5205                 return name;                  !! 4626         '                       devtitle.innerHTML = "<t0>"+title+"</t0>";\n'\
5206         }                                     !! 4627         '               return name;\n'\
5207         function deviceDetail() {             !! 4628         '       }\n'\
5208                 var devinfo = document.getEle !! 4629         '       function deviceDetail() {\n'\
5209                 devinfo.style.display = "bloc !! 4630         '               var devinfo = document.getElementById("devicedetail");\n'\
5210                 var name = deviceName(this.ti !! 4631         '               devinfo.style.display = "block";\n'\
5211                 var cpu = -1;                 !! 4632         '               var name = deviceName(this.title);\n'\
5212                 if(name.match("CPU_ON\[[0-9]* !! 4633         '               var cpu = -1;\n'\
5213                         cpu = parseInt(name.s !! 4634         '               if(name.match("CPU_ON\[[0-9]*\]"))\n'\
5214                 else if(name.match("CPU_OFF\[ !! 4635         '                       cpu = parseInt(name.slice(7));\n'\
5215                         cpu = parseInt(name.s !! 4636         '               else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\
5216                 var dmesg = document.getEleme !! 4637         '                       cpu = parseInt(name.slice(8));\n'\
5217                 var dev = dmesg.getElementsBy !! 4638         '               var dmesg = document.getElementById("dmesg");\n'\
5218                 var idlist = [];              !! 4639         '               var dev = dmesg.getElementsByClassName("thread");\n'\
5219                 var pdata = [[]];             !! 4640         '               var idlist = [];\n'\
5220                 if(document.getElementById("d !! 4641         '               var pdata = [[]];\n'\
5221                         pdata = [[], []];     !! 4642         '               if(document.getElementById("devicedetail1"))\n'\
5222                 var pd = pdata[0];            !! 4643         '                       pdata = [[], []];\n'\
5223                 var total = [0.0, 0.0, 0.0];  !! 4644         '               var pd = pdata[0];\n'\
5224                 for (var i = 0; i < dev.lengt !! 4645         '               var total = [0.0, 0.0, 0.0];\n'\
5225                         dname = deviceName(de !! 4646         '               for (var i = 0; i < dev.length; i++) {\n'\
5226                         if((cpu >= 0 && dname !! 4647         '                       dname = deviceName(dev[i].title);\n'\
5227                                 (name == dnam !! 4648         '                       if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\
5228                         {                     !! 4649         '                               (name == dname))\n'\
5229                                 idlist[idlist !! 4650         '                       {\n'\
5230                                 var tidx = 1; !! 4651         '                               idlist[idlist.length] = dev[i].id;\n'\
5231                                 if(dev[i].id[ !! 4652         '                               var tidx = 1;\n'\
5232                                         pd =  !! 4653         '                               if(dev[i].id[0] == "a") {\n'\
5233                                 } else {      !! 4654         '                                       pd = pdata[0];\n'\
5234                                         if(pd !! 4655         '                               } else {\n'\
5235                                         if(to !! 4656         '                                       if(pdata.length == 1) pdata[1] = [];\n'\
5236                                         pd =  !! 4657         '                                       if(total.length == 3) total[3]=total[4]=0.0;\n'\
5237                                         tidx  !! 4658         '                                       pd = pdata[1];\n'\
5238                                 }             !! 4659         '                                       tidx = 3;\n'\
5239                                 var info = de !! 4660         '                               }\n'\
5240                                 var pname = i !! 4661         '                               var info = dev[i].title.split(" ");\n'\
5241                                 pd[pname] = p !! 4662         '                               var pname = info[info.length-1];\n'\
5242                                 total[0] += p !! 4663         '                               pd[pname] = parseFloat(info[info.length-3].slice(1));\n'\
5243                                 if(pname.inde !! 4664         '                               total[0] += pd[pname];\n'\
5244                                         total !! 4665         '                               if(pname.indexOf("suspend") >= 0)\n'\
5245                                 else          !! 4666         '                                       total[tidx] += pd[pname];\n'\
5246                                         total !! 4667         '                               else\n'\
5247                         }                     !! 4668         '                                       total[tidx+1] += pd[pname];\n'\
5248                 }                             !! 4669         '                       }\n'\
5249                 var devname = deviceTitle(thi !! 4670         '               }\n'\
5250                 var left = 0.0;               !! 4671         '               var devname = deviceTitle(this.title, total, cpu);\n'\
5251                 for (var t = 0; t < pdata.len !! 4672         '               var left = 0.0;\n'\
5252                         pd = pdata[t];        !! 4673         '               for (var t = 0; t < pdata.length; t++) {\n'\
5253                         devinfo = document.ge !! 4674         '                       pd = pdata[t];\n'\
5254                         var phases = devinfo. !! 4675         '                       devinfo = document.getElementById("devicedetail"+t);\n'\
5255                         for (var i = 0; i < p !! 4676         '                       var phases = devinfo.getElementsByClassName("phaselet");\n'\
5256                                 if(phases[i]. !! 4677         '                       for (var i = 0; i < phases.length; i++) {\n'\
5257                                         var w !! 4678         '                               if(phases[i].id in pd) {\n'\
5258                                         var f !! 4679         '                                       var w = 100.0*pd[phases[i].id]/total[0];\n'\
5259                                         if(w  !! 4680         '                                       var fs = 32;\n'\
5260                                         var f !! 4681         '                                       if(w < 8) fs = 4*w | 0;\n'\
5261                                         phase !! 4682         '                                       var fs2 = fs*3/4;\n'\
5262                                         phase !! 4683         '                                       phases[i].style.width = w+"%";\n'\
5263                                         phase !! 4684         '                                       phases[i].style.left = left+"%";\n'\
5264                                         left  !! 4685         '                                       phases[i].title = phases[i].id+" "+pd[phases[i].id]+" ms";\n'\
5265                                         var t !! 4686         '                                       left += w;\n'\
5266                                         var p !! 4687         '                                       var time = "<t4 style=\\"font-size:"+fs+"px\\">"+pd[phases[i].id]+" ms<br></t4>";\n'\
5267                                         phase !! 4688         '                                       var pname = "<t3 style=\\"font-size:"+fs2+"px\\">"+phases[i].id.replace(new RegExp("_", "g"), " ")+"</t3>";\n'\
5268                                 } else {      !! 4689         '                                       phases[i].innerHTML = time+pname;\n'\
5269                                         phase !! 4690         '                               } else {\n'\
5270                                         phase !! 4691         '                                       phases[i].style.width = "0%";\n'\
5271                                 }             !! 4692         '                                       phases[i].style.left = left+"%";\n'\
5272                         }                     !! 4693         '                               }\n'\
5273                 }                             !! 4694         '                       }\n'\
5274                 if(typeof devstats !== 'undef !! 4695         '               }\n'\
5275                         callDetail(this.id, t !! 4696         '               if(typeof devstats !== \'undefined\')\n'\
5276                 var cglist = document.getElem !! 4697         '                       callDetail(this.id, this.title);\n'\
5277                 if(!cglist) return;           !! 4698         '               var cglist = document.getElementById("callgraphs");\n'\
5278                 var cg = cglist.getElementsBy !! 4699         '               if(!cglist) return;\n'\
5279                 if(cg.length < 10) return;    !! 4700         '               var cg = cglist.getElementsByClassName("atop");\n'\
5280                 for (var i = 0; i < cg.length !! 4701         '               if(cg.length < 10) return;\n'\
5281                         cgid = cg[i].id.split !! 4702         '               for (var i = 0; i < cg.length; i++) {\n'\
5282                         if(idlist.indexOf(cgi !! 4703         '                       cgid = cg[i].id.split("x")[0]\n'\
5283                                 cg[i].style.d !! 4704         '                       if(idlist.indexOf(cgid) >= 0) {\n'\
5284                         } else {              !! 4705         '                               cg[i].style.display = "block";\n'\
5285                                 cg[i].style.d !! 4706         '                       } else {\n'\
5286                         }                     !! 4707         '                               cg[i].style.display = "none";\n'\
5287                 }                             !! 4708         '                       }\n'\
5288         }                                     !! 4709         '               }\n'\
5289         function callDetail(devid, devtitle)  !! 4710         '       }\n'\
5290                 if(!(devid in devstats) || de !! 4711         '       function callDetail(devid, devtitle) {\n'\
5291                         return;               !! 4712         '               if(!(devid in devstats) || devstats[devid].length < 1)\n'\
5292                 var list = devstats[devid];   !! 4713         '                       return;\n'\
5293                 var tmp = devtitle.split(" ") !! 4714         '               var list = devstats[devid];\n'\
5294                 var name = tmp[0], phase = tm !! 4715         '               var tmp = devtitle.split(" ");\n'\
5295                 var dd = document.getElementB !! 4716         '               var name = tmp[0], phase = tmp[tmp.length-1];\n'\
5296                 var total = parseFloat(tmp[1] !! 4717         '               var dd = document.getElementById(phase);\n'\
5297                 var mlist = [];               !! 4718         '               var total = parseFloat(tmp[1].slice(1));\n'\
5298                 var maxlen = 0;               !! 4719         '               var mlist = [];\n'\
5299                 var info = []                 !! 4720         '               var maxlen = 0;\n'\
5300                 for(var i in list) {          !! 4721         '               var info = []\n'\
5301                         if(list[i][0] == "@") !! 4722         '               for(var i in list) {\n'\
5302                                 info = list[i !! 4723         '                       if(list[i][0] == "@") {\n'\
5303                                 continue;     !! 4724         '                               info = list[i].split("|");\n'\
5304                         }                     !! 4725         '                               continue;\n'\
5305                         var tmp = list[i].spl !! 4726         '                       }\n'\
5306                         var t = parseFloat(tm !! 4727         '                       var tmp = list[i].split("|");\n'\
5307                         var p = (t*100.0/tota !! 4728         '                       var t = parseFloat(tmp[0]), f = tmp[1], c = parseInt(tmp[2]);\n'\
5308                         mlist[mlist.length] = !! 4729         '                       var p = (t*100.0/total).toFixed(2);\n'\
5309                         if(f.length > maxlen) !! 4730         '                       mlist[mlist.length] = [f, c, t.toFixed(2), p+"%"];\n'\
5310                                 maxlen = f.le !! 4731         '                       if(f.length > maxlen)\n'\
5311                 }                             !! 4732         '                               maxlen = f.length;\n'\
5312                 var pad = 5;                  !! 4733         '               }\n'\
5313                 if(mlist.length == 0) pad = 3 !! 4734         '               var pad = 5;\n'\
5314                 var html = '<div style="paddi !! 4735         '               if(mlist.length == 0) pad = 30;\n'\
5315                 if(info.length > 2)           !! 4736         '               var html = \'<div style="padding-top:\'+pad+\'px"><t3> <b>\'+name+\':</b>\';\n'\
5316                         html += " start=<b>"+ !! 4737         '               if(info.length > 2)\n'\
5317                 if(info.length > 3)           !! 4738         '                       html += " start=<b>"+info[1]+"</b>, end=<b>"+info[2]+"</b>";\n'\
5318                         html += ", length<i>( !! 4739         '               if(info.length > 3)\n'\
5319                 if(info.length > 4)           !! 4740         '                       html += ", length<i>(w/o overhead)</i>=<b>"+info[3]+" ms</b>";\n'\
5320                         html += ", return=<b> !! 4741         '               if(info.length > 4)\n'\
5321                 html += "</t3></div>";        !! 4742         '                       html += ", return=<b>"+info[4]+"</b>";\n'\
5322                 if(mlist.length > 0) {        !! 4743         '               html += "</t3></div>";\n'\
5323                         html += '<table class !! 4744         '               if(mlist.length > 0) {\n'\
5324                         for(var i in mlist)   !! 4745         '                       html += \'<table class=fstat style="padding-top:\'+(maxlen*5)+\'px;"><tr><th>Function</th>\';\n'\
5325                                 html += "<td  !! 4746         '                       for(var i in mlist)\n'\
5326                         html += "</tr><tr><th !! 4747         '                               html += "<td class=vt>"+mlist[i][0]+"</td>";\n'\
5327                         for(var i in mlist)   !! 4748         '                       html += "</tr><tr><th>Calls</th>";\n'\
5328                                 html += "<td> !! 4749         '                       for(var i in mlist)\n'\
5329                         html += "</tr><tr><th !! 4750         '                               html += "<td>"+mlist[i][1]+"</td>";\n'\
5330                         for(var i in mlist)   !! 4751         '                       html += "</tr><tr><th>Time(ms)</th>";\n'\
5331                                 html += "<td> !! 4752         '                       for(var i in mlist)\n'\
5332                         html += "</tr><tr><th !! 4753         '                               html += "<td>"+mlist[i][2]+"</td>";\n'\
5333                         for(var i in mlist)   !! 4754         '                       html += "</tr><tr><th>Percent</th>";\n'\
5334                                 html += "<td> !! 4755         '                       for(var i in mlist)\n'\
5335                         html += "</tr></table !! 4756         '                               html += "<td>"+mlist[i][3]+"</td>";\n'\
5336                 }                             !! 4757         '                       html += "</tr></table>";\n'\
5337                 dd.innerHTML = html;          !! 4758         '               }\n'\
5338                 var height = (maxlen*5)+100;  !! 4759         '               dd.innerHTML = html;\n'\
5339                 dd.style.height = height+"px" !! 4760         '               var height = (maxlen*5)+100;\n'\
5340                 document.getElementById("devi !! 4761         '               dd.style.height = height+"px";\n'\
5341         }                                     !! 4762         '               document.getElementById("devicedetail").style.height = height+"px";\n'\
5342         function callSelect() {               !! 4763         '       }\n'\
5343                 var cglist = document.getElem !! 4764         '       function callSelect() {\n'\
5344                 if(!cglist) return;           !! 4765         '               var cglist = document.getElementById("callgraphs");\n'\
5345                 var cg = cglist.getElementsBy !! 4766         '               if(!cglist) return;\n'\
5346                 for (var i = 0; i < cg.length !! 4767         '               var cg = cglist.getElementsByClassName("atop");\n'\
5347                         if(this.id == cg[i].i !! 4768         '               for (var i = 0; i < cg.length; i++) {\n'\
5348                                 cg[i].style.d !! 4769         '                       if(this.id == cg[i].id) {\n'\
5349                         } else {              !! 4770         '                               cg[i].style.display = "block";\n'\
5350                                 cg[i].style.d !! 4771         '                       } else {\n'\
5351                         }                     !! 4772         '                               cg[i].style.display = "none";\n'\
5352                 }                             !! 4773         '                       }\n'\
5353         }                                     !! 4774         '               }\n'\
5354         function devListWindow(e) {           !! 4775         '       }\n'\
5355                 var win = window.open();      !! 4776         '       function devListWindow(e) {\n'\
5356                 var html = "<title>"+e.target !! 4777         '               var win = window.open();\n'\
5357                         "<style type=\"text/c !! 4778         '               var html = "<title>"+e.target.innerHTML+"</title>"+\n'\
5358                         "   ul {list-style-ty !! 4779         '                       "<style type=\\"text/css\\">"+\n'\
5359                         "</style>"            !! 4780         '                       "   ul {list-style-type:circle;padding-left:10px;margin-left:10px;}"+\n'\
5360                 var dt = devtable[0];         !! 4781         '                       "</style>"\n'\
5361                 if(e.target.id != "devlist1") !! 4782         '               var dt = devtable[0];\n'\
5362                         dt = devtable[1];     !! 4783         '               if(e.target.id != "devlist1")\n'\
5363                 win.document.write(html+dt);  !! 4784         '                       dt = devtable[1];\n'\
5364         }                                     !! 4785         '               win.document.write(html+dt);\n'\
5365         function errWindow() {                !! 4786         '       }\n'\
5366                 var range = this.id.split("_" !! 4787         '       function errWindow() {\n'\
5367                 var idx1 = parseInt(range[0]) !! 4788         '               var range = this.id.split("_");\n'\
5368                 var idx2 = parseInt(range[1]) !! 4789         '               var idx1 = parseInt(range[0]);\n'\
5369                 var win = window.open();      !! 4790         '               var idx2 = parseInt(range[1]);\n'\
5370                 var log = document.getElement !! 4791         '               var win = window.open();\n'\
5371                 var title = "<title>dmesg log !! 4792         '               var log = document.getElementById("dmesglog");\n'\
5372                 var text = log.innerHTML.spli !! 4793         '               var title = "<title>dmesg log</title>";\n'\
5373                 var html = "";                !! 4794         '               var text = log.innerHTML.split("\\n");\n'\
5374                 for(var i = 0; i < text.lengt !! 4795         '               var html = "";\n'\
5375                         if(i == idx1) {       !! 4796         '               for(var i = 0; i < text.length; i++) {\n'\
5376                                 html += "<e i !! 4797         '                       if(i == idx1) {\n'\
5377                         } else if(i > idx1 && !! 4798         '                               html += "<e id=target>"+text[i]+"</e>\\n";\n'\
5378                                 html += "<e>" !! 4799         '                       } else if(i > idx1 && i <= idx2) {\n'\
5379                         } else {              !! 4800         '                               html += "<e>"+text[i]+"</e>\\n";\n'\
5380                                 html += text[ !! 4801         '                       } else {\n'\
5381                         }                     !! 4802         '                               html += text[i]+"\\n";\n'\
5382                 }                             !! 4803         '                       }\n'\
5383                 win.document.write("<style>e{ !! 4804         '               }\n'\
5384                 win.location.hash = "#target" !! 4805         '               win.document.write("<style>e{color:red}</style>"+title+"<pre>"+html+"</pre>");\n'\
5385                 win.document.close();         !! 4806         '               win.location.hash = "#target";\n'\
5386         }                                     !! 4807         '               win.document.close();\n'\
5387         function logWindow(e) {               !! 4808         '       }\n'\
5388                 var name = e.target.id.slice( !! 4809         '       function logWindow(e) {\n'\
5389                 var win = window.open();      !! 4810         '               var name = e.target.id.slice(4);\n'\
5390                 var log = document.getElement !! 4811         '               var win = window.open();\n'\
5391                 var title = "<title>"+documen !! 4812         '               var log = document.getElementById(name+"log");\n'\
5392                 win.document.write(title+"<pr !! 4813         '               var title = "<title>"+document.title.split(" ")[0]+" "+name+" log</title>";\n'\
5393                 win.document.close();         !! 4814         '               win.document.write(title+"<pre>"+log.innerHTML+"</pre>");\n'\
5394         }                                     !! 4815         '               win.document.close();\n'\
5395         function onMouseDown(e) {             !! 4816         '       }\n'\
5396                 dragval[0] = e.clientX;       !! 4817         '       function onMouseDown(e) {\n'\
5397                 dragval[1] = document.getElem !! 4818         '               dragval[0] = e.clientX;\n'\
5398                 document.onmousemove = onMous !! 4819         '               dragval[1] = document.getElementById("dmesgzoombox").scrollLeft;\n'\
5399         }                                     !! 4820         '               document.onmousemove = onMouseMove;\n'\
5400         function onMouseMove(e) {             !! 4821         '       }\n'\
5401                 var zoombox = document.getEle !! 4822         '       function onMouseMove(e) {\n'\
5402                 zoombox.scrollLeft = dragval[ !! 4823         '               var zoombox = document.getElementById("dmesgzoombox");\n'\
5403         }                                     !! 4824         '               zoombox.scrollLeft = dragval[1] + dragval[0] - e.clientX;\n'\
5404         function onMouseUp(e) {               !! 4825         '       }\n'\
5405                 document.onmousemove = null;  !! 4826         '       function onMouseUp(e) {\n'\
5406         }                                     !! 4827         '               document.onmousemove = null;\n'\
5407         function onKeyPress(e) {              !! 4828         '       }\n'\
5408                 var c = e.charCode;           !! 4829         '       function onKeyPress(e) {\n'\
5409                 if(c != 42 && c != 43 && c != !! 4830         '               var c = e.charCode;\n'\
5410                 var click = document.createEv !! 4831         '               if(c != 42 && c != 43 && c != 45) return;\n'\
5411                 click.initEvent("click", true !! 4832         '               var click = document.createEvent("Events");\n'\
5412                 if(c == 43)                   !! 4833         '               click.initEvent("click", true, false);\n'\
5413                         document.getElementBy !! 4834         '               if(c == 43)  \n'\
5414                 else if(c == 45)              !! 4835         '                       document.getElementById("zoomin").dispatchEvent(click);\n'\
5415                         document.getElementBy !! 4836         '               else if(c == 45)\n'\
5416                 else if(c == 42)              !! 4837         '                       document.getElementById("zoomout").dispatchEvent(click);\n'\
5417                         document.getElementBy !! 4838         '               else if(c == 42)\n'\
5418         }                                     !! 4839         '                       document.getElementById("zoomdef").dispatchEvent(click);\n'\
5419         window.addEventListener("resize", fun !! 4840         '       }\n'\
5420         window.addEventListener("load", funct !! 4841         '       window.addEventListener("resize", function () {zoomTimeline();});\n'\
5421                 var dmesg = document.getEleme !! 4842         '       window.addEventListener("load", function () {\n'\
5422                 dmesg.style.width = "100%"    !! 4843         '               var dmesg = document.getElementById("dmesg");\n'\
5423                 dmesg.onmousedown = onMouseDo !! 4844         '               dmesg.style.width = "100%"\n'\
5424                 document.onmouseup = onMouseU !! 4845         '               dmesg.onmousedown = onMouseDown;\n'\
5425                 document.onkeypress = onKeyPr !! 4846         '               document.onmouseup = onMouseUp;\n'\
5426                 document.getElementById("zoom !! 4847         '               document.onkeypress = onKeyPress;\n'\
5427                 document.getElementById("zoom !! 4848         '               document.getElementById("zoomin").onclick = zoomTimeline;\n'\
5428                 document.getElementById("zoom !! 4849         '               document.getElementById("zoomout").onclick = zoomTimeline;\n'\
5429                 var list = document.getElemen !! 4850         '               document.getElementById("zoomdef").onclick = zoomTimeline;\n'\
5430                 for (var i = 0; i < list.leng !! 4851         '               var list = document.getElementsByClassName("err");\n'\
5431                         list[i].onclick = err !! 4852         '               for (var i = 0; i < list.length; i++)\n'\
5432                 var list = document.getElemen !! 4853         '                       list[i].onclick = errWindow;\n'\
5433                 for (var i = 0; i < list.leng !! 4854         '               var list = document.getElementsByClassName("logbtn");\n'\
5434                         list[i].onclick = log !! 4855         '               for (var i = 0; i < list.length; i++)\n'\
5435                 list = document.getElementsBy !! 4856         '                       list[i].onclick = logWindow;\n'\
5436                 for (var i = 0; i < list.leng !! 4857         '               list = document.getElementsByClassName("devlist");\n'\
5437                         list[i].onclick = dev !! 4858         '               for (var i = 0; i < list.length; i++)\n'\
5438                 var dev = dmesg.getElementsBy !! 4859         '                       list[i].onclick = devListWindow;\n'\
5439                 for (var i = 0; i < dev.lengt !! 4860         '               var dev = dmesg.getElementsByClassName("thread");\n'\
5440                         dev[i].onclick = devi !! 4861         '               for (var i = 0; i < dev.length; i++) {\n'\
5441                         dev[i].onmouseover =  !! 4862         '                       dev[i].onclick = deviceDetail;\n'\
5442                         dev[i].onmouseout = d !! 4863         '                       dev[i].onmouseover = deviceHover;\n'\
5443                 }                             !! 4864         '                       dev[i].onmouseout = deviceUnhover;\n'\
5444                 var dev = dmesg.getElementsBy !! 4865         '               }\n'\
5445                 for (var i = 0; i < dev.lengt !! 4866         '               var dev = dmesg.getElementsByClassName("srccall");\n'\
5446                         dev[i].onclick = call !! 4867         '               for (var i = 0; i < dev.length; i++)\n'\
5447                 zoomTimeline();               !! 4868         '                       dev[i].onclick = callSelect;\n'\
5448         });                                   !! 4869         '               zoomTimeline();\n'\
5449 </script> """                                 !! 4870         '       });\n'\
                                                   >> 4871         '</script>\n'
5450         hf.write(script_code);                   4872         hf.write(script_code);
5451                                                  4873 
                                                   >> 4874 def setRuntimeSuspend(before=True):
                                                   >> 4875         global sysvals
                                                   >> 4876         sv = sysvals
                                                   >> 4877         if sv.rs == 0:
                                                   >> 4878                 return
                                                   >> 4879         if before:
                                                   >> 4880                 # runtime suspend disable or enable
                                                   >> 4881                 if sv.rs > 0:
                                                   >> 4882                         sv.rstgt, sv.rsval, sv.rsdir = 'on', 'auto', 'enabled'
                                                   >> 4883                 else:
                                                   >> 4884                         sv.rstgt, sv.rsval, sv.rsdir = 'auto', 'on', 'disabled'
                                                   >> 4885                 pprint('CONFIGURING RUNTIME SUSPEND...')
                                                   >> 4886                 sv.rslist = deviceInfo(sv.rstgt)
                                                   >> 4887                 for i in sv.rslist:
                                                   >> 4888                         sv.setVal(sv.rsval, i)
                                                   >> 4889                 pprint('runtime suspend %s on all devices (%d changed)' % (sv.rsdir, len(sv.rslist)))
                                                   >> 4890                 pprint('waiting 5 seconds...')
                                                   >> 4891                 time.sleep(5)
                                                   >> 4892         else:
                                                   >> 4893                 # runtime suspend re-enable or re-disable
                                                   >> 4894                 for i in sv.rslist:
                                                   >> 4895                         sv.setVal(sv.rstgt, i)
                                                   >> 4896                 pprint('runtime suspend settings restored on %d devices' % len(sv.rslist))
                                                   >> 4897 
5452 # Function: executeSuspend                       4898 # Function: executeSuspend
5453 # Description:                                   4899 # Description:
5454 #        Execute system suspend through the s    4900 #        Execute system suspend through the sysfs interface, then copy the output
5455 #        dmesg and ftrace files to the test o    4901 #        dmesg and ftrace files to the test output directory.
5456 def executeSuspend(quiet=False):              !! 4902 def executeSuspend():
5457         sv, tp, pm = sysvals, sysvals.tpath,  !! 4903         pm = ProcessMonitor()
5458         if sv.wifi:                           !! 4904         tp = sysvals.tpath
5459                 wifi = sv.checkWifi()         !! 4905         wifi = sysvals.checkWifi()
5460                 sv.dlog('wifi check, connecte << 
5461         testdata = []                            4906         testdata = []
                                                   >> 4907         battery = True if getBattery() else False
5462         # run these commands to prepare the s    4908         # run these commands to prepare the system for suspend
5463         if sv.display:                        !! 4909         if sysvals.display:
5464                 if not quiet:                 !! 4910                 pprint('SET DISPLAY TO %s' % sysvals.display.upper())
5465                         pprint('SET DISPLAY T !! 4911                 displayControl(sysvals.display)
5466                 ret = sv.displayControl(sv.di << 
5467                 sv.dlog('xset display %s, ret << 
5468                 time.sleep(1)                    4912                 time.sleep(1)
5469         if sv.sync:                           !! 4913         if sysvals.sync:
5470                 if not quiet:                 !! 4914                 pprint('SYNCING FILESYSTEMS')
5471                         pprint('SYNCING FILES << 
5472                 sv.dlog('syncing filesystems' << 
5473                 call('sync', shell=True)         4915                 call('sync', shell=True)
5474         sv.dlog('read dmesg')                 !! 4916         # mark the start point in the kernel ring buffer just as we start
5475         sv.initdmesg()                        !! 4917         sysvals.initdmesg()
5476         sv.dlog('cmdinfo before')             !! 4918         # start ftrace
5477         sv.cmdinfo(True)                      !! 4919         if(sysvals.usecallgraph or sysvals.usetraceevents):
5478         sv.start(pm)                          !! 4920                 pprint('START TRACING')
                                                   >> 4921                 sysvals.fsetVal('1', 'tracing_on')
                                                   >> 4922                 if sysvals.useprocmon:
                                                   >> 4923                         pm.start()
5479         # execute however many s/r runs reque    4924         # execute however many s/r runs requested
5480         for count in range(1,sv.execcount+1): !! 4925         for count in range(1,sysvals.execcount+1):
5481                 # x2delay in between test run    4926                 # x2delay in between test runs
5482                 if(count > 1 and sv.x2delay > !! 4927                 if(count > 1 and sysvals.x2delay > 0):
5483                         sv.fsetVal('WAIT %d'  !! 4928                         sysvals.fsetVal('WAIT %d' % sysvals.x2delay, 'trace_marker')
5484                         time.sleep(sv.x2delay !! 4929                         time.sleep(sysvals.x2delay/1000.0)
5485                         sv.fsetVal('WAIT END' !! 4930                         sysvals.fsetVal('WAIT END', 'trace_marker')
5486                 # start message                  4931                 # start message
5487                 if sv.testcommand != '':      !! 4932                 if sysvals.testcommand != '':
5488                         pprint('COMMAND START    4933                         pprint('COMMAND START')
5489                 else:                            4934                 else:
5490                         if(sv.rtcwake):       !! 4935                         if(sysvals.rtcwake):
5491                                 pprint('SUSPE    4936                                 pprint('SUSPEND START')
5492                         else:                    4937                         else:
5493                                 pprint('SUSPE    4938                                 pprint('SUSPEND START (press a key to resume)')
                                                   >> 4939                 sysvals.mcelog(True)
                                                   >> 4940                 bat1 = getBattery() if battery else False
5494                 # set rtcwake                    4941                 # set rtcwake
5495                 if(sv.rtcwake):               !! 4942                 if(sysvals.rtcwake):
5496                         if not quiet:         !! 4943                         pprint('will issue an rtcwake in %d seconds' % sysvals.rtcwaketime)
5497                                 pprint('will  !! 4944                         sysvals.rtcWakeAlarmOn()
5498                         sv.dlog('enable RTC w << 
5499                         sv.rtcWakeAlarmOn()   << 
5500                 # start of suspend trace mark    4945                 # start of suspend trace marker
5501                 sv.fsetVal(datetime.now().str !! 4946                 if(sysvals.usecallgraph or sysvals.usetraceevents):
                                                   >> 4947                         sysvals.fsetVal('SUSPEND START', 'trace_marker')
5502                 # predelay delay                 4948                 # predelay delay
5503                 if(count == 1 and sv.predelay !! 4949                 if(count == 1 and sysvals.predelay > 0):
5504                         sv.fsetVal('WAIT %d'  !! 4950                         sysvals.fsetVal('WAIT %d' % sysvals.predelay, 'trace_marker')
5505                         time.sleep(sv.predela !! 4951                         time.sleep(sysvals.predelay/1000.0)
5506                         sv.fsetVal('WAIT END' !! 4952                         sysvals.fsetVal('WAIT END', 'trace_marker')
5507                 # initiate suspend or command    4953                 # initiate suspend or command
5508                 sv.dlog('system executing a s << 
5509                 tdata = {'error': ''}            4954                 tdata = {'error': ''}
5510                 if sv.testcommand != '':      !! 4955                 if sysvals.testcommand != '':
5511                         res = call(sv.testcom !! 4956                         res = call(sysvals.testcommand+' 2>&1', shell=True);
5512                         if res != 0:             4957                         if res != 0:
5513                                 tdata['error'    4958                                 tdata['error'] = 'cmd returned %d' % res
5514                 else:                            4959                 else:
5515                         s0ixready = sv.s0ixSu !! 4960                         mode = sysvals.suspendmode
5516                         mode = sv.suspendmode !! 4961                         if sysvals.memmode and os.path.exists(sysvals.mempowerfile):
5517                         if sv.memmode and os. << 
5518                                 mode = 'mem'     4962                                 mode = 'mem'
5519                                 sv.testVal(sv !! 4963                                 pf = open(sysvals.mempowerfile, 'w')
5520                         if sv.diskmode and os !! 4964                                 pf.write(sysvals.memmode)
                                                   >> 4965                                 pf.close()
                                                   >> 4966                         if sysvals.diskmode and os.path.exists(sysvals.diskpowerfile):
5521                                 mode = 'disk'    4967                                 mode = 'disk'
5522                                 sv.testVal(sv !! 4968                                 pf = open(sysvals.diskpowerfile, 'w')
5523                         if sv.acpidebug:      !! 4969                                 pf.write(sysvals.diskmode)
5524                                 sv.testVal(sv !! 4970                                 pf.close()
5525                         if ((mode == 'freeze' !! 4971                         if mode == 'freeze' and sysvals.haveTurbostat():
5526                                 and sv.haveTu << 
5527                                 # execution w    4972                                 # execution will pause here
5528                                 retval, turbo !! 4973                                 turbo = sysvals.turbostat()
5529                                 if retval !=  !! 4974                                 if '|' in turbo:
5530                                         tdata << 
5531                                 if turbo:     << 
5532                                         tdata    4975                                         tdata['turbo'] = turbo
                                                   >> 4976                                 else:
                                                   >> 4977                                         tdata['error'] = turbo
5533                         else:                    4978                         else:
5534                                 pf = open(sv. !! 4979                                 if sysvals.haveTurbostat():
                                                   >> 4980                                         sysvals.vprint('WARNING: ignoring turbostat in mode "%s"' % mode)
                                                   >> 4981                                 pf = open(sysvals.powerfile, 'w')
5535                                 pf.write(mode    4982                                 pf.write(mode)
5536                                 # execution w    4983                                 # execution will pause here
5537                                 try:             4984                                 try:
5538                                         pf.fl << 
5539                                         pf.cl    4985                                         pf.close()
5540                                 except Except    4986                                 except Exception as e:
5541                                         tdata    4987                                         tdata['error'] = str(e)
5542                 sv.fsetVal('CMD COMPLETE', 't !! 4988                 if(sysvals.rtcwake):
5543                 sv.dlog('system returned')    !! 4989                         sysvals.rtcWakeAlarmOff()
5544                 # reset everything            << 
5545                 sv.testVal('restoreall')      << 
5546                 if(sv.rtcwake):               << 
5547                         sv.dlog('disable RTC  << 
5548                         sv.rtcWakeAlarmOff()  << 
5549                 # postdelay delay                4990                 # postdelay delay
5550                 if(count == sv.execcount and  !! 4991                 if(count == sysvals.execcount and sysvals.postdelay > 0):
5551                         sv.fsetVal('WAIT %d'  !! 4992                         sysvals.fsetVal('WAIT %d' % sysvals.postdelay, 'trace_marker')
5552                         time.sleep(sv.postdel !! 4993                         time.sleep(sysvals.postdelay/1000.0)
5553                         sv.fsetVal('WAIT END' !! 4994                         sysvals.fsetVal('WAIT END', 'trace_marker')
5554                 # return from suspend            4995                 # return from suspend
5555                 pprint('RESUME COMPLETE')        4996                 pprint('RESUME COMPLETE')
5556                 if(count < sv.execcount):     !! 4997                 if(sysvals.usecallgraph or sysvals.usetraceevents):
5557                         sv.fsetVal(datetime.n !! 4998                         sysvals.fsetVal('RESUME COMPLETE', 'trace_marker')
5558                 elif(not sv.wifitrace):       !! 4999                 if(sysvals.suspendmode == 'mem' or sysvals.suspendmode == 'command'):
5559                         sv.fsetVal(datetime.n << 
5560                         sv.stop(pm)           << 
5561                 if sv.wifi and wifi:          << 
5562                         tdata['wifi'] = sv.po << 
5563                         sv.dlog('wifi check,  << 
5564                 if(count == sv.execcount and  << 
5565                         sv.fsetVal(datetime.n << 
5566                         sv.stop(pm)           << 
5567                 if sv.netfix:                 << 
5568                         tdata['netfix'] = sv. << 
5569                         sv.dlog('netfix, %s'  << 
5570                 if(sv.suspendmode == 'mem' or << 
5571                         sv.dlog('read the ACP << 
5572                         tdata['fw'] = getFPDT    5000                         tdata['fw'] = getFPDT(False)
                                                   >> 5001                 mcelog = sysvals.mcelog()
                                                   >> 5002                 if mcelog:
                                                   >> 5003                         tdata['mcelog'] = mcelog
                                                   >> 5004                 bat2 = getBattery() if battery else False
                                                   >> 5005                 if battery and bat1 and bat2:
                                                   >> 5006                         tdata['bat'] = (bat1, bat2)
                                                   >> 5007                 if 'device' in wifi and 'ip' in wifi:
                                                   >> 5008                         tdata['wifi'] = (wifi, sysvals.checkWifi())
5573                 testdata.append(tdata)           5009                 testdata.append(tdata)
5574         sv.dlog('cmdinfo after')              !! 5010         # stop ftrace
5575         cmdafter = sv.cmdinfo(False)          !! 5011         if(sysvals.usecallgraph or sysvals.usetraceevents):
                                                   >> 5012                 if sysvals.useprocmon:
                                                   >> 5013                         pm.stop()
                                                   >> 5014                 sysvals.fsetVal('0', 'tracing_on')
5576         # grab a copy of the dmesg output        5015         # grab a copy of the dmesg output
5577         if not quiet:                         !! 5016         pprint('CAPTURING DMESG')
5578                 pprint('CAPTURING DMESG')     !! 5017         sysvals.getdmesg(testdata)
5579         sv.getdmesg(testdata)                 << 
5580         # grab a copy of the ftrace output       5018         # grab a copy of the ftrace output
5581         if sv.useftrace:                      !! 5019         if(sysvals.usecallgraph or sysvals.usetraceevents):
5582                 if not quiet:                 !! 5020                 pprint('CAPTURING TRACE')
5583                         pprint('CAPTURING TRA !! 5021                 op = sysvals.writeDatafileHeader(sysvals.ftracefile, testdata)
5584                 op = sv.writeDatafileHeader(s !! 5022                 fp = open(tp+'trace', 'r')
5585                 fp = open(tp+'trace', 'rb')   !! 5023                 for line in fp:
5586                 op.write(ascii(fp.read()))    !! 5024                         op.write(line)
5587                 op.close()                       5025                 op.close()
5588                 sv.fsetVal('', 'trace')       !! 5026                 sysvals.fsetVal('', 'trace')
5589                 sv.platforminfo(cmdafter)     !! 5027                 devProps()
                                                   >> 5028         return testdata
5590                                                  5029 
5591 def readFile(file):                              5030 def readFile(file):
5592         if os.path.islink(file):                 5031         if os.path.islink(file):
5593                 return os.readlink(file).spli    5032                 return os.readlink(file).split('/')[-1]
5594         else:                                    5033         else:
5595                 return sysvals.getVal(file).s    5034                 return sysvals.getVal(file).strip()
5596                                                  5035 
5597 # Function: ms2nice                              5036 # Function: ms2nice
5598 # Description:                                   5037 # Description:
5599 #        Print out a very concise time string    5038 #        Print out a very concise time string in minutes and seconds
5600 # Output:                                        5039 # Output:
5601 #        The time string, e.g. "1901m16s"        5040 #        The time string, e.g. "1901m16s"
5602 def ms2nice(val):                                5041 def ms2nice(val):
5603         val = int(val)                           5042         val = int(val)
5604         h = val // 3600000                    !! 5043         h = val / 3600000
5605         m = (val // 60000) % 60               !! 5044         m = (val / 60000) % 60
5606         s = (val // 1000) % 60                !! 5045         s = (val / 1000) % 60
5607         if h > 0:                                5046         if h > 0:
5608                 return '%d:%02d:%02d' % (h, m    5047                 return '%d:%02d:%02d' % (h, m, s)
5609         if m > 0:                                5048         if m > 0:
5610                 return '%02d:%02d' % (m, s)      5049                 return '%02d:%02d' % (m, s)
5611         return '%ds' % s                         5050         return '%ds' % s
5612                                                  5051 
5613 def yesno(val):                                  5052 def yesno(val):
5614         list = {'enabled':'A', 'disabled':'S'    5053         list = {'enabled':'A', 'disabled':'S', 'auto':'E', 'on':'D',
5615                 'active':'A', 'suspended':'S'    5054                 'active':'A', 'suspended':'S', 'suspending':'S'}
5616         if val not in list:                      5055         if val not in list:
5617                 return ' '                       5056                 return ' '
5618         return list[val]                         5057         return list[val]
5619                                                  5058 
5620 # Function: deviceInfo                           5059 # Function: deviceInfo
5621 # Description:                                   5060 # Description:
5622 #        Detect all the USB hosts and devices    5061 #        Detect all the USB hosts and devices currently connected and add
5623 #        a list of USB device names to sysval    5062 #        a list of USB device names to sysvals for better timeline readability
5624 def deviceInfo(output=''):                       5063 def deviceInfo(output=''):
5625         if not output:                           5064         if not output:
5626                 pprint('LEGEND\n'\               5065                 pprint('LEGEND\n'\
5627                 '----------------------------    5066                 '---------------------------------------------------------------------------------------------\n'\
5628                 '  A = async/sync PM queue (A    5067                 '  A = async/sync PM queue (A/S)               C = runtime active children\n'\
5629                 '  R = runtime suspend enable    5068                 '  R = runtime suspend enabled/disabled (E/D)  rACTIVE = runtime active (min/sec)\n'\
5630                 '  S = runtime status active/    5069                 '  S = runtime status active/suspended (A/S)   rSUSPEND = runtime suspend (min/sec)\n'\
5631                 '  U = runtime usage count\n'    5070                 '  U = runtime usage count\n'\
5632                 '----------------------------    5071                 '---------------------------------------------------------------------------------------------\n'\
5633                 'DEVICE                     N    5072                 'DEVICE                     NAME                       A R S U C    rACTIVE   rSUSPEND\n'\
5634                 '----------------------------    5073                 '---------------------------------------------------------------------------------------------')
5635                                                  5074 
5636         res = []                                 5075         res = []
5637         tgtval = 'runtime_status'                5076         tgtval = 'runtime_status'
5638         lines = dict()                           5077         lines = dict()
5639         for dirname, dirnames, filenames in o    5078         for dirname, dirnames, filenames in os.walk('/sys/devices'):
5640                 if(not re.match(r'.*/power',  !! 5079                 if(not re.match('.*/power', dirname) or
5641                         'control' not in file    5080                         'control' not in filenames or
5642                         tgtval not in filenam    5081                         tgtval not in filenames):
5643                         continue                 5082                         continue
5644                 name = ''                        5083                 name = ''
5645                 dirname = dirname[:-6]           5084                 dirname = dirname[:-6]
5646                 device = dirname.split('/')[-    5085                 device = dirname.split('/')[-1]
5647                 power = dict()                   5086                 power = dict()
5648                 power[tgtval] = readFile('%s/    5087                 power[tgtval] = readFile('%s/power/%s' % (dirname, tgtval))
5649                 # only list devices which sup    5088                 # only list devices which support runtime suspend
5650                 if power[tgtval] not in ['act    5089                 if power[tgtval] not in ['active', 'suspended', 'suspending']:
5651                         continue                 5090                         continue
5652                 for i in ['product', 'driver'    5091                 for i in ['product', 'driver', 'subsystem']:
5653                         file = '%s/%s' % (dir    5092                         file = '%s/%s' % (dirname, i)
5654                         if os.path.exists(fil    5093                         if os.path.exists(file):
5655                                 name = readFi    5094                                 name = readFile(file)
5656                                 break            5095                                 break
5657                 for i in ['async', 'control',    5096                 for i in ['async', 'control', 'runtime_status', 'runtime_usage',
5658                         'runtime_active_kids'    5097                         'runtime_active_kids', 'runtime_active_time',
5659                         'runtime_suspended_ti    5098                         'runtime_suspended_time']:
5660                         if i in filenames:       5099                         if i in filenames:
5661                                 power[i] = re    5100                                 power[i] = readFile('%s/power/%s' % (dirname, i))
5662                 if output:                       5101                 if output:
5663                         if power['control'] =    5102                         if power['control'] == output:
5664                                 res.append('%    5103                                 res.append('%s/power/control' % dirname)
5665                         continue                 5104                         continue
5666                 lines[dirname] = '%-26s %-26s    5105                 lines[dirname] = '%-26s %-26s %1s %1s %1s %1s %1s %10s %10s' % \
5667                         (device[:26], name[:2    5106                         (device[:26], name[:26],
5668                         yesno(power['async'])    5107                         yesno(power['async']), \
5669                         yesno(power['control'    5108                         yesno(power['control']), \
5670                         yesno(power['runtime_    5109                         yesno(power['runtime_status']), \
5671                         power['runtime_usage'    5110                         power['runtime_usage'], \
5672                         power['runtime_active    5111                         power['runtime_active_kids'], \
5673                         ms2nice(power['runtim    5112                         ms2nice(power['runtime_active_time']), \
5674                         ms2nice(power['runtim    5113                         ms2nice(power['runtime_suspended_time']))
5675         for i in sorted(lines):                  5114         for i in sorted(lines):
5676                 print(lines[i])                  5115                 print(lines[i])
5677         return res                               5116         return res
5678                                                  5117 
                                                   >> 5118 # Function: devProps
                                                   >> 5119 # Description:
                                                   >> 5120 #        Retrieve a list of properties for all devices in the trace log
                                                   >> 5121 def devProps(data=0):
                                                   >> 5122         props = dict()
                                                   >> 5123 
                                                   >> 5124         if data:
                                                   >> 5125                 idx = data.index(': ') + 2
                                                   >> 5126                 if idx >= len(data):
                                                   >> 5127                         return
                                                   >> 5128                 devlist = data[idx:].split(';')
                                                   >> 5129                 for dev in devlist:
                                                   >> 5130                         f = dev.split(',')
                                                   >> 5131                         if len(f) < 3:
                                                   >> 5132                                 continue
                                                   >> 5133                         dev = f[0]
                                                   >> 5134                         props[dev] = DevProps()
                                                   >> 5135                         props[dev].altname = f[1]
                                                   >> 5136                         if int(f[2]):
                                                   >> 5137                                 props[dev].async = True
                                                   >> 5138                         else:
                                                   >> 5139                                 props[dev].async = False
                                                   >> 5140                         sysvals.devprops = props
                                                   >> 5141                 if sysvals.suspendmode == 'command' and 'testcommandstring' in props:
                                                   >> 5142                         sysvals.testcommand = props['testcommandstring'].altname
                                                   >> 5143                 return
                                                   >> 5144 
                                                   >> 5145         if(os.path.exists(sysvals.ftracefile) == False):
                                                   >> 5146                 doError('%s does not exist' % sysvals.ftracefile)
                                                   >> 5147 
                                                   >> 5148         # first get the list of devices we need properties for
                                                   >> 5149         msghead = 'Additional data added by AnalyzeSuspend'
                                                   >> 5150         alreadystamped = False
                                                   >> 5151         tp = TestProps()
                                                   >> 5152         tf = sysvals.openlog(sysvals.ftracefile, 'r')
                                                   >> 5153         for line in tf:
                                                   >> 5154                 if msghead in line:
                                                   >> 5155                         alreadystamped = True
                                                   >> 5156                         continue
                                                   >> 5157                 # determine the trace data type (required for further parsing)
                                                   >> 5158                 m = re.match(tp.tracertypefmt, line)
                                                   >> 5159                 if(m):
                                                   >> 5160                         tp.setTracerType(m.group('t'))
                                                   >> 5161                         continue
                                                   >> 5162                 # parse only valid lines, if this is not one move on
                                                   >> 5163                 m = re.match(tp.ftrace_line_fmt, line)
                                                   >> 5164                 if(not m or 'device_pm_callback_start' not in line):
                                                   >> 5165                         continue
                                                   >> 5166                 m = re.match('.*: (?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*', m.group('msg'));
                                                   >> 5167                 if(not m):
                                                   >> 5168                         continue
                                                   >> 5169                 dev = m.group('d')
                                                   >> 5170                 if dev not in props:
                                                   >> 5171                         props[dev] = DevProps()
                                                   >> 5172         tf.close()
                                                   >> 5173 
                                                   >> 5174         if not alreadystamped and sysvals.suspendmode == 'command':
                                                   >> 5175                 out = '#\n# '+msghead+'\n# Device Properties: '
                                                   >> 5176                 out += 'testcommandstring,%s,0;' % (sysvals.testcommand)
                                                   >> 5177                 with sysvals.openlog(sysvals.ftracefile, 'a') as fp:
                                                   >> 5178                         fp.write(out+'\n')
                                                   >> 5179                 sysvals.devprops = props
                                                   >> 5180                 return
                                                   >> 5181 
                                                   >> 5182         # now get the syspath for each of our target devices
                                                   >> 5183         for dirname, dirnames, filenames in os.walk('/sys/devices'):
                                                   >> 5184                 if(re.match('.*/power', dirname) and 'async' in filenames):
                                                   >> 5185                         dev = dirname.split('/')[-2]
                                                   >> 5186                         if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)):
                                                   >> 5187                                 props[dev].syspath = dirname[:-6]
                                                   >> 5188 
                                                   >> 5189         # now fill in the properties for our target devices
                                                   >> 5190         for dev in props:
                                                   >> 5191                 dirname = props[dev].syspath
                                                   >> 5192                 if not dirname or not os.path.exists(dirname):
                                                   >> 5193                         continue
                                                   >> 5194                 with open(dirname+'/power/async') as fp:
                                                   >> 5195                         text = fp.read()
                                                   >> 5196                         props[dev].async = False
                                                   >> 5197                         if 'enabled' in text:
                                                   >> 5198                                 props[dev].async = True
                                                   >> 5199                 fields = os.listdir(dirname)
                                                   >> 5200                 if 'product' in fields:
                                                   >> 5201                         with open(dirname+'/product') as fp:
                                                   >> 5202                                 props[dev].altname = fp.read()
                                                   >> 5203                 elif 'name' in fields:
                                                   >> 5204                         with open(dirname+'/name') as fp:
                                                   >> 5205                                 props[dev].altname = fp.read()
                                                   >> 5206                 elif 'model' in fields:
                                                   >> 5207                         with open(dirname+'/model') as fp:
                                                   >> 5208                                 props[dev].altname = fp.read()
                                                   >> 5209                 elif 'description' in fields:
                                                   >> 5210                         with open(dirname+'/description') as fp:
                                                   >> 5211                                 props[dev].altname = fp.read()
                                                   >> 5212                 elif 'id' in fields:
                                                   >> 5213                         with open(dirname+'/id') as fp:
                                                   >> 5214                                 props[dev].altname = fp.read()
                                                   >> 5215                 elif 'idVendor' in fields and 'idProduct' in fields:
                                                   >> 5216                         idv, idp = '', ''
                                                   >> 5217                         with open(dirname+'/idVendor') as fp:
                                                   >> 5218                                 idv = fp.read().strip()
                                                   >> 5219                         with open(dirname+'/idProduct') as fp:
                                                   >> 5220                                 idp = fp.read().strip()
                                                   >> 5221                         props[dev].altname = '%s:%s' % (idv, idp)
                                                   >> 5222 
                                                   >> 5223                 if props[dev].altname:
                                                   >> 5224                         out = props[dev].altname.strip().replace('\n', ' ')
                                                   >> 5225                         out = out.replace(',', ' ')
                                                   >> 5226                         out = out.replace(';', ' ')
                                                   >> 5227                         props[dev].altname = out
                                                   >> 5228 
                                                   >> 5229         # and now write the data to the ftrace file
                                                   >> 5230         if not alreadystamped:
                                                   >> 5231                 out = '#\n# '+msghead+'\n# Device Properties: '
                                                   >> 5232                 for dev in sorted(props):
                                                   >> 5233                         out += props[dev].out(dev)
                                                   >> 5234                 with sysvals.openlog(sysvals.ftracefile, 'a') as fp:
                                                   >> 5235                         fp.write(out+'\n')
                                                   >> 5236 
                                                   >> 5237         sysvals.devprops = props
                                                   >> 5238 
5679 # Function: getModes                             5239 # Function: getModes
5680 # Description:                                   5240 # Description:
5681 #        Determine the supported power modes     5241 #        Determine the supported power modes on this system
5682 # Output:                                        5242 # Output:
5683 #        A string list of the available modes    5243 #        A string list of the available modes
5684 def getModes():                                  5244 def getModes():
5685         modes = []                               5245         modes = []
5686         if(os.path.exists(sysvals.powerfile))    5246         if(os.path.exists(sysvals.powerfile)):
5687                 fp = open(sysvals.powerfile,     5247                 fp = open(sysvals.powerfile, 'r')
5688                 modes = fp.read().split()        5248                 modes = fp.read().split()
5689                 fp.close()                       5249                 fp.close()
5690         if(os.path.exists(sysvals.mempowerfil    5250         if(os.path.exists(sysvals.mempowerfile)):
5691                 deep = False                     5251                 deep = False
5692                 fp = open(sysvals.mempowerfil    5252                 fp = open(sysvals.mempowerfile, 'r')
5693                 for m in fp.read().split():      5253                 for m in fp.read().split():
5694                         memmode = m.strip('[]    5254                         memmode = m.strip('[]')
5695                         if memmode == 'deep':    5255                         if memmode == 'deep':
5696                                 deep = True      5256                                 deep = True
5697                         else:                    5257                         else:
5698                                 modes.append(    5258                                 modes.append('mem-%s' % memmode)
5699                 fp.close()                       5259                 fp.close()
5700                 if 'mem' in modes and not dee    5260                 if 'mem' in modes and not deep:
5701                         modes.remove('mem')      5261                         modes.remove('mem')
5702         if('disk' in modes and os.path.exists    5262         if('disk' in modes and os.path.exists(sysvals.diskpowerfile)):
5703                 fp = open(sysvals.diskpowerfi    5263                 fp = open(sysvals.diskpowerfile, 'r')
5704                 for m in fp.read().split():      5264                 for m in fp.read().split():
5705                         modes.append('disk-%s    5265                         modes.append('disk-%s' % m.strip('[]'))
5706                 fp.close()                       5266                 fp.close()
5707         return modes                             5267         return modes
5708                                                  5268 
5709 def dmidecode_backup(out, fatal=False):       << 
5710         cpath, spath, info = '/proc/cpuinfo', << 
5711                 'bios-vendor': 'bios_vendor', << 
5712                 'bios-version': 'bios_version << 
5713                 'bios-release-date': 'bios_da << 
5714                 'system-manufacturer': 'sys_v << 
5715                 'system-product-name': 'produ << 
5716                 'system-version': 'product_ve << 
5717                 'system-serial-number': 'prod << 
5718                 'baseboard-manufacturer': 'bo << 
5719                 'baseboard-product-name': 'bo << 
5720                 'baseboard-version': 'board_v << 
5721                 'baseboard-serial-number': 'b << 
5722                 'chassis-manufacturer': 'chas << 
5723                 'chassis-version': 'chassis_v << 
5724                 'chassis-serial-number': 'cha << 
5725         }                                     << 
5726         for key in info:                      << 
5727                 if key not in out:            << 
5728                         val = sysvals.getVal( << 
5729                         if val and val.lower( << 
5730                                 out[key] = va << 
5731         if 'processor-version' not in out and << 
5732                 with open(cpath, 'r') as fp:  << 
5733                         for line in fp:       << 
5734                                 m = re.match( << 
5735                                 if m:         << 
5736                                         out[' << 
5737                                         break << 
5738         if fatal and len(out) < 1:            << 
5739                 doError('dmidecode failed to  << 
5740                         (sysvals.mempath, spa << 
5741         return out                            << 
5742                                               << 
5743 # Function: dmidecode                            5269 # Function: dmidecode
5744 # Description:                                   5270 # Description:
5745 #        Read the bios tables and pull out sy    5271 #        Read the bios tables and pull out system info
5746 # Arguments:                                     5272 # Arguments:
5747 #        mempath: /dev/mem or custom mem path    5273 #        mempath: /dev/mem or custom mem path
5748 #        fatal: True to exit on error, False     5274 #        fatal: True to exit on error, False to return empty dict
5749 # Output:                                        5275 # Output:
5750 #        A dict object with all available key    5276 #        A dict object with all available key/values
5751 def dmidecode(mempath, fatal=False):             5277 def dmidecode(mempath, fatal=False):
5752         out = dict()                             5278         out = dict()
5753         if(not (os.path.exists(mempath) and o << 
5754                 return dmidecode_backup(out,  << 
5755                                                  5279 
5756         # the list of values to retrieve, wit    5280         # the list of values to retrieve, with hardcoded (type, idx)
5757         info = {                                 5281         info = {
5758                 'bios-vendor': (0, 4),           5282                 'bios-vendor': (0, 4),
5759                 'bios-version': (0, 5),          5283                 'bios-version': (0, 5),
5760                 'bios-release-date': (0, 8),     5284                 'bios-release-date': (0, 8),
5761                 'system-manufacturer': (1, 4)    5285                 'system-manufacturer': (1, 4),
5762                 'system-product-name': (1, 5)    5286                 'system-product-name': (1, 5),
5763                 'system-version': (1, 6),        5287                 'system-version': (1, 6),
5764                 'system-serial-number': (1, 7    5288                 'system-serial-number': (1, 7),
5765                 'baseboard-manufacturer': (2,    5289                 'baseboard-manufacturer': (2, 4),
5766                 'baseboard-product-name': (2,    5290                 'baseboard-product-name': (2, 5),
5767                 'baseboard-version': (2, 6),     5291                 'baseboard-version': (2, 6),
5768                 'baseboard-serial-number': (2    5292                 'baseboard-serial-number': (2, 7),
5769                 'chassis-manufacturer': (3, 4    5293                 'chassis-manufacturer': (3, 4),
                                                   >> 5294                 'chassis-type': (3, 5),
5770                 'chassis-version': (3, 6),       5295                 'chassis-version': (3, 6),
5771                 'chassis-serial-number': (3,     5296                 'chassis-serial-number': (3, 7),
5772                 'processor-manufacturer': (4,    5297                 'processor-manufacturer': (4, 7),
5773                 'processor-version': (4, 16),    5298                 'processor-version': (4, 16),
5774         }                                        5299         }
                                                   >> 5300         if(not os.path.exists(mempath)):
                                                   >> 5301                 if(fatal):
                                                   >> 5302                         doError('file does not exist: %s' % mempath)
                                                   >> 5303                 return out
                                                   >> 5304         if(not os.access(mempath, os.R_OK)):
                                                   >> 5305                 if(fatal):
                                                   >> 5306                         doError('file is not readable: %s' % mempath)
                                                   >> 5307                 return out
5775                                                  5308 
5776         # by default use legacy scan, but try    5309         # by default use legacy scan, but try to use EFI first
5777         memaddr, memsize = 0xf0000, 0x10000   !! 5310         memaddr = 0xf0000
                                                   >> 5311         memsize = 0x10000
5778         for ep in ['/sys/firmware/efi/systab'    5312         for ep in ['/sys/firmware/efi/systab', '/proc/efi/systab']:
5779                 if not os.path.exists(ep) or     5313                 if not os.path.exists(ep) or not os.access(ep, os.R_OK):
5780                         continue                 5314                         continue
5781                 fp = open(ep, 'r')               5315                 fp = open(ep, 'r')
5782                 buf = fp.read()                  5316                 buf = fp.read()
5783                 fp.close()                       5317                 fp.close()
5784                 i = buf.find('SMBIOS=')          5318                 i = buf.find('SMBIOS=')
5785                 if i >= 0:                       5319                 if i >= 0:
5786                         try:                     5320                         try:
5787                                 memaddr = int    5321                                 memaddr = int(buf[i+7:], 16)
5788                                 memsize = 0x2    5322                                 memsize = 0x20
5789                         except:                  5323                         except:
5790                                 continue         5324                                 continue
5791                                                  5325 
5792         # read in the memory for scanning        5326         # read in the memory for scanning
5793         try:                                     5327         try:
5794                 fp = open(mempath, 'rb')         5328                 fp = open(mempath, 'rb')
5795                 fp.seek(memaddr)                 5329                 fp.seek(memaddr)
5796                 buf = fp.read(memsize)           5330                 buf = fp.read(memsize)
5797         except:                                  5331         except:
5798                 return dmidecode_backup(out,  !! 5332                 if(fatal):
                                                   >> 5333                         doError('DMI table is unreachable, sorry')
                                                   >> 5334                 else:
                                                   >> 5335                         pprint('WARNING: /dev/mem is not readable, ignoring DMI data')
                                                   >> 5336                         return out
5799         fp.close()                               5337         fp.close()
5800                                                  5338 
5801         # search for either an SM table or DM    5339         # search for either an SM table or DMI table
5802         i = base = length = num = 0              5340         i = base = length = num = 0
5803         while(i < memsize):                      5341         while(i < memsize):
5804                 if buf[i:i+4] == b'_SM_' and  !! 5342                 if buf[i:i+4] == '_SM_' and i < memsize - 16:
5805                         length = struct.unpac    5343                         length = struct.unpack('H', buf[i+22:i+24])[0]
5806                         base, num = struct.un    5344                         base, num = struct.unpack('IH', buf[i+24:i+30])
5807                         break                    5345                         break
5808                 elif buf[i:i+5] == b'_DMI_':  !! 5346                 elif buf[i:i+5] == '_DMI_':
5809                         length = struct.unpac    5347                         length = struct.unpack('H', buf[i+6:i+8])[0]
5810                         base, num = struct.un    5348                         base, num = struct.unpack('IH', buf[i+8:i+14])
5811                         break                    5349                         break
5812                 i += 16                          5350                 i += 16
5813         if base == 0 and length == 0 and num     5351         if base == 0 and length == 0 and num == 0:
5814                 return dmidecode_backup(out,  !! 5352                 if(fatal):
                                                   >> 5353                         doError('Neither SMBIOS nor DMI were found')
                                                   >> 5354                 else:
                                                   >> 5355                         return out
5815                                                  5356 
5816         # read in the SM or DMI table            5357         # read in the SM or DMI table
5817         try:                                     5358         try:
5818                 fp = open(mempath, 'rb')         5359                 fp = open(mempath, 'rb')
5819                 fp.seek(base)                    5360                 fp.seek(base)
5820                 buf = fp.read(length)            5361                 buf = fp.read(length)
5821         except:                                  5362         except:
5822                 return dmidecode_backup(out,  !! 5363                 if(fatal):
                                                   >> 5364                         doError('DMI table is unreachable, sorry')
                                                   >> 5365                 else:
                                                   >> 5366                         pprint('WARNING: /dev/mem is not readable, ignoring DMI data')
                                                   >> 5367                         return out
5823         fp.close()                               5368         fp.close()
5824                                                  5369 
5825         # scan the table for the values we wa    5370         # scan the table for the values we want
5826         count = i = 0                            5371         count = i = 0
5827         while(count < num and i <= len(buf) -    5372         while(count < num and i <= len(buf) - 4):
5828                 type, size, handle = struct.u    5373                 type, size, handle = struct.unpack('BBH', buf[i:i+4])
5829                 n = i + size                     5374                 n = i + size
5830                 while n < len(buf) - 1:          5375                 while n < len(buf) - 1:
5831                         if 0 == struct.unpack    5376                         if 0 == struct.unpack('H', buf[n:n+2])[0]:
5832                                 break            5377                                 break
5833                         n += 1                   5378                         n += 1
5834                 data = buf[i+size:n+2].split( !! 5379                 data = buf[i+size:n+2].split('\0')
5835                 for name in info:                5380                 for name in info:
5836                         itype, idxadr = info[    5381                         itype, idxadr = info[name]
5837                         if itype == type:        5382                         if itype == type:
5838                                 idx = struct. !! 5383                                 idx = struct.unpack('B', buf[i+idxadr])[0]
5839                                 if idx > 0 an    5384                                 if idx > 0 and idx < len(data) - 1:
5840                                         s = d !! 5385                                         s = data[idx-1].strip()
5841                                         if s. !! 5386                                         if s and s.lower() != 'to be filled by o.e.m.':
5842                                               !! 5387                                                 out[name] = data[idx-1]
5843                 i = n + 2                        5388                 i = n + 2
5844                 count += 1                       5389                 count += 1
5845         return out                               5390         return out
5846                                                  5391 
                                                   >> 5392 def getBattery():
                                                   >> 5393         p, charge, bat = '/sys/class/power_supply', 0, {}
                                                   >> 5394         if not os.path.exists(p):
                                                   >> 5395                 return False
                                                   >> 5396         for d in os.listdir(p):
                                                   >> 5397                 type = sysvals.getVal(os.path.join(p, d, 'type')).strip().lower()
                                                   >> 5398                 if type != 'battery':
                                                   >> 5399                         continue
                                                   >> 5400                 for v in ['status', 'energy_now', 'capacity_now']:
                                                   >> 5401                         bat[v] = sysvals.getVal(os.path.join(p, d, v)).strip().lower()
                                                   >> 5402                 break
                                                   >> 5403         if 'status' not in bat:
                                                   >> 5404                 return False
                                                   >> 5405         ac = False if 'discharging' in bat['status'] else True
                                                   >> 5406         for v in ['energy_now', 'capacity_now']:
                                                   >> 5407                 if v in bat and bat[v]:
                                                   >> 5408                         charge = int(bat[v])
                                                   >> 5409         return (ac, charge)
                                                   >> 5410 
                                                   >> 5411 def displayControl(cmd):
                                                   >> 5412         xset, ret = 'xset -d :0.0 {0}', 0
                                                   >> 5413         if sysvals.sudouser:
                                                   >> 5414                 xset = 'sudo -u %s %s' % (sysvals.sudouser, xset)
                                                   >> 5415         if cmd == 'init':
                                                   >> 5416                 ret = call(xset.format('dpms 0 0 0'), shell=True)
                                                   >> 5417                 if not ret:
                                                   >> 5418                         ret = call(xset.format('s off'), shell=True)
                                                   >> 5419         elif cmd == 'reset':
                                                   >> 5420                 ret = call(xset.format('s reset'), shell=True)
                                                   >> 5421         elif cmd in ['on', 'off', 'standby', 'suspend']:
                                                   >> 5422                 b4 = displayControl('stat')
                                                   >> 5423                 ret = call(xset.format('dpms force %s' % cmd), shell=True)
                                                   >> 5424                 if not ret:
                                                   >> 5425                         curr = displayControl('stat')
                                                   >> 5426                         sysvals.vprint('Display Switched: %s -> %s' % (b4, curr))
                                                   >> 5427                         if curr != cmd:
                                                   >> 5428                                 sysvals.vprint('WARNING: Display failed to change to %s' % cmd)
                                                   >> 5429                 if ret:
                                                   >> 5430                         sysvals.vprint('WARNING: Display failed to change to %s with xset' % cmd)
                                                   >> 5431                         return ret
                                                   >> 5432         elif cmd == 'stat':
                                                   >> 5433                 fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout
                                                   >> 5434                 ret = 'unknown'
                                                   >> 5435                 for line in fp:
                                                   >> 5436                         m = re.match('[\s]*Monitor is (?P<m>.*)', line)
                                                   >> 5437                         if(m and len(m.group('m')) >= 2):
                                                   >> 5438                                 out = m.group('m').lower()
                                                   >> 5439                                 ret = out[3:] if out[0:2] == 'in' else out
                                                   >> 5440                                 break
                                                   >> 5441                 fp.close()
                                                   >> 5442         return ret
                                                   >> 5443 
5847 # Function: getFPDT                              5444 # Function: getFPDT
5848 # Description:                                   5445 # Description:
5849 #        Read the acpi bios tables and pull o    5446 #        Read the acpi bios tables and pull out FPDT, the firmware data
5850 # Arguments:                                     5447 # Arguments:
5851 #        output: True to output the info to s    5448 #        output: True to output the info to stdout, False otherwise
5852 def getFPDT(output):                             5449 def getFPDT(output):
5853         rectype = {}                             5450         rectype = {}
5854         rectype[0] = 'Firmware Basic Boot Per    5451         rectype[0] = 'Firmware Basic Boot Performance Record'
5855         rectype[1] = 'S3 Performance Table Re    5452         rectype[1] = 'S3 Performance Table Record'
5856         prectype = {}                            5453         prectype = {}
5857         prectype[0] = 'Basic S3 Resume Perfor    5454         prectype[0] = 'Basic S3 Resume Performance Record'
5858         prectype[1] = 'Basic S3 Suspend Perfo    5455         prectype[1] = 'Basic S3 Suspend Performance Record'
5859                                                  5456 
5860         sysvals.rootCheck(True)                  5457         sysvals.rootCheck(True)
5861         if(not os.path.exists(sysvals.fpdtpat    5458         if(not os.path.exists(sysvals.fpdtpath)):
5862                 if(output):                      5459                 if(output):
5863                         doError('file does no    5460                         doError('file does not exist: %s' % sysvals.fpdtpath)
5864                 return False                     5461                 return False
5865         if(not os.access(sysvals.fpdtpath, os    5462         if(not os.access(sysvals.fpdtpath, os.R_OK)):
5866                 if(output):                      5463                 if(output):
5867                         doError('file is not     5464                         doError('file is not readable: %s' % sysvals.fpdtpath)
5868                 return False                     5465                 return False
5869         if(not os.path.exists(sysvals.mempath    5466         if(not os.path.exists(sysvals.mempath)):
5870                 if(output):                      5467                 if(output):
5871                         doError('file does no    5468                         doError('file does not exist: %s' % sysvals.mempath)
5872                 return False                     5469                 return False
5873         if(not os.access(sysvals.mempath, os.    5470         if(not os.access(sysvals.mempath, os.R_OK)):
5874                 if(output):                      5471                 if(output):
5875                         doError('file is not     5472                         doError('file is not readable: %s' % sysvals.mempath)
5876                 return False                     5473                 return False
5877                                                  5474 
5878         fp = open(sysvals.fpdtpath, 'rb')        5475         fp = open(sysvals.fpdtpath, 'rb')
5879         buf = fp.read()                          5476         buf = fp.read()
5880         fp.close()                               5477         fp.close()
5881                                                  5478 
5882         if(len(buf) < 36):                       5479         if(len(buf) < 36):
5883                 if(output):                      5480                 if(output):
5884                         doError('Invalid FPDT    5481                         doError('Invalid FPDT table data, should '+\
5885                                 'be at least     5482                                 'be at least 36 bytes')
5886                 return False                     5483                 return False
5887                                                  5484 
5888         table = struct.unpack('4sIBB6s8sI4sI'    5485         table = struct.unpack('4sIBB6s8sI4sI', buf[0:36])
5889         if(output):                              5486         if(output):
5890                 pprint('\n'\                     5487                 pprint('\n'\
5891                 'Firmware Performance Data Ta    5488                 'Firmware Performance Data Table (%s)\n'\
5892                 '                  Signature     5489                 '                  Signature : %s\n'\
5893                 '               Table Length     5490                 '               Table Length : %u\n'\
5894                 '                   Revision     5491                 '                   Revision : %u\n'\
5895                 '                   Checksum     5492                 '                   Checksum : 0x%x\n'\
5896                 '                     OEM ID     5493                 '                     OEM ID : %s\n'\
5897                 '               OEM Table ID     5494                 '               OEM Table ID : %s\n'\
5898                 '               OEM Revision     5495                 '               OEM Revision : %u\n'\
5899                 '                 Creator ID     5496                 '                 Creator ID : %s\n'\
5900                 '           Creator Revision     5497                 '           Creator Revision : 0x%x\n'\
5901                 '' % (ascii(table[0]), ascii( !! 5498                 '' % (table[0], table[0], table[1], table[2], table[3],
5902                         table[3], ascii(table !! 5499                         table[4], table[5], table[6], table[7], table[8]))
5903                         ascii(table[7]), tabl << 
5904                                                  5500 
5905         if(table[0] != b'FPDT'):              !! 5501         if(table[0] != 'FPDT'):
5906                 if(output):                      5502                 if(output):
5907                         doError('Invalid FPDT    5503                         doError('Invalid FPDT table')
5908                 return False                     5504                 return False
5909         if(len(buf) <= 36):                      5505         if(len(buf) <= 36):
5910                 return False                     5506                 return False
5911         i = 0                                    5507         i = 0
5912         fwData = [0, 0]                          5508         fwData = [0, 0]
5913         records = buf[36:]                       5509         records = buf[36:]
5914         try:                                     5510         try:
5915                 fp = open(sysvals.mempath, 'r    5511                 fp = open(sysvals.mempath, 'rb')
5916         except:                                  5512         except:
5917                 pprint('WARNING: /dev/mem is     5513                 pprint('WARNING: /dev/mem is not readable, ignoring the FPDT data')
5918                 return False                     5514                 return False
5919         while(i < len(records)):                 5515         while(i < len(records)):
5920                 header = struct.unpack('HBB',    5516                 header = struct.unpack('HBB', records[i:i+4])
5921                 if(header[0] not in rectype):    5517                 if(header[0] not in rectype):
5922                         i += header[1]           5518                         i += header[1]
5923                         continue                 5519                         continue
5924                 if(header[1] != 16):             5520                 if(header[1] != 16):
5925                         i += header[1]           5521                         i += header[1]
5926                         continue                 5522                         continue
5927                 addr = struct.unpack('Q', rec    5523                 addr = struct.unpack('Q', records[i+8:i+16])[0]
5928                 try:                             5524                 try:
5929                         fp.seek(addr)            5525                         fp.seek(addr)
5930                         first = fp.read(8)       5526                         first = fp.read(8)
5931                 except:                          5527                 except:
5932                         if(output):              5528                         if(output):
5933                                 pprint('Bad a    5529                                 pprint('Bad address 0x%x in %s' % (addr, sysvals.mempath))
5934                         return [0, 0]            5530                         return [0, 0]
5935                 rechead = struct.unpack('4sI'    5531                 rechead = struct.unpack('4sI', first)
5936                 recdata = fp.read(rechead[1]-    5532                 recdata = fp.read(rechead[1]-8)
5937                 if(rechead[0] == b'FBPT'):    !! 5533                 if(rechead[0] == 'FBPT'):
5938                         record = struct.unpac !! 5534                         record = struct.unpack('HBBIQQQQQ', recdata)
5939                         if(output):              5535                         if(output):
5940                                 pprint('%s (%    5536                                 pprint('%s (%s)\n'\
5941                                 '                5537                                 '                  Reset END : %u ns\n'\
5942                                 '  OS Loader     5538                                 '  OS Loader LoadImage Start : %u ns\n'\
5943                                 ' OS Loader S    5539                                 ' OS Loader StartImage Start : %u ns\n'\
5944                                 '     ExitBoo    5540                                 '     ExitBootServices Entry : %u ns\n'\
5945                                 '      ExitBo    5541                                 '      ExitBootServices Exit : %u ns'\
5946                                 '' % (rectype !! 5542                                 '' % (rectype[header[0]], rechead[0], record[4], record[5],
5947                                         recor    5543                                         record[6], record[7], record[8]))
5948                 elif(rechead[0] == b'S3PT'):  !! 5544                 elif(rechead[0] == 'S3PT'):
5949                         if(output):              5545                         if(output):
5950                                 pprint('%s (% !! 5546                                 pprint('%s (%s)' % (rectype[header[0]], rechead[0]))
5951                         j = 0                    5547                         j = 0
5952                         while(j < len(recdata    5548                         while(j < len(recdata)):
5953                                 prechead = st    5549                                 prechead = struct.unpack('HBB', recdata[j:j+4])
5954                                 if(prechead[0    5550                                 if(prechead[0] not in prectype):
5955                                         conti    5551                                         continue
5956                                 if(prechead[0    5552                                 if(prechead[0] == 0):
5957                                         recor    5553                                         record = struct.unpack('IIQQ', recdata[j:j+prechead[1]])
5958                                         fwDat    5554                                         fwData[1] = record[2]
5959                                         if(ou    5555                                         if(output):
5960                                                  5556                                                 pprint('    %s\n'\
5961                                                  5557                                                 '               Resume Count : %u\n'\
5962                                                  5558                                                 '                 FullResume : %u ns\n'\
5963                                                  5559                                                 '              AverageResume : %u ns'\
5964                                                  5560                                                 '' % (prectype[prechead[0]], record[1],
5965                                                  5561                                                                 record[2], record[3]))
5966                                 elif(prechead    5562                                 elif(prechead[0] == 1):
5967                                         recor    5563                                         record = struct.unpack('QQ', recdata[j+4:j+prechead[1]])
5968                                         fwDat    5564                                         fwData[0] = record[1] - record[0]
5969                                         if(ou    5565                                         if(output):
5970                                                  5566                                                 pprint('    %s\n'\
5971                                                  5567                                                 '               SuspendStart : %u ns\n'\
5972                                                  5568                                                 '                 SuspendEnd : %u ns\n'\
5973                                                  5569                                                 '                SuspendTime : %u ns'\
5974                                                  5570                                                 '' % (prectype[prechead[0]], record[0],
5975                                                  5571                                                                 record[1], fwData[0]))
5976                                                  5572 
5977                                 j += prechead    5573                                 j += prechead[1]
5978                 if(output):                      5574                 if(output):
5979                         pprint('')               5575                         pprint('')
5980                 i += header[1]                   5576                 i += header[1]
5981         fp.close()                               5577         fp.close()
5982         return fwData                            5578         return fwData
5983                                                  5579 
5984 # Function: statusCheck                          5580 # Function: statusCheck
5985 # Description:                                   5581 # Description:
5986 #        Verify that the requested command an    5582 #        Verify that the requested command and options will work, and
5987 #        print the results to the terminal       5583 #        print the results to the terminal
5988 # Output:                                        5584 # Output:
5989 #        True if the test will work, False if    5585 #        True if the test will work, False if not
5990 def statusCheck(probecheck=False):               5586 def statusCheck(probecheck=False):
5991         status = ''                              5587         status = ''
5992                                                  5588 
5993         pprint('Checking this system (%s)...'    5589         pprint('Checking this system (%s)...' % platform.node())
5994                                                  5590 
5995         # check we have root access              5591         # check we have root access
5996         res = sysvals.colorText('NO (No featu    5592         res = sysvals.colorText('NO (No features of this tool will work!)')
5997         if(sysvals.rootCheck(False)):            5593         if(sysvals.rootCheck(False)):
5998                 res = 'YES'                      5594                 res = 'YES'
5999         pprint('    have root access: %s' % r    5595         pprint('    have root access: %s' % res)
6000         if(res != 'YES'):                        5596         if(res != 'YES'):
6001                 pprint('    Try running this     5597                 pprint('    Try running this script with sudo')
6002                 return 'missing root access'     5598                 return 'missing root access'
6003                                                  5599 
6004         # check sysfs is mounted                 5600         # check sysfs is mounted
6005         res = sysvals.colorText('NO (No featu    5601         res = sysvals.colorText('NO (No features of this tool will work!)')
6006         if(os.path.exists(sysvals.powerfile))    5602         if(os.path.exists(sysvals.powerfile)):
6007                 res = 'YES'                      5603                 res = 'YES'
6008         pprint('    is sysfs mounted: %s' % r    5604         pprint('    is sysfs mounted: %s' % res)
6009         if(res != 'YES'):                        5605         if(res != 'YES'):
6010                 return 'sysfs is missing'        5606                 return 'sysfs is missing'
6011                                                  5607 
6012         # check target mode is a valid mode      5608         # check target mode is a valid mode
6013         if sysvals.suspendmode != 'command':     5609         if sysvals.suspendmode != 'command':
6014                 res = sysvals.colorText('NO')    5610                 res = sysvals.colorText('NO')
6015                 modes = getModes()               5611                 modes = getModes()
6016                 if(sysvals.suspendmode in mod    5612                 if(sysvals.suspendmode in modes):
6017                         res = 'YES'              5613                         res = 'YES'
6018                 else:                            5614                 else:
6019                         status = '%s mode is     5615                         status = '%s mode is not supported' % sysvals.suspendmode
6020                 pprint('    is "%s" a valid p    5616                 pprint('    is "%s" a valid power mode: %s' % (sysvals.suspendmode, res))
6021                 if(res == 'NO'):                 5617                 if(res == 'NO'):
6022                         pprint('      valid p    5618                         pprint('      valid power modes are: %s' % modes)
6023                         pprint('      please     5619                         pprint('      please choose one with -m')
6024                                                  5620 
6025         # check if ftrace is available           5621         # check if ftrace is available
6026         if sysvals.useftrace:                 !! 5622         res = sysvals.colorText('NO')
6027                 res = sysvals.colorText('NO') !! 5623         ftgood = sysvals.verifyFtrace()
6028                 sysvals.useftrace = sysvals.v !! 5624         if(ftgood):
6029                 efmt = '"{0}" uses ftrace, an !! 5625                 res = 'YES'
6030                 if sysvals.useftrace:         !! 5626         elif(sysvals.usecallgraph):
6031                         res = 'YES'           !! 5627                 status = 'ftrace is not properly supported'
6032                 elif sysvals.usecallgraph:    !! 5628         pprint('    is ftrace supported: %s' % res)
6033                         status = efmt.format( << 
6034                 elif sysvals.usedevsrc:       << 
6035                         status = efmt.format( << 
6036                 elif sysvals.useprocmon:      << 
6037                         status = efmt.format( << 
6038                 pprint('    is ftrace support << 
6039                                                  5629 
6040         # check if kprobes are available         5630         # check if kprobes are available
6041         if sysvals.usekprobes:                   5631         if sysvals.usekprobes:
6042                 res = sysvals.colorText('NO')    5632                 res = sysvals.colorText('NO')
6043                 sysvals.usekprobes = sysvals.    5633                 sysvals.usekprobes = sysvals.verifyKprobes()
6044                 if(sysvals.usekprobes):          5634                 if(sysvals.usekprobes):
6045                         res = 'YES'              5635                         res = 'YES'
6046                 else:                            5636                 else:
6047                         sysvals.usedevsrc = F    5637                         sysvals.usedevsrc = False
6048                 pprint('    are kprobes suppo    5638                 pprint('    are kprobes supported: %s' % res)
6049                                                  5639 
6050         # what data source are we using          5640         # what data source are we using
6051         res = 'DMESG (very limited, ftrace is !! 5641         res = 'DMESG'
6052         if sysvals.useftrace:                 !! 5642         if(ftgood):
6053                 sysvals.usetraceevents = True    5643                 sysvals.usetraceevents = True
6054                 for e in sysvals.traceevents:    5644                 for e in sysvals.traceevents:
6055                         if not os.path.exists    5645                         if not os.path.exists(sysvals.epath+e):
6056                                 sysvals.usetr    5646                                 sysvals.usetraceevents = False
6057                 if(sysvals.usetraceevents):      5647                 if(sysvals.usetraceevents):
6058                         res = 'FTRACE (all tr    5648                         res = 'FTRACE (all trace events found)'
6059         pprint('    timeline data source: %s'    5649         pprint('    timeline data source: %s' % res)
6060                                                  5650 
6061         # check if rtcwake                       5651         # check if rtcwake
6062         res = sysvals.colorText('NO')            5652         res = sysvals.colorText('NO')
6063         if(sysvals.rtcpath != ''):               5653         if(sysvals.rtcpath != ''):
6064                 res = 'YES'                      5654                 res = 'YES'
6065         elif(sysvals.rtcwake):                   5655         elif(sysvals.rtcwake):
6066                 status = 'rtcwake is not prop    5656                 status = 'rtcwake is not properly supported'
6067         pprint('    is rtcwake supported: %s'    5657         pprint('    is rtcwake supported: %s' % res)
6068                                                  5658 
6069         # check info commands                 << 
6070         pprint('    optional commands this to << 
6071         no = sysvals.colorText('MISSING')     << 
6072         yes = sysvals.colorText('FOUND', 32)  << 
6073         for c in ['turbostat', 'mcelog', 'lsp << 
6074                 if c == 'turbostat':          << 
6075                         res = yes if sysvals. << 
6076                 else:                         << 
6077                         res = yes if sysvals. << 
6078                 pprint('        %s: %s' % (c, << 
6079                                               << 
6080         if not probecheck:                       5659         if not probecheck:
6081                 return status                    5660                 return status
6082                                                  5661 
6083         # verify kprobes                         5662         # verify kprobes
6084         if sysvals.usekprobes:                   5663         if sysvals.usekprobes:
6085                 for name in sysvals.tracefunc    5664                 for name in sysvals.tracefuncs:
6086                         sysvals.defaultKprobe    5665                         sysvals.defaultKprobe(name, sysvals.tracefuncs[name])
6087                 if sysvals.usedevsrc:            5666                 if sysvals.usedevsrc:
6088                         for name in sysvals.d    5667                         for name in sysvals.dev_tracefuncs:
6089                                 sysvals.defau    5668                                 sysvals.defaultKprobe(name, sysvals.dev_tracefuncs[name])
6090                 sysvals.addKprobes(True)         5669                 sysvals.addKprobes(True)
6091                                                  5670 
6092         return status                            5671         return status
6093                                                  5672 
6094 # Function: doError                              5673 # Function: doError
6095 # Description:                                   5674 # Description:
6096 #        generic error function for catastrph    5675 #        generic error function for catastrphic failures
6097 # Arguments:                                     5676 # Arguments:
6098 #        msg: the error message to print         5677 #        msg: the error message to print
6099 #        help: True if printHelp should be ca    5678 #        help: True if printHelp should be called after, False otherwise
6100 def doError(msg, help=False):                    5679 def doError(msg, help=False):
6101         if(help == True):                        5680         if(help == True):
6102                 printHelp()                      5681                 printHelp()
6103         pprint('ERROR: %s\n' % msg)              5682         pprint('ERROR: %s\n' % msg)
6104         sysvals.outputResult({'error':msg})      5683         sysvals.outputResult({'error':msg})
6105         sys.exit(1)                              5684         sys.exit(1)
6106                                                  5685 
6107 # Function: getArgInt                            5686 # Function: getArgInt
6108 # Description:                                   5687 # Description:
6109 #        pull out an integer argument from th    5688 #        pull out an integer argument from the command line with checks
6110 def getArgInt(name, args, min, max, main=True    5689 def getArgInt(name, args, min, max, main=True):
6111         if main:                                 5690         if main:
6112                 try:                             5691                 try:
6113                         arg = next(args)      !! 5692                         arg = args.next()
6114                 except:                          5693                 except:
6115                         doError(name+': no ar    5694                         doError(name+': no argument supplied', True)
6116         else:                                    5695         else:
6117                 arg = args                       5696                 arg = args
6118         try:                                     5697         try:
6119                 val = int(arg)                   5698                 val = int(arg)
6120         except:                                  5699         except:
6121                 doError(name+': non-integer v    5700                 doError(name+': non-integer value given', True)
6122         if(val < min or val > max):              5701         if(val < min or val > max):
6123                 doError(name+': value should     5702                 doError(name+': value should be between %d and %d' % (min, max), True)
6124         return val                               5703         return val
6125                                                  5704 
6126 # Function: getArgFloat                          5705 # Function: getArgFloat
6127 # Description:                                   5706 # Description:
6128 #        pull out a float argument from the c    5707 #        pull out a float argument from the command line with checks
6129 def getArgFloat(name, args, min, max, main=Tr    5708 def getArgFloat(name, args, min, max, main=True):
6130         if main:                                 5709         if main:
6131                 try:                             5710                 try:
6132                         arg = next(args)      !! 5711                         arg = args.next()
6133                 except:                          5712                 except:
6134                         doError(name+': no ar    5713                         doError(name+': no argument supplied', True)
6135         else:                                    5714         else:
6136                 arg = args                       5715                 arg = args
6137         try:                                     5716         try:
6138                 val = float(arg)                 5717                 val = float(arg)
6139         except:                                  5718         except:
6140                 doError(name+': non-numerical    5719                 doError(name+': non-numerical value given', True)
6141         if(val < min or val > max):              5720         if(val < min or val > max):
6142                 doError(name+': value should     5721                 doError(name+': value should be between %f and %f' % (min, max), True)
6143         return val                               5722         return val
6144                                                  5723 
6145 def processData(live=False, quiet=False):     !! 5724 def processData(live=False):
6146         if not quiet:                         !! 5725         pprint('PROCESSING DATA')
6147                 pprint('PROCESSING: %s' % sys << 
6148         sysvals.vprint('usetraceevents=%s, us    5726         sysvals.vprint('usetraceevents=%s, usetracemarkers=%s, usekprobes=%s' % \
6149                 (sysvals.usetraceevents, sysv    5727                 (sysvals.usetraceevents, sysvals.usetracemarkers, sysvals.usekprobes))
6150         error = ''                               5728         error = ''
6151         if(sysvals.usetraceevents):              5729         if(sysvals.usetraceevents):
6152                 testruns, error = parseTraceL    5730                 testruns, error = parseTraceLog(live)
6153                 if sysvals.dmesgfile:            5731                 if sysvals.dmesgfile:
6154                         for data in testruns:    5732                         for data in testruns:
6155                                 data.extractE    5733                                 data.extractErrorInfo()
6156         else:                                    5734         else:
6157                 testruns = loadKernelLog()       5735                 testruns = loadKernelLog()
6158                 for data in testruns:            5736                 for data in testruns:
6159                         parseKernelLog(data)     5737                         parseKernelLog(data)
6160                 if(sysvals.ftracefile and (sy    5738                 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)):
6161                         appendIncompleteTrace    5739                         appendIncompleteTraceLog(testruns)
6162         if not sysvals.stamp:                 << 
6163                 pprint('ERROR: data does not  << 
6164                 return (testruns, {'error': ' << 
6165         shown = ['os', 'bios', 'biosdate', 'c << 
6166                         'memsz', 'mode', 'num << 
6167         sysvals.vprint('System Info:')           5740         sysvals.vprint('System Info:')
6168         for key in sorted(sysvals.stamp):        5741         for key in sorted(sysvals.stamp):
6169                 if key in shown:              !! 5742                 sysvals.vprint('    %-8s : %s' % (key.upper(), sysvals.stamp[key]))
6170                         sysvals.vprint('    % !! 5743         if sysvals.kparams:
                                                   >> 5744                 sysvals.vprint('Kparams:\n    %s' % sysvals.kparams)
6171         sysvals.vprint('Command:\n    %s' % s    5745         sysvals.vprint('Command:\n    %s' % sysvals.cmdline)
6172         for data in testruns:                    5746         for data in testruns:
                                                   >> 5747                 if data.mcelog:
                                                   >> 5748                         sysvals.vprint('MCELOG Data:')
                                                   >> 5749                         for line in data.mcelog.split('\n'):
                                                   >> 5750                                 sysvals.vprint('    %s' % line)
6173                 if data.turbostat:               5751                 if data.turbostat:
6174                         idx, s = 0, 'Turbosta    5752                         idx, s = 0, 'Turbostat:\n    '
6175                         for val in data.turbo    5753                         for val in data.turbostat.split('|'):
6176                                 idx += len(va    5754                                 idx += len(val) + 1
6177                                 if idx >= 80:    5755                                 if idx >= 80:
6178                                         idx =    5756                                         idx = 0
6179                                         s +=     5757                                         s += '\n    '
6180                                 s += val + '     5758                                 s += val + ' '
6181                         sysvals.vprint(s)        5759                         sysvals.vprint(s)
                                                   >> 5760                 if data.battery:
                                                   >> 5761                         a1, c1, a2, c2 = data.battery
                                                   >> 5762                         s = 'Battery:\n    Before - AC: %s, Charge: %d\n     After - AC: %s, Charge: %d' % \
                                                   >> 5763                                 (a1, int(c1), a2, int(c2))
                                                   >> 5764                         sysvals.vprint(s)
                                                   >> 5765                 if data.wifi:
                                                   >> 5766                         w = data.wifi.replace('|', ' ').split(',')
                                                   >> 5767                         s = 'Wifi:\n    Before %s\n     After %s' % \
                                                   >> 5768                                 (w[0], w[1])
                                                   >> 5769                         sysvals.vprint(s)
6182                 data.printDetails()              5770                 data.printDetails()
6183         if len(sysvals.platinfo) > 0:         << 
6184                 sysvals.vprint('\nPlatform In << 
6185                 for info in sysvals.platinfo: << 
6186                         sysvals.vprint('[%s - << 
6187                         sysvals.vprint(info[2 << 
6188                 sysvals.vprint('')            << 
6189         if sysvals.cgdump:                       5771         if sysvals.cgdump:
6190                 for data in testruns:            5772                 for data in testruns:
6191                         data.debugPrint()        5773                         data.debugPrint()
6192                 sys.exit(0)                      5774                 sys.exit(0)
6193         if len(testruns) < 1:                    5775         if len(testruns) < 1:
6194                 pprint('ERROR: Not enough tes    5776                 pprint('ERROR: Not enough test data to build a timeline')
6195                 return (testruns, {'error': '    5777                 return (testruns, {'error': 'timeline generation failed'})
6196         sysvals.vprint('Creating the html tim    5778         sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile)
6197         createHTML(testruns, error)              5779         createHTML(testruns, error)
6198         if not quiet:                         !! 5780         pprint('DONE')
6199                 pprint('DONE:       %s' % sys << 
6200         data = testruns[0]                       5781         data = testruns[0]
6201         stamp = data.stamp                       5782         stamp = data.stamp
6202         stamp['suspend'], stamp['resume'] = d    5783         stamp['suspend'], stamp['resume'] = data.getTimeValues()
6203         if data.fwValid:                         5784         if data.fwValid:
6204                 stamp['fwsuspend'], stamp['fw    5785                 stamp['fwsuspend'], stamp['fwresume'] = data.fwSuspend, data.fwResume
6205         if error:                                5786         if error:
6206                 stamp['error'] = error           5787                 stamp['error'] = error
6207         return (testruns, stamp)                 5788         return (testruns, stamp)
6208                                                  5789 
6209 # Function: rerunTest                            5790 # Function: rerunTest
6210 # Description:                                   5791 # Description:
6211 #        generate an output from an existing     5792 #        generate an output from an existing set of ftrace/dmesg logs
6212 def rerunTest(htmlfile=''):                      5793 def rerunTest(htmlfile=''):
6213         if sysvals.ftracefile:                   5794         if sysvals.ftracefile:
6214                 doesTraceLogHaveTraceEvents()    5795                 doesTraceLogHaveTraceEvents()
6215         if not sysvals.dmesgfile and not sysv    5796         if not sysvals.dmesgfile and not sysvals.usetraceevents:
6216                 doError('recreating this html    5797                 doError('recreating this html output requires a dmesg file')
6217         if htmlfile:                             5798         if htmlfile:
6218                 sysvals.htmlfile = htmlfile      5799                 sysvals.htmlfile = htmlfile
6219         else:                                    5800         else:
6220                 sysvals.setOutputFile()          5801                 sysvals.setOutputFile()
6221         if os.path.exists(sysvals.htmlfile):     5802         if os.path.exists(sysvals.htmlfile):
6222                 if not os.path.isfile(sysvals    5803                 if not os.path.isfile(sysvals.htmlfile):
6223                         doError('a directory     5804                         doError('a directory already exists with this name: %s' % sysvals.htmlfile)
6224                 elif not os.access(sysvals.ht    5805                 elif not os.access(sysvals.htmlfile, os.W_OK):
6225                         doError('missing perm    5806                         doError('missing permission to write to %s' % sysvals.htmlfile)
6226         testruns, stamp = processData()       !! 5807         testruns, stamp = processData(False)
6227         sysvals.resetlog()                    !! 5808         sysvals.logmsg = ''
6228         return stamp                             5809         return stamp
6229                                                  5810 
6230 # Function: runTest                              5811 # Function: runTest
6231 # Description:                                   5812 # Description:
6232 #        execute a suspend/resume, gather the    5813 #        execute a suspend/resume, gather the logs, and generate the output
6233 def runTest(n=0, quiet=False):                !! 5814 def runTest(n=0):
6234         # prepare for the test                   5815         # prepare for the test
                                                   >> 5816         sysvals.initFtrace()
6235         sysvals.initTestOutput('suspend')        5817         sysvals.initTestOutput('suspend')
6236         op = sysvals.writeDatafileHeader(sysv << 
6237         op.write('# EXECUTION TRACE START\n') << 
6238         op.close()                            << 
6239         if n <= 1:                            << 
6240                 if sysvals.rs != 0:           << 
6241                         sysvals.dlog('%sablin << 
6242                         sysvals.setRuntimeSus << 
6243                 if sysvals.display:           << 
6244                         ret = sysvals.display << 
6245                         sysvals.dlog('xset di << 
6246         sysvals.testVal(sysvals.pmdpath, 'bas << 
6247         sysvals.testVal(sysvals.s0ixpath, 'ba << 
6248         sysvals.dlog('initialize ftrace')     << 
6249         sysvals.initFtrace(quiet)             << 
6250                                                  5818 
6251         # execute the test                       5819         # execute the test
6252         executeSuspend(quiet)                 !! 5820         testdata = executeSuspend()
6253         sysvals.cleanupFtrace()                  5821         sysvals.cleanupFtrace()
6254         if sysvals.skiphtml:                     5822         if sysvals.skiphtml:
6255                 sysvals.outputResult({}, n)   << 
6256                 sysvals.sudoUserchown(sysvals    5823                 sysvals.sudoUserchown(sysvals.testdir)
6257                 return                           5824                 return
6258         testruns, stamp = processData(True, q !! 5825         if not testdata[0]['error']:
6259         for data in testruns:                 !! 5826                 testruns, stamp = processData(True)
6260                 del data                      !! 5827                 for data in testruns:
                                                   >> 5828                         del data
                                                   >> 5829         else:
                                                   >> 5830                 stamp = testdata[0]
                                                   >> 5831 
6261         sysvals.sudoUserchown(sysvals.testdir    5832         sysvals.sudoUserchown(sysvals.testdir)
6262         sysvals.outputResult(stamp, n)           5833         sysvals.outputResult(stamp, n)
6263         if 'error' in stamp:                     5834         if 'error' in stamp:
6264                 return 2                         5835                 return 2
6265         return 0                                 5836         return 0
6266                                                  5837 
6267 def find_in_html(html, start, end, firstonly=    5838 def find_in_html(html, start, end, firstonly=True):
6268         cnt, out, list = len(html), [], []    !! 5839         n, out = 0, []
6269         if firstonly:                         !! 5840         while n < len(html):
6270                 m = re.search(start, html)    !! 5841                 m = re.search(start, html[n:])
6271                 if m:                         << 
6272                         list.append(m)        << 
6273         else:                                 << 
6274                 list = re.finditer(start, htm << 
6275         for match in list:                    << 
6276                 s = match.end()               << 
6277                 e = cnt if (len(out) < 1 or s << 
6278                 m = re.search(end, html[s:e]) << 
6279                 if not m:                        5842                 if not m:
6280                         break                    5843                         break
6281                 e = s + m.start()             !! 5844                 i = m.end()
6282                 str = html[s:e]               !! 5845                 m = re.search(end, html[n+i:])
                                                   >> 5846                 if not m:
                                                   >> 5847                         break
                                                   >> 5848                 j = m.start()
                                                   >> 5849                 str = html[n+i:n+i+j]
6283                 if end == 'ms':                  5850                 if end == 'ms':
6284                         num = re.search(r'[-+    5851                         num = re.search(r'[-+]?\d*\.\d+|\d+', str)
6285                         str = num.group() if     5852                         str = num.group() if num else 'NaN'
6286                 if firstonly:                    5853                 if firstonly:
6287                         return str               5854                         return str
6288                 out.append(str)                  5855                 out.append(str)
                                                   >> 5856                 n += i+j
6289         if firstonly:                            5857         if firstonly:
6290                 return ''                        5858                 return ''
6291         return out                               5859         return out
6292                                                  5860 
6293 def data_from_html(file, outpath, issues, ful    5861 def data_from_html(file, outpath, issues, fulldetail=False):
6294         try:                                  !! 5862         html = open(file, 'r').read()
6295                 html = open(file, 'r').read() << 
6296         except:                               << 
6297                 html = ascii(open(file, 'rb') << 
6298         sysvals.htmlfile = os.path.relpath(fi    5863         sysvals.htmlfile = os.path.relpath(file, outpath)
6299         # extract general info                   5864         # extract general info
6300         suspend = find_in_html(html, 'Kernel     5865         suspend = find_in_html(html, 'Kernel Suspend', 'ms')
6301         resume = find_in_html(html, 'Kernel R    5866         resume = find_in_html(html, 'Kernel Resume', 'ms')
6302         sysinfo = find_in_html(html, '<div cl    5867         sysinfo = find_in_html(html, '<div class="stamp sysinfo">', '</div>')
6303         line = find_in_html(html, '<div class    5868         line = find_in_html(html, '<div class="stamp">', '</div>')
6304         stmp = line.split()                      5869         stmp = line.split()
6305         if not suspend or not resume or len(s    5870         if not suspend or not resume or len(stmp) != 8:
6306                 return False                     5871                 return False
6307         try:                                     5872         try:
6308                 dt = datetime.strptime(' '.jo    5873                 dt = datetime.strptime(' '.join(stmp[3:]), '%B %d %Y, %I:%M:%S %p')
6309         except:                                  5874         except:
6310                 return False                     5875                 return False
6311         sysvals.hostname = stmp[0]               5876         sysvals.hostname = stmp[0]
6312         tstr = dt.strftime('%Y/%m/%d %H:%M:%S    5877         tstr = dt.strftime('%Y/%m/%d %H:%M:%S')
6313         error = find_in_html(html, '<table cl    5878         error = find_in_html(html, '<table class="testfail"><tr><td>', '</td>')
6314         if error:                                5879         if error:
6315                 m = re.match(r'[a-z0-9]* fail !! 5880                 m = re.match('[a-z]* failed in (?P<p>[a-z0-9_]*) phase', error)
6316                 if m:                            5881                 if m:
6317                         result = 'fail in %s'    5882                         result = 'fail in %s' % m.group('p')
6318                 else:                            5883                 else:
6319                         result = 'fail'          5884                         result = 'fail'
6320         else:                                    5885         else:
6321                 result = 'pass'                  5886                 result = 'pass'
6322         # extract error info                     5887         # extract error info
6323         tp, ilist = False, []                 !! 5888         ilist = []
6324         extra = dict()                           5889         extra = dict()
6325         log = find_in_html(html, '<div id="dm    5890         log = find_in_html(html, '<div id="dmesglog" style="display:none;">',
6326                 '</div>').strip()                5891                 '</div>').strip()
6327         if log:                                  5892         if log:
6328                 d = Data(0)                      5893                 d = Data(0)
6329                 d.end = 999999999                5894                 d.end = 999999999
6330                 d.dmesgtext = log.split('\n')    5895                 d.dmesgtext = log.split('\n')
6331                 tp = d.extractErrorInfo()     !! 5896                 msglist = d.extractErrorInfo()
6332                 if len(issues) < 100:         !! 5897                 for msg in msglist:
6333                         for msg in tp.msglist !! 5898                         sysvals.errorSummary(issues, msg)
6334                                 sysvals.error << 
6335                 if stmp[2] == 'freeze':          5899                 if stmp[2] == 'freeze':
6336                         extra = d.turbostatIn    5900                         extra = d.turbostatInfo()
6337                 elist = dict()                   5901                 elist = dict()
6338                 for dir in d.errorinfo:          5902                 for dir in d.errorinfo:
6339                         for err in d.errorinf    5903                         for err in d.errorinfo[dir]:
6340                                 if err[0] not    5904                                 if err[0] not in elist:
6341                                         elist    5905                                         elist[err[0]] = 0
6342                                 elist[err[0]]    5906                                 elist[err[0]] += 1
6343                 for i in elist:                  5907                 for i in elist:
6344                         ilist.append('%sx%d'     5908                         ilist.append('%sx%d' % (i, elist[i]) if elist[i] > 1 else i)
6345                 line = find_in_html(log, '# w << 
6346                 if line:                      << 
6347                         extra['wifi'] = line  << 
6348                 line = find_in_html(log, '# n << 
6349                 if line:                      << 
6350                         extra['netfix'] = lin << 
6351                 line = find_in_html(log, '# c << 
6352                 if line:                      << 
6353                         m = re.match(r'.* -m  << 
6354                         if m:                 << 
6355                                 extra['fullmo << 
6356         low = find_in_html(html, 'freeze time    5909         low = find_in_html(html, 'freeze time: <b>', ' ms</b>')
6357         for lowstr in ['waking', '+']:        !! 5910         if low and '|' in low:
6358                 if not low:                   !! 5911                 issue = 'FREEZEx%d' % len(low.split('|'))
6359                         break                 << 
6360                 if lowstr not in low:         << 
6361                         continue              << 
6362                 if lowstr == '+':             << 
6363                         issue = 'S2LOOPx%d' % << 
6364                 else:                         << 
6365                         m = re.match(r'.*waki << 
6366                         issue = 'S2WAKEx%s' % << 
6367                 match = [i for i in issues if    5912                 match = [i for i in issues if i['match'] == issue]
6368                 if len(match) > 0:               5913                 if len(match) > 0:
6369                         match[0]['count'] +=     5914                         match[0]['count'] += 1
6370                         if sysvals.hostname n    5915                         if sysvals.hostname not in match[0]['urls']:
6371                                 match[0]['url    5916                                 match[0]['urls'][sysvals.hostname] = [sysvals.htmlfile]
6372                         elif sysvals.htmlfile    5917                         elif sysvals.htmlfile not in match[0]['urls'][sysvals.hostname]:
6373                                 match[0]['url    5918                                 match[0]['urls'][sysvals.hostname].append(sysvals.htmlfile)
6374                 else:                            5919                 else:
6375                         issues.append({          5920                         issues.append({
6376                                 'match': issu    5921                                 'match': issue, 'count': 1, 'line': issue,
6377                                 'urls': {sysv    5922                                 'urls': {sysvals.hostname: [sysvals.htmlfile]},
6378                         })                       5923                         })
6379                 ilist.append(issue)              5924                 ilist.append(issue)
6380         # extract device info                    5925         # extract device info
6381         devices = dict()                         5926         devices = dict()
6382         for line in html.split('\n'):            5927         for line in html.split('\n'):
6383                 m = re.match(r' *<div id=\"[a !! 5928                 m = re.match(' *<div id=\"[a,0-9]*\" *title=\"(?P<title>.*)\" class=\"thread.*', line)
6384                 if not m or 'thread kth' in l    5929                 if not m or 'thread kth' in line or 'thread sec' in line:
6385                         continue                 5930                         continue
6386                 m = re.match(r'(?P<n>.*) \((? !! 5931                 m = re.match('(?P<n>.*) \((?P<t>[0-9,\.]*) ms\) (?P<p>.*)', m.group('title'))
6387                 if not m:                        5932                 if not m:
6388                         continue                 5933                         continue
6389                 name, time, phase = m.group('    5934                 name, time, phase = m.group('n'), m.group('t'), m.group('p')
6390                 if name == 'async_synchronize << 
6391                         continue              << 
6392                 if ' async' in name or ' sync    5935                 if ' async' in name or ' sync' in name:
6393                         name = ' '.join(name.    5936                         name = ' '.join(name.split(' ')[:-1])
6394                 if phase.startswith('suspend'    5937                 if phase.startswith('suspend'):
6395                         d = 'suspend'            5938                         d = 'suspend'
6396                 elif phase.startswith('resume    5939                 elif phase.startswith('resume'):
6397                         d = 'resume'             5940                         d = 'resume'
6398                 else:                            5941                 else:
6399                         continue                 5942                         continue
6400                 if d not in devices:             5943                 if d not in devices:
6401                         devices[d] = dict()      5944                         devices[d] = dict()
6402                 if name not in devices[d]:       5945                 if name not in devices[d]:
6403                         devices[d][name] = 0.    5946                         devices[d][name] = 0.0
6404                 devices[d][name] += float(tim    5947                 devices[d][name] += float(time)
6405         # create worst device info               5948         # create worst device info
6406         worst = dict()                           5949         worst = dict()
6407         for d in ['suspend', 'resume']:          5950         for d in ['suspend', 'resume']:
6408                 worst[d] = {'name':'', 'time'    5951                 worst[d] = {'name':'', 'time': 0.0}
6409                 dev = devices[d] if d in devi    5952                 dev = devices[d] if d in devices else 0
6410                 if dev and len(dev.keys()) >     5953                 if dev and len(dev.keys()) > 0:
6411                         n = sorted(dev, key=l !! 5954                         n = sorted(dev, key=dev.get, reverse=True)[0]
6412                         worst[d]['name'], wor    5955                         worst[d]['name'], worst[d]['time'] = n, dev[n]
6413         data = {                                 5956         data = {
6414                 'mode': stmp[2],                 5957                 'mode': stmp[2],
6415                 'host': stmp[0],                 5958                 'host': stmp[0],
6416                 'kernel': stmp[1],               5959                 'kernel': stmp[1],
6417                 'sysinfo': sysinfo,              5960                 'sysinfo': sysinfo,
6418                 'time': tstr,                    5961                 'time': tstr,
6419                 'result': result,                5962                 'result': result,
6420                 'issues': ' '.join(ilist),       5963                 'issues': ' '.join(ilist),
6421                 'suspend': suspend,              5964                 'suspend': suspend,
6422                 'resume': resume,                5965                 'resume': resume,
6423                 'devlist': devices,              5966                 'devlist': devices,
6424                 'sus_worst': worst['suspend']    5967                 'sus_worst': worst['suspend']['name'],
6425                 'sus_worsttime': worst['suspe    5968                 'sus_worsttime': worst['suspend']['time'],
6426                 'res_worst': worst['resume'][    5969                 'res_worst': worst['resume']['name'],
6427                 'res_worsttime': worst['resum    5970                 'res_worsttime': worst['resume']['time'],
6428                 'url': sysvals.htmlfile,         5971                 'url': sysvals.htmlfile,
6429         }                                        5972         }
6430         for key in extra:                        5973         for key in extra:
6431                 data[key] = extra[key]           5974                 data[key] = extra[key]
6432         if fulldetail:                           5975         if fulldetail:
6433                 data['funclist'] = find_in_ht    5976                 data['funclist'] = find_in_html(html, '<div title="', '" class="traceevent"', False)
6434         if tp:                                << 
6435                 for arg in ['-multi ', '-info << 
6436                         if arg in tp.cmdline: << 
6437                                 data['target' << 
6438                                 break         << 
6439         return data                              5977         return data
6440                                                  5978 
6441 def genHtml(subdir, force=False):             !! 5979 def genHtml(subdir):
6442         for dirname, dirnames, filenames in o    5980         for dirname, dirnames, filenames in os.walk(subdir):
6443                 sysvals.dmesgfile = sysvals.f    5981                 sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = ''
6444                 for filename in filenames:       5982                 for filename in filenames:
6445                         file = os.path.join(d !! 5983                         if(re.match('.*_dmesg.txt', filename)):
6446                         if sysvals.usable(fil !! 5984                                 sysvals.dmesgfile = os.path.join(dirname, filename)
6447                                 if(re.match(r !! 5985                         elif(re.match('.*_ftrace.txt', filename)):
6448                                         sysva !! 5986                                 sysvals.ftracefile = os.path.join(dirname, filename)
6449                                 elif(re.match << 
6450                                         sysva << 
6451                 sysvals.setOutputFile()          5987                 sysvals.setOutputFile()
6452                 if (sysvals.dmesgfile or sysv !! 5988                 if sysvals.ftracefile and sysvals.htmlfile and \
6453                         (force or not sysvals !! 5989                         not os.path.exists(sysvals.htmlfile):
6454                         pprint('FTRACE: %s' %    5990                         pprint('FTRACE: %s' % sysvals.ftracefile)
6455                         if sysvals.dmesgfile:    5991                         if sysvals.dmesgfile:
6456                                 pprint('DMESG    5992                                 pprint('DMESG : %s' % sysvals.dmesgfile)
6457                         rerunTest()              5993                         rerunTest()
6458                                                  5994 
6459 # Function: runSummary                           5995 # Function: runSummary
6460 # Description:                                   5996 # Description:
6461 #        create a summary of tests in a sub-d    5997 #        create a summary of tests in a sub-directory
6462 def runSummary(subdir, local=True, genhtml=Fa    5998 def runSummary(subdir, local=True, genhtml=False):
6463         inpath = os.path.abspath(subdir)         5999         inpath = os.path.abspath(subdir)
6464         outpath = os.path.abspath('.') if loc    6000         outpath = os.path.abspath('.') if local else inpath
6465         pprint('Generating a summary of folde    6001         pprint('Generating a summary of folder:\n   %s' % inpath)
6466         if genhtml:                              6002         if genhtml:
6467                 genHtml(subdir)                  6003                 genHtml(subdir)
6468         target, issues, testruns = '', [], [] !! 6004         issues = []
                                                   >> 6005         testruns = []
6469         desc = {'host':[],'mode':[],'kernel':    6006         desc = {'host':[],'mode':[],'kernel':[]}
6470         for dirname, dirnames, filenames in o    6007         for dirname, dirnames, filenames in os.walk(subdir):
6471                 for filename in filenames:       6008                 for filename in filenames:
6472                         if(not re.match(r'.*. !! 6009                         if(not re.match('.*.html', filename)):
6473                                 continue         6010                                 continue
6474                         data = data_from_html    6011                         data = data_from_html(os.path.join(dirname, filename), outpath, issues)
6475                         if(not data):            6012                         if(not data):
6476                                 continue         6013                                 continue
6477                         if 'target' in data:  << 
6478                                 target = data << 
6479                         testruns.append(data)    6014                         testruns.append(data)
6480                         for key in desc:         6015                         for key in desc:
6481                                 if data[key]     6016                                 if data[key] not in desc[key]:
6482                                         desc[    6017                                         desc[key].append(data[key])
6483         pprint('Summary files:')                 6018         pprint('Summary files:')
6484         if len(desc['host']) == len(desc['mod    6019         if len(desc['host']) == len(desc['mode']) == len(desc['kernel']) == 1:
6485                 title = '%s %s %s' % (desc['h    6020                 title = '%s %s %s' % (desc['host'][0], desc['kernel'][0], desc['mode'][0])
6486                 if target:                    << 
6487                         title += ' %s' % targ << 
6488         else:                                    6021         else:
6489                 title = inpath                   6022                 title = inpath
6490         createHTMLSummarySimple(testruns, os.    6023         createHTMLSummarySimple(testruns, os.path.join(outpath, 'summary.html'), title)
6491         pprint('   summary.html         - tab    6024         pprint('   summary.html         - tabular list of test data found')
6492         createHTMLDeviceSummary(testruns, os.    6025         createHTMLDeviceSummary(testruns, os.path.join(outpath, 'summary-devices.html'), title)
6493         pprint('   summary-devices.html - ker    6026         pprint('   summary-devices.html - kernel device list sorted by total execution time')
6494         createHTMLIssuesSummary(testruns, iss    6027         createHTMLIssuesSummary(testruns, issues, os.path.join(outpath, 'summary-issues.html'), title)
6495         pprint('   summary-issues.html  - ker    6028         pprint('   summary-issues.html  - kernel issues found sorted by frequency')
6496                                                  6029 
6497 # Function: checkArgBool                         6030 # Function: checkArgBool
6498 # Description:                                   6031 # Description:
6499 #        check if a boolean string value is t    6032 #        check if a boolean string value is true or false
6500 def checkArgBool(name, value):                   6033 def checkArgBool(name, value):
6501         if value in switchvalues:                6034         if value in switchvalues:
6502                 if value in switchoff:           6035                 if value in switchoff:
6503                         return False             6036                         return False
6504                 return True                      6037                 return True
6505         doError('invalid boolean --> (%s: %s)    6038         doError('invalid boolean --> (%s: %s), use "true/false" or "1/0"' % (name, value), True)
6506         return False                             6039         return False
6507                                                  6040 
6508 # Function: configFromFile                       6041 # Function: configFromFile
6509 # Description:                                   6042 # Description:
6510 #        Configure the script via the info in    6043 #        Configure the script via the info in a config file
6511 def configFromFile(file):                        6044 def configFromFile(file):
6512         Config = configparser.ConfigParser()  !! 6045         Config = ConfigParser.ConfigParser()
6513                                                  6046 
6514         Config.read(file)                        6047         Config.read(file)
6515         sections = Config.sections()             6048         sections = Config.sections()
6516         overridekprobes = False                  6049         overridekprobes = False
6517         overridedevkprobes = False               6050         overridedevkprobes = False
6518         if 'Settings' in sections:               6051         if 'Settings' in sections:
6519                 for opt in Config.options('Se    6052                 for opt in Config.options('Settings'):
6520                         value = Config.get('S    6053                         value = Config.get('Settings', opt).lower()
6521                         option = opt.lower()     6054                         option = opt.lower()
6522                         if(option == 'verbose    6055                         if(option == 'verbose'):
6523                                 sysvals.verbo    6056                                 sysvals.verbose = checkArgBool(option, value)
6524                         elif(option == 'addlo    6057                         elif(option == 'addlogs'):
6525                                 sysvals.dmesg    6058                                 sysvals.dmesglog = sysvals.ftracelog = checkArgBool(option, value)
6526                         elif(option == 'dev')    6059                         elif(option == 'dev'):
6527                                 sysvals.usede    6060                                 sysvals.usedevsrc = checkArgBool(option, value)
6528                         elif(option == 'proc'    6061                         elif(option == 'proc'):
6529                                 sysvals.usepr    6062                                 sysvals.useprocmon = checkArgBool(option, value)
6530                         elif(option == 'x2'):    6063                         elif(option == 'x2'):
6531                                 if checkArgBo    6064                                 if checkArgBool(option, value):
6532                                         sysva    6065                                         sysvals.execcount = 2
6533                         elif(option == 'callg    6066                         elif(option == 'callgraph'):
6534                                 sysvals.useca    6067                                 sysvals.usecallgraph = checkArgBool(option, value)
6535                         elif(option == 'overr    6068                         elif(option == 'override-timeline-functions'):
6536                                 overridekprob    6069                                 overridekprobes = checkArgBool(option, value)
6537                         elif(option == 'overr    6070                         elif(option == 'override-dev-timeline-functions'):
6538                                 overridedevkp    6071                                 overridedevkprobes = checkArgBool(option, value)
6539                         elif(option == 'skiph    6072                         elif(option == 'skiphtml'):
6540                                 sysvals.skiph    6073                                 sysvals.skiphtml = checkArgBool(option, value)
6541                         elif(option == 'sync'    6074                         elif(option == 'sync'):
6542                                 sysvals.sync     6075                                 sysvals.sync = checkArgBool(option, value)
6543                         elif(option == 'rs' o    6076                         elif(option == 'rs' or option == 'runtimesuspend'):
6544                                 if value in s    6077                                 if value in switchvalues:
6545                                         if va    6078                                         if value in switchoff:
6546                                                  6079                                                 sysvals.rs = -1
6547                                         else:    6080                                         else:
6548                                                  6081                                                 sysvals.rs = 1
6549                                 else:            6082                                 else:
6550                                         doErr    6083                                         doError('invalid value --> (%s: %s), use "enable/disable"' % (option, value), True)
6551                         elif(option == 'displ    6084                         elif(option == 'display'):
6552                                 disopt = ['on    6085                                 disopt = ['on', 'off', 'standby', 'suspend']
6553                                 if value not     6086                                 if value not in disopt:
6554                                         doErr    6087                                         doError('invalid value --> (%s: %s), use %s' % (option, value, disopt), True)
6555                                 sysvals.displ    6088                                 sysvals.display = value
6556                         elif(option == 'gzip'    6089                         elif(option == 'gzip'):
6557                                 sysvals.gzip     6090                                 sysvals.gzip = checkArgBool(option, value)
6558                         elif(option == 'cgfil    6091                         elif(option == 'cgfilter'):
6559                                 sysvals.setCa    6092                                 sysvals.setCallgraphFilter(value)
6560                         elif(option == 'cgski    6093                         elif(option == 'cgskip'):
6561                                 if value in s    6094                                 if value in switchoff:
6562                                         sysva    6095                                         sysvals.cgskip = ''
6563                                 else:            6096                                 else:
6564                                         sysva    6097                                         sysvals.cgskip = sysvals.configFile(val)
6565                                         if(no    6098                                         if(not sysvals.cgskip):
6566                                                  6099                                                 doError('%s does not exist' % sysvals.cgskip)
6567                         elif(option == 'cgtes    6100                         elif(option == 'cgtest'):
6568                                 sysvals.cgtes    6101                                 sysvals.cgtest = getArgInt('cgtest', value, 0, 1, False)
6569                         elif(option == 'cgpha    6102                         elif(option == 'cgphase'):
6570                                 d = Data(0)      6103                                 d = Data(0)
6571                                 if value not  !! 6104                                 if value not in d.sortedPhases():
6572                                         doErr    6105                                         doError('invalid phase --> (%s: %s), valid phases are %s'\
6573                                               !! 6106                                                 % (option, value, d.sortedPhases()), True)
6574                                 sysvals.cgpha    6107                                 sysvals.cgphase = value
6575                         elif(option == 'fadd'    6108                         elif(option == 'fadd'):
6576                                 file = sysval    6109                                 file = sysvals.configFile(value)
6577                                 if(not file):    6110                                 if(not file):
6578                                         doErr    6111                                         doError('%s does not exist' % value)
6579                                 sysvals.addFt    6112                                 sysvals.addFtraceFilterFunctions(file)
6580                         elif(option == 'resul    6113                         elif(option == 'result'):
6581                                 sysvals.resul    6114                                 sysvals.result = value
6582                         elif(option == 'multi    6115                         elif(option == 'multi'):
6583                                 nums = value.    6116                                 nums = value.split()
6584                                 if len(nums)     6117                                 if len(nums) != 2:
6585                                         doErr    6118                                         doError('multi requires 2 integers (exec_count and delay)', True)
6586                                 sysvals.multi !! 6119                                 sysvals.multitest['run'] = True
                                                   >> 6120                                 sysvals.multitest['count'] = getArgInt('multi: n d (exec count)', nums[0], 2, 1000000, False)
                                                   >> 6121                                 sysvals.multitest['delay'] = getArgInt('multi: n d (delay between tests)', nums[1], 0, 3600, False)
6587                         elif(option == 'devic    6122                         elif(option == 'devicefilter'):
6588                                 sysvals.setDe    6123                                 sysvals.setDeviceFilter(value)
6589                         elif(option == 'expan    6124                         elif(option == 'expandcg'):
6590                                 sysvals.cgexp    6125                                 sysvals.cgexp = checkArgBool(option, value)
6591                         elif(option == 'srgap    6126                         elif(option == 'srgap'):
6592                                 if checkArgBo    6127                                 if checkArgBool(option, value):
6593                                         sysva    6128                                         sysvals.srgap = 5
6594                         elif(option == 'mode'    6129                         elif(option == 'mode'):
6595                                 sysvals.suspe    6130                                 sysvals.suspendmode = value
6596                         elif(option == 'comma    6131                         elif(option == 'command' or option == 'cmd'):
6597                                 sysvals.testc    6132                                 sysvals.testcommand = value
6598                         elif(option == 'x2del    6133                         elif(option == 'x2delay'):
6599                                 sysvals.x2del    6134                                 sysvals.x2delay = getArgInt('x2delay', value, 0, 60000, False)
6600                         elif(option == 'prede    6135                         elif(option == 'predelay'):
6601                                 sysvals.prede    6136                                 sysvals.predelay = getArgInt('predelay', value, 0, 60000, False)
6602                         elif(option == 'postd    6137                         elif(option == 'postdelay'):
6603                                 sysvals.postd    6138                                 sysvals.postdelay = getArgInt('postdelay', value, 0, 60000, False)
6604                         elif(option == 'maxde    6139                         elif(option == 'maxdepth'):
6605                                 sysvals.max_g    6140                                 sysvals.max_graph_depth = getArgInt('maxdepth', value, 0, 1000, False)
6606                         elif(option == 'rtcwa    6141                         elif(option == 'rtcwake'):
6607                                 if value in s    6142                                 if value in switchoff:
6608                                         sysva    6143                                         sysvals.rtcwake = False
6609                                 else:            6144                                 else:
6610                                         sysva    6145                                         sysvals.rtcwake = True
6611                                         sysva    6146                                         sysvals.rtcwaketime = getArgInt('rtcwake', value, 0, 3600, False)
6612                         elif(option == 'timep    6147                         elif(option == 'timeprec'):
6613                                 sysvals.setPr    6148                                 sysvals.setPrecision(getArgInt('timeprec', value, 0, 6, False))
6614                         elif(option == 'minde    6149                         elif(option == 'mindev'):
6615                                 sysvals.minde    6150                                 sysvals.mindevlen = getArgFloat('mindev', value, 0.0, 10000.0, False)
6616                         elif(option == 'calll    6151                         elif(option == 'callloop-maxgap'):
6617                                 sysvals.calll    6152                                 sysvals.callloopmaxgap = getArgFloat('callloop-maxgap', value, 0.0, 1.0, False)
6618                         elif(option == 'calll    6153                         elif(option == 'callloop-maxlen'):
6619                                 sysvals.calll    6154                                 sysvals.callloopmaxgap = getArgFloat('callloop-maxlen', value, 0.0, 1.0, False)
6620                         elif(option == 'mincg    6155                         elif(option == 'mincg'):
6621                                 sysvals.mincg    6156                                 sysvals.mincglen = getArgFloat('mincg', value, 0.0, 10000.0, False)
6622                         elif(option == 'bufsi    6157                         elif(option == 'bufsize'):
6623                                 sysvals.bufsi    6158                                 sysvals.bufsize = getArgInt('bufsize', value, 1, 1024*1024*8, False)
6624                         elif(option == 'outpu    6159                         elif(option == 'output-dir'):
6625                                 sysvals.outdi    6160                                 sysvals.outdir = sysvals.setOutputFolder(value)
6626                                                  6161 
6627         if sysvals.suspendmode == 'command' a    6162         if sysvals.suspendmode == 'command' and not sysvals.testcommand:
6628                 doError('No command supplied     6163                 doError('No command supplied for mode "command"')
6629                                                  6164 
6630         # compatibility errors                   6165         # compatibility errors
6631         if sysvals.usedevsrc and sysvals.usec    6166         if sysvals.usedevsrc and sysvals.usecallgraph:
6632                 doError('-dev is not compatib    6167                 doError('-dev is not compatible with -f')
6633         if sysvals.usecallgraph and sysvals.u    6168         if sysvals.usecallgraph and sysvals.useprocmon:
6634                 doError('-proc is not compati    6169                 doError('-proc is not compatible with -f')
6635                                                  6170 
6636         if overridekprobes:                      6171         if overridekprobes:
6637                 sysvals.tracefuncs = dict()      6172                 sysvals.tracefuncs = dict()
6638         if overridedevkprobes:                   6173         if overridedevkprobes:
6639                 sysvals.dev_tracefuncs = dict    6174                 sysvals.dev_tracefuncs = dict()
6640                                                  6175 
6641         kprobes = dict()                         6176         kprobes = dict()
6642         kprobesec = 'dev_timeline_functions_'    6177         kprobesec = 'dev_timeline_functions_'+platform.machine()
6643         if kprobesec in sections:                6178         if kprobesec in sections:
6644                 for name in Config.options(kp    6179                 for name in Config.options(kprobesec):
6645                         text = Config.get(kpr    6180                         text = Config.get(kprobesec, name)
6646                         kprobes[name] = (text    6181                         kprobes[name] = (text, True)
6647         kprobesec = 'timeline_functions_'+pla    6182         kprobesec = 'timeline_functions_'+platform.machine()
6648         if kprobesec in sections:                6183         if kprobesec in sections:
6649                 for name in Config.options(kp    6184                 for name in Config.options(kprobesec):
6650                         if name in kprobes:      6185                         if name in kprobes:
6651                                 doError('Dupl    6186                                 doError('Duplicate timeline function found "%s"' % (name))
6652                         text = Config.get(kpr    6187                         text = Config.get(kprobesec, name)
6653                         kprobes[name] = (text    6188                         kprobes[name] = (text, False)
6654                                                  6189 
6655         for name in kprobes:                     6190         for name in kprobes:
6656                 function = name                  6191                 function = name
6657                 format = name                    6192                 format = name
6658                 color = ''                       6193                 color = ''
6659                 args = dict()                    6194                 args = dict()
6660                 text, dev = kprobes[name]        6195                 text, dev = kprobes[name]
6661                 data = text.split()              6196                 data = text.split()
6662                 i = 0                            6197                 i = 0
6663                 for val in data:                 6198                 for val in data:
6664                         # bracketted strings     6199                         # bracketted strings are special formatting, read them separately
6665                         if val[0] == '[' and     6200                         if val[0] == '[' and val[-1] == ']':
6666                                 for prop in v    6201                                 for prop in val[1:-1].split(','):
6667                                         p = p    6202                                         p = prop.split('=')
6668                                         if p[    6203                                         if p[0] == 'color':
6669                                                  6204                                                 try:
6670                                                  6205                                                         color = int(p[1], 16)
6671                                                  6206                                                         color = '#'+p[1]
6672                                                  6207                                                 except:
6673                                                  6208                                                         color = p[1]
6674                                 continue         6209                                 continue
6675                         # first real arg shou    6210                         # first real arg should be the format string
6676                         if i == 0:               6211                         if i == 0:
6677                                 format = val     6212                                 format = val
6678                         # all other args are     6213                         # all other args are actual function args
6679                         else:                    6214                         else:
6680                                 d = val.split    6215                                 d = val.split('=')
6681                                 args[d[0]] =     6216                                 args[d[0]] = d[1]
6682                         i += 1                   6217                         i += 1
6683                 if not function or not format    6218                 if not function or not format:
6684                         doError('Invalid kpro    6219                         doError('Invalid kprobe: %s' % name)
6685                 for arg in re.findall('{(?P<n    6220                 for arg in re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', format):
6686                         if arg not in args:      6221                         if arg not in args:
6687                                 doError('Kpro    6222                                 doError('Kprobe "%s" is missing argument "%s"' % (name, arg))
6688                 if (dev and name in sysvals.d    6223                 if (dev and name in sysvals.dev_tracefuncs) or (not dev and name in sysvals.tracefuncs):
6689                         doError('Duplicate ti    6224                         doError('Duplicate timeline function found "%s"' % (name))
6690                                                  6225 
6691                 kp = {                           6226                 kp = {
6692                         'name': name,            6227                         'name': name,
6693                         'func': function,        6228                         'func': function,
6694                         'format': format,        6229                         'format': format,
6695                         sysvals.archargs: arg    6230                         sysvals.archargs: args
6696                 }                                6231                 }
6697                 if color:                        6232                 if color:
6698                         kp['color'] = color      6233                         kp['color'] = color
6699                 if dev:                          6234                 if dev:
6700                         sysvals.dev_tracefunc    6235                         sysvals.dev_tracefuncs[name] = kp
6701                 else:                            6236                 else:
6702                         sysvals.tracefuncs[na    6237                         sysvals.tracefuncs[name] = kp
6703                                                  6238 
6704 # Function: printHelp                            6239 # Function: printHelp
6705 # Description:                                   6240 # Description:
6706 #        print out the help text                 6241 #        print out the help text
6707 def printHelp():                                 6242 def printHelp():
6708         pprint('\n%s v%s\n'\                     6243         pprint('\n%s v%s\n'\
6709         'Usage: sudo sleepgraph <options> <co    6244         'Usage: sudo sleepgraph <options> <commands>\n'\
6710         '\n'\                                    6245         '\n'\
6711         'Description:\n'\                        6246         'Description:\n'\
6712         '  This tool is designed to assist ke    6247         '  This tool is designed to assist kernel and OS developers in optimizing\n'\
6713         '  their linux stack\'s suspend/resum    6248         '  their linux stack\'s suspend/resume time. Using a kernel image built\n'\
6714         '  with a few extra options enabled,     6249         '  with a few extra options enabled, the tool will execute a suspend and\n'\
6715         '  capture dmesg and ftrace data unti    6250         '  capture dmesg and ftrace data until resume is complete. This data is\n'\
6716         '  transformed into a device timeline    6251         '  transformed into a device timeline and an optional callgraph to give\n'\
6717         '  a detailed view of which devices/s    6252         '  a detailed view of which devices/subsystems are taking the most\n'\
6718         '  time in suspend/resume.\n'\           6253         '  time in suspend/resume.\n'\
6719         '\n'\                                    6254         '\n'\
6720         '  If no specific command is given, t    6255         '  If no specific command is given, the default behavior is to initiate\n'\
6721         '  a suspend/resume and capture the d    6256         '  a suspend/resume and capture the dmesg/ftrace output as an html timeline.\n'\
6722         '\n'\                                    6257         '\n'\
6723         '  Generates output files in subdirec    6258         '  Generates output files in subdirectory: suspend-yymmdd-HHMMSS\n'\
6724         '   HTML output:                    <    6259         '   HTML output:                    <hostname>_<mode>.html\n'\
6725         '   raw dmesg output:               <    6260         '   raw dmesg output:               <hostname>_<mode>_dmesg.txt\n'\
6726         '   raw ftrace output:              <    6261         '   raw ftrace output:              <hostname>_<mode>_ftrace.txt\n'\
6727         '\n'\                                    6262         '\n'\
6728         'Options:\n'\                            6263         'Options:\n'\
6729         '   -h           Print this help text    6264         '   -h           Print this help text\n'\
6730         '   -v           Print the current to    6265         '   -v           Print the current tool version\n'\
6731         '   -config fn   Pull arguments and c    6266         '   -config fn   Pull arguments and config options from file fn\n'\
6732         '   -verbose     Print extra informat    6267         '   -verbose     Print extra information during execution and analysis\n'\
6733         '   -m mode      Mode to initiate for    6268         '   -m mode      Mode to initiate for suspend (default: %s)\n'\
6734         '   -o name      Overrides the output    6269         '   -o name      Overrides the output subdirectory name when running a new test\n'\
6735         '                default: suspend-{da    6270         '                default: suspend-{date}-{time}\n'\
6736         '   -rtcwake t   Wakeup t seconds aft    6271         '   -rtcwake t   Wakeup t seconds after suspend, set t to "off" to disable (default: 15)\n'\
6737         '   -addlogs     Add the dmesg and ft    6272         '   -addlogs     Add the dmesg and ftrace logs to the html output\n'\
6738         '   -noturbostat Dont use turbostat i !! 6273         '   -turbostat   Use turbostat to execute the command in freeze mode (default: disabled)\n'\
6739         '   -srgap       Add a visible gap in    6274         '   -srgap       Add a visible gap in the timeline between sus/res (default: disabled)\n'\
6740         '   -skiphtml    Run the test and cap    6275         '   -skiphtml    Run the test and capture the trace logs, but skip the timeline (default: disabled)\n'\
6741         '   -result fn   Export a results tab    6276         '   -result fn   Export a results table to a text file for parsing.\n'\
6742         '   -wifi        If a wifi connection << 
6743         '   -wifitrace   Trace kernel executi << 
6744         '   -netfix      Use netfix to reset  << 
6745         '  [testprep]\n'\                        6277         '  [testprep]\n'\
6746         '   -sync        Sync the filesystems    6278         '   -sync        Sync the filesystems before starting the test\n'\
6747         '   -rs on/off   Enable/disable runti    6279         '   -rs on/off   Enable/disable runtime suspend for all devices, restore all after test\n'\
6748         '   -display m   Change the display m    6280         '   -display m   Change the display mode to m for the test (on/off/standby/suspend)\n'\
6749         '  [advanced]\n'\                        6281         '  [advanced]\n'\
6750         '   -gzip        Gzip the trace and d    6282         '   -gzip        Gzip the trace and dmesg logs to save space\n'\
6751         '   -cmd {s}     Run the timeline ove    6283         '   -cmd {s}     Run the timeline over a custom command, e.g. "sync -d"\n'\
6752         '   -proc        Add usermode process    6284         '   -proc        Add usermode process info into the timeline (default: disabled)\n'\
6753         '   -dev         Add kernel function     6285         '   -dev         Add kernel function calls and threads to the timeline (default: disabled)\n'\
6754         '   -x2          Run two suspend/resu    6286         '   -x2          Run two suspend/resumes back to back (default: disabled)\n'\
6755         '   -x2delay t   Include t ms delay b    6287         '   -x2delay t   Include t ms delay between multiple test runs (default: 0 ms)\n'\
6756         '   -predelay t  Include t ms delay b    6288         '   -predelay t  Include t ms delay before 1st suspend (default: 0 ms)\n'\
6757         '   -postdelay t Include t ms delay a    6289         '   -postdelay t Include t ms delay after last resume (default: 0 ms)\n'\
6758         '   -mindev ms   Discard all device b    6290         '   -mindev ms   Discard all device blocks shorter than ms milliseconds (e.g. 0.001 for us)\n'\
6759         '   -multi n d   Execute <n> consecut !! 6291         '   -multi n d   Execute <n> consecutive tests at <d> seconds intervals. The outputs will\n'\
6760         '                by a "d", "h", or "m !! 6292         '                be created in a new subdirectory with a summary page.\n'\
6761         '                The outputs will be  << 
6762         '   -maxfail n   Abort a -multi run a << 
6763         '  [debug]\n'\                           6293         '  [debug]\n'\
6764         '   -f           Use ftrace to create    6294         '   -f           Use ftrace to create device callgraphs (default: disabled)\n'\
6765         '   -ftop        Use ftrace on the to    6295         '   -ftop        Use ftrace on the top level call: "%s" (default: disabled)\n'\
6766         '   -maxdepth N  limit the callgraph     6296         '   -maxdepth N  limit the callgraph data to N call levels (default: 0=all)\n'\
6767         '   -expandcg    pre-expand the callg    6297         '   -expandcg    pre-expand the callgraph data in the html output (default: disabled)\n'\
6768         '   -fadd file   Add functions to be     6298         '   -fadd file   Add functions to be graphed in the timeline from a list in a text file\n'\
6769         '   -filter "d1,d2,..." Filter out al    6299         '   -filter "d1,d2,..." Filter out all but this comma-delimited list of device names\n'\
6770         '   -mincg  ms   Discard all callgrap    6300         '   -mincg  ms   Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)\n'\
6771         '   -cgphase P   Only show callgraph     6301         '   -cgphase P   Only show callgraph data for phase P (e.g. suspend_late)\n'\
6772         '   -cgtest N    Only show callgraph     6302         '   -cgtest N    Only show callgraph data for test N (e.g. 0 or 1 in an x2 run)\n'\
6773         '   -timeprec N  Number of significan    6303         '   -timeprec N  Number of significant digits in timestamps (0:S, [3:ms], 6:us)\n'\
6774         '   -cgfilter S  Filter the callgraph    6304         '   -cgfilter S  Filter the callgraph output in the timeline\n'\
6775         '   -cgskip file Callgraph functions     6305         '   -cgskip file Callgraph functions to skip, off to disable (default: cgskip.txt)\n'\
6776         '   -bufsize N   Set trace buffer siz    6306         '   -bufsize N   Set trace buffer size to N kilo-bytes (default: all of free memory)\n'\
6777         '   -devdump     Print out all the ra    6307         '   -devdump     Print out all the raw device data for each phase\n'\
6778         '   -cgdump      Print out all the ra    6308         '   -cgdump      Print out all the raw callgraph data\n'\
6779         '\n'\                                    6309         '\n'\
6780         'Other commands:\n'\                     6310         'Other commands:\n'\
6781         '   -modes       List available suspe    6311         '   -modes       List available suspend modes\n'\
6782         '   -status      Test to see if the s    6312         '   -status      Test to see if the system is enabled to run this tool\n'\
6783         '   -fpdt        Print out the conten    6313         '   -fpdt        Print out the contents of the ACPI Firmware Performance Data Table\n'\
6784         '   -wificheck   Print out wifi conne !! 6314         '   -battery     Print out battery info (if available)\n'\
                                                   >> 6315         '   -wifi        Print out wifi connection info (if wireless-tools and device exists)\n'\
6785         '   -x<mode>     Test xset by togglin    6316         '   -x<mode>     Test xset by toggling the given mode (on/off/standby/suspend)\n'\
6786         '   -sysinfo     Print out system inf    6317         '   -sysinfo     Print out system info extracted from BIOS\n'\
6787         '   -devinfo     Print out the pm set    6318         '   -devinfo     Print out the pm settings of all devices which support runtime suspend\n'\
6788         '   -cmdinfo     Print out all the pl << 
6789         '   -flist       Print the list of fu    6319         '   -flist       Print the list of functions currently being captured in ftrace\n'\
6790         '   -flistall    Print all functions     6320         '   -flistall    Print all functions capable of being captured in ftrace\n'\
6791         '   -summary dir Create a summary of     6321         '   -summary dir Create a summary of tests in this dir [-genhtml builds missing html]\n'\
6792         '  [redo]\n'\                            6322         '  [redo]\n'\
6793         '   -ftrace ftracefile  Create HTML o    6323         '   -ftrace ftracefile  Create HTML output using ftrace input (used with -dmesg)\n'\
6794         '   -dmesg dmesgfile    Create HTML o    6324         '   -dmesg dmesgfile    Create HTML output using dmesg (used with -ftrace)\n'\
6795         '' % (sysvals.title, sysvals.version,    6325         '' % (sysvals.title, sysvals.version, sysvals.suspendmode, sysvals.ftopfunc))
6796         return True                              6326         return True
6797                                                  6327 
6798 # ----------------- MAIN --------------------    6328 # ----------------- MAIN --------------------
6799 # exec start (skipped if script is loaded as     6329 # exec start (skipped if script is loaded as library)
6800 if __name__ == '__main__':                       6330 if __name__ == '__main__':
6801         genhtml = False                          6331         genhtml = False
6802         cmd = ''                                 6332         cmd = ''
6803         simplecmds = ['-sysinfo', '-modes', '    6333         simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall',
6804                 '-devinfo', '-status', '-xon' !! 6334                 '-devinfo', '-status', '-battery', '-xon', '-xoff', '-xstandby',
6805                 '-xinit', '-xreset', '-xstat' !! 6335                 '-xsuspend', '-xinit', '-xreset', '-xstat', '-wifi']
6806         if '-f' in sys.argv:                     6336         if '-f' in sys.argv:
6807                 sysvals.cgskip = sysvals.conf    6337                 sysvals.cgskip = sysvals.configFile('cgskip.txt')
6808         # loop through the command line argum    6338         # loop through the command line arguments
6809         args = iter(sys.argv[1:])                6339         args = iter(sys.argv[1:])
6810         for arg in args:                         6340         for arg in args:
6811                 if(arg == '-m'):                 6341                 if(arg == '-m'):
6812                         try:                     6342                         try:
6813                                 val = next(ar !! 6343                                 val = args.next()
6814                         except:                  6344                         except:
6815                                 doError('No m    6345                                 doError('No mode supplied', True)
6816                         if val == 'command' a    6346                         if val == 'command' and not sysvals.testcommand:
6817                                 doError('No c    6347                                 doError('No command supplied for mode "command"', True)
6818                         sysvals.suspendmode =    6348                         sysvals.suspendmode = val
6819                 elif(arg in simplecmds):         6349                 elif(arg in simplecmds):
6820                         cmd = arg[1:]            6350                         cmd = arg[1:]
6821                 elif(arg == '-h'):               6351                 elif(arg == '-h'):
6822                         printHelp()              6352                         printHelp()
6823                         sys.exit(0)              6353                         sys.exit(0)
6824                 elif(arg == '-v'):               6354                 elif(arg == '-v'):
6825                         pprint("Version %s" %    6355                         pprint("Version %s" % sysvals.version)
6826                         sys.exit(0)              6356                         sys.exit(0)
6827                 elif(arg == '-debugtiming'):  << 
6828                         debugtiming = True    << 
6829                 elif(arg == '-x2'):              6357                 elif(arg == '-x2'):
6830                         sysvals.execcount = 2    6358                         sysvals.execcount = 2
6831                 elif(arg == '-x2delay'):         6359                 elif(arg == '-x2delay'):
6832                         sysvals.x2delay = get    6360                         sysvals.x2delay = getArgInt('-x2delay', args, 0, 60000)
6833                 elif(arg == '-predelay'):        6361                 elif(arg == '-predelay'):
6834                         sysvals.predelay = ge    6362                         sysvals.predelay = getArgInt('-predelay', args, 0, 60000)
6835                 elif(arg == '-postdelay'):       6363                 elif(arg == '-postdelay'):
6836                         sysvals.postdelay = g    6364                         sysvals.postdelay = getArgInt('-postdelay', args, 0, 60000)
6837                 elif(arg == '-f'):               6365                 elif(arg == '-f'):
6838                         sysvals.usecallgraph     6366                         sysvals.usecallgraph = True
6839                 elif(arg == '-ftop'):            6367                 elif(arg == '-ftop'):
6840                         sysvals.usecallgraph     6368                         sysvals.usecallgraph = True
6841                         sysvals.ftop = True      6369                         sysvals.ftop = True
6842                         sysvals.usekprobes =     6370                         sysvals.usekprobes = False
6843                 elif(arg == '-skiphtml'):        6371                 elif(arg == '-skiphtml'):
6844                         sysvals.skiphtml = Tr    6372                         sysvals.skiphtml = True
6845                 elif(arg == '-cgdump'):          6373                 elif(arg == '-cgdump'):
6846                         sysvals.cgdump = True    6374                         sysvals.cgdump = True
6847                 elif(arg == '-devdump'):         6375                 elif(arg == '-devdump'):
6848                         sysvals.devdump = Tru    6376                         sysvals.devdump = True
6849                 elif(arg == '-genhtml'):         6377                 elif(arg == '-genhtml'):
6850                         genhtml = True           6378                         genhtml = True
6851                 elif(arg == '-addlogs'):         6379                 elif(arg == '-addlogs'):
6852                         sysvals.dmesglog = sy    6380                         sysvals.dmesglog = sysvals.ftracelog = True
6853                 elif(arg == '-nologs'):          6381                 elif(arg == '-nologs'):
6854                         sysvals.dmesglog = sy    6382                         sysvals.dmesglog = sysvals.ftracelog = False
6855                 elif(arg == '-addlogdmesg'):     6383                 elif(arg == '-addlogdmesg'):
6856                         sysvals.dmesglog = Tr    6384                         sysvals.dmesglog = True
6857                 elif(arg == '-addlogftrace'):    6385                 elif(arg == '-addlogftrace'):
6858                         sysvals.ftracelog = T    6386                         sysvals.ftracelog = True
6859                 elif(arg == '-noturbostat'):  !! 6387                 elif(arg == '-turbostat'):
6860                         sysvals.tstat = False !! 6388                         sysvals.tstat = True
                                                   >> 6389                         if not sysvals.haveTurbostat():
                                                   >> 6390                                 doError('Turbostat command not found')
6861                 elif(arg == '-verbose'):         6391                 elif(arg == '-verbose'):
6862                         sysvals.verbose = Tru    6392                         sysvals.verbose = True
6863                 elif(arg == '-proc'):            6393                 elif(arg == '-proc'):
6864                         sysvals.useprocmon =     6394                         sysvals.useprocmon = True
6865                 elif(arg == '-dev'):             6395                 elif(arg == '-dev'):
6866                         sysvals.usedevsrc = T    6396                         sysvals.usedevsrc = True
6867                 elif(arg == '-sync'):            6397                 elif(arg == '-sync'):
6868                         sysvals.sync = True      6398                         sysvals.sync = True
6869                 elif(arg == '-wifi'):         << 
6870                         sysvals.wifi = True   << 
6871                 elif(arg == '-wifitrace'):    << 
6872                         sysvals.wifitrace = T << 
6873                 elif(arg == '-netfix'):       << 
6874                         sysvals.netfix = True << 
6875                 elif(arg == '-gzip'):            6399                 elif(arg == '-gzip'):
6876                         sysvals.gzip = True      6400                         sysvals.gzip = True
6877                 elif(arg == '-info'):         << 
6878                         try:                  << 
6879                                 val = next(ar << 
6880                         except:               << 
6881                                 doError('-inf << 
6882                 elif(arg == '-desc'):         << 
6883                         try:                  << 
6884                                 val = next(ar << 
6885                         except:               << 
6886                                 doError('-des << 
6887                 elif(arg == '-rs'):              6401                 elif(arg == '-rs'):
6888                         try:                     6402                         try:
6889                                 val = next(ar !! 6403                                 val = args.next()
6890                         except:                  6404                         except:
6891                                 doError('-rs     6405                                 doError('-rs requires "enable" or "disable"', True)
6892                         if val.lower() in swi    6406                         if val.lower() in switchvalues:
6893                                 if val.lower(    6407                                 if val.lower() in switchoff:
6894                                         sysva    6408                                         sysvals.rs = -1
6895                                 else:            6409                                 else:
6896                                         sysva    6410                                         sysvals.rs = 1
6897                         else:                    6411                         else:
6898                                 doError('inva    6412                                 doError('invalid option: %s, use "enable/disable" or "on/off"' % val, True)
6899                 elif(arg == '-display'):         6413                 elif(arg == '-display'):
6900                         try:                     6414                         try:
6901                                 val = next(ar !! 6415                                 val = args.next()
6902                         except:                  6416                         except:
6903                                 doError('-dis    6417                                 doError('-display requires an mode value', True)
6904                         disopt = ['on', 'off'    6418                         disopt = ['on', 'off', 'standby', 'suspend']
6905                         if val.lower() not in    6419                         if val.lower() not in disopt:
6906                                 doError('vali    6420                                 doError('valid display mode values are %s' % disopt, True)
6907                         sysvals.display = val    6421                         sysvals.display = val.lower()
6908                 elif(arg == '-maxdepth'):        6422                 elif(arg == '-maxdepth'):
6909                         sysvals.max_graph_dep    6423                         sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000)
6910                 elif(arg == '-rtcwake'):         6424                 elif(arg == '-rtcwake'):
6911                         try:                     6425                         try:
6912                                 val = next(ar !! 6426                                 val = args.next()
6913                         except:                  6427                         except:
6914                                 doError('No r    6428                                 doError('No rtcwake time supplied', True)
6915                         if val.lower() in swi    6429                         if val.lower() in switchoff:
6916                                 sysvals.rtcwa    6430                                 sysvals.rtcwake = False
6917                         else:                    6431                         else:
6918                                 sysvals.rtcwa    6432                                 sysvals.rtcwake = True
6919                                 sysvals.rtcwa    6433                                 sysvals.rtcwaketime = getArgInt('-rtcwake', val, 0, 3600, False)
6920                 elif(arg == '-timeprec'):        6434                 elif(arg == '-timeprec'):
6921                         sysvals.setPrecision(    6435                         sysvals.setPrecision(getArgInt('-timeprec', args, 0, 6))
6922                 elif(arg == '-mindev'):          6436                 elif(arg == '-mindev'):
6923                         sysvals.mindevlen = g    6437                         sysvals.mindevlen = getArgFloat('-mindev', args, 0.0, 10000.0)
6924                 elif(arg == '-mincg'):           6438                 elif(arg == '-mincg'):
6925                         sysvals.mincglen = ge    6439                         sysvals.mincglen = getArgFloat('-mincg', args, 0.0, 10000.0)
6926                 elif(arg == '-bufsize'):         6440                 elif(arg == '-bufsize'):
6927                         sysvals.bufsize = get    6441                         sysvals.bufsize = getArgInt('-bufsize', args, 1, 1024*1024*8)
6928                 elif(arg == '-cgtest'):          6442                 elif(arg == '-cgtest'):
6929                         sysvals.cgtest = getA    6443                         sysvals.cgtest = getArgInt('-cgtest', args, 0, 1)
6930                 elif(arg == '-cgphase'):         6444                 elif(arg == '-cgphase'):
6931                         try:                     6445                         try:
6932                                 val = next(ar !! 6446                                 val = args.next()
6933                         except:                  6447                         except:
6934                                 doError('No p    6448                                 doError('No phase name supplied', True)
6935                         d = Data(0)              6449                         d = Data(0)
6936                         if val not in d.phase    6450                         if val not in d.phasedef:
6937                                 doError('inva    6451                                 doError('invalid phase --> (%s: %s), valid phases are %s'\
6938                                         % (ar    6452                                         % (arg, val, d.phasedef.keys()), True)
6939                         sysvals.cgphase = val    6453                         sysvals.cgphase = val
6940                 elif(arg == '-cgfilter'):        6454                 elif(arg == '-cgfilter'):
6941                         try:                     6455                         try:
6942                                 val = next(ar !! 6456                                 val = args.next()
6943                         except:                  6457                         except:
6944                                 doError('No c    6458                                 doError('No callgraph functions supplied', True)
6945                         sysvals.setCallgraphF    6459                         sysvals.setCallgraphFilter(val)
6946                 elif(arg == '-skipkprobe'):      6460                 elif(arg == '-skipkprobe'):
6947                         try:                     6461                         try:
6948                                 val = next(ar !! 6462                                 val = args.next()
6949                         except:                  6463                         except:
6950                                 doError('No k    6464                                 doError('No kprobe functions supplied', True)
6951                         sysvals.skipKprobes(v    6465                         sysvals.skipKprobes(val)
6952                 elif(arg == '-cgskip'):          6466                 elif(arg == '-cgskip'):
6953                         try:                     6467                         try:
6954                                 val = next(ar !! 6468                                 val = args.next()
6955                         except:                  6469                         except:
6956                                 doError('No f    6470                                 doError('No file supplied', True)
6957                         if val.lower() in swi    6471                         if val.lower() in switchoff:
6958                                 sysvals.cgski    6472                                 sysvals.cgskip = ''
6959                         else:                    6473                         else:
6960                                 sysvals.cgski    6474                                 sysvals.cgskip = sysvals.configFile(val)
6961                                 if(not sysval    6475                                 if(not sysvals.cgskip):
6962                                         doErr    6476                                         doError('%s does not exist' % sysvals.cgskip)
6963                 elif(arg == '-callloop-maxgap    6477                 elif(arg == '-callloop-maxgap'):
6964                         sysvals.callloopmaxga    6478                         sysvals.callloopmaxgap = getArgFloat('-callloop-maxgap', args, 0.0, 1.0)
6965                 elif(arg == '-callloop-maxlen    6479                 elif(arg == '-callloop-maxlen'):
6966                         sysvals.callloopmaxle    6480                         sysvals.callloopmaxlen = getArgFloat('-callloop-maxlen', args, 0.0, 1.0)
6967                 elif(arg == '-cmd'):             6481                 elif(arg == '-cmd'):
6968                         try:                     6482                         try:
6969                                 val = next(ar !! 6483                                 val = args.next()
6970                         except:                  6484                         except:
6971                                 doError('No c    6485                                 doError('No command string supplied', True)
6972                         sysvals.testcommand =    6486                         sysvals.testcommand = val
6973                         sysvals.suspendmode =    6487                         sysvals.suspendmode = 'command'
6974                 elif(arg == '-expandcg'):        6488                 elif(arg == '-expandcg'):
6975                         sysvals.cgexp = True     6489                         sysvals.cgexp = True
6976                 elif(arg == '-srgap'):           6490                 elif(arg == '-srgap'):
6977                         sysvals.srgap = 5        6491                         sysvals.srgap = 5
6978                 elif(arg == '-maxfail'):      << 
6979                         sysvals.maxfail = get << 
6980                 elif(arg == '-multi'):           6492                 elif(arg == '-multi'):
6981                         try:                  !! 6493                         sysvals.multitest['run'] = True
6982                                 c, d = next(a !! 6494                         sysvals.multitest['count'] = getArgInt('-multi n d (exec count)', args, 2, 1000000)
6983                         except:               !! 6495                         sysvals.multitest['delay'] = getArgInt('-multi n d (delay between tests)', args, 0, 3600)
6984                                 doError('-mul << 
6985                         sysvals.multiinit(c,  << 
6986                 elif(arg == '-o'):               6496                 elif(arg == '-o'):
6987                         try:                     6497                         try:
6988                                 val = next(ar !! 6498                                 val = args.next()
6989                         except:                  6499                         except:
6990                                 doError('No s    6500                                 doError('No subdirectory name supplied', True)
6991                         sysvals.outdir = sysv    6501                         sysvals.outdir = sysvals.setOutputFolder(val)
6992                 elif(arg == '-config'):          6502                 elif(arg == '-config'):
6993                         try:                     6503                         try:
6994                                 val = next(ar !! 6504                                 val = args.next()
6995                         except:                  6505                         except:
6996                                 doError('No t    6506                                 doError('No text file supplied', True)
6997                         file = sysvals.config    6507                         file = sysvals.configFile(val)
6998                         if(not file):            6508                         if(not file):
6999                                 doError('%s d    6509                                 doError('%s does not exist' % val)
7000                         configFromFile(file)     6510                         configFromFile(file)
7001                 elif(arg == '-fadd'):            6511                 elif(arg == '-fadd'):
7002                         try:                     6512                         try:
7003                                 val = next(ar !! 6513                                 val = args.next()
7004                         except:                  6514                         except:
7005                                 doError('No t    6515                                 doError('No text file supplied', True)
7006                         file = sysvals.config    6516                         file = sysvals.configFile(val)
7007                         if(not file):            6517                         if(not file):
7008                                 doError('%s d    6518                                 doError('%s does not exist' % val)
7009                         sysvals.addFtraceFilt    6519                         sysvals.addFtraceFilterFunctions(file)
7010                 elif(arg == '-dmesg'):           6520                 elif(arg == '-dmesg'):
7011                         try:                     6521                         try:
7012                                 val = next(ar !! 6522                                 val = args.next()
7013                         except:                  6523                         except:
7014                                 doError('No d    6524                                 doError('No dmesg file supplied', True)
7015                         sysvals.notestrun = T    6525                         sysvals.notestrun = True
7016                         sysvals.dmesgfile = v    6526                         sysvals.dmesgfile = val
7017                         if(os.path.exists(sys    6527                         if(os.path.exists(sysvals.dmesgfile) == False):
7018                                 doError('%s d    6528                                 doError('%s does not exist' % sysvals.dmesgfile)
7019                 elif(arg == '-ftrace'):          6529                 elif(arg == '-ftrace'):
7020                         try:                     6530                         try:
7021                                 val = next(ar !! 6531                                 val = args.next()
7022                         except:                  6532                         except:
7023                                 doError('No f    6533                                 doError('No ftrace file supplied', True)
7024                         sysvals.notestrun = T    6534                         sysvals.notestrun = True
7025                         sysvals.ftracefile =     6535                         sysvals.ftracefile = val
7026                         if(os.path.exists(sys    6536                         if(os.path.exists(sysvals.ftracefile) == False):
7027                                 doError('%s d    6537                                 doError('%s does not exist' % sysvals.ftracefile)
7028                 elif(arg == '-summary'):         6538                 elif(arg == '-summary'):
7029                         try:                     6539                         try:
7030                                 val = next(ar !! 6540                                 val = args.next()
7031                         except:                  6541                         except:
7032                                 doError('No d    6542                                 doError('No directory supplied', True)
7033                         cmd = 'summary'          6543                         cmd = 'summary'
7034                         sysvals.outdir = val     6544                         sysvals.outdir = val
7035                         sysvals.notestrun = T    6545                         sysvals.notestrun = True
7036                         if(os.path.isdir(val)    6546                         if(os.path.isdir(val) == False):
7037                                 doError('%s i    6547                                 doError('%s is not accesible' % val)
7038                 elif(arg == '-filter'):          6548                 elif(arg == '-filter'):
7039                         try:                     6549                         try:
7040                                 val = next(ar !! 6550                                 val = args.next()
7041                         except:                  6551                         except:
7042                                 doError('No d    6552                                 doError('No devnames supplied', True)
7043                         sysvals.setDeviceFilt    6553                         sysvals.setDeviceFilter(val)
7044                 elif(arg == '-result'):          6554                 elif(arg == '-result'):
7045                         try:                     6555                         try:
7046                                 val = next(ar !! 6556                                 val = args.next()
7047                         except:                  6557                         except:
7048                                 doError('No r    6558                                 doError('No result file supplied', True)
7049                         sysvals.result = val     6559                         sysvals.result = val
7050                         sysvals.signalHandler    6560                         sysvals.signalHandlerInit()
7051                 else:                            6561                 else:
7052                         doError('Invalid argu    6562                         doError('Invalid argument: '+arg, True)
7053                                                  6563 
7054         # compatibility errors                   6564         # compatibility errors
7055         if(sysvals.usecallgraph and sysvals.u    6565         if(sysvals.usecallgraph and sysvals.usedevsrc):
7056                 doError('-dev is not compatib    6566                 doError('-dev is not compatible with -f')
7057         if(sysvals.usecallgraph and sysvals.u    6567         if(sysvals.usecallgraph and sysvals.useprocmon):
7058                 doError('-proc is not compati    6568                 doError('-proc is not compatible with -f')
7059                                                  6569 
7060         if sysvals.usecallgraph and sysvals.c    6570         if sysvals.usecallgraph and sysvals.cgskip:
7061                 sysvals.vprint('Using cgskip     6571                 sysvals.vprint('Using cgskip file: %s' % sysvals.cgskip)
7062                 sysvals.setCallgraphBlacklist    6572                 sysvals.setCallgraphBlacklist(sysvals.cgskip)
7063                                                  6573 
7064         # callgraph size cannot exceed device    6574         # callgraph size cannot exceed device size
7065         if sysvals.mincglen < sysvals.mindevl    6575         if sysvals.mincglen < sysvals.mindevlen:
7066                 sysvals.mincglen = sysvals.mi    6576                 sysvals.mincglen = sysvals.mindevlen
7067                                                  6577 
7068         # remove existing buffers before calc    6578         # remove existing buffers before calculating memory
7069         if(sysvals.usecallgraph or sysvals.us    6579         if(sysvals.usecallgraph or sysvals.usedevsrc):
7070                 sysvals.fsetVal('16', 'buffer    6580                 sysvals.fsetVal('16', 'buffer_size_kb')
7071         sysvals.cpuInfo()                        6581         sysvals.cpuInfo()
7072                                                  6582 
7073         # just run a utility command and exit    6583         # just run a utility command and exit
7074         if(cmd != ''):                           6584         if(cmd != ''):
7075                 ret = 0                          6585                 ret = 0
7076                 if(cmd == 'status'):             6586                 if(cmd == 'status'):
7077                         if not statusCheck(Tr    6587                         if not statusCheck(True):
7078                                 ret = 1          6588                                 ret = 1
7079                 elif(cmd == 'fpdt'):             6589                 elif(cmd == 'fpdt'):
7080                         if not getFPDT(True):    6590                         if not getFPDT(True):
7081                                 ret = 1          6591                                 ret = 1
                                                   >> 6592                 elif(cmd == 'battery'):
                                                   >> 6593                         out = getBattery()
                                                   >> 6594                         if out:
                                                   >> 6595                                 pprint('AC Connect    : %s\nBattery Charge: %d' % out)
                                                   >> 6596                         else:
                                                   >> 6597                                 pprint('no battery found')
                                                   >> 6598                                 ret = 1
7082                 elif(cmd == 'sysinfo'):          6599                 elif(cmd == 'sysinfo'):
7083                         sysvals.printSystemIn    6600                         sysvals.printSystemInfo(True)
7084                 elif(cmd == 'devinfo'):          6601                 elif(cmd == 'devinfo'):
7085                         deviceInfo()             6602                         deviceInfo()
7086                 elif(cmd == 'modes'):            6603                 elif(cmd == 'modes'):
7087                         pprint(getModes())       6604                         pprint(getModes())
7088                 elif(cmd == 'flist'):            6605                 elif(cmd == 'flist'):
7089                         sysvals.getFtraceFilt    6606                         sysvals.getFtraceFilterFunctions(True)
7090                 elif(cmd == 'flistall'):         6607                 elif(cmd == 'flistall'):
7091                         sysvals.getFtraceFilt    6608                         sysvals.getFtraceFilterFunctions(False)
7092                 elif(cmd == 'summary'):          6609                 elif(cmd == 'summary'):
7093                         runSummary(sysvals.ou    6610                         runSummary(sysvals.outdir, True, genhtml)
7094                 elif(cmd in ['xon', 'xoff', '    6611                 elif(cmd in ['xon', 'xoff', 'xstandby', 'xsuspend', 'xinit', 'xreset']):
7095                         sysvals.verbose = Tru    6612                         sysvals.verbose = True
7096                         ret = sysvals.display !! 6613                         ret = displayControl(cmd[1:])
7097                 elif(cmd == 'xstat'):            6614                 elif(cmd == 'xstat'):
7098                         pprint('Display Statu !! 6615                         pprint('Display Status: %s' % displayControl('stat').upper())
7099                 elif(cmd == 'wificheck'):     !! 6616                 elif(cmd == 'wifi'):
7100                         dev = sysvals.checkWi !! 6617                         out = sysvals.checkWifi()
7101                         if dev:               !! 6618                         if 'device' not in out:
7102                                 print('%s is  !! 6619                                 pprint('WIFI interface not found')
7103                         else:                    6620                         else:
7104                                 print('No wif !! 6621                                 for key in sorted(out):
7105                 elif(cmd == 'cmdinfo'):       !! 6622                                         pprint('%6s: %s' % (key.upper(), out[key]))
7106                         for out in sysvals.cm << 
7107                                 print('[%s -  << 
7108                 sys.exit(ret)                    6623                 sys.exit(ret)
7109                                                  6624 
7110         # if instructed, re-analyze existing     6625         # if instructed, re-analyze existing data files
7111         if(sysvals.notestrun):                   6626         if(sysvals.notestrun):
7112                 stamp = rerunTest(sysvals.out    6627                 stamp = rerunTest(sysvals.outdir)
7113                 sysvals.outputResult(stamp)      6628                 sysvals.outputResult(stamp)
7114                 sys.exit(0)                      6629                 sys.exit(0)
7115                                                  6630 
7116         # verify that we can run a test          6631         # verify that we can run a test
7117         error = statusCheck()                    6632         error = statusCheck()
7118         if(error):                               6633         if(error):
7119                 doError(error)                   6634                 doError(error)
7120                                                  6635 
7121         # extract mem/disk extra modes and co    6636         # extract mem/disk extra modes and convert
7122         mode = sysvals.suspendmode               6637         mode = sysvals.suspendmode
7123         if mode.startswith('mem'):               6638         if mode.startswith('mem'):
7124                 memmode = mode.split('-', 1)[    6639                 memmode = mode.split('-', 1)[-1] if '-' in mode else 'deep'
7125                 if memmode == 'shallow':         6640                 if memmode == 'shallow':
7126                         mode = 'standby'         6641                         mode = 'standby'
7127                 elif memmode ==  's2idle':       6642                 elif memmode ==  's2idle':
7128                         mode = 'freeze'          6643                         mode = 'freeze'
7129                 else:                            6644                 else:
7130                         mode = 'mem'             6645                         mode = 'mem'
7131                 sysvals.memmode = memmode        6646                 sysvals.memmode = memmode
7132                 sysvals.suspendmode = mode       6647                 sysvals.suspendmode = mode
7133         if mode.startswith('disk-'):             6648         if mode.startswith('disk-'):
7134                 sysvals.diskmode = mode.split    6649                 sysvals.diskmode = mode.split('-', 1)[-1]
7135                 sysvals.suspendmode = 'disk'     6650                 sysvals.suspendmode = 'disk'
                                                   >> 6651 
7136         sysvals.systemInfo(dmidecode(sysvals.    6652         sysvals.systemInfo(dmidecode(sysvals.mempath))
7137                                                  6653 
7138         failcnt, ret = 0, 0                   !! 6654         setRuntimeSuspend(True)
                                                   >> 6655         if sysvals.display:
                                                   >> 6656                 displayControl('init')
                                                   >> 6657         ret = 0
7139         if sysvals.multitest['run']:             6658         if sysvals.multitest['run']:
7140                 # run multiple tests in a sep    6659                 # run multiple tests in a separate subdirectory
7141                 if not sysvals.outdir:           6660                 if not sysvals.outdir:
7142                         if 'time' in sysvals. !! 6661                         s = 'suspend-x%d' % sysvals.multitest['count']
7143                                 s = '-%dm' %  !! 6662                         sysvals.outdir = datetime.now().strftime(s+'-%y%m%d-%H%M%S')
7144                         else:                 << 
7145                                 s = '-x%d' %  << 
7146                         sysvals.outdir = date << 
7147                 if not os.path.isdir(sysvals.    6663                 if not os.path.isdir(sysvals.outdir):
7148                         os.makedirs(sysvals.o    6664                         os.makedirs(sysvals.outdir)
7149                 sysvals.sudoUserchown(sysvals << 
7150                 finish = datetime.now()       << 
7151                 if 'time' in sysvals.multites << 
7152                         finish += timedelta(m << 
7153                 for i in range(sysvals.multit    6665                 for i in range(sysvals.multitest['count']):
7154                         sysvals.multistat(Tru !! 6666                         if(i != 0):
7155                         if i != 0 and sysvals << 
7156                                 pprint('Waiti    6667                                 pprint('Waiting %d seconds...' % (sysvals.multitest['delay']))
7157                                 time.sleep(sy    6668                                 time.sleep(sysvals.multitest['delay'])
                                                   >> 6669                         pprint('TEST (%d/%d) START' % (i+1, sysvals.multitest['count']))
7158                         fmt = 'suspend-%y%m%d    6670                         fmt = 'suspend-%y%m%d-%H%M%S'
7159                         sysvals.testdir = os.    6671                         sysvals.testdir = os.path.join(sysvals.outdir, datetime.now().strftime(fmt))
7160                         ret = runTest(i+1, no !! 6672                         ret = runTest(i+1)
7161                         failcnt = 0 if not re !! 6673                         pprint('TEST (%d/%d) COMPLETE' % (i+1, sysvals.multitest['count']))
7162                         if sysvals.maxfail >  !! 6674                         sysvals.logmsg = ''
7163                                 pprint('Maxim << 
7164                                 break         << 
7165                         sysvals.resetlog()    << 
7166                         sysvals.multistat(Fal << 
7167                         if 'time' in sysvals. << 
7168                                 break         << 
7169                 if not sysvals.skiphtml:         6675                 if not sysvals.skiphtml:
7170                         runSummary(sysvals.ou    6676                         runSummary(sysvals.outdir, False, False)
7171                 sysvals.sudoUserchown(sysvals    6677                 sysvals.sudoUserchown(sysvals.outdir)
7172         else:                                    6678         else:
7173                 if sysvals.outdir:               6679                 if sysvals.outdir:
7174                         sysvals.testdir = sys    6680                         sysvals.testdir = sysvals.outdir
7175                 # run the test in the current    6681                 # run the test in the current directory
7176                 ret = runTest()                  6682                 ret = runTest()
7177                                               << 
7178         # reset to default values after testi << 
7179         if sysvals.display:                      6683         if sysvals.display:
7180                 sysvals.displayControl('reset !! 6684                 displayControl('reset')
7181         if sysvals.rs != 0:                   !! 6685         setRuntimeSuspend(False)
7182                 sysvals.setRuntimeSuspend(Fal << 
7183         sys.exit(ret)                            6686         sys.exit(ret)
                                                      

~ [ 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