aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xscripts/analyze_suspend.py3817
1 files changed, 2981 insertions, 836 deletions
diff --git a/scripts/analyze_suspend.py b/scripts/analyze_suspend.py
index 4f2cc12dc7c7..93e1fd40f430 100755
--- a/scripts/analyze_suspend.py
+++ b/scripts/analyze_suspend.py
@@ -36,146 +36,392 @@
36# CONFIG_FUNCTION_TRACER=y 36# CONFIG_FUNCTION_TRACER=y
37# CONFIG_FUNCTION_GRAPH_TRACER=y 37# CONFIG_FUNCTION_GRAPH_TRACER=y
38# 38#
39# For kernel versions older than 3.15:
39# The following additional kernel parameters are required: 40# The following additional kernel parameters are required:
40# (e.g. in file /etc/default/grub) 41# (e.g. in file /etc/default/grub)
41# GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=16M ..." 42# GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=16M ..."
42# 43#
43 44
45# ----------------- LIBRARIES --------------------
46
44import sys 47import sys
45import time 48import time
46import os 49import os
47import string 50import string
48import re 51import re
49import array
50import platform 52import platform
51import datetime 53from datetime import datetime
52import struct 54import struct
53 55
54# -- classes -- 56# ----------------- CLASSES --------------------
55 57
58# Class: SystemValues
59# Description:
60# A global, single-instance container used to
61# store system values and test parameters
56class SystemValues: 62class SystemValues:
57 testdir = "." 63 version = 3.0
58 tpath = "/sys/kernel/debug/tracing/" 64 verbose = False
59 mempath = "/dev/mem" 65 testdir = '.'
60 powerfile = "/sys/power/state" 66 tpath = '/sys/kernel/debug/tracing/'
61 suspendmode = "mem" 67 fpdtpath = '/sys/firmware/acpi/tables/FPDT'
62 prefix = "test" 68 epath = '/sys/kernel/debug/tracing/events/power/'
63 teststamp = "" 69 traceevents = [
64 dmesgfile = "" 70 'suspend_resume',
65 ftracefile = "" 71 'device_pm_callback_end',
66 htmlfile = "" 72 'device_pm_callback_start'
73 ]
74 modename = {
75 'freeze': 'Suspend-To-Idle (S0)',
76 'standby': 'Power-On Suspend (S1)',
77 'mem': 'Suspend-to-RAM (S3)',
78 'disk': 'Suspend-to-disk (S4)'
79 }
80 mempath = '/dev/mem'
81 powerfile = '/sys/power/state'
82 suspendmode = 'mem'
83 hostname = 'localhost'
84 prefix = 'test'
85 teststamp = ''
86 dmesgfile = ''
87 ftracefile = ''
88 htmlfile = ''
67 rtcwake = False 89 rtcwake = False
90 rtcwaketime = 10
91 rtcpath = ''
92 android = False
93 adb = 'adb'
94 devicefilter = []
95 stamp = 0
96 execcount = 1
97 x2delay = 0
98 usecallgraph = False
99 usetraceevents = False
100 usetraceeventsonly = False
101 notestrun = False
102 altdevname = dict()
103 postresumetime = 0
104 tracertypefmt = '# tracer: (?P<t>.*)'
105 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$'
106 postresumefmt = '# post resume time (?P<t>[0-9]*)$'
107 stampfmt = '# suspend-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\
108 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\
109 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
110 def __init__(self):
111 self.hostname = platform.node()
112 if(self.hostname == ''):
113 self.hostname = 'localhost'
114 rtc = "rtc0"
115 if os.path.exists('/dev/rtc'):
116 rtc = os.readlink('/dev/rtc')
117 rtc = '/sys/class/rtc/'+rtc
118 if os.path.exists(rtc) and os.path.exists(rtc+'/date') and \
119 os.path.exists(rtc+'/time') and os.path.exists(rtc+'/wakealarm'):
120 self.rtcpath = rtc
68 def setOutputFile(self): 121 def setOutputFile(self):
69 if((self.htmlfile == "") and (self.dmesgfile != "")): 122 if((self.htmlfile == '') and (self.dmesgfile != '')):
70 m = re.match(r"(?P<name>.*)_dmesg\.txt$", self.dmesgfile) 123 m = re.match('(?P<name>.*)_dmesg\.txt$', self.dmesgfile)
71 if(m): 124 if(m):
72 self.htmlfile = m.group("name")+".html" 125 self.htmlfile = m.group('name')+'.html'
73 if((self.htmlfile == "") and (self.ftracefile != "")): 126 if((self.htmlfile == '') and (self.ftracefile != '')):
74 m = re.match(r"(?P<name>.*)_ftrace\.txt$", self.ftracefile) 127 m = re.match('(?P<name>.*)_ftrace\.txt$', self.ftracefile)
75 if(m): 128 if(m):
76 self.htmlfile = m.group("name")+".html" 129 self.htmlfile = m.group('name')+'.html'
77 if(self.htmlfile == ""): 130 if(self.htmlfile == ''):
78 self.htmlfile = "output.html" 131 self.htmlfile = 'output.html'
79 def initTestOutput(self): 132 def initTestOutput(self, subdir):
80 hostname = platform.node() 133 if(not self.android):
81 if(hostname != ""): 134 self.prefix = self.hostname
82 self.prefix = hostname 135 v = open('/proc/version', 'r').read().strip()
83 v = os.popen("cat /proc/version").read().strip() 136 kver = string.split(v)[2]
84 kver = string.split(v)[2] 137 else:
85 self.testdir = os.popen("date \"+suspend-%m%d%y-%H%M%S\"").read().strip() 138 self.prefix = 'android'
86 self.teststamp = "# "+self.testdir+" "+self.prefix+" "+self.suspendmode+" "+kver 139 v = os.popen(self.adb+' shell cat /proc/version').read().strip()
87 self.dmesgfile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+"_dmesg.txt" 140 kver = string.split(v)[2]
88 self.ftracefile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+"_ftrace.txt" 141 testtime = datetime.now().strftime('suspend-%m%d%y-%H%M%S')
89 self.htmlfile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+".html" 142 if(subdir != "."):
143 self.testdir = subdir+"/"+testtime
144 else:
145 self.testdir = testtime
146 self.teststamp = \
147 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver
148 self.dmesgfile = \
149 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt'
150 self.ftracefile = \
151 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt'
152 self.htmlfile = \
153 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html'
90 os.mkdir(self.testdir) 154 os.mkdir(self.testdir)
155 def setDeviceFilter(self, devnames):
156 self.devicefilter = string.split(devnames)
157 def rtcWakeAlarm(self):
158 os.system('echo 0 > '+self.rtcpath+'/wakealarm')
159 outD = open(self.rtcpath+'/date', 'r').read().strip()
160 outT = open(self.rtcpath+'/time', 'r').read().strip()
161 mD = re.match('^(?P<y>[0-9]*)-(?P<m>[0-9]*)-(?P<d>[0-9]*)', outD)
162 mT = re.match('^(?P<h>[0-9]*):(?P<m>[0-9]*):(?P<s>[0-9]*)', outT)
163 if(mD and mT):
164 # get the current time from hardware
165 utcoffset = int((datetime.now() - datetime.utcnow()).total_seconds())
166 dt = datetime(\
167 int(mD.group('y')), int(mD.group('m')), int(mD.group('d')),
168 int(mT.group('h')), int(mT.group('m')), int(mT.group('s')))
169 nowtime = int(dt.strftime('%s')) + utcoffset
170 else:
171 # if hardware time fails, use the software time
172 nowtime = int(datetime.now().strftime('%s'))
173 alarm = nowtime + self.rtcwaketime
174 os.system('echo %d > %s/wakealarm' % (alarm, self.rtcpath))
91 175
176sysvals = SystemValues()
177
178# Class: DeviceNode
179# Description:
180# A container used to create a device hierachy, with a single root node
181# and a tree of child nodes. Used by Data.deviceTopology()
182class DeviceNode:
183 name = ''
184 children = 0
185 depth = 0
186 def __init__(self, nodename, nodedepth):
187 self.name = nodename
188 self.children = []
189 self.depth = nodedepth
190
191# Class: Data
192# Description:
193# The primary container for suspend/resume test data. There is one for
194# each test run. The data is organized into a cronological hierarchy:
195#