aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile.lib1
-rwxr-xr-xscripts/analyze_suspend.py1446
-rwxr-xr-xscripts/checkpatch.pl204
-rw-r--r--scripts/coccinelle/api/pm_runtime.cocci109
-rw-r--r--scripts/gcc-goto.sh2
-rw-r--r--scripts/gen_initramfs_list.sh2
-rwxr-xr-xscripts/get_maintainer.pl93
-rw-r--r--scripts/headers_check.pl6
-rw-r--r--scripts/kconfig/streamline_config.pl7
-rw-r--r--scripts/mod/file2alias.c4
-rw-r--r--scripts/mod/modpost.c21
-rw-r--r--scripts/package/builddeb25
-rwxr-xr-xscripts/setlocalversion3
-rw-r--r--scripts/sortextable.c5
14 files changed, 1882 insertions, 46 deletions
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 49392ecbef17..79c059e70860 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -152,6 +152,7 @@ ld_flags = $(LDFLAGS) $(ldflags-y)
152dtc_cpp_flags = -Wp,-MD,$(depfile).pre.tmp -nostdinc \ 152dtc_cpp_flags = -Wp,-MD,$(depfile).pre.tmp -nostdinc \
153 -I$(srctree)/arch/$(SRCARCH)/boot/dts \ 153 -I$(srctree)/arch/$(SRCARCH)/boot/dts \
154 -I$(srctree)/arch/$(SRCARCH)/boot/dts/include \ 154 -I$(srctree)/arch/$(SRCARCH)/boot/dts/include \
155 -I$(srctree)/drivers/of/testcase-data \
155 -undef -D__DTS__ 156 -undef -D__DTS__
156 157
157# Finds the multi-part object the current object will be linked into 158# Finds the multi-part object the current object will be linked into
diff --git a/scripts/analyze_suspend.py b/scripts/analyze_suspend.py
new file mode 100755
index 000000000000..4f2cc12dc7c7
--- /dev/null
+++ b/scripts/analyze_suspend.py
@@ -0,0 +1,1446 @@
1#!/usr/bin/python
2#
3# Tool for analyzing suspend/resume timing
4# Copyright (c) 2013, Intel Corporation.
5#
6# This program is free software; you can redistribute it and/or modify it
7# under the terms and conditions of the GNU General Public License,
8# version 2, as published by the Free Software Foundation.
9#
10# This program is distributed in the hope it will be useful, but WITHOUT
11# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13# more details.
14#
15# You should have received a copy of the GNU General Public License along with
16# this program; if not, write to the Free Software Foundation, Inc.,
17# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18#
19# Authors:
20# Todd Brandt <todd.e.brandt@linux.intel.com>
21#
22# Description:
23# This tool is designed to assist kernel and OS developers in optimizing
24# their linux stack's suspend/resume time. Using a kernel image built
25# with a few extra options enabled, the tool will execute a suspend and
26# will capture dmesg and ftrace data until resume is complete. This data
27# is transformed into a device timeline and a callgraph to give a quick
28# and detailed view of which devices and callbacks are taking the most
29# time in suspend/resume. The output is a single html file which can be
30# viewed in firefox or chrome.
31#
32# The following kernel build options are required:
33# CONFIG_PM_DEBUG=y
34# CONFIG_PM_SLEEP_DEBUG=y
35# CONFIG_FTRACE=y
36# CONFIG_FUNCTION_TRACER=y
37# CONFIG_FUNCTION_GRAPH_TRACER=y
38#
39# The following additional kernel parameters are required:
40# (e.g. in file /etc/default/grub)
41# GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=16M ..."
42#
43
44import sys
45import time
46import os
47import string
48import re
49import array
50import platform
51import datetime
52import struct
53
54# -- classes --
55
56class SystemValues:
57 testdir = "."
58 tpath = "/sys/kernel/debug/tracing/"
59 mempath = "/dev/mem"
60 powerfile = "/sys/power/state"
61 suspendmode = "mem"
62 prefix = "test"
63 teststamp = ""
64 dmesgfile = ""
65 ftracefile = ""
66 htmlfile = ""
67 rtcwake = False
68 def setOutputFile(self):
69 if((self.htmlfile == "") and (self.dmesgfile != "")):
70 m = re.match(r"(?P<name>.*)_dmesg\.txt$", self.dmesgfile)
71 if(m):
72 self.htmlfile = m.group("name")+".html"
73 if((self.htmlfile == "") and (self.ftracefile != "")):
74 m = re.match(r"(?P<name>.*)_ftrace\.txt$", self.ftracefile)
75 if(m):
76 self.htmlfile = m.group("name")+".html"
77 if(self.htmlfile == ""):
78 self.htmlfile = "output.html"
79 def initTestOutput(self):
80 hostname = platform.node()
81 if(hostname != ""):
82 self.prefix = hostname
83 v = os.popen("cat /proc/version").read().strip()
84 kver = string.split(v)[2]
85 self.testdir = os.popen("date \"+suspend-%m%d%y-%H%M%S\"").read().strip()
86 self.teststamp = "# "+self.testdir+" "+self.prefix+" "+self.suspendmode+" "+kver
87 self.dmesgfile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+"_dmesg.txt"
88 self.ftracefile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+"_ftrace.txt"
89 self.htmlfile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+".html"
90 os.mkdir(self.testdir)
91
92class Data:
93 altdevname = dict()
94 usedmesg = False
95 useftrace = False
96 notestrun = False
97 verbose = False
98 phases = []
99 dmesg = {} # root data structure
100 start = 0.0
101 end = 0.0
102 stamp = {'time': "", 'host': "", 'mode': ""}
103 id = 0
104 tSuspended = 0.0
105 fwValid = False
106 fwSuspend = 0
107 fwResume = 0
108 def initialize(self):
109 self.dmesg = { # dmesg log data
110 'suspend_general': {'list': dict(), 'start': -1.0, 'end': -1.0,
111 'row': 0, 'color': "#CCFFCC", 'order': 0},
112 'suspend_early': {'list': dict(), 'start': -1.0, 'end': -1.0,
113 'row': 0, 'color': "green", 'order': 1},
114 'suspend_noirq': {'list': dict(), 'start': -1.0, 'end': -1.0,
115 'row': 0, 'color': "#00FFFF", 'order': 2},
116 'suspend_cpu': {'list': dict(), 'start': -1.0, 'end': -1.0,
117 'row': 0, 'color': "blue", 'order': 3},
118 'resume_cpu': {'list': dict(), 'start': -1.0, 'end': -1.0,
119 'row': 0, 'color': "red", 'order': 4},
120 'resume_noirq': {'list': dict(), 'start': -1.0, 'end': -1.0,
121 'row': 0, 'color': "orange", 'order': 5},
122 'resume_early': {'list': dict(), 'start': -1.0, 'end': -1.0,
123 'row': 0, 'color': "yellow", 'order': 6},
124 'resume_general': {'list': dict(), 'start': -1.0, 'end': -1.0,
125 'row': 0, 'color': "#FFFFCC", 'order': 7}
126 }
127 self.phases = self.sortedPhases()
128 def normalizeTime(self):
129 tSus = tRes = self.tSuspended
130 if self.fwValid:
131 tSus -= -self.fwSuspend / 1000000000.0
132 tRes -= self.fwResume / 1000000000.0
133 self.tSuspended = 0.0
134 self.start -= tSus
135 self.end -= tRes
136 for phase in self.phases:
137 zero = tRes
138 if "suspend" in phase:
139 zero = tSus
140 p = self.dmesg[phase]
141 p['start'] -= zero
142 p['end'] -= zero
143 list = p['list']
144 for name in list:
145 d = list[name]
146 d['start'] -= zero
147 d['end'] -= zero
148 if('ftrace' in d):
149 cg = d['ftrace']
150 cg.start -= zero
151 cg.end -= zero
152 for line in cg.list:
153 line.time -= zero
154 if self.fwValid:
155 fws = -self.fwSuspend / 1000000000.0
156 fwr = self.fwResume / 1000000000.0
157 list = dict()
158 self.id += 1
159 devid = "dc%d" % self.id
160 list["firmware-suspend"] = \
161 {'start': fws, 'end': 0, 'pid': 0, 'par': "",
162 'length': -fws, 'row': 0, 'id': devid };
163 self.id += 1
164 devid = "dc%d" % self.id
165 list["firmware-resume"] = \
166 {'start': 0, 'end': fwr, 'pid': 0, 'par': "",
167 'length': fwr, 'row': 0, 'id': devid };
168 self.dmesg['BIOS'] = \
169 {'list': list, 'start': fws, 'end': fwr,
170 'row': 0, 'color': "purple", 'order': 4}
171 self.dmesg['resume_cpu']['order'] += 1
172 self.dmesg['resume_noirq']['order'] += 1
173 self.dmesg['resume_early']['order'] += 1
174 self.dmesg['resume_general']['order'] += 1
175 self.phases = self.sortedPhases()
176 def vprint(self, msg):
177 if(self.verbose):
178 print(msg)
179 def dmesgSortVal(self, phase):
180 return self.dmesg[phase]['order']
181 def sortedPhases(self):
182 return sorted(self.dmesg, key=self.dmesgSortVal)
183 def sortedDevices(self, phase):
184 list = self.dmesg[phase]['list']
185 slist = []
186 tmp = dict()
187 for devname in list:
188 dev = list[devname]
189 tmp[dev['start']] = devname
190 for t in sorted(tmp):
191 slist.append(tmp[t])
192 return slist
193 def fixupInitcalls(self, phase, end):
194 # if any calls never returned, clip them at system resume end
195 phaselist = self.dmesg[phase]['list']
196 for devname in phaselist:
197 dev = phaselist[devname]
198 if(dev['end'] < 0):
199 dev['end'] = end
200 self.vprint("%s (%s): callback didn't return" % (devname, phase))
201 def fixupInitcallsThatDidntReturn(self):
202 # if any calls never returned, clip them at system resume end
203 for phase in self.phases:
204 self.fixupInitcalls(phase, self.dmesg['resume_general']['end'])
205 if(phase == "resume_general"):
206 break
207 def newAction(self, phase, name, pid, parent, start, end):
208 self.id += 1
209 devid = "dc%d" % self.id
210 list = self.dmesg[phase]['list']
211 length = -1.0
212 if(start >= 0 and end >= 0):
213 length = end - start
214 list[name] = {'start': start, 'end': end, 'pid': pid, 'par': parent,
215 'length': length, 'row': 0, 'id': devid }
216 def deviceIDs(self, devlist, phase):
217 idlist = []
218 for p in self.phases:
219 if(p[0] != phase[0]):
220 continue
221 list = data.dmesg[p]['list']
222 for devname in list:
223 if devname in devlist:
224 idlist.append(list[devname]['id'])
225 return idlist
226 def deviceParentID(self, devname, phase):
227 pdev = ""
228 pdevid = ""
229 for p in self.phases:
230 if(p[0] != phase[0]):
231 continue
232 list = data.dmesg[p]['list']
233 if devname in list:
234 pdev = list[devname]['par']
235 for p in self.phases:
236 if(p[0] != phase[0]):
237 continue
238 list = data.dmesg[p]['list']
239 if pdev in list:
240 return list[pdev]['id']
241 return pdev
242 def deviceChildrenIDs(self, devname, phase):
243 devlist = []
244 for p in self.phases:
245 if(p[0] != phase[0]):
246 continue
247 list = data.dmesg[p]['list']
248 for child in list:
249 if(list[child]['par'] == devname):
250 devlist.append(child)
251 return self.deviceIDs(devlist, phase)
252
253class FTraceLine:
254 time = 0.0
255 length = 0.0
256 fcall = False
257 freturn = False
258 fevent = False
259 depth = 0
260 name = ""
261 def __init__(self, t, m, d):
262 self.time = float(t)
263 # check to see if this is a trace event
264 em = re.match(r"^ *\/\* *(?P<msg>.*) \*\/ *$", m)
265 if(em):
266 self.name = em.group("msg")
267 self.fevent = True
268 return
269 # convert the duration to seconds
270 if(d):
271 self.length = float(d)/1000000
272 # the indentation determines the depth
273 match = re.match(r"^(?P<d> *)(?P<o>.*)$", m)
274 if(not match):
275 return
276 self.depth = self.getDepth(match.group('d'))
277 m = match.group('o')
278 # function return
279 if(m[0] == '}'):
280 self.freturn = True
281 if(len(m) > 1):
282 # includes comment with function name
283 match = re.match(r"^} *\/\* *(?P<n>.*) *\*\/$", m)
284 if(match):
285 self.name = match.group('n')
286 # function call
287 else:
288 self.fcall = True
289 # function call with children
290 if(m[-1] == '{'):
291 match = re.match(r"^(?P<n>.*) *\(.*", m)
292 if(match):
293 self.name = match.group('n')
294 # function call with no children (leaf)
295 elif(m[-1] == ';'):
296 self.freturn = True
297 match = re.match(r"^(?P<n>.*) *\(.*", m)
298 if(match):
299 self.name = match.group('n')
300 # something else (possibly a trace marker)
301 else:
302 self.name = m
303 def getDepth(self, str):
304 return len(str)/2
305
306class FTraceCallGraph:
307 start = -1.0
308 end = -1.0
309 list = []
310 invalid = False
311 depth = 0
312 def __init__(self):
313 self.start = -1.0
314 self.end = -1.0
315 self.list = []
316 self.depth = 0
317 def setDepth(self, line):
318 if(line.fcall and not line.freturn):
319 line.depth = self.depth
320 self.depth += 1
321 elif(line.freturn and not line.fcall):
322 self.depth -= 1
323 line.depth = self.depth
324 else:
325 line.depth = self.depth
326 def addLine(self, line, match):
327 if(not self.invalid):
328 self.setDepth(line)
329 if(line.depth == 0 and line.freturn):
330 self.end = line.time
331 self.list.append(line)
332 return True
333 if(self.invalid):
334 return False
335 if(len(self.list) >= 1000000 or self.depth < 0):
336 first = self.list[0]
337 self.list = []
338 self.list.append(first)
339 self.invalid = True
340 id = "task %s cpu %s" % (match.group("pid"), match.group("cpu"))
341 window = "(%f - %f)" % (self.start, line.time)
342 data.vprint("Too much data for "+id+" "+window+", ignoring this callback")
343 return False
344 self.list.append(line)
345 if(self.start < 0):
346 self.start = line.time
347 return False
348 def sanityCheck(self):
349 stack = dict()
350 cnt = 0
351 for l in self.list:
352 if(l.fcall and not l.freturn):
353 stack[l.depth] = l
354 cnt += 1
355 elif(l.freturn and not l.fcall):
356 if(not stack[l.depth]):
357 return False
358 stack[l.depth].length = l.length
359 stack[l.depth] = 0
360 l.length = 0
361 cnt -= 1
362 if(cnt == 0):
363 return True
364 return False
365 def debugPrint(self, filename):
366 if(filename == "stdout"):
367 print("[%f - %f]") % (self.start, self.end)
368 for l in self.list:
369 if(l.freturn and l.fcall):
370 print("%f (%02d): %s(); (%.3f us)" % (l.time, l.depth, l.name, l.length*1000000))
371 elif(l.freturn):
372 print("%f (%02d): %s} (%.3f us)" % (l.time, l.depth, l.name, l.length*1000000))
373 else:
374 print("%f (%02d): %s() { (%.3f us)" % (l.time, l.depth, l.name, l.length*1000000))
375 print(" ")
376 else:
377 fp = open(filename, 'w')
378 print(filename)
379 for l in self.list:
380 if(l.freturn and l.fcall):
381 fp.write("%f (%02d): %s(); (%.3f us)\n" % (l.time, l.depth, l.name, l.length*1000000))
382 elif(l.freturn):
383 fp.write("%f (%02d): %s} (%.3f us)\n" % (l.time, l.depth, l.name, l.length*1000000))
384 else:
385 fp.write("%f (%02d): %s() { (%.3f us)\n" % (l.time, l.depth, l.name, l.length*1000000))
386 fp.close()
387
388class Timeline:
389 html = {}
390 scaleH = 0.0 # height of the timescale row as a percent of the timeline height
391 rowH = 0.0 # height of each row in percent of the timeline height
392 row_height_pixels = 30
393 maxrows = 0
394 height = 0
395 def __init__(self):
396 self.html = {
397 'timeline': "",
398 'legend': "",
399 'scale': ""
400 }
401 def setRows(self, rows):
402 self.maxrows = int(rows)
403 self.scaleH = 100.0/float(self.maxrows)
404 self.height = self.maxrows*self.row_height_pixels
405 r = float(self.maxrows - 1)
406 if(r < 1.0):
407 r = 1.0
408 self.rowH = (100.0 - self.scaleH)/r
409
410# -- global objects --
411
412sysvals = SystemValues()
413data = Data()
414
415# -- functions --
416
417# Function: initFtrace
418# Description:
419# Configure ftrace to capture a function trace during suspend/resume
420def initFtrace():
421 global sysvals
422
423 print("INITIALIZING FTRACE...")
424 # turn trace off
425 os.system("echo 0 > "+sysvals.tpath+"tracing_on")
426 # set the trace clock to global
427 os.system("echo global > "+sysvals.tpath+"trace_clock")
428 # set trace buffer to a huge value
429 os.system("echo nop > "+sysvals.tpath+"current_tracer")
430 os.system("echo 100000 > "+sysvals.tpath+"buffer_size_kb")
431 # clear the trace buffer
432 os.system("echo \"\" > "+sysvals.tpath+"trace")
433 # set trace type
434 os.system("echo function_graph > "+sysvals.tpath+"current_tracer")
435 os.system("echo \"\" > "+sysvals.tpath+"set_ftrace_filter")
436 # set trace format options
437 os.system("echo funcgraph-abstime > "+sysvals.tpath+"trace_options")
438 os.system("echo funcgraph-proc > "+sysvals.tpath+"trace_options")
439 # focus only on device suspend and resume
440 os.system("cat "+sysvals.tpath+"available_filter_functions | grep dpm_run_callback > "+sysvals.tpath+"set_graph_function")
441
442# Function: verifyFtrace
443# Description:
444# Check that ftrace is working on the system
445def verifyFtrace():
446 global sysvals
447 files = ["available_filter_functions", "buffer_size_kb",
448 "current_tracer", "set_ftrace_filter",
449 "trace", "trace_marker"]
450 for f in files:
451 if(os.path.exists(sysvals.tpath+f) == False):
452 return False
453 return True
454
455def parseStamp(line):
456 global data, sysvals
457 stampfmt = r"# suspend-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-"+\
458 "(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})"+\
459 " (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$"
460 m = re.match(stampfmt, line)
461 if(m):
462 dt = datetime.datetime(int(m.group("y"))+2000, int(m.group("m")),
463 int(m.group("d")), int(m.group("H")), int(m.group("M")),
464 int(m.group("S")))
465 data.stamp['time'] = dt.strftime("%B %d %Y, %I:%M:%S %p")
466 data.stamp['host'] = m.group("host")
467 data.stamp['mode'] = m.group("mode")
468 data.stamp['kernel'] = m.group("kernel")
469 sysvals.suspendmode = data.stamp['mode']
470
471# Function: analyzeTraceLog
472# Description:
473# Analyse an ftrace log output file generated from this app during
474# the execution phase. Create an "ftrace" structure in memory for
475# subsequent formatting in the html output file
476def analyzeTraceLog():
477 global sysvals, data
478
479 # the ftrace data is tied to the dmesg data
480 if(not data.usedmesg):
481 return
482
483 # read through the ftrace and parse the data
484 data.vprint("Analyzing the ftrace data...")
485 ftrace_line_fmt = r"^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)"+\
486 " *(?P<proc>.*)-(?P<pid>[0-9]*) *\|"+\
487 "[ +!]*(?P<dur>[0-9\.]*) .*\| (?P<msg>.*)"
488 ftemp = dict()
489 inthepipe = False
490 tf = open(sysvals.ftracefile, 'r')
491 count = 0
492 for line in tf:
493 count = count + 1
494 # grab the time stamp if it's valid
495 if(count == 1):
496 parseStamp(line)
497 continue
498 # parse only valid lines
499 m = re.match(ftrace_line_fmt, line)
500 if(not m):
501 continue
502 m_time = m.group("time")
503 m_pid = m.group("pid")
504 m_msg = m.group("msg")
505 m_dur = m.group("dur")
506 if(m_time and m_pid and m_msg):
507 t = FTraceLine(m_time, m_msg, m_dur)
508 pid = int(m_pid)
509 else:
510 continue
511 # the line should be a call, return, or event
512 if(not t.fcall and not t.freturn and not t.fevent):
513 continue
514 # only parse the ftrace data during suspend/resume
515 if(not inthepipe):
516 # look for the suspend start marker
517 if(t.fevent):
518 if(t.name == "SUSPEND START"):
519 data.vprint("SUSPEND START %f %s:%d" % (t.time, sysvals.ftracefile, count))
520 inthepipe = True
521 continue
522 else:
523 # look for the resume end marker
524 if(t.fevent):
525 if(t.name == "RESUME COMPLETE"):
526 data.vprint("RESUME COMPLETE %f %s:%d" % (t.time, sysvals.ftracefile, count))
527 inthepipe = False
528 break
529 continue
530 # create a callgraph object for the data
531 if(pid not in ftemp):
532 ftemp[pid] = FTraceCallGraph()
533 # when the call is finished, see which device matches it
534 if(ftemp[pid].addLine(t, m)):
535 if(not ftemp[pid].sanityCheck()):
536 id = "task %s cpu %s" % (pid, m.group("cpu"))
537 data.vprint("Sanity check failed for "+id+", ignoring this callback")
538 continue
539 callstart = ftemp[pid].start
540 callend = ftemp[pid].end
541 for p in data.phases:
542 if(data.dmesg[p]['start'] <= callstart and callstart <= data.dmesg[p]['end']):
543 list = data.dmesg[p]['list']
544 for devname in list:
545 dev = list[devname]
546 if(pid == dev['pid'] and callstart <= dev['start'] and callend >= dev['end']):
547 data.vprint("%15s [%f - %f] %s(%d)" % (p, callstart, callend, devname, pid))
548 dev['ftrace'] = ftemp[pid]
549 break
550 ftemp[pid] = FTraceCallGraph()
551 tf.close()
552
553# Function: sortKernelLog
554# Description:
555# The dmesg output log sometimes comes with with lines that have
556# timestamps out of order. This could cause issues since a call
557# could accidentally end up in the wrong phase
558def sortKernelLog():
559 global sysvals, data
560 lf = open(sysvals.dmesgfile, 'r')
561 dmesglist = []
562 count = 0
563 for line in lf:
564 line = line.replace("\r\n", "")
565 if(count == 0):
566 parseStamp(line)
567 elif(count == 1):
568 m = re.match(r"# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$", line)
569 if(m):
570 data.fwSuspend = int(m.group("s"))
571 data.fwResume = int(m.group("r"))
572 if(data.fwSuspend > 0 or data.fwResume > 0):
573 data.fwValid = True
574 if(re.match(r".*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)", line)):
575 dmesglist.append(line)
576 count += 1
577 lf.close()
578 last = ""
579
580 # fix lines with the same time stamp and function with the call and return swapped
581 for line in dmesglist:
582 mc = re.match(r".*(\[ *)(?P<t>[0-9\.]*)(\]) calling (?P<f>.*)\+ @ .*, parent: .*", line)
583 mr = re.match(r".*(\[ *)(?P<t>[0-9\.]*)(\]) call (?P<f>.*)\+ returned .* after (?P<dt>.*) usecs", last)
584 if(mc and mr and (mc.group("t") == mr.group("t")) and (mc.group("f") == mr.group("f"))):
585 i = dmesglist.index(last)
586 j = dmesglist.index(line)
587 dmesglist[i] = line
588 dmesglist[j] = last
589 last = line
590 return dmesglist
591
592# Function: analyzeKernelLog
593# Description:
594# Analyse a dmesg log output file generated from this app during
595# the execution phase. Create a set of device structures in memory
596# for subsequent formatting in the html output file
597def analyzeKernelLog():
598 global sysvals, data
599
600 print("PROCESSING DATA")
601 data.vprint("Analyzing the dmesg data...")
602 if(os.path.exists(sysvals.dmesgfile) == False):
603 print("ERROR: %s doesn't exist") % sysvals.dmesgfile
604 return False
605
606 lf = sortKernelLog()
607 phase = "suspend_runtime"
608
609 dm = {
610 'suspend_general': r"PM: Syncing filesystems.*",
611 'suspend_early': r"PM: suspend of devices complete after.*",
612 'suspend_noirq': r"PM: late suspend of devices complete after.*",
613 'suspend_cpu': r"PM: noirq suspend of devices complete after.*",
614 'resume_cpu': r"ACPI: Low-level resume complete.*",
615 'resume_noirq': r"ACPI: Waking up from system sleep state.*",
616 'resume_early': r"PM: noirq resume of devices complete after.*",
617 'resume_general': r"PM: early resume of devices complete after.*",
618 'resume_complete': r".*Restarting tasks \.\.\..*",
619 }
620 if(sysvals.suspendmode == "standby"):
621 dm['resume_cpu'] = r"PM: Restoring platform NVS memory"
622 elif(sysvals.suspendmode == "disk"):
623 dm['suspend_early'] = r"PM: freeze of devices complete after.*"
624 dm['suspend_noirq'] = r"PM: late freeze of devices complete after.*"
625 dm['suspend_cpu'] = r"PM: noirq freeze of devices complete after.*"
626 dm['resume_cpu'] = r"PM: Restoring platform NVS memory"
627 dm['resume_early'] = r"PM: noirq restore of devices complete after.*"
628 dm['resume_general'] = r"PM: early restore of devices complete after.*"
629
630 action_start = 0.0
631 for line in lf:
632 # -- preprocessing --
633 # parse each dmesg line into the time and message
634 m = re.match(r".*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)", line)
635 if(m):
636 ktime = float(m.group("ktime"))
637 msg = m.group("msg")
638 else:
639 print line
640 continue
641
642 # -- phase changes --
643 # suspend_general start
644 if(re.match(dm['suspend_general'], msg)):
645 phase = "suspend_general"
646 data.dmesg[phase]['start'] = ktime
647 data.start = ktime
648 # action start: syncing filesystems
649 action_start = ktime
650 # suspend_early start
651 elif(re.match(dm['suspend_early'], msg)):
652 data.dmesg["suspend_general"]['end'] = ktime
653 phase = "suspend_early"
654 data.dmesg[phase]['start'] = ktime
655 # suspend_noirq start
656 elif(re.match(dm['suspend_noirq'], msg)):
657 data.dmesg["suspend_early"]['end'] = ktime
658 phase = "suspend_noirq"
659 data.dmesg[phase]['start'] = ktime
660 # suspend_cpu start
661 elif(re.match(dm['suspend_cpu'], msg)):
662 data.dmesg["suspend_noirq"]['end'] = ktime
663 phase = "suspend_cpu"
664 data.dmesg[phase]['start'] = ktime
665 # resume_cpu start
666 elif(re.match(dm['resume_cpu'], msg)):
667 data.tSuspended = ktime
668 data.dmesg["suspend_cpu"]['end'] = ktime
669 phase = "resume_cpu"
670 data.dmesg[phase]['start'] = ktime
671 # resume_noirq start
672 elif(re.match(dm['resume_noirq'], msg)):
673 data.dmesg["resume_cpu"]['end'] = ktime
674 phase = "resume_noirq"
675 data.dmesg[phase]['start'] = ktime
676 # action end: ACPI resume
677 data.newAction("resume_cpu", "ACPI", -1, "", action_start, ktime)
678 # resume_early start
679 elif(re.match(dm['resume_early'], msg)):
680 data.dmesg["resume_noirq"]['end'] = ktime
681 phase = "resume_early"
682 data.dmesg[phase]['start'] = ktime
683 # resume_general start
684 elif(re.match(dm['resume_general'], msg)):
685 data.dmesg["resume_early"]['end'] = ktime
686 phase = "resume_general"
687 data.dmesg[phase]['start'] = ktime
688 # resume complete start
689 elif(re.match(dm['resume_complete'], msg)):
690 data.dmesg["resume_general"]['end'] = ktime
691 data.end = ktime
692 phase = "resume_runtime"
693 break
694
695 # -- device callbacks --
696 if(phase in data.phases):
697 # device init call
698 if(re.match(r"calling (?P<f>.*)\+ @ .*, parent: .*", msg)):
699 sm = re.match(r"calling (?P<f>.*)\+ @ (?P<n>.*), parent: (?P<p>.*)", msg);
700 f = sm.group("f")
701 n = sm.group("n")
702 p = sm.group("p")
703 if(f and n and p):
704 data.newAction(phase, f, int(n), p, ktime, -1)
705 # device init return
706 elif(re.match(r"call (?P<f>.*)\+ returned .* after (?P<t>.*) usecs", msg)):
707 sm = re.match(r"call (?P<f>.*)\+ returned .* after (?P<t>.*) usecs(?P<a>.*)", msg);
708 f = sm.group("f")
709 t = sm.group("t")
710 list = data.dmesg[phase]['list']
711 if(f in list):
712 dev = list[f]
713 dev['length'] = int(t)
714 dev['end'] = ktime
715 data.vprint("%15s [%f - %f] %s(%d) %s" %
716 (phase, dev['start'], dev['end'], f, dev['pid'], dev['par']))
717
718 # -- phase specific actions --
719 if(phase == "suspend_general"):
720 if(re.match(r"PM: Preparing system for mem sleep.*", msg)):
721 data.newAction(phase, "filesystem-sync", -1, "", action_start, ktime)
722 elif(re.match(r"Freezing user space processes .*", msg)):
723 action_start = ktime
724 elif(re.match(r"Freezing remaining freezable tasks.*", msg)):
725 data.newAction(phase, "freeze-user-processes", -1, "", action_start, ktime)
726 action_start = ktime
727 elif(re.match(r"PM: Entering (?P<mode>[a-z,A-Z]*) sleep.*", msg)):
728 data.newAction(phase, "freeze-tasks", -1, "", action_start, ktime)
729 elif(phase == "suspend_cpu"):
730 m = re.match(r"smpboot: CPU (?P<cpu>[0-9]*) is now offline", msg)
731 if(m):
732 cpu = "CPU"+m.group("cpu")
733 data.newAction(phase, cpu, -1, "", action_start, ktime)
734 action_start = ktime
735 elif(re.match(r"ACPI: Preparing to enter system sleep state.*", msg)):
736 action_start = ktime
737 elif(re.match(r"Disabling non-boot CPUs .*", msg)):
738 data.newAction(phase, "ACPI", -1, "", action_start, ktime)
739 action_start = ktime
740 elif(phase == "resume_cpu"):
741 m = re.match(r"CPU(?P<cpu>[0-9]*) is up", msg)
742 if(m):
743 cpu = "CPU"+m.group("cpu")
744 data.newAction(phase, cpu, -1, "", action_start, ktime)
745 action_start = ktime
746 elif(re.match(r"Enabling non-boot CPUs .*", msg)):
747 action_start = ktime
748
749 # fill in any missing phases
750 lp = "suspend_general"
751 for p in data.phases:
752 if(p == "suspend_general"):
753 continue
754 if(data.dmesg[p]['start'] < 0):
755 data.dmesg[p]['start'] = data.dmesg[lp]['end']
756 if(p == "resume_cpu"):
757 data.tSuspended = data.dmesg[lp]['end']
758 if(data.dmesg[p]['end'] < 0):
759 data.dmesg[p]['end'] = data.dmesg[p]['start']
760 lp = p
761
762 data.fixupInitcallsThatDidntReturn()
763 return True
764
765# Function: setTimelineRows
766# Description:
767# Organize the device or thread lists into the smallest
768# number of rows possible, with no entry overlapping
769# Arguments:
770# list: the list to sort (dmesg or ftrace)
771# sortedkeys: sorted key list to use
772def setTimelineRows(list, sortedkeys):
773 global data
774
775 # clear all rows and set them to undefined
776 remaining = len(list)
777 rowdata = dict()
778 row = 0
779 for item in list:
780 list[item]['row'] = -1
781
782 # try to pack each row with as many ranges as possible
783 while(remaining > 0):
784 if(row not in rowdata):
785 rowdata[row] = []
786 for item in sortedkeys:
787 if(list[item]['row'] < 0):
788 s = list[item]['start']
789 e = list[item]['end']
790 valid = True
791 for ritem in rowdata[row]:
792 rs = ritem['start']
793 re = ritem['end']
794 if(not (((s <= rs) and (e <= rs)) or ((s >= re) and (e >= re)))):
795 valid = False
796 break
797 if(valid):
798 rowdata[row].append(list[item])
799 list[item]['row'] = row
800 remaining -= 1
801 row += 1
802 return row
803
804# Function: createTimeScale
805# Description:
806# Create timescale lines for the dmesg and ftrace timelines
807# Arguments:
808# t0: start time (suspend begin)
809# tMax: end time (resume end)
810# tSuspend: time when suspend occurs
811def createTimeScale(t0, tMax, tSuspended):
812 global data
813 timescale = "<div class=\"t\" style=\"right:{0}%\">{1}</div>\n"
814 output = '<div id="timescale">\n'
815
816 # set scale for timeline
817 tTotal = tMax - t0
818 tS = 0.1
819 if(tTotal <= 0):
820 return output
821 if(tTotal > 4):
822 tS = 1
823 if(tSuspended < 0):
824 for i in range(int(tTotal/tS)+1):
825 pos = "%0.3f" % (100 - ((float(i)*tS*100)/tTotal))
826 if(i > 0):
827 val = "%0.f" % (float(i)*tS*1000)
828 else:
829 val = ""
830 output += timescale.format(pos, val)
831 else:
832 tSuspend = tSuspended - t0
833 divTotal = int(tTotal/tS) + 1
834 divSuspend = int(tSuspend/tS)
835 s0 = (tSuspend - tS*divSuspend)*100/tTotal
836 for i in range(divTotal):
837 pos = "%0.3f" % (100 - ((float(i)*tS*100)/tTotal) - s0)
838 if((i == 0) and (s0 < 3)):
839 val = ""
840 elif(i == divSuspend):
841 val = "S/R"
842 else:
843 val = "%0.f" % (float(i-divSuspend)*tS*1000)
844 output += timescale.format(pos, val)
845 output += '</div>\n'
846 return output
847
848# Function: createHTML
849# Description:
850# Create the output html file.
851def createHTML():
852 global sysvals, data
853
854 data.normalizeTime()
855
856 # html function templates
857 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n'
858 html_zoombox = '<center><button id="zoomin">ZOOM IN</button><button id="zoomout">ZOOM OUT</button><button id="zoomdef">ZOOM 1:1</button></center>\n<div id="dmesgzoombox" class="zoombox">\n'
859 html_timeline = '<div id="{0}" class="timeline" style="height:{1}px">\n'
860 html_device = '<div id="{0}" title="{1}" class="thread" style="left:{2}%;top:{3}%;height:{4}%;width:{5}%;">{6}</div>\n'
861 html_phase = '<div class="phase" style="left:{0}%;width:{1}%;top:{2}%;height:{3}%;background-color:{4}">{5}</div>\n'
862 html_legend = '<div class="square" style="left:{0}%;background-color:{1}">&nbsp;{2}</div>\n'
863 html_timetotal = '<table class="time1">\n<tr>'\
864 '<td class="gray">{2} Suspend Time: <b>{0} ms</b></td>'\
865 '<td class="gray">{2} Resume Time: <b>{1} ms</b></td>'\
866 '</tr>\n</table>\n'
867 html_timegroups = '<table class="time2">\n<tr>'\
868 '<td class="green">Kernel Suspend: {0} ms</td>'\
869 '<td class="purple">Firmware Suspend: {1} ms</td>'\
870 '<td class="purple">Firmware Resume: {2} ms</td>'\
871 '<td class="yellow">Kernel Resume: {3} ms</td>'\
872 '</tr>\n</table>\n'
873
874 # device timeline (dmesg)
875 if(data.usedmesg):
876 data.vprint("Creating Device Timeline...")
877 devtl = Timeline()
878
879 # Generate the header for this timeline
880 t0 = data.start
881 tMax = data.end
882 tTotal = tMax - t0
883 if(tTotal == 0):
884 print("ERROR: No timeline data")
885 sys.exit()
886 suspend_time = "%.0f"%(-data.start*1000)
887 resume_time = "%.0f"%(data.end*1000)
888 if data.fwValid:
889 devtl.html['timeline'] = html_timetotal.format(suspend_time, resume_time, "Total")
890 sktime = "%.3f"%((data.dmesg['suspend_cpu']['end'] - data.dmesg['suspend_general']['start'])*1000)
891 sftime = "%.3f"%(data.fwSuspend / 1000000.0)
892 rftime = "%.3f"%(data.fwResume / 1000000.0)
893 rktime = "%.3f"%((data.dmesg['resume_general']['end'] - data.dmesg['resume_cpu']['start'])*1000)
894 devtl.html['timeline'] += html_timegroups.format(sktime, sftime, rftime, rktime)
895 else:
896 devtl.html['timeline'] = html_timetotal.format(suspend_time, resume_time, "Kernel")
897
898 # determine the maximum number of rows we need to draw
899 timelinerows = 0
900 for phase in data.dmesg:
901 list = data.dmesg[phase]['list']
902 rows = setTimelineRows(list, list)
903 data.dmesg[phase]['row'] = rows
904 if(rows > timelinerows):
905 timelinerows = rows
906
907 # calculate the timeline height and create its bounding box
908 devtl.setRows(timelinerows + 1)
909 devtl.html['timeline'] += html_zoombox;
910 devtl.html['timeline'] += html_timeline.format("dmesg", devtl.height);
911
912 # draw the colored boxes for each of the phases
913 for b in data.dmesg:
914 phase = data.dmesg[b]
915 left = "%.3f" % (((phase['start']-data.start)*100)/tTotal)
916 width = "%.3f" % (((phase['end']-phase['start'])*100)/tTotal)
917 devtl.html['timeline'] += html_phase.format(left, width, "%.3f"%devtl.scaleH, "%.3f"%(100-devtl.scaleH), data.dmesg[b]['color'], "")
918
919 # draw the time scale, try to make the number of labels readable
920 devtl.html['scale'] = createTimeScale(t0, tMax, data.tSuspended)
921 devtl.html['timeline'] += devtl.html['scale']
922 for b in data.dmesg:
923 phaselist = data.dmesg[b]['list']
924 for d in phaselist:
925 name = d
926 if(d in data.altdevname):
927 name = data.altdevname[d]
928 dev = phaselist[d]
929 height = (100.0 - devtl.scaleH)/data.dmesg[b]['row']
930 top = "%.3f" % ((dev['row']*height) + devtl.scaleH)
931 left = "%.3f" % (((dev['start']-data.start)*100)/tTotal)
932 width = "%.3f" % (((dev['end']-dev['start'])*100)/tTotal)
933 len = " (%0.3f ms) " % ((dev['end']-dev['start'])*1000)
934 color = "rgba(204,204,204,0.5)"
935 devtl.html['timeline'] += html_device.format(dev['id'], name+len+b, left, top, "%.3f"%height, width, name)
936
937 # timeline is finished
938 devtl.html['timeline'] += "</div>\n</div>\n"
939
940 # draw a legend which describes the phases by color
941 devtl.html['legend'] = "<div class=\"legend\">\n"
942 pdelta = 100.0/data.phases.__len__()
943 pmargin = pdelta / 4.0
944 for phase in data.phases:
945 order = "%.2f" % ((data.dmesg[phase]['order'] * pdelta) + pmargin)
946 name = string.replace(phase, "_", " &nbsp;")
947 devtl.html['legend'] += html_legend.format(order, data.dmesg[phase]['color'], name)
948 devtl.html['legend'] += "</div>\n"
949
950 hf = open(sysvals.htmlfile, 'w')
951 thread_height = 0
952
953 # write the html header first (html head, css code, everything up to the start of body)
954 html_header = "<!DOCTYPE html>\n<html>\n<head>\n\
955 <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n\
956 <title>AnalyzeSuspend</title>\n\
957 <style type='text/css'>\n\
958 body {overflow-y: scroll;}\n\
959 .stamp {width: 100%;text-align:center;background-color:gray;line-height:30px;color:white;font: 25px Arial;}\n\
960 .callgraph {margin-top: 30px;box-shadow: 5px 5px 20px black;}\n\
961 .callgraph article * {padding-left: 28px;}\n\
962 h1 {color:black;font: bold 30px Times;}\n\
963 table {width:100%;}\n\
964 .gray {background-color:rgba(80,80,80,0.1);}\n\
965 .green {background-color:rgba(204,255,204,0.4);}\n\
966 .purple {background-color:rgba(128,0,128,0.2);}\n\
967 .yellow {background-color:rgba(255,255,204,0.4);}\n\
968 .time1 {font: 22px Arial;border:1px solid;}\n\
969 .time2 {font: 15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\
970 td {text-align: center;}\n\
971 .tdhl {color: red;}\n\
972 .hide {display: none;}\n\
973 .pf {display: none;}\n\
974 .pf:checked + 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\
975 .pf:not(:checked) ~ 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\
976 .pf:checked ~ *:not(:nth-child(2)) {display: none;}\n\
977 .zoombox {position: relative; width: 100%; overflow-x: scroll;}\n\
978 .timeline {position: relative; font-size: 14px;cursor: pointer;width: 100%; overflow: hidden; background-color:#dddddd;}\n\
979 .thread {position: absolute; height: "+"%.3f"%thread_height+"%; overflow: hidden; line-height: 30px; border:1px solid;text-align:center;white-space:nowrap;background-color:rgba(204,204,204,0.5);}\n\
980 .thread:hover {background-color:white;border:1px solid red;z-index:10;}\n\
981 .phase {position: absolute;overflow: hidden;border:0px;text-align:center;}\n\
982 .t {position: absolute; top: 0%; height: 100%; border-right:1px solid black;}\n\
983 .legend {position: relative; width: 100%; height: 40px; text-align: center;margin-bottom:20px}\n\
984 .legend .square {position:absolute;top:10px; width: 0px;height: 20px;border:1px solid;padding-left:20px;}\n\
985 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\
986 </style>\n</head>\n<body>\n"
987 hf.write(html_header)
988
989 # write the test title and general info header
990 if(data.stamp['time'] != ""):
991 hf.write(headline_stamp.format(data.stamp['host'],
992 data.stamp['kernel'], data.stamp['mode'], data.stamp['time']))
993
994 # write the dmesg data (device timeline)
995 if(data.usedmesg):
996 hf.write(devtl.html['timeline'])
997 hf.write(devtl.html['legend'])
998 hf.write('<div id="devicedetail"></div>\n')
999 hf.write('<div id="devicetree"></div>\n')
1000
1001 # write the ftrace data (callgraph)
1002 if(data.useftrace):
1003 hf.write('<section id="callgraphs" class="callgraph">\n')
1004 # write out the ftrace data converted to html
1005 html_func_top = '<article id="{0}" class="atop" style="background-color:{1}">\n<input type="checkbox" class="pf" id="f{2}" checked/><label for="f{2}">{3} {4}</label>\n'
1006 html_func_start = '<article>\n<input type="checkbox" class="pf" id="f{0}" checked/><label for="f{0}">{1} {2}</label>\n'
1007 html_func_end = '</article>\n'
1008 html_func_leaf = '<article>{0} {1}</article>\n'
1009 num = 0
1010 for p in data.phases:
1011 list = data.dmesg[p]['list']
1012 for devname in data.sortedDevices(p):
1013 if('ftrace' not in list[devname]):
1014 continue
1015 name = devname
1016 if(devname in data.altdevname):
1017 name = data.altdevname[devname]
1018 devid = list[devname]['id']
1019 cg = list[devname]['ftrace']
1020 flen = "(%.3f ms)" % ((cg.end - cg.start)*1000)
1021 hf.write(html_func_top.format(devid, data.dmesg[p]['color'], num, name+" "+p, flen))
1022 num += 1
1023 for line in cg.list:
1024 if(line.length < 0.000000001):
1025 flen = ""
1026 else:
1027 flen = "(%.3f ms)" % (line.length*1000)
1028 if(line.freturn and line.fcall):
1029 hf.write(html_func_leaf.format(line.name, flen))
1030 elif(line.freturn):
1031 hf.write(html_func_end)
1032 else:
1033 hf.write(html_func_start.format(num, line.name, flen))
1034 num += 1
1035 hf.write(html_func_end)
1036 hf.write("\n\n </section>\n")
1037 # write the footer and close
1038 addScriptCode(hf)
1039 hf.write("</body>\n</html>\n")
1040 hf.close()
1041 return True
1042
1043def addScriptCode(hf):
1044 global data
1045
1046 t0 = (data.start - data.tSuspended) * 1000
1047 tMax = (data.end - data.tSuspended) * 1000
1048 # create an array in javascript memory with the device details
1049 detail = ' var bounds = [%f,%f];\n' % (t0, tMax)
1050 detail += ' var d = [];\n'
1051 dfmt = ' d["%s"] = { n:"%s", p:"%s", c:[%s] };\n';
1052 for p in data.dmesg:
1053 list = data.dmesg[p]['list']
1054 for d in list:
1055 parent = data.deviceParentID(d, p)
1056 idlist = data.deviceChildrenIDs(d, p)
1057 idstr = ""
1058 for i in idlist:
1059 if(idstr == ""):
1060 idstr += '"'+i+'"'
1061 else:
1062 idstr += ', '+'"'+i+'"'
1063 detail += dfmt % (list[d]['id'], d, parent, idstr)
1064
1065 # add the code which will manipulate the data in the browser
1066 script_code = \
1067 '<script type="text/javascript">\n'+detail+\
1068 ' var filter = [];\n'\
1069 ' var table = [];\n'\
1070 ' function deviceParent(devid) {\n'\
1071 ' var devlist = [];\n'\
1072 ' if(filter.indexOf(devid) < 0) filter[filter.length] = devid;\n'\
1073 ' if(d[devid].p in d)\n'\
1074 ' devlist = deviceParent(d[devid].p);\n'\
1075 ' else if(d[devid].p != "")\n'\
1076 ' devlist = [d[devid].p];\n'\
1077 ' devlist[devlist.length] = d[devid].n;\n'\
1078 ' return devlist;\n'\
1079 ' }\n'\
1080 ' function deviceChildren(devid, column, row) {\n'\
1081 ' if(!(devid in d)) return;\n'\
1082 ' if(filter.indexOf(devid) < 0) filter[filter.length] = devid;\n'\
1083 ' var cell = {name: d[devid].n, span: 1};\n'\
1084 ' var span = 0;\n'\
1085 ' if(column >= table.length) table[column] = [];\n'\
1086 ' table[column][row] = cell;\n'\
1087 ' for(var i = 0; i < d[devid].c.length; i++) {\n'\
1088 ' var cid = d[devid].c[i];\n'\
1089 ' span += deviceChildren(cid, column+1, row+span);\n'\
1090 ' }\n'\
1091 ' if(span == 0) span = 1;\n'\
1092 ' table[column][row].span = span;\n'\
1093 ' return span;\n'\
1094 ' }\n'\
1095 ' function deviceTree(devid, resume) {\n'\
1096 ' var html = "<table border=1>";\n'\
1097 ' filter = [];\n'\
1098 ' table = [];\n'\
1099 ' plist = deviceParent(devid);\n'\
1100 ' var devidx = plist.length - 1;\n'\
1101 ' for(var i = 0; i < devidx; i++)\n'\
1102 ' table[i] = [{name: plist[i], span: 1}];\n'\
1103 ' deviceChildren(devid, devidx, 0);\n'\
1104 ' for(var i = 0; i < devidx; i++)\n'\
1105 ' table[i][0].span = table[devidx][0].span;\n'\
1106 ' for(var row = 0; row < table[0][0].span; row++) {\n'\
1107 ' html += "<tr>";\n'\
1108 ' for(var col = 0; col < table.length; col++)\n'\
1109 ' if(row in table[col]) {\n'\
1110 ' var cell = table[col][row];\n'\
1111 ' var args = "";\n'\
1112 ' if(cell.span > 1)\n'\
1113 ' args += " rowspan="+cell.span;\n'\
1114 ' if((col == devidx) && (row == 0))\n'\
1115 ' args += " class=tdhl";\n'\
1116 ' if(resume)\n'\
1117 ' html += "<td"+args+">"+cell.name+" &rarr;</td>";\n'\
1118 ' else\n'\
1119 ' html += "<td"+args+">&larr; "+cell.name+"</td>";\n'\
1120 ' }\n'\
1121 ' html += "</tr>";\n'\
1122 ' }\n'\
1123 ' html += "</table>";\n'\
1124 ' return html;\n'\
1125 ' }\n'\
1126 ' function zoomTimeline() {\n'\
1127 ' var timescale = document.getElementById("timescale");\n'\
1128 ' var dmesg = document.getElementById("dmesg");\n'\
1129 ' var zoombox = document.getElementById("dmesgzoombox");\n'\
1130 ' var val = parseFloat(dmesg.style.width);\n'\
1131 ' var newval = 100;\n'\
1132 ' var sh = window.outerWidth / 2;\n'\
1133 ' if(this.id == "zoomin") {\n'\
1134 ' newval = val * 1.2;\n'\
1135 ' if(newval > 40000) newval = 40000;\n'\
1136 ' dmesg.style.width = newval+"%";\n'\
1137 ' zoombox.scrollLeft = ((zoombox.scrollLeft + sh) * newval / val) - sh;\n'\
1138 ' } else if (this.id == "zoomout") {\n'\
1139 ' newval = val / 1.2;\n'\
1140 ' if(newval < 100) newval = 100;\n'\
1141 ' dmesg.style.width = newval+"%";\n'\
1142 ' zoombox.scrollLeft = ((zoombox.scrollLeft + sh) * newval / val) - sh;\n'\
1143 ' } else {\n'\
1144 ' zoombox.scrollLeft = 0;\n'\
1145 ' dmesg.style.width = "100%";\n'\
1146 ' }\n'\
1147 ' var html = "";\n'\
1148 ' var t0 = bounds[0];\n'\
1149 ' var tMax = bounds[1];\n'\
1150 ' var tTotal = tMax - t0;\n'\
1151 ' var wTotal = tTotal * 100.0 / newval;\n'\
1152 ' for(var tS = 1000; (wTotal / tS) < 3; tS /= 10);\n'\
1153 ' if(tS < 1) tS = 1;\n'\
1154 ' for(var s = ((t0 / tS)|0) * tS; s < tMax; s += tS) {\n'\
1155 ' var pos = (tMax - s) * 100.0 / tTotal;\n'\
1156 ' var name = (s == 0)?"S/R":(s+"ms");\n'\
1157 ' html += \"<div class=\\\"t\\\" style=\\\"right:\"+pos+\"%\\\">\"+name+\"</div>\";\n'\
1158 ' }\n'\
1159 ' timescale.innerHTML = html;\n'\
1160 ' }\n'\
1161 ' function deviceDetail() {\n'\
1162 ' var devtitle = document.getElementById("devicedetail");\n'\
1163 ' devtitle.innerHTML = "<h1>"+this.title+"</h1>";\n'\
1164 ' var devtree = document.getElementById("devicetree");\n'\
1165 ' devtree.innerHTML = deviceTree(this.id, (this.title.indexOf("resume") >= 0));\n'\
1166 ' var cglist = document.getElementById("callgraphs");\n'\
1167 ' if(!cglist) return;\n'\
1168 ' var cg = cglist.getElementsByClassName("atop");\n'\
1169 ' for (var i = 0; i < cg.length; i++) {\n'\
1170 ' if(filter.indexOf(cg[i].id) >= 0) {\n'\
1171 ' cg[i].style.display = "block";\n'\
1172 ' } else {\n'\
1173 ' cg[i].style.display = "none";\n'\
1174 ' }\n'\
1175 ' }\n'\
1176 ' }\n'\
1177 ' window.addEventListener("load", function () {\n'\
1178 ' var dmesg = document.getElementById("dmesg");\n'\
1179 ' dmesg.style.width = "100%"\n'\
1180 ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\
1181 ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\
1182 ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\
1183 ' var dev = dmesg.getElementsByClassName("thread");\n'\
1184 ' for (var i = 0; i < dev.length; i++) {\n'\
1185 ' dev[i].onclick = deviceDetail;\n'\
1186 ' }\n'\
1187 ' zoomTimeline();\n'\
1188 ' });\n'\
1189 '</script>\n'
1190 hf.write(script_code);
1191
1192# Function: executeSuspend
1193# Description:
1194# Execute system suspend through the sysfs interface
1195def executeSuspend():
1196 global sysvals, data
1197
1198 detectUSB()
1199 pf = open(sysvals.powerfile, 'w')
1200 # clear the kernel ring buffer just as we start
1201 os.system("dmesg -C")
1202 # start ftrace
1203 if(data.useftrace):
1204 print("START TRACING")
1205 os.system("echo 1 > "+sysvals.tpath+"tracing_on")
1206 os.system("echo SUSPEND START > "+sysvals.tpath+"trace_marker")
1207 # initiate suspend
1208 if(sysvals.rtcwake):
1209 print("SUSPEND START")
1210 os.system("rtcwake -s 10 -m "+sysvals.suspendmode)
1211 else:
1212 print("SUSPEND START (press a key to resume)")
1213 pf.write(sysvals.suspendmode)
1214 # execution will pause here
1215 pf.close()
1216 # return from suspend
1217 print("RESUME COMPLETE")
1218 # stop ftrace
1219 if(data.useftrace):
1220 os.system("echo RESUME COMPLETE > "+sysvals.tpath+"trace_marker")
1221 os.system("echo 0 > "+sysvals.tpath+"tracing_on")
1222 print("CAPTURING FTRACE")
1223 os.system("echo \""+sysvals.teststamp+"\" > "+sysvals.ftracefile)
1224 os.system("cat "+sysvals.tpath+"trace >> "+sysvals.ftracefile)
1225 # grab a copy of the dmesg output
1226 print("CAPTURING DMESG")
1227 os.system("echo \""+sysvals.teststamp+"\" > "+sysvals.dmesgfile)
1228 os.system("dmesg -c >> "+sysvals.dmesgfile)
1229
1230# Function: detectUSB
1231# Description:
1232# Detect all the USB hosts and devices currently connected
1233def detectUSB():
1234 global sysvals, data
1235
1236 for dirname, dirnames, filenames in os.walk("/sys/devices"):
1237 if(re.match(r".*/usb[0-9]*.*", dirname) and
1238 "idVendor" in filenames and "idProduct" in filenames):
1239 vid = os.popen("cat %s/idVendor 2>/dev/null" % dirname).read().replace('\n', '')
1240 pid = os.popen("cat %s/idProduct 2>/dev/null" % dirname).read().replace('\n', '')
1241 product = os.popen("cat %s/product 2>/dev/null" % dirname).read().replace('\n', '')
1242 name = dirname.split('/')[-1]
1243 if(len(product) > 0):
1244 data.altdevname[name] = "%s [%s]" % (product, name)
1245 else:
1246 data.altdevname[name] = "%s:%s [%s]" % (vid, pid, name)
1247
1248def getModes():
1249 global sysvals
1250 modes = ""
1251 if(os.path.exists(sysvals.powerfile)):
1252 fp = open(sysvals.powerfile, 'r')
1253 modes = string.split(fp.read())
1254 fp.close()
1255 return modes
1256
1257# Function: statusCheck
1258# Description:
1259# Verify that the requested command and options will work
1260def statusCheck(dryrun):
1261 global sysvals, data
1262 res = dict()
1263
1264 if(data.notestrun):
1265 print("SUCCESS: The command should run!")
1266 return
1267
1268 # check we have root access
1269 check = "YES"
1270 if(os.environ['USER'] != "root"):
1271 if(not dryrun):
1272 doError("root access is required", False)
1273 check = "NO"
1274 res[" have root access: "] = check
1275
1276 # check sysfs is mounted
1277 check = "YES"
1278 if(not os.path.exists(sysvals.powerfile)):
1279 if(not dryrun):
1280 doError("sysfs must be mounted", False)
1281 check = "NO"
1282 res[" is sysfs mounted: "] = check
1283
1284 # check target mode is a valid mode
1285 check = "YES"
1286 modes = getModes()
1287 if(sysvals.suspendmode not in modes):
1288 if(not dryrun):
1289 doError("%s is not a value power mode" % sysvals.suspendmode, False)
1290 check = "NO"
1291 res[" is "+sysvals.suspendmode+" a power mode: "] = check
1292
1293 # check if ftrace is available
1294 if(data.useftrace):
1295 check = "YES"
1296 if(not verifyFtrace()):
1297 if(not dryrun):
1298 doError("ftrace is not configured", False)
1299 check = "NO"
1300 res[" is ftrace usable: "] = check
1301
1302 # check if rtcwake
1303 if(sysvals.rtcwake):
1304 check = "YES"
1305 version = os.popen("rtcwake -V 2>/dev/null").read()
1306 if(not version.startswith("rtcwake")):
1307 if(not dryrun):
1308 doError("rtcwake is not installed", False)
1309 check = "NO"
1310 res[" is rtcwake usable: "] = check
1311
1312 if(dryrun):
1313 status = True
1314 print("Checking if system can run the current command:")
1315 for r in res:
1316 print("%s\t%s" % (r, res[r]))
1317 if(res[r] != "YES"):
1318 status = False
1319 if(status):
1320 print("SUCCESS: The command should run!")
1321 else:
1322 print("FAILURE: The command won't run!")
1323
1324def printHelp():
1325 global sysvals
1326 modes = getModes()
1327
1328 print("")
1329 print("AnalyzeSuspend")
1330 print("Usage: sudo analyze_suspend.py <options>")
1331 print("")
1332 print("Description:")
1333 print(" Initiates a system suspend/resume while capturing dmesg")
1334 print(" and (optionally) ftrace data to analyze device timing")
1335 print("")
1336 print(" Generates output files in subdirectory: suspend-mmddyy-HHMMSS")
1337 print(" HTML output: <hostname>_<mode>.html")
1338 print(" raw dmesg output: <hostname>_<mode>_dmesg.txt")
1339 print(" raw ftrace output (with -f): <hostname>_<mode>_ftrace.txt")
1340 print("")
1341 print("Options:")
1342 print(" [general]")
1343 print(" -h Print this help text")
1344 print(" -verbose Print extra information during execution and analysis")
1345 print(" -status Test to see if the system is enabled to run this tool")
1346 print(" -modes List available suspend modes")
1347 print(" -m mode Mode to initiate for suspend %s (default: %s)") % (modes, sysvals.suspendmode)
1348 print(" -rtcwake Use rtcwake to autoresume after 10 seconds (default: disabled)")
1349 print(" -f Use ftrace to create device callgraphs (default: disabled)")
1350 print(" [re-analyze data from previous runs]")
1351 print(" -dmesg dmesgfile Create HTML timeline from dmesg file")
1352 print(" -ftrace ftracefile Create HTML callgraph from ftrace file")
1353 print("")
1354 return True
1355
1356def doError(msg, help):
1357 print("ERROR: %s") % msg
1358 if(help == True):
1359 printHelp()
1360 sys.exit()
1361
1362# -- script main --
1363# loop through the command line arguments
1364cmd = ""
1365args = iter(sys.argv[1:])
1366for arg in args:
1367 if(arg == "-m"):
1368 try:
1369 val = args.next()
1370 except:
1371 doError("No mode supplied", True)
1372 sysvals.suspendmode = val
1373 elif(arg == "-f"):
1374 data.useftrace = True
1375 elif(arg == "-modes"):
1376 cmd = "modes"
1377 elif(arg == "-status"):
1378 cmd = "status"
1379 elif(arg == "-verbose"):
1380 data.verbose = True
1381 elif(arg == "-rtcwake"):
1382 sysvals.rtcwake = True
1383 elif(arg == "-dmesg"):
1384 try:
1385 val = args.next()
1386 except:
1387 doError("No dmesg file supplied", True)
1388 data.notestrun = True
1389 data.usedmesg = True
1390 sysvals.dmesgfile = val
1391 elif(arg == "-ftrace"):
1392 try:
1393 val = args.next()
1394 except:
1395 doError("No ftrace file supplied", True)
1396 data.notestrun = True
1397 data.useftrace = True
1398 sysvals.ftracefile = val
1399 elif(arg == "-h"):
1400 printHelp()
1401 sys.exit()
1402 else:
1403 doError("Invalid argument: "+arg, True)
1404
1405# just run a utility command and exit
1406if(cmd != ""):
1407 if(cmd == "status"):
1408 statusCheck(True)
1409 elif(cmd == "modes"):
1410 modes = getModes()
1411 print modes
1412 sys.exit()
1413
1414data.initialize()
1415
1416# if instructed, re-analyze existing data files
1417if(data.notestrun):
1418 sysvals.setOutputFile()
1419 data.vprint("Output file: %s" % sysvals.htmlfile)
1420 if(sysvals.dmesgfile != ""):
1421 analyzeKernelLog()
1422 if(sysvals.ftracefile != ""):
1423 analyzeTraceLog()
1424 createHTML()
1425 sys.exit()
1426
1427# verify that we can run a test
1428data.usedmesg = True
1429statusCheck(False)
1430
1431# prepare for the test
1432if(data.useftrace):
1433 initFtrace()
1434sysvals.initTestOutput()
1435
1436data.vprint("Output files:\n %s" % sysvals.dmesgfile)
1437if(data.useftrace):
1438 data.vprint(" %s" % sysvals.ftracefile)
1439data.vprint(" %s" % sysvals.htmlfile)
1440
1441# execute the test
1442executeSuspend()
1443analyzeKernelLog()
1444if(data.useftrace):
1445 analyzeTraceLog()
1446createHTML()
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 9c9810030377..464dcef79b35 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -29,6 +29,7 @@ my $mailback = 0;
29my $summary_file = 0; 29my $summary_file = 0;
30my $show_types = 0; 30my $show_types = 0;
31my $fix = 0; 31my $fix = 0;
32my $fix_inplace = 0;
32my $root; 33my $root;
33my %debug; 34my %debug;
34my %camelcase = (); 35my %camelcase = ();
@@ -76,6 +77,9 @@ Options:
76 "<inputfile>.EXPERIMENTAL-checkpatch-fixes" 77 "<inputfile>.EXPERIMENTAL-checkpatch-fixes"
77 with potential errors corrected to the preferred 78 with potential errors corrected to the preferred
78 checkpatch style 79 checkpatch style
80 --fix-inplace EXPERIMENTAL - may create horrible results
81 Is the same as --fix, but overwrites the input
82 file. It's your fault if there's no backup or git
79 --ignore-perl-version override checking of perl version. expect 83 --ignore-perl-version override checking of perl version. expect
80 runtime errors. 84 runtime errors.
81 -h, --help, --version display this help and exit 85 -h, --help, --version display this help and exit
@@ -131,6 +135,7 @@ GetOptions(
131 'mailback!' => \$mailback, 135 'mailback!' => \$mailback,
132 'summary-file!' => \$summary_file, 136 'summary-file!' => \$summary_file,
133 'fix!' => \$fix, 137 'fix!' => \$fix,
138 'fix-inplace!' => \$fix_inplace,
134 'ignore-perl-version!' => \$ignore_perl_version, 139 'ignore-perl-version!' => \$ignore_perl_version,
135 'debug=s' => \%debug, 140 'debug=s' => \%debug,
136 'test-only=s' => \$tst_only, 141 'test-only=s' => \$tst_only,
@@ -140,6 +145,8 @@ GetOptions(
140 145
141help(0) if ($help); 146help(0) if ($help);
142 147
148$fix = 1 if ($fix_inplace);
149
143my $exit = 0; 150my $exit = 0;
144 151
145if ($^V && $^V lt $minimum_perl_version) { 152if ($^V && $^V lt $minimum_perl_version) {
@@ -464,7 +471,7 @@ sub seed_camelcase_includes {
464 471
465 $camelcase_seeded = 1; 472 $camelcase_seeded = 1;
466 473
467 if (-d ".git") { 474 if (-e ".git") {
468 my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`; 475 my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`;
469 chomp $git_last_include_commit; 476 chomp $git_last_include_commit;
470 $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit"; 477 $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit";
@@ -492,7 +499,7 @@ sub seed_camelcase_includes {
492 return; 499 return;
493 } 500 }
494 501
495 if (-d ".git") { 502 if (-e ".git") {
496 $files = `git ls-files "include/*.h"`; 503 $files = `git ls-files "include/*.h"`;
497 @include_files = split('\n', $files); 504 @include_files = split('\n', $files);
498 } 505 }
@@ -1963,15 +1970,14 @@ sub process {
1963 } 1970 }
1964 1971
1965# Check for FSF mailing addresses. 1972# Check for FSF mailing addresses.
1966 if ($rawline =~ /You should have received a copy/ || 1973 if ($rawline =~ /\bwrite to the Free/i ||
1967 $rawline =~ /write to the Free Software/ || 1974 $rawline =~ /\b59\s+Temple\s+Pl/i ||
1968 $rawline =~ /59 Temple Place/ || 1975 $rawline =~ /\b51\s+Franklin\s+St/i) {
1969 $rawline =~ /51 Franklin Street/) {
1970 my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 1976 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
1971 my $msg_type = \&ERROR; 1977 my $msg_type = \&ERROR;
1972 $msg_type = \&CHK if ($file); 1978 $msg_type = \&CHK if ($file);
1973 &{$msg_type}("FSF_MAILING_ADDRESS", 1979 &{$msg_type}("FSF_MAILING_ADDRESS",
1974 "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet) 1980 "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet)
1975 } 1981 }
1976 1982
1977# check for Kconfig help text having a real description 1983# check for Kconfig help text having a real description
@@ -2034,6 +2040,33 @@ sub process {
2034 "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag}); 2040 "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag});
2035 } 2041 }
2036 2042
2043# check for DT compatible documentation
2044 if (defined $root && $realfile =~ /\.dts/ &&
2045 $rawline =~ /^\+\s*compatible\s*=/) {
2046 my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g;
2047
2048 foreach my $compat (@compats) {
2049 my $compat2 = $compat;
2050 my $dt_path = $root . "/Documentation/devicetree/bindings/";
2051 $compat2 =~ s/\,[a-z]*\-/\,<\.\*>\-/;
2052 `grep -Erq "$compat|$compat2" $dt_path`;
2053 if ( $? >> 8 ) {
2054 WARN("UNDOCUMENTED_DT_STRING",
2055 "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr);
2056 }
2057
2058 my $vendor = $compat;
2059 my $vendor_path = $dt_path . "vendor-prefixes.txt";
2060 next if (! -f $vendor_path);
2061 $vendor =~ s/^([a-zA-Z0-9]+)\,.*/$1/;
2062 `grep -Eq "$vendor" $vendor_path`;
2063 if ( $? >> 8 ) {
2064 WARN("UNDOCUMENTED_DT_STRING",
2065 "DT compatible string vendor \"$vendor\" appears un-documented -- check $vendor_path\n" . $herecurr);
2066 }
2067 }
2068 }
2069
2037# check we are in a valid source file if not then ignore this hunk 2070# check we are in a valid source file if not then ignore this hunk
2038 next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/); 2071 next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
2039 2072
@@ -2049,16 +2082,12 @@ sub process {
2049 } 2082 }
2050 2083
2051# Check for user-visible strings broken across lines, which breaks the ability 2084# Check for user-visible strings broken across lines, which breaks the ability
2052# to grep for the string. Limited to strings used as parameters (those 2085# to grep for the string. Make exceptions when the previous string ends in a
2053# following an open parenthesis), which almost completely eliminates false 2086# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{'
2054# positives, as well as warning only once per parameter rather than once per 2087# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value
2055# line of the string. Make an exception when the previous string ends in a
2056# newline (multiple lines in one string constant) or \n\t (common in inline
2057# assembly to indent the instruction on the following line).
2058 if ($line =~ /^\+\s*"/ && 2088 if ($line =~ /^\+\s*"/ &&
2059 $prevline =~ /"\s*$/ && 2089 $prevline =~ /"\s*$/ &&
2060 $prevline =~ /\(/ && 2090 $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) {
2061 $prevrawline !~ /\\n(?:\\t)*"\s*$/) {
2062 WARN("SPLIT_STRING", 2091 WARN("SPLIT_STRING",
2063 "quoted string split across lines\n" . $hereprev); 2092 "quoted string split across lines\n" . $hereprev);
2064 } 2093 }
@@ -2115,8 +2144,10 @@ sub process {
2115 if (WARN("SPACE_BEFORE_TAB", 2144 if (WARN("SPACE_BEFORE_TAB",
2116 "please, no space before tabs\n" . $herevet) && 2145 "please, no space before tabs\n" . $herevet) &&
2117 $fix) { 2146 $fix) {
2118 $fixed[$linenr - 1] =~ 2147 while ($fixed[$linenr - 1] =~
2119 s/(^\+.*) +\t/$1\t/; 2148 s/(^\+.*) {8,8}+\t/$1\t\t/) {}
2149 while ($fixed[$linenr - 1] =~
2150 s/(^\+.*) +\t/$1\t/) {}
2120 } 2151 }
2121 } 2152 }
2122 2153
@@ -2634,10 +2665,22 @@ sub process {
2634 $herecurr); 2665 $herecurr);
2635 } 2666 }
2636 2667
2637# check for declarations of struct pci_device_id 2668# check for function declarations without arguments like "int foo()"
2638 if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) { 2669 if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) {
2639 WARN("DEFINE_PCI_DEVICE_TABLE", 2670 if (ERROR("FUNCTION_WITHOUT_ARGS",
2640 "Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr); 2671 "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) &&
2672 $fix) {
2673 $fixed[$linenr - 1] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/;
2674 }
2675 }
2676
2677# check for uses of DEFINE_PCI_DEVICE_TABLE
2678 if ($line =~ /\bDEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=/) {
2679 if (WARN("DEFINE_PCI_DEVICE_TABLE",
2680 "Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) &&
2681 $fix) {
2682 $fixed[$linenr - 1] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /;
2683 }
2641 } 2684 }
2642 2685
2643# check for new typedefs, only function parameters and sparse annotations 2686# check for new typedefs, only function parameters and sparse annotations
@@ -2802,6 +2845,65 @@ sub process {
2802 } 2845 }
2803 } 2846 }
2804 2847
2848# Function pointer declarations
2849# check spacing between type, funcptr, and args
2850# canonical declaration is "type (*funcptr)(args...)"
2851#
2852# the $Declare variable will capture all spaces after the type
2853# so check it for trailing missing spaces or multiple spaces
2854 if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)$Ident(\s*)\)(\s*)\(/) {
2855 my $declare = $1;
2856 my $pre_pointer_space = $2;
2857 my $post_pointer_space = $3;
2858 my $funcname = $4;
2859 my $post_funcname_space = $5;
2860 my $pre_args_space = $6;
2861
2862 if ($declare !~ /\s$/) {
2863 WARN("SPACING",
2864 "missing space after return type\n" . $herecurr);
2865 }
2866
2867# unnecessary space "type (*funcptr)(args...)"
2868 elsif ($declare =~ /\s{2,}$/) {
2869 WARN("SPACING",
2870 "Multiple spaces after return type\n" . $herecurr);
2871 }
2872
2873# unnecessary space "type ( *funcptr)(args...)"
2874 if (defined $pre_pointer_space &&
2875 $pre_pointer_space =~ /^\s/) {
2876 WARN("SPACING",
2877 "Unnecessary space after function pointer open parenthesis\n" . $herecurr);
2878 }
2879
2880# unnecessary space "type (* funcptr)(args...)"
2881 if (defined $post_pointer_space &&
2882 $post_pointer_space =~ /^\s/) {
2883 WARN("SPACING",
2884 "Unnecessary space before function pointer name\n" . $herecurr);
2885 }
2886
2887# unnecessary space "type (*funcptr )(args...)"
2888 if (defined $post_funcname_space &&
2889 $post_funcname_space =~ /^\s/) {
2890 WARN("SPACING",
2891 "Unnecessary space after function pointer name\n" . $herecurr);
2892 }
2893
2894# unnecessary space "type (*funcptr) (args...)"
2895 if (defined $pre_args_space &&
2896 $pre_args_space =~ /^\s/) {
2897 WARN("SPACING",
2898 "Unnecessary space before function pointer arguments\n" . $herecurr);
2899 }
2900
2901 if (show_type("SPACING") && $fix) {
2902 $fixed[$linenr - 1] =~
2903 s/^(.\s*$Declare)\(\s*\*\s*($Ident)\s*\)\s*\(/rtrim($1) . " " . "\(\*$2\)\("/ex;
2904 }
2905 }
2906
2805# check for spacing round square brackets; allowed: 2907# check for spacing round square brackets; allowed:
2806# 1. with a type on the left -- int [] a; 2908# 1. with a type on the left -- int [] a;
2807# 2. at the beginning of a line for slice initialisers -- [0...10] = 5, 2909# 2. at the beginning of a line for slice initialisers -- [0...10] = 5,
@@ -3122,7 +3224,7 @@ sub process {
3122 } 3224 }
3123 3225
3124# check for whitespace before a non-naked semicolon 3226# check for whitespace before a non-naked semicolon
3125 if ($line =~ /^\+.*\S\s+;/) { 3227 if ($line =~ /^\+.*\S\s+;\s*$/) {
3126 if (WARN("SPACING", 3228 if (WARN("SPACING",
3127 "space prohibited before semicolon\n" . $herecurr) && 3229 "space prohibited before semicolon\n" . $herecurr) &&
3128 $fix) { 3230 $fix) {
@@ -3246,6 +3348,20 @@ sub process {
3246 } 3348 }
3247 } 3349 }
3248 3350
3351# if statements using unnecessary parentheses - ie: if ((foo == bar))
3352 if ($^V && $^V ge 5.10.0 &&
3353 $line =~ /\bif\s*((?:\(\s*){2,})/) {
3354 my $openparens = $1;
3355 my $count = $openparens =~ tr@\(@\(@;
3356 my $msg = "";
3357 if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) {
3358 my $comp = $4; #Not $1 because of $LvalOrFunc
3359 $msg = " - maybe == should be = ?" if ($comp eq "==");
3360 WARN("UNNECESSARY_PARENTHESES",
3361 "Unnecessary parentheses$msg\n" . $herecurr);
3362 }
3363 }
3364
3249# Return of what appears to be an errno should normally be -'ve 3365# Return of what appears to be an errno should normally be -'ve
3250 if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) { 3366 if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
3251 my $name = $1; 3367 my $name = $1;
@@ -3980,6 +4096,16 @@ sub process {
3980 } 4096 }
3981 } 4097 }
3982 4098
4099# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar)
4100 if ($^V && $^V ge 5.10.0 &&
4101 $line =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/s) {
4102 if (WARN("PREFER_ETHER_ADDR_COPY",
4103 "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . $herecurr) &&
4104 $fix) {
4105 $fixed[$linenr - 1] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;
4106 }
4107 }
4108
3983# typecasts on min/max could be min_t/max_t 4109# typecasts on min/max could be min_t/max_t
3984 if ($^V && $^V ge 5.10.0 && 4110 if ($^V && $^V ge 5.10.0 &&
3985 defined $stat && 4111 defined $stat &&
@@ -4114,6 +4240,12 @@ sub process {
4114 "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr); 4240 "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
4115 } 4241 }
4116 4242
4243# check for GFP_NOWAIT use
4244 if ($line =~ /\b__GFP_NOFAIL\b/) {
4245 WARN("__GFP_NOFAIL",
4246 "Use of __GFP_NOFAIL is deprecated, no new users should be added\n" . $herecurr);
4247 }
4248
4117# check for multiple semicolons 4249# check for multiple semicolons
4118 if ($line =~ /;\s*;\s*$/) { 4250 if ($line =~ /;\s*;\s*$/) {
4119 if (WARN("ONE_SEMICOLON", 4251 if (WARN("ONE_SEMICOLON",
@@ -4123,6 +4255,31 @@ sub process {
4123 } 4255 }
4124 } 4256 }
4125 4257
4258# check for case / default statements not preceeded by break/fallthrough/switch
4259 if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) {
4260 my $has_break = 0;
4261 my $has_statement = 0;
4262 my $count = 0;
4263 my $prevline = $linenr;
4264 while ($prevline > 1 && $count < 3 && !$has_break) {
4265 $prevline--;
4266 my $rline = $rawlines[$prevline - 1];
4267 my $fline = $lines[$prevline - 1];
4268 last if ($fline =~ /^\@\@/);
4269 next if ($fline =~ /^\-/);
4270 next if ($fline =~ /^.(?:\s*(?:case\s+(?:$Ident|$Constant)[\s$;]*|default):[\s$;]*)*$/);
4271 $has_break = 1 if ($rline =~ /fall[\s_-]*(through|thru)/i);
4272 next if ($fline =~ /^.[\s$;]*$/);
4273 $has_statement = 1;
4274 $count++;
4275 $has_break = 1 if ($fline =~ /\bswitch\b|\b(?:break\s*;[\s$;]*$|return\b|goto\b|continue\b)/);
4276 }
4277 if (!$has_break && $has_statement) {
4278 WARN("MISSING_BREAK",
4279 "Possible switch case/default not preceeded by break or fallthrough comment\n" . $herecurr);
4280 }
4281 }
4282
4126# check for switch/default statements without a break; 4283# check for switch/default statements without a break;
4127 if ($^V && $^V ge 5.10.0 && 4284 if ($^V && $^V ge 5.10.0 &&
4128 defined $stat && 4285 defined $stat &&
@@ -4358,7 +4515,8 @@ sub process {
4358 hash_show_words(\%ignore_type, "Ignored"); 4515 hash_show_words(\%ignore_type, "Ignored");
4359 4516
4360 if ($clean == 0 && $fix && "@rawlines" ne "@fixed") { 4517 if ($clean == 0 && $fix && "@rawlines" ne "@fixed") {
4361 my $newfile = $filename . ".EXPERIMENTAL-checkpatch-fixes"; 4518 my $newfile = $filename;
4519 $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace);
4362 my $linecount = 0; 4520 my $linecount = 0;
4363 my $f; 4521 my $f;
4364 4522
diff --git a/scripts/coccinelle/api/pm_runtime.cocci b/scripts/coccinelle/api/pm_runtime.cocci
new file mode 100644
index 000000000000..f01789e967ec
--- /dev/null
+++ b/scripts/coccinelle/api/pm_runtime.cocci
@@ -0,0 +1,109 @@
1/// Make sure pm_runtime_* calls does not use unnecessary IS_ERR_VALUE
2//
3// Keywords: pm_runtime
4// Confidence: Medium
5// Copyright (C) 2013 Texas Instruments Incorporated - GPLv2.
6// URL: http://coccinelle.lip6.fr/
7// Options: --include-headers
8
9virtual patch
10virtual context
11virtual org
12virtual report
13
14//----------------------------------------------------------
15// Detection
16//----------------------------------------------------------
17
18@runtime_bad_err_handle exists@
19expression ret;
20@@
21(
22ret = \(pm_runtime_idle\|
23 pm_runtime_suspend\|
24 pm_runtime_autosuspend\|
25 pm_runtime_resume\|
26 pm_request_idle\|
27 pm_request_resume\|
28 pm_request_autosuspend\|
29 pm_runtime_get\|
30 pm_runtime_get_sync\|
31 pm_runtime_put\|
32 pm_runtime_put_autosuspend\|
33 pm_runtime_put_sync\|
34 pm_runtime_put_sync_suspend\|
35 pm_runtime_put_sync_autosuspend\|
36 pm_runtime_set_active\|
37 pm_schedule_suspend\|
38 pm_runtime_barrier\|
39 pm_generic_runtime_suspend\|
40 pm_generic_runtime_resume\)(...);
41...
42IS_ERR_VALUE(ret)
43...
44)
45
46//----------------------------------------------------------
47// For context mode
48//----------------------------------------------------------
49
50@depends on runtime_bad_err_handle && context@
51identifier pm_runtime_api;
52expression ret;
53@@
54(
55ret = pm_runtime_api(...);
56...
57* IS_ERR_VALUE(ret)
58...
59)
60
61//----------------------------------------------------------
62// For patch mode
63//----------------------------------------------------------
64
65@depends on runtime_bad_err_handle && patch@
66identifier pm_runtime_api;
67expression ret;
68@@
69(
70ret = pm_runtime_api(...);
71...
72- IS_ERR_VALUE(ret)
73+ ret < 0
74...
75)
76
77//----------------------------------------------------------
78// For org and report mode
79//----------------------------------------------------------
80
81@r depends on runtime_bad_err_handle exists@
82position p1, p2;
83identifier pm_runtime_api;
84expression ret;
85@@
86(
87ret = pm_runtime_api@p1(...);
88...
89IS_ERR_VALUE@p2(ret)
90...
91)
92
93@script:python depends on org@
94p1 << r.p1;
95p2 << r.p2;
96pm_runtime_api << r.pm_runtime_api;
97@@
98
99cocci.print_main(pm_runtime_api,p1)
100cocci.print_secs("IS_ERR_VALUE",p2)
101
102@script:python depends on report@
103p1 << r.p1;
104p2 << r.p2;
105pm_runtime_api << r.pm_runtime_api;
106@@
107
108msg = "%s returns < 0 as error. Unecessary IS_ERR_VALUE at line %s" % (pm_runtime_api, p2[0].line)
109coccilib.report.print_report(p1[0],msg)
diff --git a/scripts/gcc-goto.sh b/scripts/gcc-goto.sh
index a2af2e88daf3..c9469d34ecc6 100644
--- a/scripts/gcc-goto.sh
+++ b/scripts/gcc-goto.sh
@@ -5,7 +5,7 @@
5cat << "END" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y" 5cat << "END" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
6int main(void) 6int main(void)
7{ 7{
8#ifdef __arm__ 8#if defined(__arm__) || defined(__aarch64__)
9 /* 9 /*
10 * Not related to asm goto, but used by jump label 10 * Not related to asm goto, but used by jump label
11 * and broken on some ARM GCC versions (see GCC Bug 48637). 11 * and broken on some ARM GCC versions (see GCC Bug 48637).
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index ef474098d9f1..17fa901418ae 100644
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -257,7 +257,7 @@ case "$arg" in
257 && compr="lzop -9 -f" 257 && compr="lzop -9 -f"
258 echo "$output_file" | grep -q "\.lz4$" \ 258 echo "$output_file" | grep -q "\.lz4$" \
259 && [ -x "`which lz4 2> /dev/null`" ] \ 259 && [ -x "`which lz4 2> /dev/null`" ] \
260 && compr="lz4 -9 -f" 260 && compr="lz4 -l -9 -f"
261 echo "$output_file" | grep -q "\.cpio$" && compr="cat" 261 echo "$output_file" | grep -q "\.cpio$" && compr="cat"
262 shift 262 shift
263 ;; 263 ;;
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 5e4fb144a04f..41987885bd31 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -95,9 +95,10 @@ my %VCS_cmds;
95 95
96my %VCS_cmds_git = ( 96my %VCS_cmds_git = (
97 "execute_cmd" => \&git_execute_cmd, 97 "execute_cmd" => \&git_execute_cmd,
98 "available" => '(which("git") ne "") && (-d ".git")', 98 "available" => '(which("git") ne "") && (-e ".git")',
99 "find_signers_cmd" => 99 "find_signers_cmd" =>
100 "git log --no-color --follow --since=\$email_git_since " . 100 "git log --no-color --follow --since=\$email_git_since " .
101 '--numstat --no-merges ' .
101 '--format="GitCommit: %H%n' . 102 '--format="GitCommit: %H%n' .
102 'GitAuthor: %an <%ae>%n' . 103 'GitAuthor: %an <%ae>%n' .
103 'GitDate: %aD%n' . 104 'GitDate: %aD%n' .
@@ -106,6 +107,7 @@ my %VCS_cmds_git = (
106 " -- \$file", 107 " -- \$file",
107 "find_commit_signers_cmd" => 108 "find_commit_signers_cmd" =>
108 "git log --no-color " . 109 "git log --no-color " .
110 '--numstat ' .
109 '--format="GitCommit: %H%n' . 111 '--format="GitCommit: %H%n' .
110 'GitAuthor: %an <%ae>%n' . 112 'GitAuthor: %an <%ae>%n' .
111 'GitDate: %aD%n' . 113 'GitDate: %aD%n' .
@@ -114,6 +116,7 @@ my %VCS_cmds_git = (
114 " -1 \$commit", 116 " -1 \$commit",
115 "find_commit_author_cmd" => 117 "find_commit_author_cmd" =>
116 "git log --no-color " . 118 "git log --no-color " .
119 '--numstat ' .
117 '--format="GitCommit: %H%n' . 120 '--format="GitCommit: %H%n' .
118 'GitAuthor: %an <%ae>%n' . 121 'GitAuthor: %an <%ae>%n' .
119 'GitDate: %aD%n' . 122 'GitDate: %aD%n' .
@@ -125,6 +128,7 @@ my %VCS_cmds_git = (
125 "blame_commit_pattern" => "^([0-9a-f]+) ", 128 "blame_commit_pattern" => "^([0-9a-f]+) ",
126 "author_pattern" => "^GitAuthor: (.*)", 129 "author_pattern" => "^GitAuthor: (.*)",
127 "subject_pattern" => "^GitSubject: (.*)", 130 "subject_pattern" => "^GitSubject: (.*)",
131 "stat_pattern" => "^(\\d+)\\t(\\d+)\\t\$file\$",
128); 132);
129 133
130my %VCS_cmds_hg = ( 134my %VCS_cmds_hg = (
@@ -152,6 +156,7 @@ my %VCS_cmds_hg = (
152 "blame_commit_pattern" => "^([ 0-9a-f]+):", 156 "blame_commit_pattern" => "^([ 0-9a-f]+):",
153 "author_pattern" => "^HgAuthor: (.*)", 157 "author_pattern" => "^HgAuthor: (.*)",
154 "subject_pattern" => "^HgSubject: (.*)", 158 "subject_pattern" => "^HgSubject: (.*)",
159 "stat_pattern" => "^(\\d+)\t(\\d+)\t\$file\$",
155); 160);
156 161
157my $conf = which_conf(".get_maintainer.conf"); 162my $conf = which_conf(".get_maintainer.conf");
@@ -1269,20 +1274,30 @@ sub extract_formatted_signatures {
1269} 1274}
1270 1275
1271sub vcs_find_signers { 1276sub vcs_find_signers {
1272 my ($cmd) = @_; 1277 my ($cmd, $file) = @_;
1273 my $commits; 1278 my $commits;
1274 my @lines = (); 1279 my @lines = ();
1275 my @signatures = (); 1280 my @signatures = ();
1281 my @authors = ();
1282 my @stats = ();
1276 1283
1277 @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); 1284 @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
1278 1285
1279 my $pattern = $VCS_cmds{"commit_pattern"}; 1286 my $pattern = $VCS_cmds{"commit_pattern"};
1287 my $author_pattern = $VCS_cmds{"author_pattern"};
1288 my $stat_pattern = $VCS_cmds{"stat_pattern"};
1289
1290 $stat_pattern =~ s/(\$\w+)/$1/eeg; #interpolate $stat_pattern
1280 1291
1281 $commits = grep(/$pattern/, @lines); # of commits 1292 $commits = grep(/$pattern/, @lines); # of commits
1282 1293
1294 @authors = grep(/$author_pattern/, @lines);
1283 @signatures = grep(/^[ \t]*${signature_pattern}.*\@.*$/, @lines); 1295 @signatures = grep(/^[ \t]*${signature_pattern}.*\@.*$/, @lines);
1296 @stats = grep(/$stat_pattern/, @lines);
1284 1297
1285 return (0, @signatures) if !@signatures; 1298# print("stats: <@stats>\n");
1299
1300 return (0, \@signatures, \@authors, \@stats) if !@signatures;
1286 1301
1287 save_commits_by_author(@lines) if ($interactive); 1302 save_commits_by_author(@lines) if ($interactive);
1288 save_commits_by_signer(@lines) if ($interactive); 1303 save_commits_by_signer(@lines) if ($interactive);
@@ -1291,9 +1306,10 @@ sub vcs_find_signers {
1291 @signatures = grep(!/${penguin_chiefs}/i, @signatures); 1306 @signatures = grep(!/${penguin_chiefs}/i, @signatures);
1292 } 1307 }
1293 1308
1309 my ($author_ref, $authors_ref) = extract_formatted_signatures(@authors);
1294 my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures); 1310 my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
1295 1311
1296 return ($commits, @$signers_ref); 1312 return ($commits, $signers_ref, $authors_ref, \@stats);
1297} 1313}
1298 1314
1299sub vcs_find_author { 1315sub vcs_find_author {
@@ -1849,7 +1865,12 @@ sub vcs_assign {
1849sub vcs_file_signoffs { 1865sub vcs_file_signoffs {
1850 my ($file) = @_; 1866 my ($file) = @_;
1851 1867
1868 my $authors_ref;
1869 my $signers_ref;
1870 my $stats_ref;
1871 my @authors = ();
1852 my @signers = (); 1872 my @signers = ();
1873 my @stats = ();
1853 my $commits; 1874 my $commits;
1854 1875
1855 $vcs_used = vcs_exists(); 1876 $vcs_used = vcs_exists();
@@ -1858,13 +1879,59 @@ sub vcs_file_signoffs {
1858 my $cmd = $VCS_cmds{"find_signers_cmd"}; 1879 my $cmd = $VCS_cmds{"find_signers_cmd"};
1859 $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd 1880 $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd
1860 1881
1861 ($commits, @signers) = vcs_find_signers($cmd); 1882 ($commits, $signers_ref, $authors_ref, $stats_ref) = vcs_find_signers($cmd, $file);
1883
1884 @signers = @{$signers_ref} if defined $signers_ref;
1885 @authors = @{$authors_ref} if defined $authors_ref;
1886 @stats = @{$stats_ref} if defined $stats_ref;
1887
1888# print("commits: <$commits>\nsigners:<@signers>\nauthors: <@authors>\nstats: <@stats>\n");
1862 1889
1863 foreach my $signer (@signers) { 1890 foreach my $signer (@signers) {
1864 $signer = deduplicate_email($signer); 1891 $signer = deduplicate_email($signer);
1865 } 1892 }
1866 1893
1867 vcs_assign("commit_signer", $commits, @signers); 1894 vcs_assign("commit_signer", $commits, @signers);
1895 vcs_assign("authored", $commits, @authors);
1896 if ($#authors == $#stats) {
1897 my $stat_pattern = $VCS_cmds{"stat_pattern"};
1898 $stat_pattern =~ s/(\$\w+)/$1/eeg; #interpolate $stat_pattern
1899
1900 my $added = 0;
1901 my $deleted = 0;
1902 for (my $i = 0; $i <= $#stats; $i++) {
1903 if ($stats[$i] =~ /$stat_pattern/) {
1904 $added += $1;
1905 $deleted += $2;
1906 }
1907 }
1908 my @tmp_authors = uniq(@authors);
1909 foreach my $author (@tmp_authors) {
1910 $author = deduplicate_email($author);
1911 }
1912 @tmp_authors = uniq(@tmp_authors);
1913 my @list_added = ();
1914 my @list_deleted = ();
1915 foreach my $author (@tmp_authors) {
1916 my $auth_added = 0;
1917 my $auth_deleted = 0;
1918 for (my $i = 0; $i <= $#stats; $i++) {
1919 if ($author eq deduplicate_email($authors[$i]) &&
1920 $stats[$i] =~ /$stat_pattern/) {
1921 $auth_added += $1;
1922 $auth_deleted += $2;
1923 }
1924 }
1925 for (my $i = 0; $i < $auth_added; $i++) {
1926 push(@list_added, $author);
1927 }
1928 for (my $i = 0; $i < $auth_deleted; $i++) {
1929 push(@list_deleted, $author);
1930 }
1931 }
1932 vcs_assign("added_lines", $added, @list_added);
1933 vcs_assign("removed_lines", $deleted, @list_deleted);
1934 }
1868} 1935}
1869 1936
1870sub vcs_file_blame { 1937sub vcs_file_blame {
@@ -1887,6 +1954,10 @@ sub vcs_file_blame {
1887 if ($email_git_blame_signatures) { 1954 if ($email_git_blame_signatures) {
1888 if (vcs_is_hg()) { 1955 if (vcs_is_hg()) {
1889 my $commit_count; 1956 my $commit_count;
1957 my $commit_authors_ref;
1958 my $commit_signers_ref;
1959 my $stats_ref;
1960 my @commit_authors = ();
1890 my @commit_signers = (); 1961 my @commit_signers = ();
1891 my $commit = join(" -r ", @commits); 1962 my $commit = join(" -r ", @commits);
1892 my $cmd; 1963 my $cmd;
@@ -1894,19 +1965,27 @@ sub vcs_file_blame {
1894 $cmd = $VCS_cmds{"find_commit_signers_cmd"}; 1965 $cmd = $VCS_cmds{"find_commit_signers_cmd"};
1895 $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd 1966 $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
1896 1967
1897 ($commit_count, @commit_signers) = vcs_find_signers($cmd); 1968 ($commit_count, $commit_signers_ref, $commit_authors_ref, $stats_ref) = vcs_find_signers($cmd, $file);
1969 @commit_authors = @{$commit_authors_ref} if defined $commit_authors_ref;
1970 @commit_signers = @{$commit_signers_ref} if defined $commit_signers_ref;
1898 1971
1899 push(@signers, @commit_signers); 1972 push(@signers, @commit_signers);
1900 } else { 1973 } else {
1901 foreach my $commit (@commits) { 1974 foreach my $commit (@commits) {
1902 my $commit_count; 1975 my $commit_count;
1976 my $commit_authors_ref;
1977 my $commit_signers_ref;
1978 my $stats_ref;
1979 my @commit_authors = ();
1903 my @commit_signers = (); 1980 my @commit_signers = ();
1904 my $cmd; 1981 my $cmd;
1905 1982
1906 $cmd = $VCS_cmds{"find_commit_signers_cmd"}; 1983 $cmd = $VCS_cmds{"find_commit_signers_cmd"};
1907 $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd 1984 $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
1908 1985
1909 ($commit_count, @commit_signers) = vcs_find_signers($cmd); 1986 ($commit_count, $commit_signers_ref, $commit_authors_ref, $stats_ref) = vcs_find_signers($cmd, $file);
1987 @commit_authors = @{$commit_authors_ref} if defined $commit_authors_ref;
1988 @commit_signers = @{$commit_signers_ref} if defined $commit_signers_ref;
1910 1989
1911 push(@signers, @commit_signers); 1990 push(@signers, @commit_signers);
1912 } 1991 }
diff --git a/scripts/headers_check.pl b/scripts/headers_check.pl
index 64ac2380e4d5..62320f93e903 100644
--- a/scripts/headers_check.pl
+++ b/scripts/headers_check.pl
@@ -65,7 +65,11 @@ sub check_include
65 65
66sub check_declarations 66sub check_declarations
67{ 67{
68 if ($line =~m/^(\s*extern|unsigned|char|short|int|long|void)\b/) { 68 # soundcard.h is what it is
69 if ($line =~ m/^void seqbuf_dump\(void\);/) {
70 return;
71 }
72 if ($line =~ m/^(\s*extern|unsigned|char|short|int|long|void)\b/) {
69 printf STDERR "$filename:$lineno: " . 73 printf STDERR "$filename:$lineno: " .
70 "userspace cannot reference function or " . 74 "userspace cannot reference function or " .
71 "variable defined in the kernel\n"; 75 "variable defined in the kernel\n";
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index 4606cdfb859d..31331723e810 100644
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -219,6 +219,13 @@ sub read_kconfig {
219 $depends{$config} = $1; 219 $depends{$config} = $1;
220 } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) { 220 } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) {
221 $depends{$config} .= " " . $1; 221 $depends{$config} .= " " . $1;
222 } elsif ($state eq "DEP" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) {
223 my $dep = $3;
224 if ($dep !~ /^\s*(y|m|n)\s*$/) {
225 $dep =~ s/.*\sif\s+//;
226 $depends{$config} .= " " . $dep;
227 dprint "Added default depends $dep to $config\n";
228 }
222 229
223 # Get the configs that select this config 230 # Get the configs that select this config
224 } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { 231 } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 23708636b05c..25e5cb0aaef6 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -210,8 +210,8 @@ static void do_usb_entry(void *symval,
210 range_lo < 0x9 ? "[%X-9" : "[%X", 210 range_lo < 0x9 ? "[%X-9" : "[%X",
211 range_lo); 211 range_lo);
212 sprintf(alias + strlen(alias), 212 sprintf(alias + strlen(alias),
213 range_hi > 0xA ? "a-%X]" : "%X]", 213 range_hi > 0xA ? "A-%X]" : "%X]",
214 range_lo); 214 range_hi);
215 } 215 }
216 } 216 }
217 if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1)) 217 if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1))
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 17855761e6b7..99a45fdc1bbf 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -584,12 +584,16 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname)
584 if (strncmp(symname, "_restgpr_", sizeof("_restgpr_") - 1) == 0 || 584 if (strncmp(symname, "_restgpr_", sizeof("_restgpr_") - 1) == 0 ||
585 strncmp(symname, "_savegpr_", sizeof("_savegpr_") - 1) == 0 || 585 strncmp(symname, "_savegpr_", sizeof("_savegpr_") - 1) == 0 ||
586 strncmp(symname, "_rest32gpr_", sizeof("_rest32gpr_") - 1) == 0 || 586 strncmp(symname, "_rest32gpr_", sizeof("_rest32gpr_") - 1) == 0 ||
587 strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0) 587 strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0 ||
588 strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 ||
589 strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0)
588 return 1; 590 return 1;
589 if (info->hdr->e_machine == EM_PPC64) 591 if (info->hdr->e_machine == EM_PPC64)
590 /* Special register function linked on all modules during final link of .ko */ 592 /* Special register function linked on all modules during final link of .ko */
591 if (strncmp(symname, "_restgpr0_", sizeof("_restgpr0_") - 1) == 0 || 593 if (strncmp(symname, "_restgpr0_", sizeof("_restgpr0_") - 1) == 0 ||
592 strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0) 594 strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0 ||
595 strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 ||
596 strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0)
593 return 1; 597 return 1;
594 /* Do not ignore this symbol */ 598 /* Do not ignore this symbol */
595 return 0; 599 return 0;
@@ -1498,6 +1502,16 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
1498#define R_ARM_JUMP24 29 1502#define R_ARM_JUMP24 29
1499#endif 1503#endif
1500 1504
1505#ifndef R_ARM_THM_CALL
1506#define R_ARM_THM_CALL 10
1507#endif
1508#ifndef R_ARM_THM_JUMP24
1509#define R_ARM_THM_JUMP24 30
1510#endif
1511#ifndef R_ARM_THM_JUMP19
1512#define R_ARM_THM_JUMP19 51
1513#endif
1514
1501static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) 1515static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
1502{ 1516{
1503 unsigned int r_typ = ELF_R_TYPE(r->r_info); 1517 unsigned int r_typ = ELF_R_TYPE(r->r_info);
@@ -1511,6 +1525,9 @@ static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
1511 case R_ARM_PC24: 1525 case R_ARM_PC24:
1512 case R_ARM_CALL: 1526 case R_ARM_CALL:
1513 case R_ARM_JUMP24: 1527 case R_ARM_JUMP24:
1528 case R_ARM_THM_CALL:
1529 case R_ARM_THM_JUMP24:
1530 case R_ARM_THM_JUMP19:
1514 /* From ARM ABI: ((S + A) | T) - P */ 1531 /* From ARM ABI: ((S + A) | T) - P */
1515 r->r_addend = (int)(long)(elf->hdr + 1532 r->r_addend = (int)(long)(elf->hdr +
1516 sechdr->sh_offset + 1533 sechdr->sh_offset +
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 90e521fde35f..f46e4dd0558d 100644
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -41,9 +41,9 @@ create_package() {
41 parisc*) 41 parisc*)
42 debarch=hppa ;; 42 debarch=hppa ;;
43 mips*) 43 mips*)
44 debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo el) ;; 44 debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo el || true) ;;
45 arm*) 45 arm*)
46 debarch=arm$(grep -q CONFIG_AEABI=y $KCONFIG_CONFIG && echo el) ;; 46 debarch=arm$(grep -q CONFIG_AEABI=y $KCONFIG_CONFIG && echo el || true) ;;
47 *) 47 *)
48 echo "" >&2 48 echo "" >&2
49 echo "** ** ** WARNING ** ** **" >&2 49 echo "** ** ** WARNING ** ** **" >&2
@@ -62,7 +62,7 @@ create_package() {
62 fi 62 fi
63 63
64 # Create the package 64 # Create the package
65 dpkg-gencontrol -isp $forcearch -p$pname -P"$pdir" 65 dpkg-gencontrol -isp $forcearch -Vkernel:debarch="${debarch:-$(dpkg --print-architecture)}" -p$pname -P"$pdir"
66 dpkg --build "$pdir" .. 66 dpkg --build "$pdir" ..
67} 67}
68 68
@@ -172,8 +172,15 @@ fi
172 172
173# Install the maintainer scripts 173# Install the maintainer scripts
174# Note: hook scripts under /etc/kernel are also executed by official Debian 174# Note: hook scripts under /etc/kernel are also executed by official Debian
175# kernel packages, as well as kernel packages built using make-kpkg 175# kernel packages, as well as kernel packages built using make-kpkg.
176# make-kpkg sets $INITRD to indicate whether an initramfs is wanted, and
177# so do we; recent versions of dracut and initramfs-tools will obey this.
176debhookdir=${KDEB_HOOKDIR:-/etc/kernel} 178debhookdir=${KDEB_HOOKDIR:-/etc/kernel}
179if grep -q '^CONFIG_BLK_DEV_INITRD=y' $KCONFIG_CONFIG; then
180 want_initrd=Yes
181else
182 want_initrd=No
183fi
177for script in postinst postrm preinst prerm ; do 184for script in postinst postrm preinst prerm ; do
178 mkdir -p "$tmpdir$debhookdir/$script.d" 185 mkdir -p "$tmpdir$debhookdir/$script.d"
179 cat <<EOF > "$tmpdir/DEBIAN/$script" 186 cat <<EOF > "$tmpdir/DEBIAN/$script"
@@ -184,6 +191,9 @@ set -e
184# Pass maintainer script parameters to hook scripts 191# Pass maintainer script parameters to hook scripts
185export DEB_MAINT_PARAMS="\$*" 192export DEB_MAINT_PARAMS="\$*"
186 193
194# Tell initramfs builder whether it's wanted
195export INITRD=$want_initrd
196
187test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d 197test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d
188exit 0 198exit 0
189EOF 199EOF
@@ -288,15 +298,14 @@ mkdir -p "$destdir"
288(cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be 298(cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be
289ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build" 299ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build"
290rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles" 300rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
291arch=$(dpkg --print-architecture)
292 301
293cat <<EOF >> debian/control 302cat <<EOF >> debian/control
294 303
295Package: $kernel_headers_packagename 304Package: $kernel_headers_packagename
296Provides: linux-headers, linux-headers-2.6 305Provides: linux-headers, linux-headers-2.6
297Architecture: $arch 306Architecture: any
298Description: Linux kernel headers for $KERNELRELEASE on $arch 307Description: Linux kernel headers for $KERNELRELEASE on \${kernel:debarch}
299 This package provides kernel header files for $KERNELRELEASE on $arch 308 This package provides kernel header files for $KERNELRELEASE on \${kernel:debarch}
300 . 309 .
301 This is useful for people who need to build external modules 310 This is useful for people who need to build external modules
302EOF 311EOF
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index d105a44b68f6..63d91e22ed7c 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -43,7 +43,8 @@ scm_version()
43 fi 43 fi
44 44
45 # Check for git and a git repo. 45 # Check for git and a git repo.
46 if test -d .git && head=`git rev-parse --verify --short HEAD 2>/dev/null`; then 46 if test -z "$(git rev-parse --show-cdup 2>/dev/null)" &&
47 head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
47 48
48 # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore 49 # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
49 # it, because this version is defined in the top level Makefile. 50 # it, because this version is defined in the top level Makefile.
diff --git a/scripts/sortextable.c b/scripts/sortextable.c
index 7941fbdfb050..cc49062acdee 100644
--- a/scripts/sortextable.c
+++ b/scripts/sortextable.c
@@ -39,6 +39,10 @@
39#define EM_AARCH64 183 39#define EM_AARCH64 183
40#endif 40#endif
41 41
42#ifndef EM_MICROBLAZE
43#define EM_MICROBLAZE 189
44#endif
45
42static int fd_map; /* File descriptor for file being modified. */ 46static int fd_map; /* File descriptor for file being modified. */
43static int mmap_failed; /* Boolean flag. */ 47static int mmap_failed; /* Boolean flag. */
44static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */ 48static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */
@@ -275,6 +279,7 @@ do_file(char const *const fname)
275 case EM_ARCOMPACT: 279 case EM_ARCOMPACT:
276 case EM_ARM: 280 case EM_ARM:
277 case EM_AARCH64: 281 case EM_AARCH64:
282 case EM_MICROBLAZE:
278 case EM_MIPS: 283 case EM_MIPS:
279 break; 284 break;
280 } /* end switch */ 285 } /* end switch */