aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2014-11-20 08:42:02 -0500
committerJiri Kosina <jkosina@suse.cz>2014-11-20 08:42:02 -0500
commita02001086bbfb4da35d1228bebc2f1b442db455f (patch)
tree62ab47936cef06fd08657ca5b6cd1df98c19be57 /scripts
parenteff264efeeb0898408e8c9df72d8a32621035bed (diff)
parentfc14f9c1272f62c3e8d01300f52467c0d9af50f9 (diff)
Merge Linus' tree to be be to apply submitted patches to newer code than
current trivial.git base
Diffstat (limited to 'scripts')
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Kbuild.include18
-rw-r--r--scripts/Makefile1
-rw-r--r--scripts/Makefile.build14
-rw-r--r--scripts/Makefile.clean10
-rw-r--r--scripts/Makefile.extrawarn21
-rw-r--r--scripts/Makefile.fwinst2
-rw-r--r--scripts/Makefile.host63
-rw-r--r--scripts/Makefile.lib9
-rw-r--r--scripts/Makefile.modinst7
-rw-r--r--scripts/Makefile.modsign2
-rwxr-xr-xscripts/analyze_suspend.py3817
-rw-r--r--scripts/basic/.gitignore1
-rw-r--r--scripts/basic/Makefile1
-rw-r--r--scripts/basic/bin2c.c (renamed from scripts/bin2c.c)7
-rwxr-xr-xscripts/bloat-o-meter2
-rwxr-xr-x[-rw-r--r--]scripts/bootgraph.pl0
-rwxr-xr-xscripts/checkpatch.pl687
-rwxr-xr-xscripts/checkstack.pl12
-rw-r--r--scripts/coccinelle/api/alloc/alloc_cast.cocci72
-rw-r--r--scripts/coccinelle/free/ifnullfree.cocci53
-rw-r--r--scripts/coccinelle/misc/array_size.cocci87
-rw-r--r--scripts/coccinelle/misc/badty.cocci76
-rw-r--r--scripts/coccinelle/misc/bugon.cocci (renamed from scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci)47
-rw-r--r--scripts/coccinelle/misc/simple_return.cocci180
-rw-r--r--scripts/coccinelle/null/badzero.cocci3
-rwxr-xr-x[-rw-r--r--]scripts/export_report.pl0
-rwxr-xr-x[-rw-r--r--]scripts/gcc-goto.sh0
-rwxr-xr-x[-rw-r--r--]scripts/gcc-ld0
-rwxr-xr-x[-rw-r--r--]scripts/gcc-version.sh0
-rwxr-xr-x[-rw-r--r--]scripts/gcc-x86_32-has-stack-protector.sh0
-rwxr-xr-x[-rw-r--r--]scripts/gcc-x86_64-has-stack-protector.sh0
-rwxr-xr-x[-rw-r--r--]scripts/gen_initramfs_list.sh0
-rwxr-xr-x[-rw-r--r--]scripts/headers_check.pl0
-rwxr-xr-x[-rw-r--r--]scripts/headers_install.sh4
-rw-r--r--scripts/kallsyms.c2
-rw-r--r--scripts/kconfig/Makefile57
-rwxr-xr-x[-rw-r--r--]scripts/kconfig/lxdialog/check-lxdialog.sh6
-rw-r--r--scripts/kconfig/lxdialog/dialog.h2
-rwxr-xr-x[-rw-r--r--]scripts/kconfig/streamline_config.pl0
-rwxr-xr-xscripts/kernel-doc1
-rwxr-xr-x[-rw-r--r--]scripts/link-vmlinux.sh0
-rwxr-xr-x[-rw-r--r--]scripts/markup_oops.pl0
-rwxr-xr-x[-rw-r--r--]scripts/mkmakefile0
-rwxr-xr-x[-rw-r--r--]scripts/mksysmap0
-rw-r--r--scripts/mod/modpost.c85
-rwxr-xr-x[-rw-r--r--]scripts/package/builddeb26
-rwxr-xr-x[-rw-r--r--]scripts/package/buildtar0
-rwxr-xr-x[-rw-r--r--]scripts/profile2linkerlist.pl0
-rw-r--r--scripts/recordmcount.c4
-rwxr-xr-xscripts/recordmcount.pl7
-rwxr-xr-x[-rw-r--r--]scripts/rt-tester/rt-tester.py0
-rwxr-xr-x[-rw-r--r--]scripts/selinux/install_policy.sh0
-rw-r--r--scripts/sortextable.h2
-rw-r--r--scripts/spelling.txt1042
-rwxr-xr-xscripts/tags.sh18
-rwxr-xr-x[-rw-r--r--]scripts/tracing/draw_functrace.py0
-rwxr-xr-x[-rw-r--r--]scripts/xz_wrap.sh0
58 files changed, 5237 insertions, 1212 deletions
diff --git a/scripts/.gitignore b/scripts/.gitignore
index fb070fa1038f..5ecfe93f2028 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -4,7 +4,6 @@
4conmakehash 4conmakehash
5kallsyms 5kallsyms
6pnmtologo 6pnmtologo
7bin2c
8unifdef 7unifdef
9ihex2fw 8ihex2fw
10recordmcount 9recordmcount
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 122f95c95869..65e7b08bb2cc 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -171,13 +171,13 @@ ld-ifversion = $(shell [ $(call ld-version) $(1) $(2) ] && echo $(3))
171# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= 171# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
172# Usage: 172# Usage:
173# $(Q)$(MAKE) $(build)=dir 173# $(Q)$(MAKE) $(build)=dir
174build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj 174build := -f $(srctree)/scripts/Makefile.build obj
175 175
176### 176###
177# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj= 177# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj=
178# Usage: 178# Usage:
179# $(Q)$(MAKE) $(modbuiltin)=dir 179# $(Q)$(MAKE) $(modbuiltin)=dir
180modbuiltin := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.modbuiltin obj 180modbuiltin := -f $(srctree)/scripts/Makefile.modbuiltin obj
181 181
182# Prefix -I with $(srctree) if it is not an absolute path. 182# Prefix -I with $(srctree) if it is not an absolute path.
183# skip if -I has no parameter 183# skip if -I has no parameter
@@ -215,11 +215,13 @@ else
215arg-check = $(if $(strip $(cmd_$@)),,1) 215arg-check = $(if $(strip $(cmd_$@)),,1)
216endif 216endif
217 217
218# >'< substitution is for echo to work, 218# Replace >$< with >$$< to preserve $ when reloading the .cmd file
219# >$< substitution to preserve $ when reloading .cmd file 219# (needed for make)
220# note: when using inline perl scripts [perl -e '...$$t=1;...'] 220# Replace >#< with >\#< to avoid starting a comment in the .cmd file
221# in $(cmd_xxx) double $$ your perl vars 221# (needed for make)
222make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))) 222# Replace >'< with >'\''< to be able to enclose the whole string in '...'
223# (needed for the shell)
224make-cmd = $(call escsq,$(subst \#,\\\#,$(subst $$,$$$$,$(cmd_$(1)))))
223 225
224# Find any prerequisites that is newer than target or that does not exist. 226# Find any prerequisites that is newer than target or that does not exist.
225# PHONY targets skipped in both cases. 227# PHONY targets skipped in both cases.
@@ -230,7 +232,7 @@ any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
230if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ 232if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
231 @set -e; \ 233 @set -e; \
232 $(echo-cmd) $(cmd_$(1)); \ 234 $(echo-cmd) $(cmd_$(1)); \
233 echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd) 235 printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
234 236
235# Execute the command and also postprocess generated .d dependencies file. 237# Execute the command and also postprocess generated .d dependencies file.
236if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \ 238if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \
diff --git a/scripts/Makefile b/scripts/Makefile
index 890df5c6adfb..72902b5f2721 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -13,7 +13,6 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include
13hostprogs-$(CONFIG_KALLSYMS) += kallsyms 13hostprogs-$(CONFIG_KALLSYMS) += kallsyms
14hostprogs-$(CONFIG_LOGO) += pnmtologo 14hostprogs-$(CONFIG_LOGO) += pnmtologo
15hostprogs-$(CONFIG_VT) += conmakehash 15hostprogs-$(CONFIG_VT) += conmakehash
16hostprogs-$(CONFIG_IKCONFIG) += bin2c
17hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount 16hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
18hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable 17hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
19hostprogs-$(CONFIG_ASN1) += asn1_compiler 18hostprogs-$(CONFIG_ASN1) += asn1_compiler
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index bf3e6778cd71..649ce6844033 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -79,11 +79,11 @@ endif
79 79
80# =========================================================================== 80# ===========================================================================
81 81
82ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),) 82ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
83lib-target := $(obj)/lib.a 83lib-target := $(obj)/lib.a
84endif 84endif
85 85
86ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(subdir-m) $(lib-target)),) 86ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)
87builtin-target := $(obj)/built-in.o 87builtin-target := $(obj)/built-in.o
88endif 88endif
89 89
@@ -382,16 +382,14 @@ cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) $(cmd_secanalys
382quiet_cmd_link_multi-m = LD [M] $@ 382quiet_cmd_link_multi-m = LD [M] $@
383cmd_link_multi-m = $(cmd_link_multi-y) 383cmd_link_multi-m = $(cmd_link_multi-y)
384 384
385# We would rather have a list of rules like 385$(multi-used-y): FORCE
386# foo.o: $(foo-objs)
387# but that's not so easy, so we rather make all composite objects depend
388# on the set of all their parts
389$(multi-used-y) : %.o: $(multi-objs-y) FORCE
390 $(call if_changed,link_multi-y) 386 $(call if_changed,link_multi-y)
387$(call multi_depend, $(multi-used-y), .o, -objs -y)
391 388
392$(multi-used-m) : %.o: $(multi-objs-m) FORCE 389$(multi-used-m): FORCE
393 $(call if_changed,link_multi-m) 390 $(call if_changed,link_multi-m)
394 @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod) 391 @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod)
392$(call multi_depend, $(multi-used-m), .o, -objs -y)
395 393
396targets += $(multi-used-y) $(multi-used-m) 394targets += $(multi-used-y) $(multi-used-m)
397 395
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index 686cb0d31c7c..b1c668dc6815 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -10,7 +10,7 @@ __clean:
10# Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir 10# Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir
11# Usage: 11# Usage:
12# $(Q)$(MAKE) $(clean)=dir 12# $(Q)$(MAKE) $(clean)=dir
13clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj 13clean := -f $(srctree)/scripts/Makefile.clean obj
14 14
15# The filename Kbuild has precedence over Makefile 15# The filename Kbuild has precedence over Makefile
16kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) 16kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
@@ -23,15 +23,13 @@ __subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
23subdir-y += $(__subdir-y) 23subdir-y += $(__subdir-y)
24__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m))) 24__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m)))
25subdir-m += $(__subdir-m) 25subdir-m += $(__subdir-m)
26__subdir-n := $(patsubst %/,%,$(filter %/, $(obj-n)))
27subdir-n += $(__subdir-n)
28__subdir- := $(patsubst %/,%,$(filter %/, $(obj-))) 26__subdir- := $(patsubst %/,%,$(filter %/, $(obj-)))
29subdir- += $(__subdir-) 27subdir- += $(__subdir-)
30 28
31# Subdirectories we need to descend into 29# Subdirectories we need to descend into
32 30
33subdir-ym := $(sort $(subdir-y) $(subdir-m)) 31subdir-ym := $(sort $(subdir-y) $(subdir-m))
34subdir-ymn := $(sort $(subdir-ym) $(subdir-n) $(subdir-)) 32subdir-ymn := $(sort $(subdir-ym) $(subdir-))
35 33
36# Add subdir path 34# Add subdir path
37 35
@@ -40,8 +38,8 @@ subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn))
40# build a list of files to remove, usually relative to the current 38# build a list of files to remove, usually relative to the current
41# directory 39# directory
42 40
43__clean-files := $(extra-y) $(always) \ 41__clean-files := $(extra-y) $(extra-m) $(extra-) \
44 $(targets) $(clean-files) \ 42 $(always) $(targets) $(clean-files) \
45 $(host-progs) \ 43 $(host-progs) \
46 $(hostprogs-y) $(hostprogs-m) $(hostprogs-) 44 $(hostprogs-y) $(hostprogs-m) $(hostprogs-)
47 45
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
index 65643506c71c..f734033af219 100644
--- a/scripts/Makefile.extrawarn
+++ b/scripts/Makefile.extrawarn
@@ -26,16 +26,6 @@ warning-1 += $(call cc-option, -Wmissing-include-dirs)
26warning-1 += $(call cc-option, -Wunused-but-set-variable) 26warning-1 += $(call cc-option, -Wunused-but-set-variable)
27warning-1 += $(call cc-disable-warning, missing-field-initializers) 27warning-1 += $(call cc-disable-warning, missing-field-initializers)
28 28
29# Clang
30warning-1 += $(call cc-disable-warning, initializer-overrides)
31warning-1 += $(call cc-disable-warning, unused-value)
32warning-1 += $(call cc-disable-warning, format)
33warning-1 += $(call cc-disable-warning, unknown-warning-option)
34warning-1 += $(call cc-disable-warning, sign-compare)
35warning-1 += $(call cc-disable-warning, format-zero-length)
36warning-1 += $(call cc-disable-warning, uninitialized)
37warning-1 += $(call cc-option, -fcatch-undefined-behavior)
38
39warning-2 := -Waggregate-return 29warning-2 := -Waggregate-return
40warning-2 += -Wcast-align 30warning-2 += -Wcast-align
41warning-2 += -Wdisabled-optimization 31warning-2 += -Wdisabled-optimization
@@ -64,4 +54,15 @@ ifeq ("$(strip $(warning))","")
64endif 54endif
65 55
66KBUILD_CFLAGS += $(warning) 56KBUILD_CFLAGS += $(warning)
57else
58
59ifeq ($(COMPILER),clang)
60KBUILD_CFLAGS += $(call cc-disable-warning, initializer-overrides)
61KBUILD_CFLAGS += $(call cc-disable-warning, unused-value)
62KBUILD_CFLAGS += $(call cc-disable-warning, format)
63KBUILD_CFLAGS += $(call cc-disable-warning, unknown-warning-option)
64KBUILD_CFLAGS += $(call cc-disable-warning, sign-compare)
65KBUILD_CFLAGS += $(call cc-disable-warning, format-zero-length)
66KBUILD_CFLAGS += $(call cc-disable-warning, uninitialized)
67endif
67endif 68endif
diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst
index d8e335eed226..5b698add4f31 100644
--- a/scripts/Makefile.fwinst
+++ b/scripts/Makefile.fwinst
@@ -2,7 +2,7 @@
2# Installing firmware 2# Installing firmware
3# 3#
4# We don't include the .config, so all firmware files are in $(fw-shipped-) 4# We don't include the .config, so all firmware files are in $(fw-shipped-)
5# rather than in $(fw-shipped-y) or $(fw-shipped-n). 5# rather than in $(fw-shipped-y) or $(fw-shipped-m).
6# ========================================================================== 6# ==========================================================================
7 7
8INSTALL := install 8INSTALL := install
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
index 66893643fd7d..133edfae5b8a 100644
--- a/scripts/Makefile.host
+++ b/scripts/Makefile.host
@@ -20,21 +20,12 @@
20# Will compile qconf as a C++ program, and menu as a C program. 20# Will compile qconf as a C++ program, and menu as a C program.
21# They are linked as C++ code to the executable qconf 21# They are linked as C++ code to the executable qconf
22 22
23# hostprogs-y := conf
24# conf-objs := conf.o libkconfig.so
25# libkconfig-objs := expr.o type.o
26# Will create a shared library named libkconfig.so that consists of
27# expr.o and type.o (they are both compiled as C code and the object files
28# are made as position independent code).
29# conf.c is compiled as a C program, and conf.o is linked together with
30# libkconfig.so as the executable conf.
31# Note: Shared libraries consisting of C++ files are not supported
32
33__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m)) 23__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))
34 24
35# C code 25# C code
36# Executables compiled from a single .c file 26# Executables compiled from a single .c file
37host-csingle := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m))) 27host-csingle := $(foreach m,$(__hostprogs), \
28 $(if $($(m)-objs)$($(m)-cxxobjs),,$(m)))
38 29
39# C executables linked based on several .o files 30# C executables linked based on several .o files
40host-cmulti := $(foreach m,$(__hostprogs),\ 31host-cmulti := $(foreach m,$(__hostprogs),\
@@ -44,33 +35,17 @@ host-cmulti := $(foreach m,$(__hostprogs),\
44host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs))) 35host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))
45 36
46# C++ code 37# C++ code
47# C++ executables compiled from at least on .cc file 38# C++ executables compiled from at least one .cc file
48# and zero or more .c files 39# and zero or more .c files
49host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m))) 40host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m)))
50 41
51# C++ Object (.o) files compiled from .cc files 42# C++ Object (.o) files compiled from .cc files
52host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs))) 43host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))
53 44
54# Shared libaries (only .c supported)
55# Shared libraries (.so) - all .so files referenced in "xxx-objs"
56host-cshlib := $(sort $(filter %.so, $(host-cobjs)))
57# Remove .so files from "xxx-objs"
58host-cobjs := $(filter-out %.so,$(host-cobjs))
59
60#Object (.o) files used by the shared libaries
61host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
62
63# output directory for programs/.o files 45# output directory for programs/.o files
64# hostprogs-y := tools/build may have been specified. Retrieve directory 46# hostprogs-y := tools/build may have been specified.
65host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f)))) 47# Retrieve also directory of .o files from prog-objs or prog-cxxobjs notation
66# directory of .o files from prog-objs notation 48host-objdirs := $(dir $(__hostprogs) $(host-cobjs) $(host-cxxobjs))
67host-objdirs += $(foreach f,$(host-cmulti), \
68 $(foreach m,$($(f)-objs), \
69 $(if $(dir $(m)),$(dir $(m)))))
70# directory of .o files from prog-cxxobjs notation
71host-objdirs += $(foreach f,$(host-cxxmulti), \
72 $(foreach m,$($(f)-cxxobjs), \
73 $(if $(dir $(m)),$(dir $(m)))))
74 49
75host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs)))) 50host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs))))
76 51
@@ -81,8 +56,6 @@ host-cmulti := $(addprefix $(obj)/,$(host-cmulti))
81host-cobjs := $(addprefix $(obj)/,$(host-cobjs)) 56host-cobjs := $(addprefix $(obj)/,$(host-cobjs))
82host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti)) 57host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti))
83host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs)) 58host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs))
84host-cshlib := $(addprefix $(obj)/,$(host-cshlib))
85host-cshobjs := $(addprefix $(obj)/,$(host-cshobjs))
86host-objdirs := $(addprefix $(obj)/,$(host-objdirs)) 59host-objdirs := $(addprefix $(obj)/,$(host-objdirs))
87 60
88obj-dirs += $(host-objdirs) 61obj-dirs += $(host-objdirs)
@@ -123,8 +96,9 @@ quiet_cmd_host-cmulti = HOSTLD $@
123 cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \ 96 cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
124 $(addprefix $(obj)/,$($(@F)-objs)) \ 97 $(addprefix $(obj)/,$($(@F)-objs)) \
125 $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) 98 $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
126$(host-cmulti): $(obj)/%: $(host-cobjs) $(host-cshlib) FORCE 99$(host-cmulti): FORCE
127 $(call if_changed,host-cmulti) 100 $(call if_changed,host-cmulti)
101$(call multi_depend, $(host-cmulti), , -objs)
128 102
129# Create .o file from a single .c file 103# Create .o file from a single .c file
130# host-cobjs -> .o 104# host-cobjs -> .o
@@ -140,8 +114,9 @@ quiet_cmd_host-cxxmulti = HOSTLD $@
140 $(foreach o,objs cxxobjs,\ 114 $(foreach o,objs cxxobjs,\
141 $(addprefix $(obj)/,$($(@F)-$(o)))) \ 115 $(addprefix $(obj)/,$($(@F)-$(o)))) \
142 $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) 116 $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
143$(host-cxxmulti): $(obj)/%: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE 117$(host-cxxmulti): FORCE
144 $(call if_changed,host-cxxmulti) 118 $(call if_changed,host-cxxmulti)
119$(call multi_depend, $(host-cxxmulti), , -objs -cxxobjs)
145 120
146# Create .o file from a single .cc (C++) file 121# Create .o file from a single .cc (C++) file
147quiet_cmd_host-cxxobjs = HOSTCXX $@ 122quiet_cmd_host-cxxobjs = HOSTCXX $@
@@ -149,21 +124,5 @@ quiet_cmd_host-cxxobjs = HOSTCXX $@
149$(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE 124$(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE
150 $(call if_changed_dep,host-cxxobjs) 125 $(call if_changed_dep,host-cxxobjs)
151 126
152# Compile .c file, create position independent .o file
153# host-cshobjs -> .o
154quiet_cmd_host-cshobjs = HOSTCC -fPIC $@
155 cmd_host-cshobjs = $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $<
156$(host-cshobjs): $(obj)/%.o: $(src)/%.c FORCE
157 $(call if_changed_dep,host-cshobjs)
158
159# Link a shared library, based on position independent .o files
160# *.o -> .so shared library (host-cshlib)
161quiet_cmd_host-cshlib = HOSTLLD -shared $@
162 cmd_host-cshlib = $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \
163 $(addprefix $(obj)/,$($(@F:.so=-objs))) \
164 $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
165$(host-cshlib): $(obj)/%: $(host-cshobjs) FORCE
166 $(call if_changed,host-cshlib)
167
168targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\ 127targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\
169 $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) 128 $(host-cxxmulti) $(host-cxxobjs)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 260bf8acfce9..54be19a0fa51 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -159,6 +159,15 @@ dtc_cpp_flags = -Wp,-MD,$(depfile).pre.tmp -nostdinc \
159modname-multi = $(sort $(foreach m,$(multi-used),\ 159modname-multi = $(sort $(foreach m,$(multi-used),\
160 $(if $(filter $(subst $(obj)/,,$*.o), $($(m:.o=-objs)) $($(m:.o=-y))),$(m:.o=)))) 160 $(if $(filter $(subst $(obj)/,,$*.o), $($(m:.o=-objs)) $($(m:.o=-y))),$(m:.o=))))
161 161
162# Useful for describing the dependency of composite objects
163# Usage:
164# $(call multi_depend, multi_used_targets, suffix_to_remove, suffix_to_add)
165define multi_depend
166$(foreach m, $(notdir $1), \
167 $(eval $(obj)/$m: \
168 $(addprefix $(obj)/, $(foreach s, $3, $($(m:%$(strip $2)=%$(s)))))))
169endef
170
162ifdef REGENERATE_PARSERS 171ifdef REGENERATE_PARSERS
163 172
164# GPERF 173# GPERF
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index 95ec7b35e8b6..e48a4e9d8868 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -18,7 +18,12 @@ __modinst: $(modules)
18 18
19# Don't stop modules_install if we can't sign external modules. 19# Don't stop modules_install if we can't sign external modules.
20quiet_cmd_modules_install = INSTALL $@ 20quiet_cmd_modules_install = INSTALL $@
21 cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) 21 cmd_modules_install = \
22 mkdir -p $(2) ; \
23 cp $@ $(2) ; \
24 $(mod_strip_cmd) $(2)/$(notdir $@) ; \
25 $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) ; \
26 $(mod_compress_cmd) $(2)/$(notdir $@)
22 27
23# Modules built outside the kernel source tree go into extra by default 28# Modules built outside the kernel source tree go into extra by default
24INSTALL_MOD_DIR ?= extra 29INSTALL_MOD_DIR ?= extra
diff --git a/scripts/Makefile.modsign b/scripts/Makefile.modsign
index abfda626dbad..b6ac7084da79 100644
--- a/scripts/Makefile.modsign
+++ b/scripts/Makefile.modsign
@@ -7,7 +7,7 @@ __modsign:
7 7
8include scripts/Kbuild.include 8include scripts/Kbuild.include
9 9
10__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) 10__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
11modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) 11modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
12 12
13PHONY += $(modules) 13PHONY += $(modules)
diff --git a/scripts/analyze_suspend.py b/scripts/analyze_suspend.py
index 4f2cc12dc7c7..93e1fd40f430 100755
--- a/scripts/analyze_suspend.py
+++ b/scripts/analyze_suspend.py
@@ -36,146 +36,392 @@
36# CONFIG_FUNCTION_TRACER=y 36# CONFIG_FUNCTION_TRACER=y
37# CONFIG_FUNCTION_GRAPH_TRACER=y 37# CONFIG_FUNCTION_GRAPH_TRACER=y
38# 38#
39# For kernel versions older than 3.15:
39# The following additional kernel parameters are required: 40# The following additional kernel parameters are required:
40# (e.g. in file /etc/default/grub) 41# (e.g. in file /etc/default/grub)
41# GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=16M ..." 42# GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=16M ..."
42# 43#
43 44
45# ----------------- LIBRARIES --------------------
46
44import sys 47import sys
45import time 48import time
46import os 49import os
47import string 50import string
48import re 51import re
49import array
50import platform 52import platform
51import datetime 53from datetime import datetime
52import struct 54import struct
53 55
54# -- classes -- 56# ----------------- CLASSES --------------------
55 57
58# Class: SystemValues
59# Description:
60# A global, single-instance container used to
61# store system values and test parameters
56class SystemValues: 62class SystemValues:
57 testdir = "." 63 version = 3.0
58 tpath = "/sys/kernel/debug/tracing/" 64 verbose = False
59 mempath = "/dev/mem" 65 testdir = '.'
60 powerfile = "/sys/power/state" 66 tpath = '/sys/kernel/debug/tracing/'
61 suspendmode = "mem" 67 fpdtpath = '/sys/firmware/acpi/tables/FPDT'
62 prefix = "test" 68 epath = '/sys/kernel/debug/tracing/events/power/'
63 teststamp = "" 69 traceevents = [
64 dmesgfile = "" 70 'suspend_resume',
65 ftracefile = "" 71 'device_pm_callback_end',
66 htmlfile = "" 72 'device_pm_callback_start'
73 ]
74 modename = {
75 'freeze': 'Suspend-To-Idle (S0)',
76 'standby': 'Power-On Suspend (S1)',
77 'mem': 'Suspend-to-RAM (S3)',
78 'disk': 'Suspend-to-disk (S4)'
79 }
80 mempath = '/dev/mem'
81 powerfile = '/sys/power/state'
82 suspendmode = 'mem'
83 hostname = 'localhost'
84 prefix = 'test'
85 teststamp = ''
86 dmesgfile = ''
87 ftracefile = ''
88 htmlfile = ''
67 rtcwake = False 89 rtcwake = False
90 rtcwaketime = 10
91 rtcpath = ''
92 android = False
93 adb = 'adb'
94 devicefilter = []
95 stamp = 0
96 execcount = 1
97 x2delay = 0
98 usecallgraph = False
99 usetraceevents = False
100 usetraceeventsonly = False
101 notestrun = False
102 altdevname = dict()
103 postresumetime = 0
104 tracertypefmt = '# tracer: (?P<t>.*)'
105 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$'
106 postresumefmt = '# post resume time (?P<t>[0-9]*)$'
107 stampfmt = '# suspend-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\
108 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\
109 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
110 def __init__(self):
111 self.hostname = platform.node()
112 if(self.hostname == ''):
113 self.hostname = 'localhost'
114 rtc = "rtc0"
115 if os.path.exists('/dev/rtc'):
116 rtc = os.readlink('/dev/rtc')
117 rtc = '/sys/class/rtc/'+rtc
118 if os.path.exists(rtc) and os.path.exists(rtc+'/date') and \
119 os.path.exists(rtc+'/time') and os.path.exists(rtc+'/wakealarm'):
120 self.rtcpath = rtc
68 def setOutputFile(self): 121 def setOutputFile(self):
69 if((self.htmlfile == "") and (self.dmesgfile != "")): 122 if((self.htmlfile == '') and (self.dmesgfile != '')):
70 m = re.match(r"(?P<name>.*)_dmesg\.txt$", self.dmesgfile) 123 m = re.match('(?P<name>.*)_dmesg\.txt$', self.dmesgfile)
71 if(m): 124 if(m):
72 self.htmlfile = m.group("name")+".html" 125 self.htmlfile = m.group('name')+'.html'
73 if((self.htmlfile == "") and (self.ftracefile != "")): 126 if((self.htmlfile == '') and (self.ftracefile != '')):
74 m = re.match(r"(?P<name>.*)_ftrace\.txt$", self.ftracefile) 127 m = re.match('(?P<name>.*)_ftrace\.txt$', self.ftracefile)
75 if(m): 128 if(m):
76 self.htmlfile = m.group("name")+".html" 129 self.htmlfile = m.group('name')+'.html'
77 if(self.htmlfile == ""): 130 if(self.htmlfile == ''):
78 self.htmlfile = "output.html" 131 self.htmlfile = 'output.html'
79 def initTestOutput(self): 132 def initTestOutput(self, subdir):
80 hostname = platform.node() 133 if(not self.android):
81 if(hostname != ""): 134 self.prefix = self.hostname
82 self.prefix = hostname 135 v = open('/proc/version', 'r').read().strip()
83 v = os.popen("cat /proc/version").read().strip() 136 kver = string.split(v)[2]
84 kver = string.split(v)[2] 137 else:
85 self.testdir = os.popen("date \"+suspend-%m%d%y-%H%M%S\"").read().strip() 138 self.prefix = 'android'
86 self.teststamp = "# "+self.testdir+" "+self.prefix+" "+self.suspendmode+" "+kver 139 v = os.popen(self.adb+' shell cat /proc/version').read().strip()
87 self.dmesgfile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+"_dmesg.txt" 140 kver = string.split(v)[2]
88 self.ftracefile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+"_ftrace.txt" 141 testtime = datetime.now().strftime('suspend-%m%d%y-%H%M%S')
89 self.htmlfile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+".html" 142 if(subdir != "."):
143 self.testdir = subdir+"/"+testtime
144 else:
145 self.testdir = testtime
146 self.teststamp = \
147 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver
148 self.dmesgfile = \
149 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt'
150 self.ftracefile = \
151 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt'
152 self.htmlfile = \
153 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html'
90 os.mkdir(self.testdir) 154 os.mkdir(self.testdir)
155 def setDeviceFilter(self, devnames):
156 self.devicefilter = string.split(devnames)
157 def rtcWakeAlarm(self):
158 os.system('echo 0 > '+self.rtcpath+'/wakealarm')
159 outD = open(self.rtcpath+'/date', 'r').read().strip()
160 outT = open(self.rtcpath+'/time', 'r').read().strip()
161 mD = re.match('^(?P<y>[0-9]*)-(?P<m>[0-9]*)-(?P<d>[0-9]*)', outD)
162 mT = re.match('^(?P<h>[0-9]*):(?P<m>[0-9]*):(?P<s>[0-9]*)', outT)
163 if(mD and mT):
164 # get the current time from hardware
165 utcoffset = int((datetime.now() - datetime.utcnow()).total_seconds())
166 dt = datetime(\
167 int(mD.group('y')), int(mD.group('m')), int(mD.group('d')),
168 int(mT.group('h')), int(mT.group('m')), int(mT.group('s')))
169 nowtime = int(dt.strftime('%s')) + utcoffset
170 else:
171 # if hardware time fails, use the software time
172 nowtime = int(datetime.now().strftime('%s'))
173 alarm = nowtime + self.rtcwaketime
174 os.system('echo %d > %s/wakealarm' % (alarm, self.rtcpath))
91 175
176sysvals = SystemValues()
177
178# Class: DeviceNode
179# Description:
180# A container used to create a device hierachy, with a single root node
181# and a tree of child nodes. Used by Data.deviceTopology()
182class DeviceNode:
183 name = ''
184 children = 0
185 depth = 0
186 def __init__(self, nodename, nodedepth):
187 self.name = nodename
188 self.children = []
189 self.depth = nodedepth
190
191# Class: Data
192# Description:
193# The primary container for suspend/resume test data. There is one for
194# each test run. The data is organized into a cronological hierarchy:
195# Data.dmesg {
196# root structure, started as dmesg & ftrace, but now only ftrace
197# contents: times for suspend start/end, resume start/end, fwdata
198# phases {
199# 10 sequential, non-overlapping phases of S/R
200# contents: times for phase start/end, order/color data for html
201# devlist {
202# device callback or action list for this phase
203# device {
204# a single device callback or generic action
205# contents: start/stop times, pid/cpu/driver info
206# parents/children, html id for timeline/callgraph
207# optionally includes an ftrace callgraph
208# optionally includes intradev trace events
209# }
210# }
211# }
212# }
213#
92class Data: 214class Data:
93 altdevname = dict() 215 dmesg = {} # root data structure
94 usedmesg = False 216 phases = [] # ordered list of phases
95 useftrace = False 217 start = 0.0 # test start
96 notestrun = False 218 end = 0.0 # test end
97 verbose = False 219 tSuspended = 0.0 # low-level suspend start
98 phases = [] 220 tResumed = 0.0 # low-level resume start
99 dmesg = {} # root data structure 221 tLow = 0.0 # time spent in low-level suspend (standby/freeze)
100 start = 0.0 222 fwValid = False # is firmware data available
101 end = 0.0 223 fwSuspend = 0 # time spent in firmware suspend
102 stamp = {'time': "", 'host': "", 'mode': ""} 224 fwResume = 0 # time spent in firmware resume
103 id = 0 225 dmesgtext = [] # dmesg text file in memory
104 tSuspended = 0.0 226 testnumber = 0
105 fwValid = False 227 idstr = ''
106 fwSuspend = 0 228 html_device_id = 0
107 fwResume = 0 229 stamp = 0
108 def initialize(self): 230 outfile = ''
109 self.dmesg = { # dmesg log data 231 def __init__(self, num):
110 'suspend_general': {'list': dict(), 'start': -1.0, 'end': -1.0, 232 idchar = 'abcdefghijklmnopqrstuvwxyz'
111 'row': 0, 'color': "#CCFFCC", 'order': 0}, 233 self.testnumber = num
112 'suspend_early': {'list': dict(), 'start': -1.0, 'end': -1.0, 234 self.idstr = idchar[num]
113 'row': 0, 'color': "green", 'order': 1}, 235 self.dmesgtext = []
236 self.phases = []
237 self.dmesg = { # fixed list of 10 phases
238 'suspend_prepare': {'list': dict(), 'start': -1.0, 'end': -1.0,
239 'row': 0, 'color': '#CCFFCC', 'order': 0},
240 'suspend': {'list': dict(), 'start': -1.0, 'end': -1.0,
241 'row': 0, 'color': '#88FF88', 'order': 1},
242 'suspend_late': {'list': dict(), 'start': -1.0, 'end': -1.0,
243 'row': 0, 'color': '#00AA00', 'order': 2},
114 'suspend_noirq': {'list': dict(), 'start': -1.0, 'end': -1.0, 244 'suspend_noirq': {'list': dict(), 'start': -1.0, 'end': -1.0,
115 'row': 0, 'color': "#00FFFF", 'order': 2}, 245 'row': 0, 'color': '#008888', 'order': 3},
116 'suspend_cpu': {'list': dict(), 'start': -1.0, 'end': -1.0, 246 'suspend_machine': {'list': dict(), 'start': -1.0, 'end': -1.0,
117 'row': 0, 'color': "blue", 'order': 3}, 247 'row': 0, 'color': '#0000FF', 'order': 4},
118 'resume_cpu': {'list': dict(), 'start': -1.0, 'end': -1.0, 248 'resume_machine': {'list': dict(), 'start': -1.0, 'end': -1.0,
119 'row': 0, 'color': "red", 'order': 4}, 249 'row': 0, 'color': '#FF0000', 'order': 5},
120 'resume_noirq': {'list': dict(), 'start': -1.0, 'end': -1.0, 250 'resume_noirq': {'list': dict(), 'start': -1.0, 'end': -1.0,
121 'row': 0, 'color': "orange", 'order': 5}, 251 'row': 0, 'color': '#FF9900', 'order': 6},
122 'resume_early': {'list': dict(), 'start': -1.0, 'end': -1.0, 252 'resume_early': {'list': dict(), 'start': -1.0, 'end': -1.0,
123 'row': 0, 'color': "yellow", 'order': 6}, 253 'row': 0, 'color': '#FFCC00', 'order': 7},
124 'resume_general': {'list': dict(), 'start': -1.0, 'end': -1.0, 254 'resume': {'list': dict(), 'start': -1.0, 'end': -1.0,
125 'row': 0, 'color': "#FFFFCC", 'order': 7} 255 'row': 0, 'color': '#FFFF88', 'order': 8},
256 'resume_complete': {'list': dict(), 'start': -1.0, 'end': -1.0,
257 'row': 0, 'color': '#FFFFCC', 'order': 9}
126 } 258 }
127 self.phases = self.sortedPhases() 259 self.phases = self.sortedPhases()
128 def normalizeTime(self): 260 def getStart(self):
129 tSus = tRes = self.tSuspended 261 return self.dmesg[self.phases[0]]['start']
130 if self.fwValid: 262 def setStart(self, time):
131 tSus -= -self.fwSuspend / 1000000000.0 263 self.start = time
132 tRes -= self.fwResume / 1000000000.0 264 self.dmesg[self.phases[0]]['start'] = time
133 self.tSuspended = 0.0 265 def getEnd(self):
134 self.start -= tSus 266 return self.dmesg[self.phases[-1]]['end']
135 self.end -= tRes 267 def setEnd(self, time):
268 self.end = time
269 self.dmesg[self.phases[-1]]['end'] = time
270 def isTraceEventOutsideDeviceCalls(self, pid, time):
271 for phase in self.phases:
272 list = self.dmesg[phase]['list']
273 for dev in list:
274 d = list[dev]
275 if(d['pid'] == pid and time >= d['start'] and
276 time <= d['end']):
277 return False
278 return True
279 def addIntraDevTraceEvent(self, action, name, pid, time):
280 if(action == 'mutex_lock_try'):
281 color = 'red'
282 elif(action == 'mutex_lock_pass'):
283 color = 'green'
284 elif(action == 'mutex_unlock'):
285 color = 'blue'
286 else:
287 # create separate colors based on the name
288 v1 = len(name)*10 % 256
289 v2 = string.count(name, 'e')*100 % 256
290 v3 = ord(name[0])*20 % 256
291 color = '#%06X' % ((v1*0x10000) + (v2*0x100) + v3)
292 for phase in self.phases:
293 list = self.dmesg[phase]['list']
294 for dev in list:
295 d = list[dev]
296 if(d['pid'] == pid and time >= d['start'] and
297 time <= d['end']):
298 e = TraceEvent(action, name, color, time)
299 if('traceevents' not in d):
300 d['traceevents'] = []
301 d['traceevents'].append(e)
302 return d
303 break
304 return 0
305 def capIntraDevTraceEvent(self, action, name, pid, time):
306 for phase in self.phases:
307 list = self.dmesg[phase]['list']
308 for dev in list:
309 d = list[dev]
310 if(d['pid'] == pid and time >= d['start'] and
311 time <= d['end']):
312 if('traceevents' not in d):
313 return
314 for e in d['traceevents']:
315 if(e.action == action and
316 e.name == name and not e.ready):
317 e.length = time - e.time
318 e.ready = True
319 break
320 return
321 def trimTimeVal(self, t, t0, dT, left):
322 if left:
323 if(t > t0):
324 if(t - dT < t0):
325 return t0
326 return t - dT
327 else:
328 return t
329 else:
330 if(t < t0 + dT):
331 if(t > t0):
332 return t0 + dT
333 return t + dT
334 else:
335 return t
336 def trimTime(self, t0, dT, left):
337 self.tSuspended = self.trimTimeVal(self.tSuspended, t0, dT, left)
338 self.tResumed = self.trimTimeVal(self.tResumed, t0, dT, left)
339 self.start = self.trimTimeVal(self.start, t0, dT, left)
340 self.end = self.trimTimeVal(self.end, t0, dT, left)
136 for phase in self.phases: 341 for phase in self.phases:
137 zero = tRes
138 if "suspend" in phase:
139 zero = tSus
140 p = self.dmesg[phase] 342 p = self.dmesg[phase]
141 p['start'] -= zero 343 p['start'] = self.trimTimeVal(p['start'], t0, dT, left)
142 p['end'] -= zero 344 p['end'] = self.trimTimeVal(p['end'], t0, dT, left)
143 list = p['list'] 345 list = p['list']
144 for name in list: 346 for name in list:
145 d = list[name] 347 d = list[name]
146 d['start'] -= zero 348 d['start'] = self.trimTimeVal(d['start'], t0, dT, left)
147 d['end'] -= zero 349 d['end'] = self.trimTimeVal(d['end'], t0, dT, left)
148 if('ftrace' in d): 350 if('ftrace' in d):
149 cg = d['ftrace'] 351 cg = d['ftrace']
150 cg.start -= zero 352 cg.start = self.trimTimeVal(cg.start, t0, dT, left)
151 cg.end -= zero 353 cg.end = self.trimTimeVal(cg.end, t0, dT, left)
152 for line in cg.list: 354 for line in cg.list:
153 line.time -= zero 355 line.time = self.trimTimeVal(line.time, t0, dT, left)
154 if self.fwValid: 356 if('traceevents' in d):
155 fws = -self.fwSuspend / 1000000000.0 357 for e in d['traceevents']:
156 fwr = self.fwResume / 1000000000.0 358 e.time = self.trimTimeVal(e.time, t0, dT, left)
157 list = dict() 359 def normalizeTime(self, tZero):
158 self.id += 1 360 # first trim out any standby or freeze clock time
159 devid = "dc%d" % self.id 361 if(self.tSuspended != self.tResumed):
160 list["firmware-suspend"] = \ 362 if(self.tResumed > tZero):
161 {'start': fws, 'end': 0, 'pid': 0, 'par': "", 363 self.trimTime(self.tSuspended, \
162 'length': -fws, 'row': 0, 'id': devid }; 364 self.tResumed-self.tSuspended, True)
163 self.id += 1 365 else:
164 devid = "dc%d" % self.id 366 self.trimTime(self.tSuspended, \
165 list["firmware-resume"] = \ 367 self.tResumed-self.tSuspended, False)
166 {'start': 0, 'end': fwr, 'pid': 0, 'par': "", 368 # shift the timeline so that tZero is the new 0
167 'length': fwr, 'row': 0, 'id': devid }; 369 self.tSuspended -= tZero
168 self.dmesg['BIOS'] = \ 370 self.tResumed -= tZero
169 {'list': list, 'start': fws, 'end': fwr, 371 self.start -= tZero
170 'row': 0, 'color': "purple", 'order': 4} 372 self.end -= tZero
171 self.dmesg['resume_cpu']['order'] += 1 373 for phase in self.phases:
172 self.dmesg['resume_noirq']['order'] += 1 374 p = self.dmesg[phase]
173 self.dmesg['resume_early']['order'] += 1 375 p['start'] -= tZero
174 self.dmesg['resume_general']['order'] += 1 376 p['end'] -= tZero
175 self.phases = self.sortedPhases() 377 list = p['list']
176 def vprint(self, msg): 378 for name in list:
177 if(self.verbose): 379 d = list[name]
178 print(msg) 380 d['start'] -= tZero
381 d['end'] -= tZero
382 if('ftrace' in d):
383 cg = d['ftrace']
384 cg.start -= tZero
385 cg.end -= tZero
386 for line in cg.list:
387 line.time -= tZero
388 if('traceevents' in d):
389 for e in d['traceevents']:
390 e.time -= tZero
391 def newPhaseWithSingleAction(self, phasename, devname, start, end, color):
392 for phase in self.phases:
393 self.dmesg[phase]['order'] += 1
394 self.html_device_id += 1
395 devid = '%s%d' % (self.idstr, self.html_device_id)
396 list = dict()
397 list[devname] = \
398 {'start': start, 'end': end, 'pid': 0, 'par': '',
399 'length': (end-start), 'row': 0, 'id': devid, 'drv': '' };
400 self.dmesg[phasename] = \
401 {'list': list, 'start': start, 'end': end,
402 'row': 0, 'color': color, 'order': 0}
403 self.phases = self.sortedPhases()
404 def newPhase(self, phasename, start, end, color, order):
405 if(order < 0):
406 order = len(self.phases)
407 for phase in self.phases[order:]:
408 self.dmesg[phase]['order'] += 1
409 if(order > 0):
410 p = self.phases[order-1]
411 self.dmesg[p]['end'] = start
412 if(order < len(self.phases)):
413 p = self.phases[order]
414 self.dmesg[p]['start'] = end
415 list = dict()
416 self.dmesg[phasename] = \
417 {'list': list, 'start': start, 'end': end,
418 'row': 0, 'color': color, 'order': order}
419 self.phases = self.sortedPhases()
420 def setPhase(self, phase, ktime, isbegin):
421 if(isbegin):
422 self.dmesg[phase]['start'] = ktime
423 else:
424 self.dmesg[phase]['end'] = ktime
179 def dmesgSortVal(self, phase): 425 def dmesgSortVal(self, phase):
180 return self.dmesg[phase]['order'] 426 return self.dmesg[phase]['order']
181 def sortedPhases(self): 427 def sortedPhases(self):
@@ -197,59 +443,180 @@ class Data:
197 dev = phaselist[devname] 443 dev = phaselist[devname]
198 if(dev['end'] < 0): 444 if(dev['end'] < 0):
199 dev['end'] = end 445 dev['end'] = end
200 self.vprint("%s (%s): callback didn't return" % (devname, phase)) 446 vprint('%s (%s): callback didnt return' % (devname, phase))
447 def deviceFilter(self, devicefilter):
448 # remove all by the relatives of the filter devnames
449 filter = []
450 for phase in self.phases:
451 list = self.dmesg[phase]['list']
452 for name in devicefilter:
453 dev = name
454 while(dev in list):
455 if(dev not in filter):
456 filter.append(dev)
457 dev = list[dev]['par']
458 children = self.deviceDescendants(name, phase)
459 for dev in children:
460 if(dev not in filter):
461 filter.append(dev)
462 for phase in self.phases:
463 list = self.dmesg[phase]['list']
464 rmlist = []
465 for name in list:
466 pid = list[name]['pid']
467 if(name not in filter and pid >= 0):
468 rmlist.append(name)
469 for name in rmlist:
470 del list[name]
201 def fixupInitcallsThatDidntReturn(self): 471 def fixupInitcallsThatDidntReturn(self):
202 # if any calls never returned, clip them at system resume end 472 # if any calls never returned, clip them at system resume end
203 for phase in self.phases: 473 for phase in self.phases:
204 self.fixupInitcalls(phase, self.dmesg['resume_general']['end']) 474 self.fixupInitcalls(phase, self.getEnd())
205 if(phase == "resume_general"): 475 def newActionGlobal(self, name, start, end):
206 break 476 # which phase is this device callback or action "in"
207 def newAction(self, phase, name, pid, parent, start, end): 477 targetphase = "none"
208 self.id += 1 478 overlap = 0.0
209 devid = "dc%d" % self.id 479 for phase in self.phases:
480 pstart = self.dmesg[phase]['start']
481 pend = self.dmesg[phase]['end']
482 o = max(0, min(end, pend) - max(start, pstart))
483 if(o > overlap):
484 targetphase = phase
485 overlap = o
486 if targetphase in self.phases:
487 self.newAction(targetphase, name, -1, '', start, end, '')
488 return True
489 return False
490 def newAction(self, phase, name, pid, parent, start, end, drv):
491 # new device callback for a specific phase
492 self.html_device_id += 1
493 devid = '%s%d' % (self.idstr, self.html_device_id)
210 list = self.dmesg[phase]['list'] 494 list = self.dmesg[phase]['list']
211 length = -1.0 495 length = -1.0
212 if(start >= 0 and end >= 0): 496 if(start >= 0 and end >= 0):
213 length = end - start 497 length = end - start
214 list[name] = {'start': start, 'end': end, 'pid': pid, 'par': parent, 498 list[name] = {'start': start, 'end': end, 'pid': pid, 'par': parent,
215 'length': length, 'row': 0, 'id': devid } 499 'length': length, 'row': 0, 'id': devid, 'drv': drv }
216 def deviceIDs(self, devlist, phase): 500 def deviceIDs(self, devlist, phase):
217 idlist = [] 501 idlist = []
218 for p in self.phases: 502 list = self.dmesg[phase]['list']
219 if(p[0] != phase[0]): 503 for devname in list:
220 continue 504 if devname in devlist:
221 list = data.dmesg[p]['list'] 505 idlist.append(list[devname]['id'])
222 for devname in list:
223 if devname in devlist:
224 idlist.append(list[devname]['id'])
225 return idlist 506 return idlist
226 def deviceParentID(self, devname, phase): 507 def deviceParentID(self, devname, phase):
227 pdev = "" 508 pdev = ''
228 pdevid = "" 509 pdevid = ''
229 for p in self.phases: 510 list = self.dmesg[phase]['list']
230 if(p[0] != phase[0]): 511 if devname in list:
231 continue 512 pdev = list[devname]['par']
232 list = data.dmesg[p]['list'] 513 if pdev in list:
233 if devname in list: 514 return list[pdev]['id']
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 515 return pdev
242 def deviceChildrenIDs(self, devname, phase): 516 def deviceChildren(self, devname, phase):
243 devlist = [] 517 devlist = []
244 for p in self.phases: 518 list = self.dmesg[phase]['list']
245 if(p[0] != phase[0]): 519 for child in list:
246 continue 520 if(list[child]['par'] == devname):
247 list = data.dmesg[p]['list'] 521 devlist.append(child)
248 for child in list: 522 return devlist
249 if(list[child]['par'] == devname): 523 def deviceDescendants(self, devname, phase):
250 devlist.append(child) 524 children = self.deviceChildren(devname, phase)
525 family = children
526 for child in children:
527 family += self.deviceDescendants(child, phase)
528 return family
529 def deviceChildrenIDs(self, devname, phase):
530 devlist = self.deviceChildren(devname, phase)
251 return self.deviceIDs(devlist, phase) 531 return self.deviceIDs(devlist, phase)
252 532 def printDetails(self):
533 vprint(' test start: %f' % self.start)
534 for phase in self.phases:
535 dc = len(self.dmesg[phase]['list'])
536 vprint(' %16s: %f - %f (%d devices)' % (phase, \
537 self.dmesg[phase]['start'], self.dmesg[phase]['end'], dc))
538 vprint(' test end: %f' % self.end)
539 def masterTopology(self, name, list, depth):
540 node = DeviceNode(name, depth)
541 for cname in list:
542 clist = self.deviceChildren(cname, 'resume')
543 cnode = self.masterTopology(cname, clist, depth+1)
544 node.children.append(cnode)
545 return node
546 def printTopology(self, node):
547 html = ''
548 if node.name:
549 info = ''
550 drv = ''
551 for phase in self.phases:
552 list = self.dmesg[phase]['list']
553 if node.name in list:
554 s = list[node.name]['start']
555 e = list[node.name]['end']
556 if list[node.name]['drv']:
557 drv = ' {'+list[node.name]['drv']+'}'
558 info += ('<li>%s: %.3fms</li>' % (phase, (e-s)*1000))
559 html += '<li><b>'+node.name+drv+'</b>'
560 if info:
561 html += '<ul>'+info+'</ul>'
562 html += '</li>'
563 if len(node.children) > 0:
564 html += '<ul>'
565 for cnode in node.children:
566 html += self.printTopology(cnode)
567 html += '</ul>'
568 return html
569 def rootDeviceList(self):
570 # list of devices graphed
571 real = []
572 for phase in self.dmesg:
573 list = self.dmesg[phase]['list']
574 for dev in list:
575 if list[dev]['pid'] >= 0 and dev not in real:
576 real.append(dev)
577 # list of top-most root devices
578 rootlist = []
579 for phase in self.dmesg:
580 list = self.dmesg[phase]['list']
581 for dev in list:
582 pdev = list[dev]['par']
583 if(re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)):
584 continue
585 if pdev and pdev not in real and pdev not in rootlist:
586 rootlist.append(pdev)
587 return rootlist
588 def deviceTopology(self):
589 rootlist = self.rootDeviceList()
590 master = self.masterTopology('', rootlist, 0)
591 return self.printTopology(master)
592
593# Class: TraceEvent
594# Description:
595# A container for trace event data found in the ftrace file
596class TraceEvent:
597 ready = False
598 name = ''
599 time = 0.0
600 color = '#FFFFFF'
601 length = 0.0
602 action = ''
603 def __init__(self, a, n, c, t):
604 self.action = a
605 self.name = n
606 self.color = c
607 self.time = t
608
609# Class: FTraceLine
610# Description:
611# A container for a single line of ftrace data. There are six basic types:
612# callgraph line:
613# call: " dpm_run_callback() {"
614# return: " }"
615# leaf: " dpm_run_callback();"
616# trace event:
617# tracing_mark_write: SUSPEND START or RESUME COMPLETE
618# suspend_resume: phase or custom exec block data
619# device_pm_callback: device callback info
253class FTraceLine: 620class FTraceLine:
254 time = 0.0 621 time = 0.0
255 length = 0.0 622 length = 0.0
@@ -257,20 +624,33 @@ class FTraceLine:
257 freturn = False 624 freturn = False
258 fevent = False 625 fevent = False
259 depth = 0 626 depth = 0
260 name = "" 627 name = ''
628 type = ''
261 def __init__(self, t, m, d): 629 def __init__(self, t, m, d):
262 self.time = float(t) 630 self.time = float(t)
263 # check to see if this is a trace event 631 # is this a trace event
264 em = re.match(r"^ *\/\* *(?P<msg>.*) \*\/ *$", m) 632 if(d == 'traceevent' or re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m)):
265 if(em): 633 if(d == 'traceevent'):
266 self.name = em.group("msg") 634 # nop format trace event
635 msg = m
636 else:
637 # function_graph format trace event
638 em = re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m)
639 msg = em.group('msg')
640
641 emm = re.match('^(?P<call>.*?): (?P<msg>.*)', msg)
642 if(emm):
643 self.name = emm.group('msg')
644 self.type = emm.group('call')
645 else:
646 self.name = msg
267 self.fevent = True 647 self.fevent = True
268 return 648 return
269 # convert the duration to seconds 649 # convert the duration to seconds
270 if(d): 650 if(d):
271 self.length = float(d)/1000000 651 self.length = float(d)/1000000
272 # the indentation determines the depth 652 # the indentation determines the depth
273 match = re.match(r"^(?P<d> *)(?P<o>.*)$", m) 653 match = re.match('^(?P<d> *)(?P<o>.*)$', m)
274 if(not match): 654 if(not match):
275 return 655 return
276 self.depth = self.getDepth(match.group('d')) 656 self.depth = self.getDepth(match.group('d'))
@@ -280,7 +660,7 @@ class FTraceLine:
280 self.freturn = True 660 self.freturn = True
281 if(len(m) > 1): 661 if(len(m) > 1):
282 # includes comment with function name 662 # includes comment with function name
283 match = re.match(r"^} *\/\* *(?P<n>.*) *\*\/$", m) 663 match = re.match('^} *\/\* *(?P<n>.*) *\*\/$', m)
284 if(match): 664 if(match):
285 self.name = match.group('n') 665 self.name = match.group('n')
286 # function call 666 # function call
@@ -288,13 +668,13 @@ class FTraceLine:
288 self.fcall = True 668 self.fcall = True
289 # function call with children 669 # function call with children
290 if(m[-1] == '{'): 670 if(m[-1] == '{'):
291 match = re.match(r"^(?P<n>.*) *\(.*", m) 671 match = re.match('^(?P<n>.*) *\(.*', m)
292 if(match): 672 if(match):
293 self.name = match.group('n') 673 self.name = match.group('n')
294 # function call with no children (leaf) 674 # function call with no children (leaf)
295 elif(m[-1] == ';'): 675 elif(m[-1] == ';'):
296 self.freturn = True 676 self.freturn = True
297 match = re.match(r"^(?P<n>.*) *\(.*", m) 677 match = re.match('^(?P<n>.*) *\(.*', m)
298 if(match): 678 if(match):
299 self.name = match.group('n') 679 self.name = match.group('n')
300 # something else (possibly a trace marker) 680 # something else (possibly a trace marker)
@@ -302,7 +682,23 @@ class FTraceLine:
302 self.name = m 682 self.name = m
303 def getDepth(self, str): 683 def getDepth(self, str):
304 return len(str)/2 684 return len(str)/2
685 def debugPrint(self, dev):
686 if(self.freturn and self.fcall):
687 print('%s -- %f (%02d): %s(); (%.3f us)' % (dev, self.time, \
688 self.depth, self.name, self.length*1000000))
689 elif(self.freturn):
690 print('%s -- %f (%02d): %s} (%.3f us)' % (dev, self.time, \
691 self.depth, self.name, self.length*1000000))
692 else:
693 print('%s -- %f (%02d): %s() { (%.3f us)' % (dev, self.time, \
694 self.depth, self.name, self.length*1000000))
305 695
696# Class: FTraceCallGraph
697# Description:
698# A container for the ftrace callgraph of a single recursive function.
699# This can be a dpm_run_callback, dpm_prepare, or dpm_complete callgraph
700# Each instance is tied to a single device in a single phase, and is
701# comprised of an ordered list of FTraceLine objects
306class FTraceCallGraph: 702class FTraceCallGraph:
307 start = -1.0 703 start = -1.0
308 end = -1.0 704 end = -1.0
@@ -327,24 +723,53 @@ class FTraceCallGraph:
327 if(not self.invalid): 723 if(not self.invalid):
328 self.setDepth(line) 724 self.setDepth(line)
329 if(line.depth == 0 and line.freturn): 725 if(line.depth == 0 and line.freturn):
726 if(self.start < 0):
727 self.start = line.time
330 self.end = line.time 728 self.end = line.time
331 self.list.append(line) 729 self.list.append(line)
332 return True 730 return True
333 if(self.invalid): 731 if(self.invalid):
334 return False 732 return False
335 if(len(self.list) >= 1000000 or self.depth < 0): 733 if(len(self.list) >= 1000000 or self.depth < 0):
336 first = self.list[0] 734 if(len(self.list) > 0):
337 self.list = [] 735 first = self.list[0]
338 self.list.append(first) 736 self.list = []
339 self.invalid = True 737 self.list.append(first)
340 id = "task %s cpu %s" % (match.group("pid"), match.group("cpu")) 738 self.invalid = True
341 window = "(%f - %f)" % (self.start, line.time) 739 if(not match):
342 data.vprint("Too much data for "+id+" "+window+", ignoring this callback") 740 return False
343 return False 741 id = 'task %s cpu %s' % (match.group('pid'), match.group('cpu'))
742 window = '(%f - %f)' % (self.start, line.time)
743 if(self.depth < 0):
744 print('Too much data for '+id+\
745 ' (buffer overflow), ignoring this callback')
746 else:
747 print('Too much data for '+id+\
748 ' '+window+', ignoring this callback')
749 return False
344 self.list.append(line) 750 self.list.append(line)
345 if(self.start < 0): 751 if(self.start < 0):
346 self.start = line.time 752 self.start = line.time
347 return False 753 return False
754 def slice(self, t0, tN):
755 minicg = FTraceCallGraph()
756 count = -1
757 firstdepth = 0
758 for l in self.list:
759 if(l.time < t0 or l.time > tN):
760 continue
761 if(count < 0):
762 if(not l.fcall or l.name == 'dev_driver_string'):
763 continue
764 firstdepth = l.depth
765 count = 0
766 l.depth -= firstdepth
767 minicg.addLine(l, 0)
768 if((count == 0 and l.freturn and l.fcall) or
769 (count > 0 and l.depth <= 0)):
770 break
771 count += 1
772 return minicg
348 def sanityCheck(self): 773 def sanityCheck(self):
349 stack = dict() 774 stack = dict()
350 cnt = 0 775 cnt = 0
@@ -353,7 +778,7 @@ class FTraceCallGraph:
353 stack[l.depth] = l 778 stack[l.depth] = l
354 cnt += 1 779 cnt += 1
355 elif(l.freturn and not l.fcall): 780 elif(l.freturn and not l.fcall):
356 if(not stack[l.depth]): 781 if(l.depth not in stack):
357 return False 782 return False
358 stack[l.depth].length = l.length 783 stack[l.depth].length = l.length
359 stack[l.depth] = 0 784 stack[l.depth] = 0
@@ -363,40 +788,51 @@ class FTraceCallGraph:
363 return True 788 return True
364 return False 789 return False
365 def debugPrint(self, filename): 790 def debugPrint(self, filename):
366 if(filename == "stdout"): 791 if(filename == 'stdout'):
367 print("[%f - %f]") % (self.start, self.end) 792 print('[%f - %f]') % (self.start, self.end)
368 for l in self.list: 793 for l in self.list:
369 if(l.freturn and l.fcall): 794 if(l.freturn and l.fcall):
370 print("%f (%02d): %s(); (%.3f us)" % (l.time, l.depth, l.name, l.length*1000000)) 795 print('%f (%02d): %s(); (%.3f us)' % (l.time, \
796 l.depth, l.name, l.length*1000000))
371 elif(l.freturn): 797 elif(l.freturn):
372 print("%f (%02d): %s} (%.3f us)" % (l.time, l.depth, l.name, l.length*1000000)) 798 print('%f (%02d): %s} (%.3f us)' % (l.time, \
799 l.depth, l.name, l.length*1000000))
373 else: 800 else:
374 print("%f (%02d): %s() { (%.3f us)" % (l.time, l.depth, l.name, l.length*1000000)) 801 print('%f (%02d): %s() { (%.3f us)' % (l.time, \
375 print(" ") 802 l.depth, l.name, l.length*1000000))
803 print(' ')
376 else: 804 else:
377 fp = open(filename, 'w') 805 fp = open(filename, 'w')
378 print(filename) 806 print(filename)
379 for l in self.list: 807 for l in self.list:
380 if(l.freturn and l.fcall): 808 if(l.freturn and l.fcall):
381 fp.write("%f (%02d): %s(); (%.3f us)\n" % (l.time, l.depth, l.name, l.length*1000000)) 809 fp.write('%f (%02d): %s(); (%.3f us)\n' % (l.time, \
810 l.depth, l.name, l.length*1000000))
382 elif(l.freturn): 811 elif(l.freturn):
383 fp.write("%f (%02d): %s} (%.3f us)\n" % (l.time, l.depth, l.name, l.length*1000000)) 812 fp.write('%f (%02d): %s} (%.3f us)\n' % (l.time, \
813 l.depth, l.name, l.length*1000000))
384 else: 814 else:
385 fp.write("%f (%02d): %s() { (%.3f us)\n" % (l.time, l.depth, l.name, l.length*1000000)) 815 fp.write('%f (%02d): %s() { (%.3f us)\n' % (l.time, \
816 l.depth, l.name, l.length*1000000))
386 fp.close() 817 fp.close()
387 818
819# Class: Timeline
820# Description:
821# A container for a suspend/resume html timeline. In older versions
822# of the script there were multiple timelines, but in the latest
823# there is only one.
388class Timeline: 824class Timeline:
389 html = {} 825 html = {}
390 scaleH = 0.0 # height of the timescale row as a percent of the timeline height 826 scaleH = 0.0 # height of the row as a percent of the timeline height
391 rowH = 0.0 # height of each row in percent of the timeline height 827 rowH = 0.0 # height of each row in percent of the timeline height
392 row_height_pixels = 30 828 row_height_pixels = 30
393 maxrows = 0 829 maxrows = 0
394 height = 0 830 height = 0
395 def __init__(self): 831 def __init__(self):
396 self.html = { 832 self.html = {
397 'timeline': "", 833 'timeline': '',
398 'legend': "", 834 'legend': '',
399 'scale': "" 835 'scale': ''
400 } 836 }
401 def setRows(self, rows): 837 def setRows(self, rows):
402 self.maxrows = int(rows) 838 self.maxrows = int(rows)
@@ -407,104 +843,261 @@ class Timeline:
407 r = 1.0 843 r = 1.0
408 self.rowH = (100.0 - self.scaleH)/r 844 self.rowH = (100.0 - self.scaleH)/r
409 845
410# -- global objects -- 846# Class: TestRun
847# Description:
848# A container for a suspend/resume test run. This is necessary as
849# there could be more than one, and they need to be separate.
850class TestRun:
851 ftrace_line_fmt_fg = \
852 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\
853 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\
854 '[ +!]*(?P<dur>[0-9\.]*) .*\| (?P<msg>.*)'
855 ftrace_line_fmt_nop = \
856 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\[(?P<cpu>[0-9]*)\] *'+\
857 '(?P<flags>.{4}) *(?P<time>[0-9\.]*): *'+\
858 '(?P<msg>.*)'
859 ftrace_line_fmt = ftrace_line_fmt_nop
860 cgformat = False
861 ftemp = dict()
862 ttemp = dict()
863 inthepipe = False
864 tracertype = ''
865 data = 0
866 def __init__(self, dataobj):
867 self.data = dataobj
868 self.ftemp = dict()
869 self.ttemp = dict()
870 def isReady(self):
871 if(tracertype == '' or not data):
872 return False
873 return True
874 def setTracerType(self, tracer):
875 self.tracertype = tracer
876 if(tracer == 'function_graph'):
877 self.cgformat = True
878 self.ftrace_line_fmt = self.ftrace_line_fmt_fg
879 elif(tracer == 'nop'):
880 self.ftrace_line_fmt = self.ftrace_line_fmt_nop
881 else:
882 doError('Invalid tracer format: [%s]' % tracer, False)
411 883
412sysvals = SystemValues() 884# ----------------- FUNCTIONS --------------------
413data = Data()
414 885
415# -- functions -- 886# Function: vprint
887# Description:
888# verbose print (prints only with -verbose option)
889# Arguments:
890# msg: the debug/log message to print
891def vprint(msg):
892 global sysvals
893 if(sysvals.verbose):
894 print(msg)
416 895
417# Function: initFtrace 896# Function: initFtrace
418# Description: 897# Description:
419# Configure ftrace to capture a function trace during suspend/resume 898# Configure ftrace to use trace events and/or a callgraph
420def initFtrace(): 899def initFtrace():
421 global sysvals 900 global sysvals
422 901
423 print("INITIALIZING FTRACE...") 902 tp = sysvals.tpath
424 # turn trace off 903 cf = 'dpm_run_callback'
425 os.system("echo 0 > "+sysvals.tpath+"tracing_on") 904 if(sysvals.usetraceeventsonly):
426 # set the trace clock to global 905 cf = '-e dpm_prepare -e dpm_complete -e dpm_run_callback'
427 os.system("echo global > "+sysvals.tpath+"trace_clock") 906 if(sysvals.usecallgraph or sysvals.usetraceevents):
428 # set trace buffer to a huge value 907 print('INITIALIZING FTRACE...')
429 os.system("echo nop > "+sysvals.tpath+"current_tracer") 908 # turn trace off
430 os.system("echo 100000 > "+sysvals.tpath+"buffer_size_kb") 909 os.system('echo 0 > '+tp+'tracing_on')
431 # clear the trace buffer 910 # set the trace clock to global
432 os.system("echo \"\" > "+sysvals.tpath+"trace") 911 os.system('echo global > '+tp+'trace_clock')
433 # set trace type 912 # set trace buffer to a huge value
434 os.system("echo function_graph > "+sysvals.tpath+"current_tracer") 913 os.system('echo nop > '+tp+'current_tracer')
435 os.system("echo \"\" > "+sysvals.tpath+"set_ftrace_filter") 914 os.system('echo 100000 > '+tp+'buffer_size_kb')
436 # set trace format options 915 # initialize the callgraph trace, unless this is an x2 run
437 os.system("echo funcgraph-abstime > "+sysvals.tpath+"trace_options") 916 if(sysvals.usecallgraph and sysvals.execcount == 1):
438 os.system("echo funcgraph-proc > "+sysvals.tpath+"trace_options") 917 # set trace type
439 # focus only on device suspend and resume 918 os.system('echo function_graph > '+tp+'current_tracer')
440 os.system("cat "+sysvals.tpath+"available_filter_functions | grep dpm_run_callback > "+sysvals.tpath+"set_graph_function") 919 os.system('echo "" > '+tp+'set_ftrace_filter')
920 # set trace format options
921 os.system('echo funcgraph-abstime > '+tp+'trace_options')
922 os.system('echo funcgraph-proc > '+tp+'trace_options')
923 # focus only on device suspend and resume
924 os.system('cat '+tp+'available_filter_functions | grep '+\
925 cf+' > '+tp+'set_graph_function')
926 if(sysvals.usetraceevents):
927 # turn trace events on
928 events = iter(sysvals.traceevents)
929 for e in events:
930 os.system('echo 1 > '+sysvals.epath+e+'/enable')
931 # clear the trace buffer
932 os.system('echo "" > '+tp+'trace')
933
934# Function: initFtraceAndroid
935# Description:
936# Configure ftrace to capture trace events
937def initFtraceAndroid():
938 global sysvals
939
940 tp = sysvals.tpath
941 if(sysvals.usetraceevents):
942 print('INITIALIZING FTRACE...')
943 # turn trace off
944 os.system(sysvals.adb+" shell 'echo 0 > "+tp+"tracing_on'")
945 # set the trace clock to global
946 os.system(sysvals.adb+" shell 'echo global > "+tp+"trace_clock'")
947 # set trace buffer to a huge value
948 os.system(sysvals.adb+" shell 'echo nop > "+tp+"current_tracer'")
949 os.system(sysvals.adb+" shell 'echo 10000 > "+tp+"buffer_size_kb'")
950 # turn trace events on
951 events = iter(sysvals.traceevents)
952 for e in events:
953 os.system(sysvals.adb+" shell 'echo 1 > "+\
954 sysvals.epath+e+"/enable'")
955 # clear the trace buffer
956 os.system(sysvals.adb+" shell 'echo \"\" > "+tp+"trace'")
441 957
442# Function: verifyFtrace 958# Function: verifyFtrace
443# Description: 959# Description:
444# Check that ftrace is working on the system 960# Check that ftrace is working on the system
961# Output:
962# True or False
445def verifyFtrace(): 963def verifyFtrace():
446 global sysvals 964 global sysvals
447 files = ["available_filter_functions", "buffer_size_kb", 965 # files needed for any trace data
448 "current_tracer", "set_ftrace_filter", 966 files = ['buffer_size_kb', 'current_tracer', 'trace', 'trace_clock',
449 "trace", "trace_marker"] 967 'trace_marker', 'trace_options', 'tracing_on']
968 # files needed for callgraph trace data
969 tp = sysvals.tpath
970 if(sysvals.usecallgraph):
971 files += [
972 'available_filter_functions',
973 'set_ftrace_filter',
974 'set_graph_function'
975 ]
450 for f in files: 976 for f in files:
451 if(os.path.exists(sysvals.tpath+f) == False): 977 if(sysvals.android):
452 return False 978 out = os.popen(sysvals.adb+' shell ls '+tp+f).read().strip()
979 if(out != tp+f):
980 return False
981 else:
982 if(os.path.exists(tp+f) == False):
983 return False
453 return True 984 return True
454 985
455def parseStamp(line): 986# Function: parseStamp
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: 987# Description:
473# Analyse an ftrace log output file generated from this app during 988# Pull in the stamp comment line from the data file(s),
474# the execution phase. Create an "ftrace" structure in memory for 989# create the stamp, and add it to the global sysvals object
475# subsequent formatting in the html output file 990# Arguments:
476def analyzeTraceLog(): 991# m: the valid re.match output for the stamp line
477 global sysvals, data 992def parseStamp(m, data):
478 993 global sysvals
479 # the ftrace data is tied to the dmesg data 994 data.stamp = {'time': '', 'host': '', 'mode': ''}
480 if(not data.usedmesg): 995 dt = datetime(int(m.group('y'))+2000, int(m.group('m')),
481 return 996 int(m.group('d')), int(m.group('H')), int(m.group('M')),
482 997 int(m.group('S')))
483 # read through the ftrace and parse the data 998 data.stamp['time'] = dt.strftime('%B %d %Y, %I:%M:%S %p')
484 data.vprint("Analyzing the ftrace data...") 999 data.stamp['host'] = m.group('host')
485 ftrace_line_fmt = r"^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)"+\ 1000 data.stamp['mode'] = m.group('mode')
486 " *(?P<proc>.*)-(?P<pid>[0-9]*) *\|"+\ 1001 data.stamp['kernel'] = m.group('kernel')
487 "[ +!]*(?P<dur>[0-9\.]*) .*\| (?P<msg>.*)" 1002 sysvals.suspendmode = data.stamp['mode']
488 ftemp = dict() 1003 if not sysvals.stamp:
489 inthepipe = False 1004 sysvals.stamp = data.stamp
1005
1006# Function: diffStamp
1007# Description:
1008# compare the host, kernel, and mode fields in 3 stamps
1009# Arguments:
1010# stamp1: string array with mode, kernel, and host
1011# stamp2: string array with mode, kernel, and host
1012# Return:
1013# True if stamps differ, False if they're the same
1014def diffStamp(stamp1, stamp2):
1015 if 'host' in stamp1 and 'host' in stamp2:
1016 if stamp1['host'] != stamp2['host']:
1017 return True
1018 if 'kernel' in stamp1 and 'kernel' in stamp2:
1019 if stamp1['kernel'] != stamp2['kernel']:
1020 return True
1021 if 'mode' in stamp1 and 'mode' in stamp2:
1022 if stamp1['mode'] != stamp2['mode']:
1023 return True
1024 return False
1025
1026# Function: doesTraceLogHaveTraceEvents
1027# Description:
1028# Quickly determine if the ftrace log has some or all of the trace events
1029# required for primary parsing. Set the usetraceevents and/or
1030# usetraceeventsonly flags in the global sysvals object
1031def doesTraceLogHaveTraceEvents():
1032 global sysvals
1033
1034 sysvals.usetraceeventsonly = True
1035 sysvals.usetraceevents = False
1036 for e in sysvals.traceevents:
1037 out = os.popen('cat '+sysvals.ftracefile+' | grep "'+e+': "').read()
1038 if(not out):
1039 sysvals.usetraceeventsonly = False
1040 if(e == 'suspend_resume' and out):
1041 sysvals.usetraceevents = True
1042
1043# Function: appendIncompleteTraceLog
1044# Description:
1045# [deprecated for kernel 3.15 or newer]
1046# Legacy support of ftrace outputs that lack the device_pm_callback
1047# and/or suspend_resume trace events. The primary data should be
1048# taken from dmesg, and this ftrace is used only for callgraph data
1049# or custom actions in the timeline. The data is appended to the Data
1050# objects provided.
1051# Arguments:
1052# testruns: the array of Data objects obtained from parseKernelLog
1053def appendIncompleteTraceLog(testruns):
1054 global sysvals
1055
1056 # create TestRun vessels for ftrace parsing
1057 testcnt = len(testruns)
1058 testidx = -1
1059 testrun = []
1060 for data in testruns:
1061 testrun.append(TestRun(data))
1062
1063 # extract the callgraph and traceevent data
1064 vprint('Analyzing the ftrace data...')
490 tf = open(sysvals.ftracefile, 'r') 1065 tf = open(sysvals.ftracefile, 'r')
491 count = 0
492 for line in tf: 1066 for line in tf:
493 count = count + 1 1067 # remove any latent carriage returns
494 # grab the time stamp if it's valid 1068 line = line.replace('\r\n', '')
495 if(count == 1): 1069 # grab the time stamp first (signifies the start of the test run)
496 parseStamp(line) 1070 m = re.match(sysvals.stampfmt, line)
1071 if(m):
1072 testidx += 1
1073 parseStamp(m, testrun[testidx].data)
1074 continue
1075 # pull out any firmware data
1076 if(re.match(sysvals.firmwarefmt, line)):
1077 continue
1078 # if we havent found a test time stamp yet keep spinning til we do
1079 if(testidx < 0):
1080 continue
1081 # determine the trace data type (required for further parsing)
1082 m = re.match(sysvals.tracertypefmt, line)
1083 if(m):
1084 tracer = m.group('t')
1085 testrun[testidx].setTracerType(tracer)
497 continue 1086 continue
498 # parse only valid lines 1087 # parse only valid lines, if this isnt one move on
499 m = re.match(ftrace_line_fmt, line) 1088 m = re.match(testrun[testidx].ftrace_line_fmt, line)
500 if(not m): 1089 if(not m):
501 continue 1090 continue
502 m_time = m.group("time") 1091 # gather the basic message data from the line
503 m_pid = m.group("pid") 1092 m_time = m.group('time')
504 m_msg = m.group("msg") 1093 m_pid = m.group('pid')
505 m_dur = m.group("dur") 1094 m_msg = m.group('msg')
1095 if(testrun[testidx].cgformat):
1096 m_param3 = m.group('dur')
1097 else:
1098 m_param3 = 'traceevent'
506 if(m_time and m_pid and m_msg): 1099 if(m_time and m_pid and m_msg):
507 t = FTraceLine(m_time, m_msg, m_dur) 1100 t = FTraceLine(m_time, m_msg, m_param3)
508 pid = int(m_pid) 1101 pid = int(m_pid)
509 else: 1102 else:
510 continue 1103 continue
@@ -512,265 +1105,840 @@ def analyzeTraceLog():
512 if(not t.fcall and not t.freturn and not t.fevent): 1105 if(not t.fcall and not t.freturn and not t.fevent):
513 continue 1106 continue
514 # only parse the ftrace data during suspend/resume 1107 # only parse the ftrace data during suspend/resume
515 if(not inthepipe): 1108 data = testrun[testidx].data
1109 if(not testrun[testidx].inthepipe):
516 # look for the suspend start marker 1110 # look for the suspend start marker
517 if(t.fevent): 1111 if(t.fevent):
518 if(t.name == "SUSPEND START"): 1112 if(t.name == 'SUSPEND START'):
519 data.vprint("SUSPEND START %f %s:%d" % (t.time, sysvals.ftracefile, count)) 1113 testrun[testidx].inthepipe = True
520 inthepipe = True 1114 data.setStart(t.time)
521 continue 1115 continue
522 else: 1116 else:
523 # look for the resume end marker 1117 # trace event processing
524 if(t.fevent): 1118 if(t.fevent):
525 if(t.name == "RESUME COMPLETE"): 1119 if(t.name == 'RESUME COMPLETE'):
526 data.vprint("RESUME COMPLETE %f %s:%d" % (t.time, sysvals.ftracefile, count)) 1120 testrun[testidx].inthepipe = False
527 inthepipe = False 1121 data.setEnd(t.time)
528 break 1122 if(testidx == testcnt - 1):
1123 break
1124 continue
1125 # general trace events have two types, begin and end
1126 if(re.match('(?P<name>.*) begin$', t.name)):
1127 isbegin = True
1128 elif(re.match('(?P<name>.*) end$', t.name)):
1129 isbegin = False
1130 else:
1131 continue
1132 m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name)
1133 if(m):
1134 val = m.group('val')
1135 if val == '0':
1136 name = m.group('name')
1137 else:
1138 name = m.group('name')+'['+val+']'
1139 else:
1140 m = re.match('(?P<name>.*) .*', t.name)
1141 name = m.group('name')
1142 # special processing for trace events
1143 if re.match('dpm_prepare\[.*', name):
1144 continue
1145 elif re.match('machine_suspend.*', name):
1146 continue
1147 elif re.match('suspend_enter\[.*', name):
1148 if(not isbegin):
1149 data.dmesg['suspend_prepare']['end'] = t.time
1150 continue
1151 elif re.match('dpm_suspend\[.*', name):
1152 if(not isbegin):
1153 data.dmesg['suspend']['end'] = t.time
1154 continue
1155 elif re.match('dpm_suspend_late\[.*', name):
1156 if(isbegin):
1157 data.dmesg['suspend_late']['start'] = t.time
1158 else:
1159 data.dmesg['suspend_late']['end'] = t.time
1160 continue
1161 elif re.match('dpm_suspend_noirq\[.*', name):
1162 if(isbegin):
1163 data.dmesg['suspend_noirq']['start'] = t.time
1164 else:
1165 data.dmesg['suspend_noirq']['end'] = t.time
1166 continue
1167 elif re.match('dpm_resume_noirq\[.*', name):
1168 if(isbegin):
1169 data.dmesg['resume_machine']['end'] = t.time
1170 data.dmesg['resume_noirq']['start'] = t.time
1171 else:
1172 data.dmesg['resume_noirq']['end'] = t.time
1173 continue
1174 elif re.match('dpm_resume_early\[.*', name):
1175 if(isbegin):
1176 data.dmesg['resume_early']['start'] = t.time
1177 else:
1178 data.dmesg['resume_early']['end'] = t.time
1179 continue
1180 elif re.match('dpm_resume\[.*', name):
1181 if(isbegin):
1182 data.dmesg['resume']['start'] = t.time
1183 else:
1184 data.dmesg['resume']['end'] = t.time
1185 continue
1186 elif re.match('dpm_complete\[.*', name):
1187 if(isbegin):
1188 data.dmesg['resume_complete']['start'] = t.time
1189 else:
1190 data.dmesg['resume_complete']['end'] = t.time
1191 continue
1192 # is this trace event outside of the devices calls
1193 if(data.isTraceEventOutsideDeviceCalls(pid, t.time)):
1194 # global events (outside device calls) are simply graphed
1195 if(isbegin):
1196 # store each trace event in ttemp
1197 if(name not in testrun[testidx].ttemp):
1198 testrun[testidx].ttemp[name] = []
1199 testrun[testidx].ttemp[name].append(\
1200 {'begin': t.time, 'end': t.time})
1201 else:
1202 # finish off matching trace event in ttemp
1203 if(name in testrun[testidx].ttemp):
1204 testrun[testidx].ttemp[name][-1]['end'] = t.time
1205 else:
1206 if(isbegin):
1207 data.addIntraDevTraceEvent('', name, pid, t.time)
1208 else:
1209 data.capIntraDevTraceEvent('', name, pid, t.time)
1210 # call/return processing
1211 elif sysvals.usecallgraph:
1212 # create a callgraph object for the data
1213 if(pid not in testrun[testidx].ftemp):
1214 testrun[testidx].ftemp[pid] = []
1215 testrun[testidx].ftemp[pid].append(FTraceCallGraph())
1216 # when the call is finished, see which device matches it
1217 cg = testrun[testidx].ftemp[pid][-1]
1218 if(cg.addLine(t, m)):
1219 testrun[testidx].ftemp[pid].append(FTraceCallGraph())
1220 tf.close()
1221
1222 for test in testrun:
1223 # add the traceevent data to the device hierarchy
1224 if(sysvals.usetraceevents):
1225 for name in test.ttemp:
1226 for event in test.ttemp[name]:
1227 begin = event['begin']
1228 end = event['end']
1229 # if event starts before timeline start, expand timeline
1230 if(begin < test.data.start):
1231 test.data.setStart(begin)
1232 # if event ends after timeline end, expand the timeline
1233 if(end > test.data.end):
1234 test.data.setEnd(end)
1235 test.data.newActionGlobal(name, begin, end)
1236
1237 # add the callgraph data to the device hierarchy
1238 for pid in test.ftemp:
1239 for cg in test.ftemp[pid]:
1240 if(not cg.sanityCheck()):
1241 id = 'task %s cpu %s' % (pid, m.group('cpu'))
1242 vprint('Sanity check failed for '+\
1243 id+', ignoring this callback')
1244 continue
1245 callstart = cg.start
1246 callend = cg.end
1247 for p in test.data.phases:
1248 if(test.data.dmesg[p]['start'] <= callstart and
1249 callstart <= test.data.dmesg[p]['end']):
1250 list = test.data.dmesg[p]['list']
1251 for devname in list:
1252 dev = list[devname]
1253 if(pid == dev['pid'] and
1254 callstart <= dev['start'] and
1255 callend >= dev['end']):
1256 dev['ftrace'] = cg
1257 break
1258
1259 if(sysvals.verbose):
1260 test.data.printDetails()
1261
1262
1263 # add the time in between the tests as a new phase so we can see it
1264 if(len(testruns) > 1):
1265 t1e = testruns[0].getEnd()
1266 t2s = testruns[-1].getStart()
1267 testruns[-1].newPhaseWithSingleAction('user mode', \
1268 'user mode', t1e, t2s, '#FF9966')
1269
1270# Function: parseTraceLog
1271# Description:
1272# Analyze an ftrace log output file generated from this app during
1273# the execution phase. Used when the ftrace log is the primary data source
1274# and includes the suspend_resume and device_pm_callback trace events
1275# The ftrace filename is taken from sysvals
1276# Output:
1277# An array of Data objects
1278def parseTraceLog():
1279 global sysvals
1280
1281 vprint('Analyzing the ftrace data...')
1282 if(os.path.exists(sysvals.ftracefile) == False):
1283 doError('%s doesnt exist' % sysvals.ftracefile, False)
1284
1285 # extract the callgraph and traceevent data
1286 testruns = []
1287 testdata = []
1288 testrun = 0
1289 data = 0
1290 tf = open(sysvals.ftracefile, 'r')
1291 phase = 'suspend_prepare'
1292 for line in tf:
1293 # remove any latent carriage returns
1294 line = line.replace('\r\n', '')
1295 # stamp line: each stamp means a new test run
1296 m = re.match(sysvals.stampfmt, line)
1297 if(m):
1298 data = Data(len(testdata))
1299 testdata.append(data)
1300 testrun = TestRun(data)
1301 testruns.append(testrun)
1302 parseStamp(m, data)
1303 continue
1304 if(not data):
1305 continue
1306 # firmware line: pull out any firmware data
1307 m = re.match(sysvals.firmwarefmt, line)
1308 if(m):
1309 data.fwSuspend = int(m.group('s'))
1310 data.fwResume = int(m.group('r'))
1311 if(data.fwSuspend > 0 or data.fwResume > 0):
1312 data.fwValid = True
1313 continue
1314 # tracer type line: determine the trace data type
1315 m = re.match(sysvals.tracertypefmt, line)
1316 if(m):
1317 tracer = m.group('t')
1318 testrun.setTracerType(tracer)
1319 continue
1320 # post resume time line: did this test run include post-resume data
1321 m = re.match(sysvals.postresumefmt, line)
1322 if(m):
1323 t = int(m.group('t'))
1324 if(t > 0):
1325 sysvals.postresumetime = t
1326 continue
1327 # ftrace line: parse only valid lines
1328 m = re.match(testrun.ftrace_line_fmt, line)
1329 if(not m):
1330 continue
1331 # gather the basic message data from the line
1332 m_time = m.group('time')
1333 m_pid = m.group('pid')
1334 m_msg = m.group('msg')
1335 if(testrun.cgformat):
1336 m_param3 = m.group('dur')
1337 else:
1338 m_param3 = 'traceevent'
1339 if(m_time and m_pid and m_msg):
1340 t = FTraceLine(m_time, m_msg, m_param3)
1341 pid = int(m_pid)
1342 else:
1343 continue
1344 # the line should be a call, return, or event
1345 if(not t.fcall and not t.freturn and not t.fevent):
1346 continue
1347 # only parse the ftrace data during suspend/resume
1348 if(not testrun.inthepipe):
1349 # look for the suspend start marker
1350 if(t.fevent):
1351 if(t.name == 'SUSPEND START'):
1352 testrun.inthepipe = True
1353 data.setStart(t.time)
1354 continue
1355 # trace event processing
1356 if(t.fevent):
1357 if(t.name == 'RESUME COMPLETE'):
1358 if(sysvals.postresumetime > 0):
1359 phase = 'post_resume'
1360 data.newPhase(phase, t.time, t.time, '#FF9966', -1)
1361 else:
1362 testrun.inthepipe = False
1363 data.setEnd(t.time)
1364 continue
1365 if(phase == 'post_resume'):
1366 data.setEnd(t.time)
1367 if(t.type == 'suspend_resume'):
1368 # suspend_resume trace events have two types, begin and end
1369 if(re.match('(?P<name>.*) begin$', t.name)):
1370 isbegin = True
1371 elif(re.match('(?P<name>.*) end$', t.name)):
1372 isbegin = False
1373 else:
1374 continue
1375 m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name)
1376 if(m):
1377 val = m.group('val')
1378 if val == '0':
1379 name = m.group('name')
1380 else:
1381 name = m.group('name')+'['+val+']'
1382 else:
1383 m = re.match('(?P<name>.*) .*', t.name)
1384 name = m.group('name')
1385 # ignore these events
1386 if(re.match('acpi_suspend\[.*', t.name) or
1387 re.match('suspend_enter\[.*', name)):
1388 continue
1389 # -- phase changes --
1390 # suspend_prepare start
1391 if(re.match('dpm_prepare\[.*', t.name)):
1392 phase = 'suspend_prepare'
1393 if(not isbegin):
1394 data.dmesg[phase]['end'] = t.time
1395 continue
1396 # suspend start
1397 elif(re.match('dpm_suspend\[.*', t.name)):
1398 phase = 'suspend'
1399 data.setPhase(phase, t.time, isbegin)
1400 continue
1401 # suspend_late start
1402 elif(re.match('dpm_suspend_late\[.*', t.name)):
1403 phase = 'suspend_late'
1404 data.setPhase(phase, t.time, isbegin)
1405 continue
1406 # suspend_noirq start
1407 elif(re.match('dpm_suspend_noirq\[.*', t.name)):
1408 phase = 'suspend_noirq'
1409 data.setPhase(phase, t.time, isbegin)
1410 if(not isbegin):
1411 phase = 'suspend_machine'
1412 data.dmesg[phase]['start'] = t.time
1413 continue
1414 # suspend_machine/resume_machine
1415 elif(re.match('machine_suspend\[.*', t.name)):
1416 if(isbegin):
1417 phase = 'suspend_machine'
1418 data.dmesg[phase]['end'] = t.time
1419 data.tSuspended = t.time
1420 else:
1421 if(sysvals.suspendmode in ['mem', 'disk']):
1422 data.dmesg['suspend_machine']['end'] = t.time
1423 data.tSuspended = t.time
1424 phase = 'resume_machine'
1425 data.dmesg[phase]['start'] = t.time
1426 data.tResumed = t.time
1427 data.tLow = data.tResumed - data.tSuspended
1428 continue
1429 # resume_noirq start
1430 elif(re.match('dpm_resume_noirq\[.*', t.name)):
1431 phase = 'resume_noirq'
1432 data.setPhase(phase, t.time, isbegin)
1433 if(isbegin):
1434 data.dmesg['resume_machine']['end'] = t.time
1435 continue
1436 # resume_early start
1437 elif(re.match('dpm_resume_early\[.*', t.name)):
1438 phase = 'resume_early'
1439 data.setPhase(phase, t.time, isbegin)
1440 continue
1441 # resume start
1442 elif(re.match('dpm_resume\[.*', t.name)):
1443 phase = 'resume'
1444 data.setPhase(phase, t.time, isbegin)
1445 continue
1446 # resume complete start
1447 elif(re.match('dpm_complete\[.*', t.name)):
1448 phase = 'resume_complete'
1449 if(isbegin):
1450 data.dmesg[phase]['start'] = t.time
1451 continue
1452
1453 # is this trace event outside of the devices calls
1454 if(data.isTraceEventOutsideDeviceCalls(pid, t.time)):
1455 # global events (outside device calls) are simply graphed
1456 if(name not in testrun.ttemp):
1457 testrun.ttemp[name] = []
1458 if(isbegin):
1459 # create a new list entry
1460 testrun.ttemp[name].append(\
1461 {'begin': t.time, 'end': t.time})
1462 else:
1463 if(len(testrun.ttemp[name]) > 0):
1464 # if an antry exists, assume this is its end
1465 testrun.ttemp[name][-1]['end'] = t.time
1466 elif(phase == 'post_resume'):
1467 # post resume events can just have ends
1468 testrun.ttemp[name].append({
1469 'begin': data.dmesg[phase]['start'],
1470 'end': t.time})
1471 else:
1472 if(isbegin):
1473 data.addIntraDevTraceEvent('', name, pid, t.time)
1474 else:
1475 data.capIntraDevTraceEvent('', name, pid, t.time)
1476 # device callback start
1477 elif(t.type == 'device_pm_callback_start'):
1478 m = re.match('(?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*',\
1479 t.name);
1480 if(not m):
1481 continue
1482 drv = m.group('drv')
1483 n = m.group('d')
1484 p = m.group('p')
1485 if(n and p):
1486 data.newAction(phase, n, pid, p, t.time, -1, drv)
1487 # device callback finish
1488 elif(t.type == 'device_pm_callback_end'):
1489 m = re.match('(?P<drv>.*) (?P<d>.*), err.*', t.name);
1490 if(not m):
1491 continue
1492 n = m.group('d')
1493 list = data.dmesg[phase]['list']
1494 if(n in list):
1495 dev = list[n]
1496 dev['length'] = t.time - dev['start']
1497 dev['end'] = t.time
1498 # callgraph processing
1499 elif sysvals.usecallgraph:
1500 # this shouldn't happen, but JIC, ignore callgraph data post-res
1501 if(phase == 'post_resume'):
529 continue 1502 continue
530 # create a callgraph object for the data 1503 # create a callgraph object for the data
531 if(pid not in ftemp): 1504 if(pid not in testrun.ftemp):
532 ftemp[pid] = FTraceCallGraph() 1505 testrun.ftemp[pid] = []
1506 testrun.ftemp[pid].append(FTraceCallGraph())
533 # when the call is finished, see which device matches it 1507 # when the call is finished, see which device matches it
534 if(ftemp[pid].addLine(t, m)): 1508 cg = testrun.ftemp[pid][-1]
535 if(not ftemp[pid].sanityCheck()): 1509 if(cg.addLine(t, m)):
536 id = "task %s cpu %s" % (pid, m.group("cpu")) 1510 testrun.ftemp[pid].append(FTraceCallGraph())
537 data.vprint("Sanity check failed for "+id+", ignoring this callback") 1511 tf.close()
1512
1513 for test in testruns:
1514 # add the traceevent data to the device hierarchy
1515 if(sysvals.usetraceevents):
1516 for name in test.ttemp:
1517 for event in test.ttemp[name]:
1518 begin = event['begin']
1519 end = event['end']
1520 # if event starts before timeline start, expand timeline
1521 if(begin < test.data.start):
1522 test.data.setStart(begin)
1523 # if event ends after timeline end, expand the timeline
1524 if(end > test.data.end):
1525 test.data.setEnd(end)
1526 test.data.newActionGlobal(name, begin, end)
1527
1528 # add the callgraph data to the device hierarchy
1529 borderphase = {
1530 'dpm_prepare': 'suspend_prepare',
1531 'dpm_complete': 'resume_complete'
1532 }
1533 for pid in test.ftemp:
1534 for cg in test.ftemp[pid]:
1535 if len(cg.list) < 2:
1536 continue
1537 if(not cg.sanityCheck()):
1538 id = 'task %s cpu %s' % (pid, m.group('cpu'))
1539 vprint('Sanity check failed for '+\
1540 id+', ignoring this callback')
1541 continue
1542 callstart = cg.start
1543 callend = cg.end
1544 if(cg.list[0].name in borderphase):
1545 p = borderphase[cg.list[0].name]
1546 list = test.data.dmesg[p]['list']
1547 for devname in list:
1548 dev = list[devname]
1549 if(pid == dev['pid'] and
1550 callstart <= dev['start'] and
1551 callend >= dev['end']):
1552 dev['ftrace'] = cg.slice(dev['start'], dev['end'])
538 continue 1553 continue
539 callstart = ftemp[pid].start 1554 if(cg.list[0].name != 'dpm_run_callback'):
540 callend = ftemp[pid].end 1555 continue
541 for p in data.phases: 1556 for p in test.data.phases:
542 if(data.dmesg[p]['start'] <= callstart and callstart <= data.dmesg[p]['end']): 1557 if(test.data.dmesg[p]['start'] <= callstart and
543 list = data.dmesg[p]['list'] 1558 callstart <= test.data.dmesg[p]['end']):
1559 list = test.data.dmesg[p]['list']
544 for devname in list: 1560 for devname in list:
545 dev = list[devname] 1561 dev = list[devname]
546 if(pid == dev['pid'] and callstart <= dev['start'] and callend >= dev['end']): 1562 if(pid == dev['pid'] and
547 data.vprint("%15s [%f - %f] %s(%d)" % (p, callstart, callend, devname, pid)) 1563 callstart <= dev['start'] and
548 dev['ftrace'] = ftemp[pid] 1564 callend >= dev['end']):
1565 dev['ftrace'] = cg
549 break 1566 break
550 ftemp[pid] = FTraceCallGraph()
551 tf.close()
552 1567
553# Function: sortKernelLog 1568 # fill in any missing phases
1569 for data in testdata:
1570 lp = data.phases[0]
1571 for p in data.phases:
1572 if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0):
1573 print('WARNING: phase "%s" is missing!' % p)
1574 if(data.dmesg[p]['start'] < 0):
1575 data.dmesg[p]['start'] = data.dmesg[lp]['end']
1576 if(p == 'resume_machine'):
1577 data.tSuspended = data.dmesg[lp]['end']
1578 data.tResumed = data.dmesg[lp]['end']
1579 data.tLow = 0
1580 if(data.dmesg[p]['end'] < 0):
1581 data.dmesg[p]['end'] = data.dmesg[p]['start']
1582 lp = p
1583
1584 if(len(sysvals.devicefilter) > 0):
1585 data.deviceFilter(sysvals.devicefilter)
1586 data.fixupInitcallsThatDidntReturn()
1587 if(sysvals.verbose):
1588 data.printDetails()
1589
1590 # add the time in between the tests as a new phase so we can see it
1591 if(len(testdata) > 1):
1592 t1e = testdata[0].getEnd()
1593 t2s = testdata[-1].getStart()
1594 testdata[-1].newPhaseWithSingleAction('user mode', \
1595 'user mode', t1e, t2s, '#FF9966')
1596 return testdata
1597
1598# Function: loadKernelLog
554# Description: 1599# Description:
555# The dmesg output log sometimes comes with with lines that have 1600# [deprecated for kernel 3.15.0 or newer]
556# timestamps out of order. This could cause issues since a call 1601# load the dmesg file into memory and fix up any ordering issues
557# could accidentally end up in the wrong phase 1602# The dmesg filename is taken from sysvals
558def sortKernelLog(): 1603# Output:
559 global sysvals, data 1604# An array of empty Data objects with only their dmesgtext attributes set
1605def loadKernelLog():
1606 global sysvals
1607
1608 vprint('Analyzing the dmesg data...')
1609 if(os.path.exists(sysvals.dmesgfile) == False):
1610 doError('%s doesnt exist' % sysvals.dmesgfile, False)
1611
1612 # there can be multiple test runs in a single file delineated by stamps
1613 testruns = []
1614 data = 0
560 lf = open(sysvals.dmesgfile, 'r') 1615 lf = open(sysvals.dmesgfile, 'r')
561 dmesglist = []
562 count = 0
563 for line in lf: 1616 for line in lf:
564 line = line.replace("\r\n", "") 1617 line = line.replace('\r\n', '')
565 if(count == 0): 1618 idx = line.find('[')
566 parseStamp(line) 1619 if idx > 1:
567 elif(count == 1): 1620 line = line[idx:]
568 m = re.match(r"# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$", line) 1621 m = re.match(sysvals.stampfmt, line)
569 if(m): 1622 if(m):
570 data.fwSuspend = int(m.group("s")) 1623 if(data):
571 data.fwResume = int(m.group("r")) 1624 testruns.append(data)
572 if(data.fwSuspend > 0 or data.fwResume > 0): 1625 data = Data(len(testruns))
573 data.fwValid = True 1626 parseStamp(m, data)
574 if(re.match(r".*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)", line)): 1627 continue
575 dmesglist.append(line) 1628 if(not data):
576 count += 1 1629 continue
1630 m = re.match(sysvals.firmwarefmt, line)
1631 if(m):
1632 data.fwSuspend = int(m.group('s'))
1633 data.fwResume = int(m.group('r'))
1634 if(data.fwSuspend > 0 or data.fwResume > 0):
1635 data.fwValid = True
1636 continue
1637 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
1638 if(m):
1639 data.dmesgtext.append(line)
1640 if(re.match('ACPI: resume from mwait', m.group('msg'))):
1641 print('NOTE: This suspend appears to be freeze rather than'+\
1642 ' %s, it will be treated as such' % sysvals.suspendmode)
1643 sysvals.suspendmode = 'freeze'
1644 else:
1645 vprint('ignoring dmesg line: %s' % line.replace('\n', ''))
1646 testruns.append(data)
577 lf.close() 1647 lf.close()
578 last = "" 1648
579 1649 if(not data):
580 # fix lines with the same time stamp and function with the call and return swapped 1650 print('ERROR: analyze_suspend header missing from dmesg log')
581 for line in dmesglist: 1651 sys.exit()
582 mc = re.match(r".*(\[ *)(?P<t>[0-9\.]*)(\]) calling (?P<f>.*)\+ @ .*, parent: .*", line) 1652
583 mr = re.match(r".*(\[ *)(?P<t>[0-9\.]*)(\]) call (?P<f>.*)\+ returned .* after (?P<dt>.*) usecs", last) 1653 # fix lines with same timestamp/function with the call and return swapped
584 if(mc and mr and (mc.group("t") == mr.group("t")) and (mc.group("f") == mr.group("f"))): 1654 for data in testruns:
585 i = dmesglist.index(last) 1655 last = ''
586 j = dmesglist.index(line) 1656 for line in data.dmesgtext:
587 dmesglist[i] = line 1657 mc = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) calling '+\
588 dmesglist[j] = last 1658 '(?P<f>.*)\+ @ .*, parent: .*', line)
589 last = line 1659 mr = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) call '+\
590 return dmesglist 1660 '(?P<f>.*)\+ returned .* after (?P<dt>.*) usecs', last)
591 1661 if(mc and mr and (mc.group('t') == mr.group('t')) and
592# Function: analyzeKernelLog 1662 (mc.group('f') == mr.group('f'))):
1663 i = data.dmesgtext.index(last)
1664 j = data.dmesgtext.index(line)
1665 data.dmesgtext[i] = line
1666 data.dmesgtext[j] = last
1667 last = line
1668 return testruns
1669
1670# Function: parseKernelLog
593# Description: 1671# Description:
1672# [deprecated for kernel 3.15.0 or newer]
594# Analyse a dmesg log output file generated from this app during 1673# Analyse a dmesg log output file generated from this app during
595# the execution phase. Create a set of device structures in memory 1674# the execution phase. Create a set of device structures in memory
596# for subsequent formatting in the html output file 1675# for subsequent formatting in the html output file
597def analyzeKernelLog(): 1676# This call is only for legacy support on kernels where the ftrace
598 global sysvals, data 1677# data lacks the suspend_resume or device_pm_callbacks trace events.
1678# Arguments:
1679# data: an empty Data object (with dmesgtext) obtained from loadKernelLog
1680# Output:
1681# The filled Data object
1682def parseKernelLog(data):
1683 global sysvals
599 1684
600 print("PROCESSING DATA") 1685 phase = 'suspend_runtime'
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 1686
606 lf = sortKernelLog() 1687 if(data.fwValid):
607 phase = "suspend_runtime" 1688 vprint('Firmware Suspend = %u ns, Firmware Resume = %u ns' % \
1689 (data.fwSuspend, data.fwResume))
608 1690
1691 # dmesg phase match table
609 dm = { 1692 dm = {
610 'suspend_general': r"PM: Syncing filesystems.*", 1693 'suspend_prepare': 'PM: Syncing filesystems.*',
611 'suspend_early': r"PM: suspend of devices complete after.*", 1694 'suspend': 'PM: Entering [a-z]* sleep.*',
612 'suspend_noirq': r"PM: late suspend of devices complete after.*", 1695 'suspend_late': 'PM: suspend of devices complete after.*',
613 'suspend_cpu': r"PM: noirq suspend of devices complete after.*", 1696 'suspend_noirq': 'PM: late suspend of devices complete after.*',
614 'resume_cpu': r"ACPI: Low-level resume complete.*", 1697 'suspend_machine': 'PM: noirq suspend of devices complete after.*',
615 'resume_noirq': r"ACPI: Waking up from system sleep state.*", 1698 'resume_machine': 'ACPI: Low-level resume complete.*',
616 'resume_early': r"PM: noirq resume of devices complete after.*", 1699 'resume_noirq': 'ACPI: Waking up from system sleep state.*',
617 'resume_general': r"PM: early resume of devices complete after.*", 1700 'resume_early': 'PM: noirq resume of devices complete after.*',
618 'resume_complete': r".*Restarting tasks \.\.\..*", 1701 'resume': 'PM: early resume of devices complete after.*',
1702 'resume_complete': 'PM: resume of devices complete after.*',
1703 'post_resume': '.*Restarting tasks \.\.\..*',
619 } 1704 }
620 if(sysvals.suspendmode == "standby"): 1705 if(sysvals.suspendmode == 'standby'):
621 dm['resume_cpu'] = r"PM: Restoring platform NVS memory" 1706 dm['resume_machine'] = 'PM: Restoring platform NVS memory'
622 elif(sysvals.suspendmode == "disk"): 1707 elif(sysvals.suspendmode == 'disk'):
623 dm['suspend_early'] = r"PM: freeze of devices complete after.*" 1708 dm['suspend_late'] = 'PM: freeze of devices complete after.*'
624 dm['suspend_noirq'] = r"PM: late freeze of devices complete after.*" 1709 dm['suspend_noirq'] = 'PM: late freeze of devices complete after.*'
625 dm['suspend_cpu'] = r"PM: noirq freeze of devices complete after.*" 1710 dm['suspend_machine'] = 'PM: noirq freeze of devices complete after.*'
626 dm['resume_cpu'] = r"PM: Restoring platform NVS memory" 1711 dm['resume_machine'] = 'PM: Restoring platform NVS memory'
627 dm['resume_early'] = r"PM: noirq restore of devices complete after.*" 1712 dm['resume_early'] = 'PM: noirq restore of devices complete after.*'
628 dm['resume_general'] = r"PM: early restore of devices complete after.*" 1713 dm['resume'] = 'PM: early restore of devices complete after.*'
629 1714 dm['resume_complete'] = 'PM: restore of devices complete after.*'
630 action_start = 0.0 1715 elif(sysvals.suspendmode == 'freeze'):
631 for line in lf: 1716 dm['resume_machine'] = 'ACPI: resume from mwait'
1717
1718 # action table (expected events that occur and show up in dmesg)
1719 at = {
1720 'sync_filesystems': {
1721 'smsg': 'PM: Syncing filesystems.*',
1722 'emsg': 'PM: Preparing system for mem sleep.*' },
1723 'freeze_user_processes': {
1724 'smsg': 'Freezing user space processes .*',
1725 'emsg': 'Freezing remaining freezable tasks.*' },
1726 'freeze_tasks': {
1727 'smsg': 'Freezing remaining freezable tasks.*',
1728 'emsg': 'PM: Entering (?P<mode>[a-z,A-Z]*) sleep.*' },
1729 'ACPI prepare': {
1730 'smsg': 'ACPI: Preparing to enter system sleep state.*',
1731 'emsg': 'PM: Saving platform NVS memory.*' },
1732 'PM vns': {
1733 'smsg': 'PM: Saving platform NVS memory.*',
1734 'emsg': 'Disabling non-boot CPUs .*' },
1735 }
1736
1737 t0 = -1.0
1738 cpu_start = -1.0
1739 prevktime = -1.0
1740 actions = dict()
1741 for line in data.dmesgtext:
632 # -- preprocessing -- 1742 # -- preprocessing --
633 # parse each dmesg line into the time and message 1743 # parse each dmesg line into the time and message
634 m = re.match(r".*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)", line) 1744 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
635 if(m): 1745 if(m):
636 ktime = float(m.group("ktime")) 1746 val = m.group('ktime')
637 msg = m.group("msg") 1747 try:
1748 ktime = float(val)
1749 except:
1750 doWarning('INVALID DMESG LINE: '+\
1751 line.replace('\n', ''), 'dmesg')
1752 continue
1753 msg = m.group('msg')
1754 # initialize data start to first line time
1755 if t0 < 0:
1756 data.setStart(ktime)
1757 t0 = ktime
638 else: 1758 else:
639 print line
640 continue 1759 continue
641 1760
1761 # hack for determining resume_machine end for freeze
1762 if(not sysvals.usetraceevents and sysvals.suspendmode == 'freeze' \
1763 and phase == 'resume_machine' and \
1764 re.match('calling (?P<f>.*)\+ @ .*, parent: .*', msg)):
1765 data.dmesg['resume_machine']['end'] = ktime
1766 phase = 'resume_noirq'
1767 data.dmesg[phase]['start'] = ktime
1768
642 # -- phase changes -- 1769 # -- phase changes --
643 # suspend_general start 1770 # suspend start
644 if(re.match(dm['suspend_general'], msg)): 1771 if(re.match(dm['suspend_prepare'], msg)):
645 phase = "suspend_general" 1772 phase = 'suspend_prepare'
1773 data.dmesg[phase]['start'] = ktime
1774 data.setStart(ktime)
1775 # suspend start
1776 elif(re.match(dm['suspend'], msg)):
1777 data.dmesg['suspend_prepare']['end'] = ktime
1778 phase = 'suspend'
646 data.dmesg[phase]['start'] = ktime 1779 data.dmesg[phase]['start'] = ktime
647 data.start = ktime 1780 # suspend_late start
648 # action start: syncing filesystems 1781 elif(re.match(dm['suspend_late'], msg)):
649 action_start = ktime 1782 data.dmesg['suspend']['end'] = ktime
650 # suspend_early start 1783 phase = 'suspend_late'
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 1784 data.dmesg[phase]['start'] = ktime
655 # suspend_noirq start 1785 # suspend_noirq start
656 elif(re.match(dm['suspend_noirq'], msg)): 1786 elif(re.match(dm['suspend_noirq'], msg)):
657 data.dmesg["suspend_early"]['end'] = ktime 1787 data.dmesg['suspend_late']['end'] = ktime
658 phase = "suspend_noirq" 1788 phase = 'suspend_noirq'
659 data.dmesg[phase]['start'] = ktime 1789 data.dmesg[phase]['start'] = ktime
660 # suspend_cpu start 1790 # suspend_machine start
661 elif(re.match(dm['suspend_cpu'], msg)): 1791 elif(re.match(dm['suspend_machine'], msg)):
662 data.dmesg["suspend_noirq"]['end'] = ktime 1792 data.dmesg['suspend_noirq']['end'] = ktime
663 phase = "suspend_cpu" 1793 phase = 'suspend_machine'
664 data.dmesg[phase]['start'] = ktime 1794 data.dmesg[phase]['start'] = ktime
665 # resume_cpu start 1795 # resume_machine start
666 elif(re.match(dm['resume_cpu'], msg)): 1796 elif(re.match(dm['resume_machine'], msg)):
667 data.tSuspended = ktime 1797 if(sysvals.suspendmode in ['freeze', 'standby']):
668 data.dmesg["suspend_cpu"]['end'] = ktime 1798 data.tSuspended = prevktime
669 phase = "resume_cpu" 1799 data.dmesg['suspend_machine']['end'] = prevktime
1800 else:
1801 data.tSuspended = ktime
1802 data.dmesg['suspend_machine']['end'] = ktime
1803 phase = 'resume_machine'
1804 data.tResumed = ktime
1805 data.tLow = data.tResumed - data.tSuspended
670 data.dmesg[phase]['start'] = ktime 1806 data.dmesg[phase]['start'] = ktime
671 # resume_noirq start 1807 # resume_noirq start
672 elif(re.match(dm['resume_noirq'], msg)): 1808 elif(re.match(dm['resume_noirq'], msg)):
673 data.dmesg["resume_cpu"]['end'] = ktime 1809 data.dmesg['resume_machine']['end'] = ktime
674 phase = "resume_noirq" 1810 phase = 'resume_noirq'
675 data.dmesg[phase]['start'] = ktime 1811 data.dmesg[phase]['start'] = ktime
676 # action end: ACPI resume
677 data.newAction("resume_cpu", "ACPI", -1, "", action_start, ktime)
678 # resume_early start 1812 # resume_early start
679 elif(re.match(dm['resume_early'], msg)): 1813 elif(re.match(dm['resume_early'], msg)):
680 data.dmesg["resume_noirq"]['end'] = ktime 1814 data.dmesg['resume_noirq']['end'] = ktime
681 phase = "resume_early" 1815 phase = 'resume_early'
682 data.dmesg[phase]['start'] = ktime 1816 data.dmesg[phase]['start'] = ktime
683 # resume_general start 1817 # resume start
684 elif(re.match(dm['resume_general'], msg)): 1818 elif(re.match(dm['resume'], msg)):
685 data.dmesg["resume_early"]['end'] = ktime 1819 data.dmesg['resume_early']['end'] = ktime
686 phase = "resume_general" 1820 phase = 'resume'
687 data.dmesg[phase]['start'] = ktime 1821 data.dmesg[phase]['start'] = ktime
688 # resume complete start 1822 # resume complete start
689 elif(re.match(dm['resume_complete'], msg)): 1823 elif(re.match(dm['resume_complete'], msg)):
690 data.dmesg["resume_general"]['end'] = ktime 1824 data.dmesg['resume']['end'] = ktime
691 data.end = ktime 1825 phase = 'resume_complete'
692 phase = "resume_runtime" 1826 data.dmesg[phase]['start'] = ktime
1827 # post resume start
1828 elif(re.match(dm['post_resume'], msg)):
1829 data.dmesg['resume_complete']['end'] = ktime
1830 data.setEnd(ktime)
1831 phase = 'post_resume'
693 break 1832 break
694 1833
695 # -- device callbacks -- 1834 # -- device callbacks --
696 if(phase in data.phases): 1835 if(phase in data.phases):
697 # device init call 1836 # device init call
698 if(re.match(r"calling (?P<f>.*)\+ @ .*, parent: .*", msg)): 1837 if(re.match('calling (?P<f>.*)\+ @ .*, parent: .*', msg)):
699 sm = re.match(r"calling (?P<f>.*)\+ @ (?P<n>.*), parent: (?P<p>.*)", msg); 1838 sm = re.match('calling (?P<f>.*)\+ @ '+\
700 f = sm.group("f") 1839 '(?P<n>.*), parent: (?P<p>.*)', msg);
701 n = sm.group("n") 1840 f = sm.group('f')
702 p = sm.group("p") 1841 n = sm.group('n')
1842 p = sm.group('p')
703 if(f and n and p): 1843 if(f and n and p):
704 data.newAction(phase, f, int(n), p, ktime, -1) 1844 data.newAction(phase, f, int(n), p, ktime, -1, '')
705 # device init return 1845 # device init return
706 elif(re.match(r"call (?P<f>.*)\+ returned .* after (?P<t>.*) usecs", msg)): 1846 elif(re.match('call (?P<f>.*)\+ returned .* after '+\
707 sm = re.match(r"call (?P<f>.*)\+ returned .* after (?P<t>.*) usecs(?P<a>.*)", msg); 1847 '(?P<t>.*) usecs', msg)):
708 f = sm.group("f") 1848 sm = re.match('call (?P<f>.*)\+ returned .* after '+\
709 t = sm.group("t") 1849 '(?P<t>.*) usecs(?P<a>.*)', msg);
1850 f = sm.group('f')
1851 t = sm.group('t')
710 list = data.dmesg[phase]['list'] 1852 list = data.dmesg[phase]['list']
711 if(f in list): 1853 if(f in list):
712 dev = list[f] 1854 dev = list[f]
713 dev['length'] = int(t) 1855 dev['length'] = int(t)
714 dev['end'] = ktime 1856 dev['end'] = ktime
715 data.vprint("%15s [%f - %f] %s(%d) %s" % 1857
716 (phase, dev['start'], dev['end'], f, dev['pid'], dev['par'])) 1858 # -- non-devicecallback actions --
717 1859 # if trace events are not available, these are better than nothing
718 # -- phase specific actions -- 1860 if(not sysvals.usetraceevents):
719 if(phase == "suspend_general"): 1861 # look for known actions
720 if(re.match(r"PM: Preparing system for mem sleep.*", msg)): 1862 for a in at:
721 data.newAction(phase, "filesystem-sync", -1, "", action_start, ktime) 1863 if(re.match(at[a]['smsg'], msg)):
722 elif(re.match(r"Freezing user space processes .*", msg)): 1864 if(a not in actions):
723 action_start = ktime 1865 actions[a] = []
724 elif(re.match(r"Freezing remaining freezable tasks.*", msg)): 1866 actions[a].append({'begin': ktime, 'end': ktime})
725 data.newAction(phase, "freeze-user-processes", -1, "", action_start, ktime) 1867 if(re.match(at[a]['emsg'], msg)):
726 action_start = ktime 1868 actions[a][-1]['end'] = ktime
727 elif(re.match(r"PM: Entering (?P<mode>[a-z,A-Z]*) sleep.*", msg)): 1869 # now look for CPU on/off events
728 data.newAction(phase, "freeze-tasks", -1, "", action_start, ktime) 1870 if(re.match('Disabling non-boot CPUs .*', msg)):
729 elif(phase == "suspend_cpu"): 1871 # start of first cpu suspend
730 m = re.match(r"smpboot: CPU (?P<cpu>[0-9]*) is now offline", msg) 1872 cpu_start = ktime
731 if(m): 1873 elif(re.match('Enabling non-boot CPUs .*', msg)):
732 cpu = "CPU"+m.group("cpu") 1874 # start of first cpu resume
733 data.newAction(phase, cpu, -1, "", action_start, ktime) 1875 cpu_start = ktime
734 action_start = ktime 1876 elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)):
735 elif(re.match(r"ACPI: Preparing to enter system sleep state.*", msg)): 1877 # end of a cpu suspend, start of the next
736 action_start = ktime 1878 m = re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)
737 elif(re.match(r"Disabling non-boot CPUs .*", msg)): 1879 cpu = 'CPU'+m.group('cpu')
738 data.newAction(phase, "ACPI", -1, "", action_start, ktime) 1880 if(cpu not in actions):
739 action_start = ktime 1881 actions[cpu] = []
740 elif(phase == "resume_cpu"): 1882 actions[cpu].append({'begin': cpu_start, 'end': ktime})
741 m = re.match(r"CPU(?P<cpu>[0-9]*) is up", msg) 1883 cpu_start = ktime
742 if(m): 1884 elif(re.match('CPU(?P<cpu>[0-9]*) is up', msg)):
743 cpu = "CPU"+m.group("cpu") 1885 # end of a cpu resume, start of the next
744 data.newAction(phase, cpu, -1, "", action_start, ktime) 1886 m = re.match('CPU(?P<cpu>[0-9]*) is up', msg)
745 action_start = ktime 1887 cpu = 'CPU'+m.group('cpu')
746 elif(re.match(r"Enabling non-boot CPUs .*", msg)): 1888 if(cpu not in actions):
747 action_start = ktime 1889 actions[cpu] = []
1890 actions[cpu].append({'begin': cpu_start, 'end': ktime})
1891 cpu_start = ktime
1892 prevktime = ktime
748 1893
749 # fill in any missing phases 1894 # fill in any missing phases
750 lp = "suspend_general" 1895 lp = data.phases[0]
751 for p in data.phases: 1896 for p in data.phases:
752 if(p == "suspend_general"): 1897 if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0):
753 continue 1898 print('WARNING: phase "%s" is missing, something went wrong!' % p)
1899 print(' In %s, this dmesg line denotes the start of %s:' % \
1900 (sysvals.suspendmode, p))
1901 print(' "%s"' % dm[p])
754 if(data.dmesg[p]['start'] < 0): 1902 if(data.dmesg[p]['start'] < 0):
755 data.dmesg[p]['start'] = data.dmesg[lp]['end'] 1903 data.dmesg[p]['start'] = data.dmesg[lp]['end']
756 if(p == "resume_cpu"): 1904 if(p == 'resume_machine'):
757 data.tSuspended = data.dmesg[lp]['end'] 1905 data.tSuspended = data.dmesg[lp]['end']
1906 data.tResumed = data.dmesg[lp]['end']
1907 data.tLow = 0
758 if(data.dmesg[p]['end'] < 0): 1908 if(data.dmesg[p]['end'] < 0):
759 data.dmesg[p]['end'] = data.dmesg[p]['start'] 1909 data.dmesg[p]['end'] = data.dmesg[p]['start']
760 lp = p 1910 lp = p
761 1911
1912 # fill in any actions we've found
1913 for name in actions:
1914 for event in actions[name]:
1915 begin = event['begin']
1916 end = event['end']
1917 # if event starts before timeline start, expand timeline
1918 if(begin < data.start):
1919 data.setStart(begin)
1920 # if event ends after timeline end, expand the timeline
1921 if(end > data.end):
1922 data.setEnd(end)
1923 data.newActionGlobal(name, begin, end)
1924
1925 if(sysvals.verbose):
1926 data.printDetails()
1927 if(len(sysvals.devicefilter) > 0):
1928 data.deviceFilter(sysvals.devicefilter)
762 data.fixupInitcallsThatDidntReturn() 1929 data.fixupInitcallsThatDidntReturn()
763 return True 1930 return True
764 1931
765# Function: setTimelineRows 1932# Function: setTimelineRows
766# Description: 1933# Description:
767# Organize the device or thread lists into the smallest 1934# Organize the timeline entries into the smallest
768# number of rows possible, with no entry overlapping 1935# number of rows possible, with no entry overlapping
769# Arguments: 1936# Arguments:
770# list: the list to sort (dmesg or ftrace) 1937# list: the list of devices/actions for a single phase
771# sortedkeys: sorted key list to use 1938# sortedkeys: cronologically sorted key list to use
1939# Output:
1940# The total number of rows needed to display this phase of the timeline
772def setTimelineRows(list, sortedkeys): 1941def setTimelineRows(list, sortedkeys):
773 global data
774 1942
775 # clear all rows and set them to undefined 1943 # clear all rows and set them to undefined
776 remaining = len(list) 1944 remaining = len(list)
@@ -791,7 +1959,8 @@ def setTimelineRows(list, sortedkeys):
791 for ritem in rowdata[row]: 1959 for ritem in rowdata[row]:
792 rs = ritem['start'] 1960 rs = ritem['start']
793 re = ritem['end'] 1961 re = ritem['end']
794 if(not (((s <= rs) and (e <= rs)) or ((s >= re) and (e >= re)))): 1962 if(not (((s <= rs) and (e <= rs)) or
1963 ((s >= re) and (e >= re)))):
795 valid = False 1964 valid = False
796 break 1965 break
797 if(valid): 1966 if(valid):
@@ -803,14 +1972,15 @@ def setTimelineRows(list, sortedkeys):
803 1972
804# Function: createTimeScale 1973# Function: createTimeScale
805# Description: 1974# Description:
806# Create timescale lines for the dmesg and ftrace timelines 1975# Create the timescale header for the html timeline
807# Arguments: 1976# Arguments:
808# t0: start time (suspend begin) 1977# t0: start time (suspend begin)
809# tMax: end time (resume end) 1978# tMax: end time (resume end)
810# tSuspend: time when suspend occurs 1979# tSuspend: time when suspend occurs, i.e. the zero time
1980# Output:
1981# The html code needed to display the time scale
811def createTimeScale(t0, tMax, tSuspended): 1982def createTimeScale(t0, tMax, tSuspended):
812 global data 1983 timescale = '<div class="t" style="right:{0}%">{1}</div>\n'
813 timescale = "<div class=\"t\" style=\"right:{0}%\">{1}</div>\n"
814 output = '<div id="timescale">\n' 1984 output = '<div id="timescale">\n'
815 1985
816 # set scale for timeline 1986 # set scale for timeline
@@ -822,11 +1992,11 @@ def createTimeScale(t0, tMax, tSuspended):
822 tS = 1 1992 tS = 1
823 if(tSuspended < 0): 1993 if(tSuspended < 0):
824 for i in range(int(tTotal/tS)+1): 1994 for i in range(int(tTotal/tS)+1):
825 pos = "%0.3f" % (100 - ((float(i)*tS*100)/tTotal)) 1995 pos = '%0.3f' % (100 - ((float(i)*tS*100)/tTotal))
826 if(i > 0): 1996 if(i > 0):
827 val = "%0.f" % (float(i)*tS*1000) 1997 val = '%0.fms' % (float(i)*tS*1000)
828 else: 1998 else:
829 val = "" 1999 val = ''
830 output += timescale.format(pos, val) 2000 output += timescale.format(pos, val)
831 else: 2001 else:
832 tSuspend = tSuspended - t0 2002 tSuspend = tSuspended - t0
@@ -834,69 +2004,253 @@ def createTimeScale(t0, tMax, tSuspended):
834 divSuspend = int(tSuspend/tS) 2004 divSuspend = int(tSuspend/tS)
835 s0 = (tSuspend - tS*divSuspend)*100/tTotal 2005 s0 = (tSuspend - tS*divSuspend)*100/tTotal
836 for i in range(divTotal): 2006 for i in range(divTotal):
837 pos = "%0.3f" % (100 - ((float(i)*tS*100)/tTotal) - s0) 2007 pos = '%0.3f' % (100 - ((float(i)*tS*100)/tTotal) - s0)
838 if((i == 0) and (s0 < 3)): 2008 if((i == 0) and (s0 < 3)):
839 val = "" 2009 val = ''
840 elif(i == divSuspend): 2010 elif(i == divSuspend):
841 val = "S/R" 2011 val = 'S/R'
842 else: 2012 else:
843 val = "%0.f" % (float(i-divSuspend)*tS*1000) 2013 val = '%0.fms' % (float(i-divSuspend)*tS*1000)
844 output += timescale.format(pos, val) 2014 output += timescale.format(pos, val)
845 output += '</div>\n' 2015 output += '</div>\n'
846 return output 2016 return output
847 2017
2018# Function: createHTMLSummarySimple
2019# Description:
2020# Create summary html file for a series of tests
2021# Arguments:
2022# testruns: array of Data objects from parseTraceLog
2023def createHTMLSummarySimple(testruns, htmlfile):
2024 global sysvals
2025
2026 # print out the basic summary of all the tests
2027 hf = open(htmlfile, 'w')
2028
2029 # write the html header first (html head, css code, up to body start)
2030 html = '<!DOCTYPE html>\n<html>\n<head>\n\
2031 <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\
2032 <title>AnalyzeSuspend Summary</title>\n\
2033 <style type=\'text/css\'>\n\
2034 body {overflow-y: scroll;}\n\
2035 .stamp {width: 100%;text-align:center;background-color:#495E09;line-height:30px;color:white;font: 25px Arial;}\n\
2036 table {width:100%;border-collapse: collapse;}\n\
2037 .summary {font: 22px Arial;border:1px solid;}\n\
2038 th {border: 1px solid black;background-color:#A7C942;color:white;}\n\
2039 td {text-align: center;}\n\
2040 tr.alt td {background-color:#EAF2D3;}\n\
2041 tr.avg td {background-color:#BDE34C;}\n\
2042 a:link {color: #90B521;}\n\
2043 a:visited {color: #495E09;}\n\
2044 a:hover {color: #B1DF28;}\n\
2045 a:active {color: #FFFFFF;}\n\
2046 </style>\n</head>\n<body>\n'
2047
2048 # group test header
2049 count = len(testruns)
2050 headline_stamp = '<div class="stamp">{0} {1} {2} {3} ({4} tests)</div>\n'
2051 html += headline_stamp.format(sysvals.stamp['host'],
2052 sysvals.stamp['kernel'], sysvals.stamp['mode'],
2053 sysvals.stamp['time'], count)
2054
2055 # check to see if all the tests have the same value
2056 stampcolumns = False
2057 for data in testruns:
2058 if diffStamp(sysvals.stamp, data.stamp):
2059 stampcolumns = True
2060 break
2061
2062 th = '\t<th>{0}</th>\n'
2063 td = '\t<td>{0}</td>\n'
2064 tdlink = '\t<td><a href="{0}">Click Here</a></td>\n'
2065
2066 # table header
2067 html += '<table class="summary">\n<tr>\n'
2068 html += th.format("Test #")
2069 if stampcolumns:
2070 html += th.format("Hostname")
2071 html += th.format("Kernel Version")
2072 html += th.format("Suspend Mode")
2073 html += th.format("Test Time")
2074 html += th.format("Suspend Time")
2075 html += th.format("Resume Time")
2076 html += th.format("Detail")
2077 html += '</tr>\n'
2078
2079 # test data, 1 row per test
2080 sTimeAvg = 0.0
2081 rTimeAvg = 0.0
2082 num = 1
2083 for data in testruns:
2084 # data.end is the end of post_resume
2085 resumeEnd = data.dmesg['resume_complete']['end']
2086 if num % 2 == 1:
2087 html += '<tr class="alt">\n'
2088 else:
2089 html += '<tr>\n'
2090
2091 # test num
2092 html += td.format("test %d" % num)
2093 num += 1
2094 if stampcolumns:
2095 # host name
2096 val = "unknown"
2097 if('host' in data.stamp):
2098 val = data.stamp['host']
2099 html += td.format(val)
2100 # host kernel
2101 val = "unknown"
2102 if('kernel' in data.stamp):
2103 val = data.stamp['kernel']
2104 html += td.format(val)
2105 # suspend mode
2106 val = "unknown"
2107 if('mode' in data.stamp):
2108 val = data.stamp['mode']
2109 html += td.format(val)
2110 # test time
2111 val = "unknown"
2112 if('time' in data.stamp):
2113 val = data.stamp['time']
2114 html += td.format(val)
2115 # suspend time
2116 sTime = (data.tSuspended - data.start)*1000
2117 sTimeAvg += sTime
2118 html += td.format("%3.3f ms" % sTime)
2119 # resume time
2120 rTime = (resumeEnd - data.tResumed)*1000
2121 rTimeAvg += rTime
2122 html += td.format("%3.3f ms" % rTime)
2123 # link to the output html
2124 html += tdlink.format(data.outfile)
2125
2126 html += '</tr>\n'
2127
2128 # last line: test average
2129 if(count > 0):
2130 sTimeAvg /= count
2131 rTimeAvg /= count
2132 html += '<tr class="avg">\n'
2133 html += td.format('Average') # name
2134 if stampcolumns:
2135 html += td.format('') # host
2136 html += td.format('') # kernel
2137 html += td.format('') # mode
2138 html += td.format('') # time
2139 html += td.format("%3.3f ms" % sTimeAvg) # suspend time
2140 html += td.format("%3.3f ms" % rTimeAvg) # resume time
2141 html += td.format('') # output link
2142 html += '</tr>\n'
2143
2144 # flush the data to file
2145 hf.write(html+'</table>\n')
2146 hf.write('</body>\n</html>\n')
2147 hf.close()
2148
848# Function: createHTML 2149# Function: createHTML
849# Description: 2150# Description:
850# Create the output html file. 2151# Create the output html file from the resident test data
851def createHTML(): 2152# Arguments:
852 global sysvals, data 2153# testruns: array of Data objects from parseKernelLog or parseTraceLog
2154# Output:
2155# True if the html file was created, false if it failed
2156def createHTML(testruns):
2157 global sysvals
853 2158
854 data.normalizeTime() 2159 for data in testruns:
2160 data.normalizeTime(testruns[-1].tSuspended)
855 2161
2162 x2changes = ['', 'absolute']
2163 if len(testruns) > 1:
2164 x2changes = ['1', 'relative']
856 # html function templates 2165 # html function templates
857 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n' 2166 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' 2167 html_devlist1 = '<button id="devlist1" class="devlist" style="float:left;">Device Detail%s</button>' % x2changes[0]
859 html_timeline = '<div id="{0}" class="timeline" style="height:{1}px">\n' 2168 html_zoombox = '<center><button id="zoomin">ZOOM IN</button><button id="zoomout">ZOOM OUT</button><button id="zoomdef">ZOOM 1:1</button></center>\n'
2169 html_devlist2 = '<button id="devlist2" class="devlist" style="float:right;">Device Detail2</button>\n'
2170 html_timeline = '<div id="dmesgzoombox" class="zoombox">\n<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' 2171 html_device = '<div id="{0}" title="{1}" class="thread" style="left:{2}%;top:{3}%;height:{4}%;width:{5}%;">{6}</div>\n'
2172 html_traceevent = '<div title="{0}" class="traceevent" style="left:{1}%;top:{2}%;height:{3}%;width:{4}%;border:1px solid {5};background-color:{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' 2173 html_phase = '<div class="phase" style="left:{0}%;width:{1}%;top:{2}%;height:{3}%;background-color:{4}">{5}</div>\n'
2174 html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background-color:{3}"></div>\n'
862 html_legend = '<div class="square" style="left:{0}%;background-color:{1}">&nbsp;{2}</div>\n' 2175 html_legend = '<div class="square" style="left:{0}%;background-color:{1}">&nbsp;{2}</div>\n'
863 html_timetotal = '<table class="time1">\n<tr>'\ 2176 html_timetotal = '<table class="time1">\n<tr>'\
864 '<td class="gray">{2} Suspend Time: <b>{0} ms</b></td>'\ 2177 '<td class="green">{2} Suspend Time: <b>{0} ms</b></td>'\
865 '<td class="gray">{2} Resume Time: <b>{1} ms</b></td>'\ 2178 '<td class="yellow">{2} Resume Time: <b>{1} ms</b></td>'\
2179 '</tr>\n</table>\n'
2180 html_timetotal2 = '<table class="time1">\n<tr>'\
2181 '<td class="green">{3} Suspend Time: <b>{0} ms</b></td>'\
2182 '<td class="gray">'+sysvals.suspendmode+' time: <b>{1} ms</b></td>'\
2183 '<td class="yellow">{3} Resume Time: <b>{2} ms</b></td>'\
866 '</tr>\n</table>\n' 2184 '</tr>\n</table>\n'
867 html_timegroups = '<table class="time2">\n<tr>'\ 2185 html_timegroups = '<table class="time2">\n<tr>'\
868 '<td class="green">Kernel Suspend: {0} ms</td>'\ 2186 '<td class="green">{4}Kernel Suspend: {0} ms</td>'\
869 '<td class="purple">Firmware Suspend: {1} ms</td>'\ 2187 '<td class="purple">{4}Firmware Suspend: {1} ms</td>'\
870 '<td class="purple">Firmware Resume: {2} ms</td>'\ 2188 '<td class="purple">{4}Firmware Resume: {2} ms</td>'\
871 '<td class="yellow">Kernel Resume: {3} ms</td>'\ 2189 '<td class="yellow">{4}Kernel Resume: {3} ms</td>'\
872 '</tr>\n</table>\n' 2190 '</tr>\n</table>\n'
873 2191
874 # device timeline (dmesg) 2192 # device timeline
875 if(data.usedmesg): 2193 vprint('Creating Device Timeline...')
876 data.vprint("Creating Device Timeline...") 2194 devtl = Timeline()
877 devtl = Timeline()
878 2195
879 # Generate the header for this timeline 2196 # Generate the header for this timeline
880 t0 = data.start 2197 textnum = ['First', 'Second']
881 tMax = data.end 2198 for data in testruns:
882 tTotal = tMax - t0 2199 tTotal = data.end - data.start
2200 tEnd = data.dmesg['resume_complete']['end']
883 if(tTotal == 0): 2201 if(tTotal == 0):
884 print("ERROR: No timeline data") 2202 print('ERROR: No timeline data')
885 sys.exit() 2203 sys.exit()
886 suspend_time = "%.0f"%(-data.start*1000) 2204 if(data.tLow > 0):
887 resume_time = "%.0f"%(data.end*1000) 2205 low_time = '%.0f'%(data.tLow*1000)
888 if data.fwValid: 2206 if data.fwValid:
889 devtl.html['timeline'] = html_timetotal.format(suspend_time, resume_time, "Total") 2207 suspend_time = '%.0f'%((data.tSuspended-data.start)*1000 + \
890 sktime = "%.3f"%((data.dmesg['suspend_cpu']['end'] - data.dmesg['suspend_general']['start'])*1000) 2208 (data.fwSuspend/1000000.0))
891 sftime = "%.3f"%(data.fwSuspend / 1000000.0) 2209 resume_time = '%.0f'%((tEnd-data.tSuspended)*1000 + \
892 rftime = "%.3f"%(data.fwResume / 1000000.0) 2210 (data.fwResume/1000000.0))
893 rktime = "%.3f"%((data.dmesg['resume_general']['end'] - data.dmesg['resume_cpu']['start'])*1000) 2211 testdesc1 = 'Total'
894 devtl.html['timeline'] += html_timegroups.format(sktime, sftime, rftime, rktime) 2212 testdesc2 = ''
2213 if(len(testruns) > 1):
2214 testdesc1 = testdesc2 = textnum[data.testnumber]
2215 testdesc2 += ' '
2216 if(data.tLow == 0):
2217 thtml = html_timetotal.format(suspend_time, \
2218 resume_time, testdesc1)
2219 else:
2220 thtml = html_timetotal2.format(suspend_time, low_time, \
2221 resume_time, testdesc1)
2222 devtl.html['timeline'] += thtml
2223 sktime = '%.3f'%((data.dmesg['suspend_machine']['end'] - \
2224 data.getStart())*1000)
2225 sftime = '%.3f'%(data.fwSuspend / 1000000.0)
2226 rftime = '%.3f'%(data.fwResume / 1000000.0)
2227 rktime = '%.3f'%((data.getEnd() - \
2228 data.dmesg['resume_machine']['start'])*1000)
2229 devtl.html['timeline'] += html_timegroups.format(sktime, \
2230 sftime, rftime, rktime, testdesc2)
895 else: 2231 else:
896 devtl.html['timeline'] = html_timetotal.format(suspend_time, resume_time, "Kernel") 2232 suspend_time = '%.0f'%((data.tSuspended-data.start)*1000)
2233 resume_time = '%.0f'%((tEnd-data.tSuspended)*1000)
2234 testdesc = 'Kernel'
2235 if(len(testruns) > 1):
2236 testdesc = textnum[data.testnumber]+' '+testdesc
2237 if(data.tLow == 0):
2238 thtml = html_timetotal.format(suspend_time, \
2239 resume_time, testdesc)
2240 else:
2241 thtml = html_timetotal2.format(suspend_time, low_time, \
2242 resume_time, testdesc)
2243 devtl.html['timeline'] += thtml
2244
2245 # time scale for potentially multiple datasets
2246 t0 = testruns[0].start
2247 tMax = testruns[-1].end
2248 tSuspended = testruns[-1].tSuspended
2249 tTotal = tMax - t0
897 2250
898 # determine the maximum number of rows we need to draw 2251 # determine the maximum number of rows we need to draw
899 timelinerows = 0 2252 timelinerows = 0
2253 for data in testruns:
900 for phase in data.dmesg: 2254 for phase in data.dmesg:
901 list = data.dmesg[phase]['list'] 2255 list = data.dmesg[phase]['list']
902 rows = setTimelineRows(list, list) 2256 rows = setTimelineRows(list, list)
@@ -904,62 +2258,104 @@ def createHTML():
904 if(rows > timelinerows): 2258 if(rows > timelinerows):
905 timelinerows = rows 2259 timelinerows = rows
906 2260
907 # calculate the timeline height and create its bounding box 2261 # calculate the timeline height and create bounding box, add buttons
908 devtl.setRows(timelinerows + 1) 2262 devtl.setRows(timelinerows + 1)
909 devtl.html['timeline'] += html_zoombox; 2263 devtl.html['timeline'] += html_devlist1
910 devtl.html['timeline'] += html_timeline.format("dmesg", devtl.height); 2264 if len(testruns) > 1:
2265 devtl.html['timeline'] += html_devlist2
2266 devtl.html['timeline'] += html_zoombox
2267 devtl.html['timeline'] += html_timeline.format('dmesg', devtl.height)
911 2268
912 # draw the colored boxes for each of the phases 2269 # draw the colored boxes for each of the phases
2270 for data in testruns:
913 for b in data.dmesg: 2271 for b in data.dmesg:
914 phase = data.dmesg[b] 2272 phase = data.dmesg[b]
915 left = "%.3f" % (((phase['start']-data.start)*100)/tTotal) 2273 length = phase['end']-phase['start']
916 width = "%.3f" % (((phase['end']-phase['start'])*100)/tTotal) 2274 left = '%.3f' % (((phase['start']-t0)*100.0)/tTotal)
917 devtl.html['timeline'] += html_phase.format(left, width, "%.3f"%devtl.scaleH, "%.3f"%(100-devtl.scaleH), data.dmesg[b]['color'], "") 2275 width = '%.3f' % ((length*100.0)/tTotal)
918 2276 devtl.html['timeline'] += html_phase.format(left, width, \
919 # draw the time scale, try to make the number of labels readable 2277 '%.3f'%devtl.scaleH, '%.3f'%(100-devtl.scaleH), \
920 devtl.html['scale'] = createTimeScale(t0, tMax, data.tSuspended) 2278 data.dmesg[b]['color'], '')
921 devtl.html['timeline'] += devtl.html['scale'] 2279
2280 # draw the time scale, try to make the number of labels readable
2281 devtl.html['scale'] = createTimeScale(t0, tMax, tSuspended)
2282 devtl.html['timeline'] += devtl.html['scale']
2283 for data in testruns:
922 for b in data.dmesg: 2284 for b in data.dmesg:
923 phaselist = data.dmesg[b]['list'] 2285 phaselist = data.dmesg[b]['list']
924 for d in phaselist: 2286 for d in phaselist:
925 name = d 2287 name = d
926 if(d in data.altdevname): 2288 drv = ''
927 name = data.altdevname[d]
928 dev = phaselist[d] 2289 dev = phaselist[d]
2290 if(d in sysvals.altdevname):
2291 name = sysvals.altdevname[d]
2292 if('drv' in dev and dev['drv']):
2293 drv = ' {%s}' % dev['drv']
929 height = (100.0 - devtl.scaleH)/data.dmesg[b]['row'] 2294 height = (100.0 - devtl.scaleH)/data.dmesg[b]['row']
930 top = "%.3f" % ((dev['row']*height) + devtl.scaleH) 2295 top = '%.3f' % ((dev['row']*height) + devtl.scaleH)
931 left = "%.3f" % (((dev['start']-data.start)*100)/tTotal) 2296 left = '%.3f' % (((dev['start']-t0)*100)/tTotal)
932 width = "%.3f" % (((dev['end']-dev['start'])*100)/tTotal) 2297 width = '%.3f' % (((dev['end']-dev['start'])*100)/tTotal)
933 len = " (%0.3f ms) " % ((dev['end']-dev['start'])*1000) 2298 length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000)
934 color = "rgba(204,204,204,0.5)" 2299 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) 2300 devtl.html['timeline'] += html_device.format(dev['id'], \
936 2301 d+drv+length+b, left, top, '%.3f'%height, width, name+drv)
937 # timeline is finished 2302
938 devtl.html['timeline'] += "</div>\n</div>\n" 2303 # draw any trace events found
939 2304 for data in testruns:
940 # draw a legend which describes the phases by color 2305 for b in data.dmesg:
941 devtl.html['legend'] = "<div class=\"legend\">\n" 2306 phaselist = data.dmesg[b]['list']
942 pdelta = 100.0/data.phases.__len__() 2307 for name in phaselist:
943 pmargin = pdelta / 4.0 2308 dev = phaselist[name]
944 for phase in data.phases: 2309 if('traceevents' in dev):
945 order = "%.2f" % ((data.dmesg[phase]['order'] * pdelta) + pmargin) 2310 vprint('Debug trace events found for device %s' % name)
946 name = string.replace(phase, "_", " &nbsp;") 2311 vprint('%20s %20s %10s %8s' % ('action', \
947 devtl.html['legend'] += html_legend.format(order, data.dmesg[phase]['color'], name) 2312 'name', 'time(ms)', 'length(ms)'))
948 devtl.html['legend'] += "</div>\n" 2313 for e in dev['traceevents']:
2314 vprint('%20s %20s %10.3f %8.3f' % (e.action, \
2315 e.name, e.time*1000, e.length*1000))
2316 height = (100.0 - devtl.scaleH)/data.dmesg[b]['row']
2317 top = '%.3f' % ((dev['row']*height) + devtl.scaleH)
2318 left = '%.3f' % (((e.time-t0)*100)/tTotal)
2319 width = '%.3f' % (e.length*100/tTotal)
2320 color = 'rgba(204,204,204,0.5)'
2321 devtl.html['timeline'] += \
2322 html_traceevent.format(e.action+' '+e.name, \
2323 left, top, '%.3f'%height, \
2324 width, e.color, '')
2325
2326 # timeline is finished
2327 devtl.html['timeline'] += '</div>\n</div>\n'
2328
2329 # draw a legend which describes the phases by color
2330 data = testruns[-1]
2331 devtl.html['legend'] = '<div class="legend">\n'
2332 pdelta = 100.0/len(data.phases)
2333 pmargin = pdelta / 4.0
2334 for phase in data.phases:
2335 order = '%.2f' % ((data.dmesg[phase]['order'] * pdelta) + pmargin)
2336 name = string.replace(phase, '_', ' &nbsp;')
2337 devtl.html['legend'] += html_legend.format(order, \
2338 data.dmesg[phase]['color'], name)
2339 devtl.html['legend'] += '</div>\n'
949 2340
950 hf = open(sysvals.htmlfile, 'w') 2341 hf = open(sysvals.htmlfile, 'w')
951 thread_height = 0 2342 thread_height = 0
952 2343
953 # write the html header first (html head, css code, everything up to the start of body) 2344 # write the html header first (html head, css code, up to body start)
954 html_header = "<!DOCTYPE html>\n<html>\n<head>\n\ 2345 html_header = '<!DOCTYPE html>\n<html>\n<head>\n\
955 <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n\ 2346 <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\
956 <title>AnalyzeSuspend</title>\n\ 2347 <title>AnalyzeSuspend</title>\n\
957 <style type='text/css'>\n\ 2348 <style type=\'text/css\'>\n\
958 body {overflow-y: scroll;}\n\ 2349 body {overflow-y: scroll;}\n\
959 .stamp {width: 100%;text-align:center;background-color:gray;line-height:30px;color:white;font: 25px Arial;}\n\ 2350 .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\ 2351 .callgraph {margin-top: 30px;box-shadow: 5px 5px 20px black;}\n\
961 .callgraph article * {padding-left: 28px;}\n\ 2352 .callgraph article * {padding-left: 28px;}\n\
962 h1 {color:black;font: bold 30px Times;}\n\ 2353 h1 {color:black;font: bold 30px Times;}\n\
2354 t0 {color:black;font: bold 30px Times;}\n\
2355 t1 {color:black;font: 30px Times;}\n\
2356 t2 {color:black;font: 25px Times;}\n\
2357 t3 {color:black;font: 20px Times;white-space:nowrap;}\n\
2358 t4 {color:black;font: bold 30px Times;line-height:60px;white-space:nowrap;}\n\
963 table {width:100%;}\n\ 2359 table {width:100%;}\n\
964 .gray {background-color:rgba(80,80,80,0.1);}\n\ 2360 .gray {background-color:rgba(80,80,80,0.1);}\n\
965 .green {background-color:rgba(204,255,204,0.4);}\n\ 2361 .green {background-color:rgba(204,255,204,0.4);}\n\
@@ -968,38 +2364,58 @@ def createHTML():
968 .time1 {font: 22px Arial;border:1px solid;}\n\ 2364 .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\ 2365 .time2 {font: 15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\
970 td {text-align: center;}\n\ 2366 td {text-align: center;}\n\
2367 r {color:#500000;font:15px Tahoma;}\n\
2368 n {color:#505050;font:15px Tahoma;}\n\
971 .tdhl {color: red;}\n\ 2369 .tdhl {color: red;}\n\
972 .hide {display: none;}\n\ 2370 .hide {display: none;}\n\
973 .pf {display: none;}\n\ 2371 .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\ 2372 .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\ 2373 .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\ 2374 .pf:checked ~ *:not(:nth-child(2)) {display: none;}\n\
977 .zoombox {position: relative; width: 100%; overflow-x: scroll;}\n\ 2375 .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\ 2376 .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\ 2377 .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\ 2378 .thread:hover {background-color:white;border:1px solid red;z-index:10;}\n\
2379 .hover {background-color:white;border:1px solid red;z-index:10;}\n\
2380 .traceevent {position: absolute;opacity: 0.3;height: '+'%.3f'%thread_height+'%;width:0;overflow:hidden;line-height:30px;text-align:center;white-space:nowrap;}\n\
981 .phase {position: absolute;overflow: hidden;border:0px;text-align:center;}\n\ 2381 .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\ 2382 .phaselet {position:absolute;overflow:hidden;border:0px;text-align:center;height:100px;font-size:24px;}\n\
2383 .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\ 2384 .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\ 2385 .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\ 2386 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\
986 </style>\n</head>\n<body>\n" 2387 .devlist {position:'+x2changes[1]+';width:190px;}\n\
2388 #devicedetail {height:100px;box-shadow: 5px 5px 20px black;}\n\
2389 </style>\n</head>\n<body>\n'
987 hf.write(html_header) 2390 hf.write(html_header)
988 2391
989 # write the test title and general info header 2392 # write the test title and general info header
990 if(data.stamp['time'] != ""): 2393 if(sysvals.stamp['time'] != ""):
991 hf.write(headline_stamp.format(data.stamp['host'], 2394 hf.write(headline_stamp.format(sysvals.stamp['host'],
992 data.stamp['kernel'], data.stamp['mode'], data.stamp['time'])) 2395 sysvals.stamp['kernel'], sysvals.stamp['mode'], \
993 2396 sysvals.stamp['time']))
994 # write the dmesg data (device timeline) 2397
995 if(data.usedmesg): 2398 # write the device timeline
996 hf.write(devtl.html['timeline']) 2399 hf.write(devtl.html['timeline'])
997 hf.write(devtl.html['legend']) 2400 hf.write(devtl.html['legend'])
998 hf.write('<div id="devicedetail"></div>\n') 2401 hf.write('<div id="devicedetailtitle"></div>\n')
999 hf.write('<div id="devicetree"></div>\n') 2402 hf.write('<div id="devicedetail" style="display:none;">\n')
2403 # draw the colored boxes for the device detail section
2404 for data in testruns:
2405 hf.write('<div id="devicedetail%d">\n' % data.testnumber)
2406 for b in data.phases:
2407 phase = data.dmesg[b]
2408 length = phase['end']-phase['start']
2409 left = '%.3f' % (((phase['start']-t0)*100.0)/tTotal)
2410 width = '%.3f' % ((length*100.0)/tTotal)
2411 hf.write(html_phaselet.format(b, left, width, \
2412 data.dmesg[b]['color']))
2413 hf.write('</div>\n')
2414 hf.write('</div>\n')
1000 2415
1001 # write the ftrace data (callgraph) 2416 # write the ftrace data (callgraph)
1002 if(data.useftrace): 2417 data = testruns[-1]
2418 if(sysvals.usecallgraph):
1003 hf.write('<section id="callgraphs" class="callgraph">\n') 2419 hf.write('<section id="callgraphs" class="callgraph">\n')
1004 # write out the ftrace data converted to html 2420 # 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' 2421 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'
@@ -1013,18 +2429,21 @@ def createHTML():
1013 if('ftrace' not in list[devname]): 2429 if('ftrace' not in list[devname]):
1014 continue 2430 continue
1015 name = devname 2431 name = devname
1016 if(devname in data.altdevname): 2432 if(devname in sysvals.altdevname):
1017 name = data.altdevname[devname] 2433 name = sysvals.altdevname[devname]
1018 devid = list[devname]['id'] 2434 devid = list[devname]['id']
1019 cg = list[devname]['ftrace'] 2435 cg = list[devname]['ftrace']
1020 flen = "(%.3f ms)" % ((cg.end - cg.start)*1000) 2436 flen = '<r>(%.3f ms @ %.3f to %.3f)</r>' % \
1021 hf.write(html_func_top.format(devid, data.dmesg[p]['color'], num, name+" "+p, flen)) 2437 ((cg.end - cg.start)*1000, cg.start*1000, cg.end*1000)
2438 hf.write(html_func_top.format(devid, data.dmesg[p]['color'], \
2439 num, name+' '+p, flen))
1022 num += 1 2440 num += 1
1023 for line in cg.list: 2441 for line in cg.list:
1024 if(line.length < 0.000000001): 2442 if(line.length < 0.000000001):
1025 flen = "" 2443 flen = ''
1026 else: 2444 else:
1027 flen = "(%.3f ms)" % (line.length*1000) 2445 flen = '<n>(%.3f ms @ %.3f)</n>' % (line.length*1000, \
2446 line.time*1000)
1028 if(line.freturn and line.fcall): 2447 if(line.freturn and line.fcall):
1029 hf.write(html_func_leaf.format(line.name, flen)) 2448 hf.write(html_func_leaf.format(line.name, flen))
1030 elif(line.freturn): 2449 elif(line.freturn):
@@ -1033,96 +2452,31 @@ def createHTML():
1033 hf.write(html_func_start.format(num, line.name, flen)) 2452 hf.write(html_func_start.format(num, line.name, flen))
1034 num += 1 2453 num += 1
1035 hf.write(html_func_end) 2454 hf.write(html_func_end)
1036 hf.write("\n\n </section>\n") 2455 hf.write('\n\n </section>\n')
1037 # write the footer and close 2456 # write the footer and close
1038 addScriptCode(hf) 2457 addScriptCode(hf, testruns)
1039 hf.write("</body>\n</html>\n") 2458 hf.write('</body>\n</html>\n')
1040 hf.close() 2459 hf.close()
1041 return True 2460 return True
1042 2461
1043def addScriptCode(hf): 2462# Function: addScriptCode
1044 global data 2463# Description:
1045 2464# Adds the javascript code to the output html
1046 t0 = (data.start - data.tSuspended) * 1000 2465# Arguments:
1047 tMax = (data.end - data.tSuspended) * 1000 2466# hf: the open html file pointer
2467# testruns: array of Data objects from parseKernelLog or parseTraceLog
2468def addScriptCode(hf, testruns):
2469 t0 = (testruns[0].start - testruns[-1].tSuspended) * 1000
2470 tMax = (testruns[-1].end - testruns[-1].tSuspended) * 1000
1048 # create an array in javascript memory with the device details 2471 # create an array in javascript memory with the device details
1049 detail = ' var bounds = [%f,%f];\n' % (t0, tMax) 2472 detail = ' var devtable = [];\n'
1050 detail += ' var d = [];\n' 2473 for data in testruns:
1051 dfmt = ' d["%s"] = { n:"%s", p:"%s", c:[%s] };\n'; 2474 topo = data.deviceTopology()
1052 for p in data.dmesg: 2475 detail += ' devtable[%d] = "%s";\n' % (data.testnumber, topo)
1053 list = data.dmesg[p]['list'] 2476 detail += ' var bounds = [%f,%f];\n' % (t0, tMax)
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 2477 # add the code which will manipulate the data in the browser
1066 script_code = \ 2478 script_code = \
1067 '<script type="text/javascript">\n'+detail+\ 2479 '<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'\ 2480 ' function zoomTimeline() {\n'\
1127 ' var timescale = document.getElementById("timescale");\n'\ 2481 ' var timescale = document.getElementById("timescale");\n'\
1128 ' var dmesg = document.getElementById("dmesg");\n'\ 2482 ' var dmesg = document.getElementById("dmesg");\n'\
@@ -1154,35 +2508,170 @@ def addScriptCode(hf):
1154 ' for(var s = ((t0 / tS)|0) * tS; s < tMax; s += tS) {\n'\ 2508 ' for(var s = ((t0 / tS)|0) * tS; s < tMax; s += tS) {\n'\
1155 ' var pos = (tMax - s) * 100.0 / tTotal;\n'\ 2509 ' var pos = (tMax - s) * 100.0 / tTotal;\n'\
1156 ' var name = (s == 0)?"S/R":(s+"ms");\n'\ 2510 ' var name = (s == 0)?"S/R":(s+"ms");\n'\
1157 ' html += \"<div class=\\\"t\\\" style=\\\"right:\"+pos+\"%\\\">\"+name+\"</div>\";\n'\ 2511 ' html += "<div class=\\"t\\" style=\\"right:"+pos+"%\\">"+name+"</div>";\n'\
1158 ' }\n'\ 2512 ' }\n'\
1159 ' timescale.innerHTML = html;\n'\ 2513 ' timescale.innerHTML = html;\n'\
1160 ' }\n'\ 2514 ' }\n'\
2515 ' function deviceHover() {\n'\
2516 ' var name = this.title.slice(0, this.title.indexOf(" ("));\n'\
2517 ' var dmesg = document.getElementById("dmesg");\n'\
2518 ' var dev = dmesg.getElementsByClassName("thread");\n'\
2519 ' var cpu = -1;\n'\
2520 ' if(name.match("CPU_ON\[[0-9]*\]"))\n'\
2521 ' cpu = parseInt(name.slice(7));\n'\
2522 ' else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\
2523 ' cpu = parseInt(name.slice(8));\n'\
2524 ' for (var i = 0; i < dev.length; i++) {\n'\
2525 ' dname = dev[i].title.slice(0, dev[i].title.indexOf(" ("));\n'\
2526 ' if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\
2527 ' (name == dname))\n'\
2528 ' {\n'\
2529 ' dev[i].className = "thread hover";\n'\
2530 ' } else {\n'\
2531 ' dev[i].className = "thread";\n'\
2532 ' }\n'\
2533 ' }\n'\
2534 ' }\n'\
2535 ' function deviceUnhover() {\n'\
2536 ' var dmesg = document.getElementById("dmesg");\n'\
2537 ' var dev = dmesg.getElementsByClassName("thread");\n'\
2538 ' for (var i = 0; i < dev.length; i++) {\n'\
2539 ' dev[i].className = "thread";\n'\
2540 ' }\n'\
2541 ' }\n'\
2542 ' function deviceTitle(title, total, cpu) {\n'\
2543 ' var prefix = "Total";\n'\
2544 ' if(total.length > 3) {\n'\
2545 ' prefix = "Average";\n'\
2546 ' total[1] = (total[1]+total[3])/2;\n'\
2547 ' total[2] = (total[2]+total[4])/2;\n'\
2548 ' }\n'\
2549 ' var devtitle = document.getElementById("devicedetailtitle");\n'\
2550 ' var name = title.slice(0, title.indexOf(" "));\n'\
2551 ' if(cpu >= 0) name = "CPU"+cpu;\n'\
2552 ' var driver = "";\n'\
2553 ' var tS = "<t2>(</t2>";\n'\
2554 ' var tR = "<t2>)</t2>";\n'\
2555 ' if(total[1] > 0)\n'\
2556 ' tS = "<t2>("+prefix+" Suspend:</t2><t0> "+total[1].toFixed(3)+" ms</t0> ";\n'\
2557 ' if(total[2] > 0)\n'\
2558 ' tR = " <t2>"+prefix+" Resume:</t2><t0> "+total[2].toFixed(3)+" ms<t2>)</t2></t0>";\n'\
2559 ' var s = title.indexOf("{");\n'\
2560 ' var e = title.indexOf("}");\n'\
2561 ' if((s >= 0) && (e >= 0))\n'\
2562 ' driver = title.slice(s+1, e) + " <t1>@</t1> ";\n'\
2563 ' if(total[1] > 0 && total[2] > 0)\n'\
2564 ' devtitle.innerHTML = "<t0>"+driver+name+"</t0> "+tS+tR;\n'\
2565 ' else\n'\
2566 ' devtitle.innerHTML = "<t0>"+title+"</t0>";\n'\
2567 ' return name;\n'\
2568 ' }\n'\
1161 ' function deviceDetail() {\n'\ 2569 ' function deviceDetail() {\n'\
1162 ' var devtitle = document.getElementById("devicedetail");\n'\ 2570 ' var devinfo = document.getElementById("devicedetail");\n'\
1163 ' devtitle.innerHTML = "<h1>"+this.title+"</h1>";\n'\ 2571 ' devinfo.style.display = "block";\n'\
1164 ' var devtree = document.getElementById("devicetree");\n'\ 2572 ' var name = this.title.slice(0, this.title.indexOf(" ("));\n'\
1165 ' devtree.innerHTML = deviceTree(this.id, (this.title.indexOf("resume") >= 0));\n'\ 2573 ' var cpu = -1;\n'\
2574 ' if(name.match("CPU_ON\[[0-9]*\]"))\n'\
2575 ' cpu = parseInt(name.slice(7));\n'\
2576 ' else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\
2577 ' cpu = parseInt(name.slice(8));\n'\
2578 ' var dmesg = document.getElementById("dmesg");\n'\
2579 ' var dev = dmesg.getElementsByClassName("thread");\n'\
2580 ' var idlist = [];\n'\
2581 ' var pdata = [[]];\n'\
2582 ' var pd = pdata[0];\n'\
2583 ' var total = [0.0, 0.0, 0.0];\n'\
2584 ' for (var i = 0; i < dev.length; i++) {\n'\
2585 ' dname = dev[i].title.slice(0, dev[i].title.indexOf(" ("));\n'\
2586 ' if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\
2587 ' (name == dname))\n'\
2588 ' {\n'\
2589 ' idlist[idlist.length] = dev[i].id;\n'\
2590 ' var tidx = 1;\n'\
2591 ' if(dev[i].id[0] == "a") {\n'\
2592 ' pd = pdata[0];\n'\
2593 ' } else {\n'\
2594 ' if(pdata.length == 1) pdata[1] = [];\n'\
2595 ' if(total.length == 3) total[3]=total[4]=0.0;\n'\
2596 ' pd = pdata[1];\n'\
2597 ' tidx = 3;\n'\
2598 ' }\n'\
2599 ' var info = dev[i].title.split(" ");\n'\
2600 ' var pname = info[info.length-1];\n'\
2601 ' pd[pname] = parseFloat(info[info.length-3].slice(1));\n'\
2602 ' total[0] += pd[pname];\n'\
2603 ' if(pname.indexOf("suspend") >= 0)\n'\
2604 ' total[tidx] += pd[pname];\n'\
2605 ' else\n'\
2606 ' total[tidx+1] += pd[pname];\n'\
2607 ' }\n'\
2608 ' }\n'\
2609 ' var devname = deviceTitle(this.title, total, cpu);\n'\
2610 ' var left = 0.0;\n'\
2611 ' for (var t = 0; t < pdata.length; t++) {\n'\
2612 ' pd = pdata[t];\n'\
2613 ' devinfo = document.getElementById("devicedetail"+t);\n'\
2614 ' var phases = devinfo.getElementsByClassName("phaselet");\n'\
2615 ' for (var i = 0; i < phases.length; i++) {\n'\
2616 ' if(phases[i].id in pd) {\n'\
2617 ' var w = 100.0*pd[phases[i].id]/total[0];\n'\
2618 ' var fs = 32;\n'\
2619 ' if(w < 8) fs = 4*w | 0;\n'\
2620 ' var fs2 = fs*3/4;\n'\
2621 ' phases[i].style.width = w+"%";\n'\
2622 ' phases[i].style.left = left+"%";\n'\
2623 ' phases[i].title = phases[i].id+" "+pd[phases[i].id]+" ms";\n'\
2624 ' left += w;\n'\
2625 ' var time = "<t4 style=\\"font-size:"+fs+"px\\">"+pd[phases[i].id]+" ms<br></t4>";\n'\
2626 ' var pname = "<t3 style=\\"font-size:"+fs2+"px\\">"+phases[i].id.replace("_", " ")+"</t3>";\n'\
2627 ' phases[i].innerHTML = time+pname;\n'\
2628 ' } else {\n'\
2629 ' phases[i].style.width = "0%";\n'\
2630 ' phases[i].style.left = left+"%";\n'\
2631 ' }\n'\
2632 ' }\n'\
2633 ' }\n'\
1166 ' var cglist = document.getElementById("callgraphs");\n'\ 2634 ' var cglist = document.getElementById("callgraphs");\n'\
1167 ' if(!cglist) return;\n'\ 2635 ' if(!cglist) return;\n'\
1168 ' var cg = cglist.getElementsByClassName("atop");\n'\ 2636 ' var cg = cglist.getElementsByClassName("atop");\n'\
1169 ' for (var i = 0; i < cg.length; i++) {\n'\ 2637 ' for (var i = 0; i < cg.length; i++) {\n'\
1170 ' if(filter.indexOf(cg[i].id) >= 0) {\n'\ 2638 ' if(idlist.indexOf(cg[i].id) >= 0) {\n'\
1171 ' cg[i].style.display = "block";\n'\ 2639 ' cg[i].style.display = "block";\n'\
1172 ' } else {\n'\ 2640 ' } else {\n'\
1173 ' cg[i].style.display = "none";\n'\ 2641 ' cg[i].style.display = "none";\n'\
1174 ' }\n'\ 2642 ' }\n'\
1175 ' }\n'\ 2643 ' }\n'\
1176 ' }\n'\ 2644 ' }\n'\
2645 ' function devListWindow(e) {\n'\
2646 ' var sx = e.clientX;\n'\
2647 ' if(sx > window.innerWidth - 440)\n'\
2648 ' sx = window.innerWidth - 440;\n'\
2649 ' var cfg="top="+e.screenY+", left="+sx+", width=440, height=720, scrollbars=yes";\n'\
2650 ' var win = window.open("", "_blank", cfg);\n'\
2651 ' if(window.chrome) win.moveBy(sx, 0);\n'\
2652 ' var html = "<title>"+e.target.innerHTML+"</title>"+\n'\
2653 ' "<style type=\\"text/css\\">"+\n'\
2654 ' " ul {list-style-type:circle;padding-left:10px;margin-left:10px;}"+\n'\
2655 ' "</style>"\n'\
2656 ' var dt = devtable[0];\n'\
2657 ' if(e.target.id != "devlist1")\n'\
2658 ' dt = devtable[1];\n'\
2659 ' win.document.write(html+dt);\n'\
2660 ' }\n'\
1177 ' window.addEventListener("load", function () {\n'\ 2661 ' window.addEventListener("load", function () {\n'\
1178 ' var dmesg = document.getElementById("dmesg");\n'\ 2662 ' var dmesg = document.getElementById("dmesg");\n'\
1179 ' dmesg.style.width = "100%"\n'\ 2663 ' dmesg.style.width = "100%"\n'\
1180 ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\ 2664 ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\
1181 ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\ 2665 ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\
1182 ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\ 2666 ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\
2667 ' var devlist = document.getElementsByClassName("devlist");\n'\
2668 ' for (var i = 0; i < devlist.length; i++)\n'\
2669 ' devlist[i].onclick = devListWindow;\n'\
1183 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 2670 ' var dev = dmesg.getElementsByClassName("thread");\n'\
1184 ' for (var i = 0; i < dev.length; i++) {\n'\ 2671 ' for (var i = 0; i < dev.length; i++) {\n'\
1185 ' dev[i].onclick = deviceDetail;\n'\ 2672 ' dev[i].onclick = deviceDetail;\n'\
2673 ' dev[i].onmouseover = deviceHover;\n'\
2674 ' dev[i].onmouseout = deviceUnhover;\n'\
1186 ' }\n'\ 2675 ' }\n'\
1187 ' zoomTimeline();\n'\ 2676 ' zoomTimeline();\n'\
1188 ' });\n'\ 2677 ' });\n'\
@@ -1191,256 +2680,912 @@ def addScriptCode(hf):
1191 2680
1192# Function: executeSuspend 2681# Function: executeSuspend
1193# Description: 2682# Description:
1194# Execute system suspend through the sysfs interface 2683# Execute system suspend through the sysfs interface, then copy the output
2684# dmesg and ftrace files to the test output directory.
1195def executeSuspend(): 2685def executeSuspend():
1196 global sysvals, data 2686 global sysvals
1197 2687
1198 detectUSB() 2688 detectUSB(False)
1199 pf = open(sysvals.powerfile, 'w') 2689 t0 = time.time()*1000
1200 # clear the kernel ring buffer just as we start 2690 tp = sysvals.tpath
1201 os.system("dmesg -C") 2691 # execute however many s/r runs requested
1202 # start ftrace 2692 for count in range(1,sysvals.execcount+1):
1203 if(data.useftrace): 2693 # clear the kernel ring buffer just as we start
1204 print("START TRACING") 2694 os.system('dmesg -C')
1205 os.system("echo 1 > "+sysvals.tpath+"tracing_on") 2695 # enable callgraph ftrace only for the second run
1206 os.system("echo SUSPEND START > "+sysvals.tpath+"trace_marker") 2696 if(sysvals.usecallgraph and count == 2):
1207 # initiate suspend 2697 # set trace type
1208 if(sysvals.rtcwake): 2698 os.system('echo function_graph > '+tp+'current_tracer')
1209 print("SUSPEND START") 2699 os.system('echo "" > '+tp+'set_ftrace_filter')
1210 os.system("rtcwake -s 10 -m "+sysvals.suspendmode) 2700 # set trace format options
1211 else: 2701 os.system('echo funcgraph-abstime > '+tp+'trace_options')
1212 print("SUSPEND START (press a key to resume)") 2702 os.system('echo funcgraph-proc > '+tp+'trace_options')
2703 # focus only on device suspend and resume
2704 os.system('cat '+tp+'available_filter_functions | '+\
2705 'grep dpm_run_callback > '+tp+'set_graph_function')
2706 # if this is test2 and there's a delay, start here
2707 if(count > 1 and sysvals.x2delay > 0):
2708 tN = time.time()*1000
2709 while (tN - t0) < sysvals.x2delay:
2710 tN = time.time()*1000
2711 time.sleep(0.001)
2712 # start ftrace
2713 if(sysvals.usecallgraph or sysvals.usetraceevents):
2714 print('START TRACING')
2715 os.system('echo 1 > '+tp+'tracing_on')
2716 # initiate suspend
2717 if(sysvals.usecallgraph or sysvals.usetraceevents):
2718 os.system('echo SUSPEND START > '+tp+'trace_marker')
2719 if(sysvals.rtcwake):
2720 print('SUSPEND START')
2721 print('will autoresume in %d seconds' % sysvals.rtcwaketime)
2722 sysvals.rtcWakeAlarm()
2723 else:
2724 print('SUSPEND START (press a key to resume)')
2725 pf = open(sysvals.powerfile, 'w')
1213 pf.write(sysvals.suspendmode) 2726 pf.write(sysvals.suspendmode)
1214 # execution will pause here 2727 # execution will pause here
1215 pf.close() 2728 pf.close()
1216 # return from suspend 2729 t0 = time.time()*1000
1217 print("RESUME COMPLETE") 2730 # return from suspend
1218 # stop ftrace 2731 print('RESUME COMPLETE')
1219 if(data.useftrace): 2732 if(sysvals.usecallgraph or sysvals.usetraceevents):
1220 os.system("echo RESUME COMPLETE > "+sysvals.tpath+"trace_marker") 2733 os.system('echo RESUME COMPLETE > '+tp+'trace_marker')
1221 os.system("echo 0 > "+sysvals.tpath+"tracing_on") 2734 # see if there's firmware timing data to be had
1222 print("CAPTURING FTRACE") 2735 t = sysvals.postresumetime
1223 os.system("echo \""+sysvals.teststamp+"\" > "+sysvals.ftracefile) 2736 if(t > 0):
1224 os.system("cat "+sysvals.tpath+"trace >> "+sysvals.ftracefile) 2737 print('Waiting %d seconds for POST-RESUME trace events...' % t)
1225 # grab a copy of the dmesg output 2738 time.sleep(t)
1226 print("CAPTURING DMESG") 2739 # stop ftrace
1227 os.system("echo \""+sysvals.teststamp+"\" > "+sysvals.dmesgfile) 2740 if(sysvals.usecallgraph or sysvals.usetraceevents):
1228 os.system("dmesg -c >> "+sysvals.dmesgfile) 2741 os.system('echo 0 > '+tp+'tracing_on')
2742 print('CAPTURING TRACE')
2743 writeDatafileHeader(sysvals.ftracefile)
2744 os.system('cat '+tp+'trace >> '+sysvals.ftracefile)
2745 os.system('echo "" > '+tp+'trace')
2746 # grab a copy of the dmesg output
2747 print('CAPTURING DMESG')
2748 writeDatafileHeader(sysvals.dmesgfile)
2749 os.system('dmesg -c >> '+sysvals.dmesgfile)
2750
2751def writeDatafileHeader(filename):
2752 global sysvals
2753
2754 fw = getFPDT(False)
2755 prt = sysvals.postresumetime
2756 fp = open(filename, 'a')
2757 fp.write(sysvals.teststamp+'\n')
2758 if(fw):
2759 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1]))
2760 if(prt > 0):
2761 fp.write('# post resume time %u\n' % prt)
2762 fp.close()
2763
2764# Function: executeAndroidSuspend
2765# Description:
2766# Execute system suspend through the sysfs interface
2767# on a remote android device, then transfer the output
2768# dmesg and ftrace files to the local output directory.
2769def executeAndroidSuspend():
2770 global sysvals
2771
2772 # check to see if the display is currently off
2773 tp = sysvals.tpath
2774 out = os.popen(sysvals.adb+\
2775 ' shell dumpsys power | grep mScreenOn').read().strip()
2776 # if so we need to turn it on so we can issue a new suspend
2777 if(out.endswith('false')):
2778 print('Waking the device up for the test...')
2779 # send the KEYPAD_POWER keyevent to wake it up
2780 os.system(sysvals.adb+' shell input keyevent 26')
2781 # wait a few seconds so the user can see the device wake up
2782 time.sleep(3)
2783 # execute however many s/r runs requested
2784 for count in range(1,sysvals.execcount+1):
2785 # clear the kernel ring buffer just as we start
2786 os.system(sysvals.adb+' shell dmesg -c > /dev/null 2>&1')
2787 # start ftrace
2788 if(sysvals.usetraceevents):
2789 print('START TRACING')
2790 os.system(sysvals.adb+" shell 'echo 1 > "+tp+"tracing_on'")
2791 # initiate suspend
2792 for count in range(1,sysvals.execcount+1):
2793 if(sysvals.usetraceevents):
2794 os.system(sysvals.adb+\
2795 " shell 'echo SUSPEND START > "+tp+"trace_marker'")
2796 print('SUSPEND START (press a key on the device to resume)')
2797 os.system(sysvals.adb+" shell 'echo "+sysvals.suspendmode+\
2798 " > "+sysvals.powerfile+"'")
2799 # execution will pause here, then adb will exit
2800 while(True):
2801 check = os.popen(sysvals.adb+\
2802 ' shell pwd 2>/dev/null').read().strip()
2803 if(len(check) > 0):
2804 break
2805 time.sleep(1)
2806 if(sysvals.usetraceevents):
2807 os.system(sysvals.adb+" shell 'echo RESUME COMPLETE > "+tp+\
2808 "trace_marker'")
2809 # return from suspend
2810 print('RESUME COMPLETE')
2811 # stop ftrace
2812 if(sysvals.usetraceevents):
2813 os.system(sysvals.adb+" shell 'echo 0 > "+tp+"tracing_on'")
2814 print('CAPTURING TRACE')
2815 os.system('echo "'+sysvals.teststamp+'" > '+sysvals.ftracefile)
2816 os.system(sysvals.adb+' shell cat '+tp+\
2817 'trace >> '+sysvals.ftracefile)
2818 # grab a copy of the dmesg output
2819 print('CAPTURING DMESG')
2820 os.system('echo "'+sysvals.teststamp+'" > '+sysvals.dmesgfile)
2821 os.system(sysvals.adb+' shell dmesg >> '+sysvals.dmesgfile)
2822
2823# Function: setUSBDevicesAuto
2824# Description:
2825# Set the autosuspend control parameter of all USB devices to auto
2826# This can be dangerous, so use at your own risk, most devices are set
2827# to always-on since the kernel cant determine if the device can
2828# properly autosuspend
2829def setUSBDevicesAuto():
2830 global sysvals
2831
2832 rootCheck()
2833 for dirname, dirnames, filenames in os.walk('/sys/devices'):
2834 if(re.match('.*/usb[0-9]*.*', dirname) and
2835 'idVendor' in filenames and 'idProduct' in filenames):
2836 os.system('echo auto > %s/power/control' % dirname)
2837 name = dirname.split('/')[-1]
2838 desc = os.popen('cat %s/product 2>/dev/null' % \
2839 dirname).read().replace('\n', '')
2840 ctrl = os.popen('cat %s/power/control 2>/dev/null' % \
2841 dirname).read().replace('\n', '')
2842 print('control is %s for %6s: %s' % (ctrl, name, desc))
2843
2844# Function: yesno
2845# Description:
2846# Print out an equivalent Y or N for a set of known parameter values
2847# Output:
2848# 'Y', 'N', or ' ' if the value is unknown
2849def yesno(val):
2850 yesvals = ['auto', 'enabled', 'active', '1']
2851 novals = ['on', 'disabled', 'suspended', 'forbidden', 'unsupported']
2852 if val in yesvals:
2853 return 'Y'
2854 elif val in novals:
2855 return 'N'
2856 return ' '
2857
2858# Function: ms2nice
2859# Description:
2860# Print out a very concise time string in minutes and seconds
2861# Output:
2862# The time string, e.g. "1901m16s"
2863def ms2nice(val):
2864 ms = 0
2865 try:
2866 ms = int(val)
2867 except:
2868 return 0.0
2869 m = ms / 60000
2870 s = (ms / 1000) - (m * 60)
2871 return '%3dm%2ds' % (m, s)
1229 2872
1230# Function: detectUSB 2873# Function: detectUSB
1231# Description: 2874# Description:
1232# Detect all the USB hosts and devices currently connected 2875# Detect all the USB hosts and devices currently connected and add
1233def detectUSB(): 2876# a list of USB device names to sysvals for better timeline readability
1234 global sysvals, data 2877# Arguments:
1235 2878# output: True to output the info to stdout, False otherwise
1236 for dirname, dirnames, filenames in os.walk("/sys/devices"): 2879def detectUSB(output):
1237 if(re.match(r".*/usb[0-9]*.*", dirname) and 2880 global sysvals
1238 "idVendor" in filenames and "idProduct" in filenames): 2881
1239 vid = os.popen("cat %s/idVendor 2>/dev/null" % dirname).read().replace('\n', '') 2882 field = {'idVendor':'', 'idProduct':'', 'product':'', 'speed':''}
1240 pid = os.popen("cat %s/idProduct 2>/dev/null" % dirname).read().replace('\n', '') 2883 power = {'async':'', 'autosuspend':'', 'autosuspend_delay_ms':'',
1241 product = os.popen("cat %s/product 2>/dev/null" % dirname).read().replace('\n', '') 2884 'control':'', 'persist':'', 'runtime_enabled':'',
2885 'runtime_status':'', 'runtime_usage':'',
2886 'runtime_active_time':'',
2887 'runtime_suspended_time':'',
2888 'active_duration':'',
2889 'connected_duration':''}
2890 if(output):
2891 print('LEGEND')
2892 print('---------------------------------------------------------------------------------------------')
2893 print(' A = async/sync PM queue Y/N D = autosuspend delay (seconds)')
2894 print(' S = autosuspend Y/N rACTIVE = runtime active (min/sec)')
2895 print(' P = persist across suspend Y/N rSUSPEN = runtime suspend (min/sec)')
2896 print(' E = runtime suspend enabled/forbidden Y/N ACTIVE = active duration (min/sec)')
2897 print(' R = runtime status active/suspended Y/N CONNECT = connected duration (min/sec)')
2898 print(' U = runtime usage count')
2899 print('---------------------------------------------------------------------------------------------')
2900 print(' NAME ID DESCRIPTION SPEED A S P E R U D rACTIVE rSUSPEN ACTIVE CONNECT')
2901 print('---------------------------------------------------------------------------------------------')
2902
2903 for dirname, dirnames, filenames in os.walk('/sys/devices'):
2904 if(re.match('.*/usb[0-9]*.*', dirname) and
2905 'idVendor' in filenames and 'idProduct' in filenames):
2906 for i in field:
2907 field[i] = os.popen('cat %s/%s 2>/dev/null' % \
2908 (dirname, i)).read().replace('\n', '')
1242 name = dirname.split('/')[-1] 2909 name = dirname.split('/')[-1]
1243 if(len(product) > 0): 2910 if(len(field['product']) > 0):
1244 data.altdevname[name] = "%s [%s]" % (product, name) 2911 sysvals.altdevname[name] = \
2912 '%s [%s]' % (field['product'], name)
1245 else: 2913 else:
1246 data.altdevname[name] = "%s:%s [%s]" % (vid, pid, name) 2914 sysvals.altdevname[name] = \
1247 2915 '%s:%s [%s]' % (field['idVendor'], \
2916 field['idProduct'], name)
2917 if(output):
2918 for i in power:
2919 power[i] = os.popen('cat %s/power/%s 2>/dev/null' % \
2920 (dirname, i)).read().replace('\n', '')
2921 if(re.match('usb[0-9]*', name)):
2922 first = '%-8s' % name
2923 else:
2924 first = '%8s' % name
2925 print('%s [%s:%s] %-20s %-4s %1s %1s %1s %1s %1s %1s %1s %s %s %s %s' % \
2926 (first, field['idVendor'], field['idProduct'], \
2927 field['product'][0:20], field['speed'], \
2928 yesno(power['async']), \
2929 yesno(power['control']), \
2930 yesno(power['persist']), \
2931 yesno(power['runtime_enabled']), \
2932 yesno(power['runtime_status']), \
2933 power['runtime_usage'], \
2934 power['autosuspend'], \
2935 ms2nice(power['runtime_active_time']), \
2936 ms2nice(power['runtime_suspended_time']), \
2937 ms2nice(power['active_duration']), \
2938 ms2nice(power['connected_duration'])))
2939
2940# Function: getModes
2941# Description:
2942# Determine the supported power modes on this system
2943# Output:
2944# A string list of the available modes
1248def getModes(): 2945def getModes():
1249 global sysvals 2946 global sysvals
1250 modes = "" 2947 modes = ''
1251 if(os.path.exists(sysvals.powerfile)): 2948 if(not sysvals.android):
1252 fp = open(sysvals.powerfile, 'r') 2949 if(os.path.exists(sysvals.powerfile)):
1253 modes = string.split(fp.read()) 2950 fp = open(sysvals.powerfile, 'r')
1254 fp.close() 2951 modes = string.split(fp.read())
2952 fp.close()
2953 else:
2954 line = os.popen(sysvals.adb+' shell cat '+\
2955 sysvals.powerfile).read().strip()
2956 modes = string.split(line)
1255 return modes 2957 return modes
1256 2958
2959# Function: getFPDT
2960# Description:
2961# Read the acpi bios tables and pull out FPDT, the firmware data
2962# Arguments:
2963# output: True to output the info to stdout, False otherwise
2964def getFPDT(output):
2965 global sysvals
2966
2967 rectype = {}
2968 rectype[0] = 'Firmware Basic Boot Performance Record'
2969 rectype[1] = 'S3 Performance Table Record'
2970 prectype = {}
2971 prectype[0] = 'Basic S3 Resume Performance Record'
2972 prectype[1] = 'Basic S3 Suspend Performance Record'
2973
2974 rootCheck()
2975 if(not os.path.exists(sysvals.fpdtpath)):
2976 if(output):
2977 doError('file doesnt exist: %s' % sysvals.fpdtpath, False)
2978 return False
2979 if(not os.access(sysvals.fpdtpath, os.R_OK)):
2980 if(output):
2981 doError('file isnt readable: %s' % sysvals.fpdtpath, False)
2982 return False
2983 if(not os.path.exists(sysvals.mempath)):
2984 if(output):
2985 doError('file doesnt exist: %s' % sysvals.mempath, False)
2986 return False
2987 if(not os.access(sysvals.mempath, os.R_OK)):
2988 if(output):
2989 doError('file isnt readable: %s' % sysvals.mempath, False)
2990 return False
2991
2992 fp = open(sysvals.fpdtpath, 'rb')
2993 buf = fp.read()
2994 fp.close()
2995
2996 if(len(buf) < 36):
2997 if(output):
2998 doError('Invalid FPDT table data, should '+\
2999 'be at least 36 bytes', False)
3000 return False
3001
3002 table = struct.unpack('4sIBB6s8sI4sI', buf[0:36])
3003 if(output):
3004 print('')
3005 print('Firmware Performance Data Table (%s)' % table[0])
3006 print(' Signature : %s' % table[0])
3007 print(' Table Length : %u' % table[1])
3008 print(' Revision : %u' % table[2])
3009 print(' Checksum : 0x%x' % table[3])
3010 print(' OEM ID : %s' % table[4])
3011 print(' OEM Table ID : %s' % table[5])
3012 print(' OEM Revision : %u' % table[6])
3013 print(' Creator ID : %s' % table[7])
3014 print(' Creator Revision : 0x%x' % table[8])
3015 print('')
3016
3017 if(table[0] != 'FPDT'):
3018 if(output):
3019 doError('Invalid FPDT table')
3020 return False
3021 if(len(buf) <= 36):
3022 return False
3023 i = 0
3024 fwData = [0, 0]
3025 records = buf[36:]
3026 fp = open(sysvals.mempath, 'rb')
3027 while(i < len(records)):
3028 header = struct.unpack('HBB', records[i:i+4])
3029 if(header[0] not in rectype):
3030 continue
3031 if(header[1] != 16):
3032 continue
3033 addr = struct.unpack('Q', records[i+8:i+16])[0]
3034 try:
3035 fp.seek(addr)
3036 first = fp.read(8)
3037 except:
3038 doError('Bad address 0x%x in %s' % (addr, sysvals.mempath), False)
3039 rechead = struct.unpack('4sI', first)
3040 recdata = fp.read(rechead[1]-8)
3041 if(rechead[0] == 'FBPT'):
3042 record = struct.unpack('HBBIQQQQQ', recdata)
3043 if(output):
3044 print('%s (%s)' % (rectype[header[0]], rechead[0]))
3045 print(' Reset END : %u ns' % record[4])
3046 print(' OS Loader LoadImage Start : %u ns' % record[5])
3047 print(' OS Loader StartImage Start : %u ns' % record[6])
3048 print(' ExitBootServices Entry : %u ns' % record[7])
3049 print(' ExitBootServices Exit : %u ns' % record[8])
3050 elif(rechead[0] == 'S3PT'):
3051 if(output):
3052 print('%s (%s)' % (rectype[header[0]], rechead[0]))
3053 j = 0
3054 while(j < len(recdata)):
3055 prechead = struct.unpack('HBB', recdata[j:j+4])
3056 if(prechead[0] not in prectype):
3057 continue
3058 if(prechead[0] == 0):
3059 record = struct.unpack('IIQQ', recdata[j:j+prechead[1]])
3060 fwData[1] = record[2]
3061 if(output):
3062 print(' %s' % prectype[prechead[0]])
3063 print(' Resume Count : %u' % \
3064 record[1])
3065 print(' FullResume : %u ns' % \
3066 record[2])
3067 print(' AverageResume : %u ns' % \
3068 record[3])
3069 elif(prechead[0] == 1):
3070 record = struct.unpack('QQ', recdata[j+4:j+prechead[1]])
3071 fwData[0] = record[1] - record[0]
3072 if(output):
3073 print(' %s' % prectype[prechead[0]])
3074 print(' SuspendStart : %u ns' % \
3075 record[0])
3076 print(' SuspendEnd : %u ns' % \
3077 record[1])
3078 print(' SuspendTime : %u ns' % \
3079 fwData[0])
3080 j += prechead[1]
3081 if(output):
3082 print('')
3083 i += header[1]
3084 fp.close()
3085 return fwData
3086
1257# Function: statusCheck 3087# Function: statusCheck
1258# Description: 3088# Description:
1259# Verify that the requested command and options will work 3089# Verify that the requested command and options will work, and
1260def statusCheck(dryrun): 3090# print the results to the terminal
1261 global sysvals, data 3091# Output:
1262 res = dict() 3092# True if the test will work, False if not
3093def statusCheck():
3094 global sysvals
3095 status = True
1263 3096
1264 if(data.notestrun): 3097 if(sysvals.android):
1265 print("SUCCESS: The command should run!") 3098 print('Checking the android system ...')
1266 return 3099 else:
3100 print('Checking this system (%s)...' % platform.node())
3101
3102 # check if adb is connected to a device
3103 if(sysvals.android):
3104 res = 'NO'
3105 out = os.popen(sysvals.adb+' get-state').read().strip()
3106 if(out == 'device'):
3107 res = 'YES'
3108 print(' is android device connected: %s' % res)
3109 if(res != 'YES'):
3110 print(' Please connect the device before using this tool')
3111 return False
1267 3112
1268 # check we have root access 3113 # check we have root access
1269 check = "YES" 3114 res = 'NO (No features of this tool will work!)'
1270 if(os.environ['USER'] != "root"): 3115 if(sysvals.android):
1271 if(not dryrun): 3116 out = os.popen(sysvals.adb+' shell id').read().strip()
1272 doError("root access is required", False) 3117 if('root' in out):
1273 check = "NO" 3118 res = 'YES'
1274 res[" have root access: "] = check 3119 else:
3120 if(os.environ['USER'] == 'root'):
3121 res = 'YES'
3122 print(' have root access: %s' % res)
3123 if(res != 'YES'):
3124 if(sysvals.android):
3125 print(' Try running "adb root" to restart the daemon as root')
3126 else:
3127 print(' Try running this script with sudo')
3128 return False
1275 3129
1276 # check sysfs is mounted 3130 # check sysfs is mounted
1277 check = "YES" 3131 res = 'NO (No features of this tool will work!)'
1278 if(not os.path.exists(sysvals.powerfile)): 3132 if(sysvals.android):
1279 if(not dryrun): 3133 out = os.popen(sysvals.adb+' shell ls '+\
1280 doError("sysfs must be mounted", False) 3134 sysvals.powerfile).read().strip()
1281 check = "NO" 3135 if(out == sysvals.powerfile):
1282 res[" is sysfs mounted: "] = check 3136 res = 'YES'
3137 else:
3138 if(os.path.exists(sysvals.powerfile)):
3139 res = 'YES'
3140 print(' is sysfs mounted: %s' % res)
3141 if(res != 'YES'):
3142 return False
1283 3143
1284 # check target mode is a valid mode 3144 # check target mode is a valid mode
1285 check = "YES" 3145 res = 'NO'
1286 modes = getModes() 3146 modes = getModes()
1287 if(sysvals.suspendmode not in modes): 3147 if(sysvals.suspendmode in modes):
1288 if(not dryrun): 3148 res = 'YES'
1289 doError("%s is not a value power mode" % sysvals.suspendmode, False) 3149 else:
1290 check = "NO" 3150 status = False
1291 res[" is "+sysvals.suspendmode+" a power mode: "] = check 3151 print(' is "%s" a valid power mode: %s' % (sysvals.suspendmode, res))
3152 if(res == 'NO'):
3153 print(' valid power modes are: %s' % modes)
3154 print(' please choose one with -m')
3155
3156 # check if the tool can unlock the device
3157 if(sysvals.android):
3158 res = 'YES'
3159 out1 = os.popen(sysvals.adb+\
3160 ' shell dumpsys power | grep mScreenOn').read().strip()
3161 out2 = os.popen(sysvals.adb+\
3162 ' shell input').read().strip()
3163 if(not out1.startswith('mScreenOn') or not out2.startswith('usage')):
3164 res = 'NO (wake the android device up before running the test)'
3165 print(' can I unlock the screen: %s' % res)
1292 3166
1293 # check if ftrace is available 3167 # check if ftrace is available
1294 if(data.useftrace): 3168 res = 'NO'
1295 check = "YES" 3169 ftgood = verifyFtrace()
1296 if(not verifyFtrace()): 3170 if(ftgood):
1297 if(not dryrun): 3171 res = 'YES'
1298 doError("ftrace is not configured", False) 3172 elif(sysvals.usecallgraph):
1299 check = "NO" 3173 status = False
1300 res[" is ftrace usable: "] = check 3174 print(' is ftrace supported: %s' % res)
3175
3176 # what data source are we using
3177 res = 'DMESG'
3178 if(ftgood):
3179 sysvals.usetraceeventsonly = True
3180 sysvals.usetraceevents = False
3181 for e in sysvals.traceevents:
3182 check = False
3183 if(sysvals.android):
3184 out = os.popen(sysvals.adb+' shell ls -d '+\
3185 sysvals.epath+e).read().strip()
3186 if(out == sysvals.epath+e):
3187 check = True
3188 else:
3189 if(os.path.exists(sysvals.epath+e)):
3190 check = True
3191 if(not check):
3192 sysvals.usetraceeventsonly = False
3193 if(e == 'suspend_resume' and check):
3194 sysvals.usetraceevents = True
3195 if(sysvals.usetraceevents and sysvals.usetraceeventsonly):
3196 res = 'FTRACE (all trace events found)'
3197 elif(sysvals.usetraceevents):
3198 res = 'DMESG and FTRACE (suspend_resume trace event found)'
3199 print(' timeline data source: %s' % res)
1301 3200
1302 # check if rtcwake 3201 # check if rtcwake
1303 if(sysvals.rtcwake): 3202 res = 'NO'
1304 check = "YES" 3203 if(sysvals.rtcpath != ''):
1305 version = os.popen("rtcwake -V 2>/dev/null").read() 3204 res = 'YES'
1306 if(not version.startswith("rtcwake")): 3205 elif(sysvals.rtcwake):
1307 if(not dryrun): 3206 status = False
1308 doError("rtcwake is not installed", False) 3207 print(' is rtcwake supported: %s' % res)
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 3208
1324def printHelp(): 3209 return status
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 3210
3211# Function: doError
3212# Description:
3213# generic error function for catastrphic failures
3214# Arguments:
3215# msg: the error message to print
3216# help: True if printHelp should be called after, False otherwise
1356def doError(msg, help): 3217def doError(msg, help):
1357 print("ERROR: %s") % msg
1358 if(help == True): 3218 if(help == True):
1359 printHelp() 3219 printHelp()
3220 print('ERROR: %s\n') % msg
1360 sys.exit() 3221 sys.exit()
1361 3222
1362# -- script main -- 3223# Function: doWarning
1363# loop through the command line arguments 3224# Description:
1364cmd = "" 3225# generic warning function for non-catastrophic anomalies
1365args = iter(sys.argv[1:]) 3226# Arguments:
1366for arg in args: 3227# msg: the warning message to print
1367 if(arg == "-m"): 3228# file: If not empty, a filename to request be sent to the owner for debug
1368 try: 3229def doWarning(msg, file):
1369 val = args.next() 3230 print('/* %s */') % msg
1370 except: 3231 if(file):
1371 doError("No mode supplied", True) 3232 print('/* For a fix, please send this'+\
1372 sysvals.suspendmode = val 3233 ' %s file to <todd.e.brandt@intel.com> */' % file)
1373 elif(arg == "-f"): 3234
1374 data.useftrace = True 3235# Function: rootCheck
1375 elif(arg == "-modes"): 3236# Description:
1376 cmd = "modes" 3237# quick check to see if we have root access
1377 elif(arg == "-status"): 3238def rootCheck():
1378 cmd = "status" 3239 if(os.environ['USER'] != 'root'):
1379 elif(arg == "-verbose"): 3240 doError('This script must be run as root', False)
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 3241
1414data.initialize() 3242# Function: getArgInt
3243# Description:
3244# pull out an integer argument from the command line with checks
3245def getArgInt(name, args, min, max):
3246 try:
3247 arg = args.next()
3248 except:
3249 doError(name+': no argument supplied', True)
3250 try:
3251 val = int(arg)
3252 except:
3253 doError(name+': non-integer value given', True)
3254 if(val < min or val > max):
3255 doError(name+': value should be between %d and %d' % (min, max), True)
3256 return val
3257
3258# Function: rerunTest
3259# Description:
3260# generate an output from an existing set of ftrace/dmesg logs
3261def rerunTest():
3262 global sysvals
1415 3263
1416# if instructed, re-analyze existing data files 3264 if(sysvals.ftracefile != ''):
1417if(data.notestrun): 3265 doesTraceLogHaveTraceEvents()
3266 if(sysvals.dmesgfile == '' and not sysvals.usetraceeventsonly):
3267 doError('recreating this html output '+\
3268 'requires a dmesg file', False)
1418 sysvals.setOutputFile() 3269 sysvals.setOutputFile()
1419 data.vprint("Output file: %s" % sysvals.htmlfile) 3270 vprint('Output file: %s' % sysvals.htmlfile)
1420 if(sysvals.dmesgfile != ""): 3271 print('PROCESSING DATA')
1421 analyzeKernelLog() 3272 if(sysvals.usetraceeventsonly):
1422 if(sysvals.ftracefile != ""): 3273 testruns = parseTraceLog()
1423 analyzeTraceLog() 3274 else:
1424 createHTML() 3275 testruns = loadKernelLog()
1425 sys.exit() 3276 for data in testruns:
3277 parseKernelLog(data)
3278 if(sysvals.ftracefile != ''):
3279 appendIncompleteTraceLog(testruns)
3280 createHTML(testruns)
3281
3282# Function: runTest
3283# Description:
3284# execute a suspend/resume, gather the logs, and generate the output
3285def runTest(subdir):
3286 global sysvals
3287
3288 # prepare for the test
3289 if(not sysvals.android):
3290 initFtrace()
3291 else:
3292 initFtraceAndroid()
3293 sysvals.initTestOutput(subdir)
3294
3295 vprint('Output files:\n %s' % sysvals.dmesgfile)
3296 if(sysvals.usecallgraph or
3297 sysvals.usetraceevents or
3298 sysvals.usetraceeventsonly):
3299 vprint(' %s' % sysvals.ftracefile)
3300 vprint(' %s' % sysvals.htmlfile)
3301
3302 # execute the test
3303 if(not sysvals.android):
3304 executeSuspend()
3305 else:
3306 executeAndroidSuspend()
3307
3308 # analyze the data and create the html output
3309 print('PROCESSING DATA')
3310 if(sysvals.usetraceeventsonly):
3311 # data for kernels 3.15 or newer is entirely in ftrace
3312 testruns = parseTraceLog()
3313 else:
3314 # data for kernels older than 3.15 is primarily in dmesg
3315 testruns = loadKernelLog()
3316 for data in testruns:
3317 parseKernelLog(data)
3318 if(sysvals.usecallgraph or sysvals.usetraceevents):
3319 appendIncompleteTraceLog(testruns)
3320 createHTML(testruns)
3321
3322# Function: runSummary
3323# Description:
3324# create a summary of tests in a sub-directory
3325def runSummary(subdir, output):
3326 global sysvals
3327
3328 # get a list of ftrace output files
3329 files = []
3330 for dirname, dirnames, filenames in os.walk(subdir):
3331 for filename in filenames:
3332 if(re.match('.*_ftrace.txt', filename)):
3333 files.append("%s/%s" % (dirname, filename))
3334
3335 # process the files in order and get an array of data objects
3336 testruns = []
3337 for file in sorted(files):
3338 if output:
3339 print("Test found in %s" % os.path.dirname(file))
3340 sysvals.ftracefile = file
3341 sysvals.dmesgfile = file.replace('_ftrace.txt', '_dmesg.txt')
3342 doesTraceLogHaveTraceEvents()
3343 sysvals.usecallgraph = False
3344 if not sysvals.usetraceeventsonly:
3345 if(not os.path.exists(sysvals.dmesgfile)):
3346 print("Skipping %s: not a valid test input" % file)
3347 continue
3348 else:
3349 if output:
3350 f = os.path.basename(sysvals.ftracefile)
3351 d = os.path.basename(sysvals.dmesgfile)
3352 print("\tInput files: %s and %s" % (f, d))
3353 testdata = loadKernelLog()
3354 data = testdata[0]
3355 parseKernelLog(data)
3356 testdata = [data]
3357 appendIncompleteTraceLog(testdata)
3358 else:
3359 if output:
3360 print("\tInput file: %s" % os.path.basename(sysvals.ftracefile))
3361 testdata = parseTraceLog()
3362 data = testdata[0]
3363 data.normalizeTime(data.tSuspended)
3364 link = file.replace(subdir+'/', '').replace('_ftrace.txt', '.html')
3365 data.outfile = link
3366 testruns.append(data)
3367
3368 createHTMLSummarySimple(testruns, subdir+'/summary.html')
3369
3370# Function: printHelp
3371# Description:
3372# print out the help text
3373def printHelp():
3374 global sysvals
3375 modes = getModes()
3376
3377 print('')
3378 print('AnalyzeSuspend v%.1f' % sysvals.version)
3379 print('Usage: sudo analyze_suspend.py <options>')
3380 print('')
3381 print('Description:')
3382 print(' This tool is designed to assist kernel and OS developers in optimizing')
3383 print(' their linux stack\'s suspend/resume time. Using a kernel image built')
3384 print(' with a few extra options enabled, the tool will execute a suspend and')
3385 print(' capture dmesg and ftrace data until resume is complete. This data is')
3386 print(' transformed into a device timeline and an optional callgraph to give')
3387 print(' a detailed view of which devices/subsystems are taking the most')
3388 print(' time in suspend/resume.')
3389 print('')
3390 print(' Generates output files in subdirectory: suspend-mmddyy-HHMMSS')
3391 print(' HTML output: <hostname>_<mode>.html')
3392 print(' raw dmesg output: <hostname>_<mode>_dmesg.txt')
3393 print(' raw ftrace output: <hostname>_<mode>_ftrace.txt')
3394 print('')
3395 print('Options:')
3396 print(' [general]')
3397 print(' -h Print this help text')
3398 print(' -v Print the current tool version')
3399 print(' -verbose Print extra information during execution and analysis')
3400 print(' -status Test to see if the system is enabled to run this tool')
3401 print(' -modes List available suspend modes')
3402 print(' -m mode Mode to initiate for suspend %s (default: %s)') % (modes, sysvals.suspendmode)
3403 print(' -rtcwake t Use rtcwake to autoresume after <t> seconds (default: disabled)')
3404 print(' [advanced]')
3405 print(' -f Use ftrace to create device callgraphs (default: disabled)')
3406 print(' -filter "d1 d2 ..." Filter out all but this list of dev names')
3407 print(' -x2 Run two suspend/resumes back to back (default: disabled)')
3408 print(' -x2delay t Minimum millisecond delay <t> between the two test runs (default: 0 ms)')
3409 print(' -postres t Time after resume completion to wait for post-resume events (default: 0 S)')
3410 print(' -multi n d Execute <n> consecutive tests at <d> seconds intervals. The outputs will')
3411 print(' be created in a new subdirectory with a summary page.')
3412 print(' [utilities]')
3413 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table')
3414 print(' -usbtopo Print out the current USB topology with power info')
3415 print(' -usbauto Enable autosuspend for all connected USB devices')
3416 print(' [android testing]')
3417 print(' -adb binary Use the given adb binary to run the test on an android device.')
3418 print(' The device should already be connected and with root access.')
3419 print(' Commands will be executed on the device using "adb shell"')
3420 print(' [re-analyze data from previous runs]')
3421 print(' -ftrace ftracefile Create HTML output using ftrace input')
3422 print(' -dmesg dmesgfile Create HTML output using dmesg (not needed for kernel >= 3.15)')
3423 print(' -summary directory Create a summary of all test in this dir')
3424 print('')
3425 return True
1426 3426
1427# verify that we can run a test 3427# ----------------- MAIN --------------------
1428data.usedmesg = True 3428# exec start (skipped if script is loaded as library)
1429statusCheck(False) 3429if __name__ == '__main__':
1430 3430 cmd = ''
1431# prepare for the test 3431 cmdarg = ''
1432if(data.useftrace): 3432 multitest = {'run': False, 'count': 0, 'delay': 0}
1433 initFtrace() 3433 # loop through the command line arguments
1434sysvals.initTestOutput() 3434 args = iter(sys.argv[1:])
1435 3435 for arg in args:
1436data.vprint("Output files:\n %s" % sysvals.dmesgfile) 3436 if(arg == '-m'):
1437if(data.useftrace): 3437 try:
1438 data.vprint(" %s" % sysvals.ftracefile) 3438 val = args.next()
1439data.vprint(" %s" % sysvals.htmlfile) 3439 except:
1440 3440 doError('No mode supplied', True)
1441# execute the test 3441 sysvals.suspendmode = val
1442executeSuspend() 3442 elif(arg == '-adb'):
1443analyzeKernelLog() 3443 try:
1444if(data.useftrace): 3444 val = args.next()
1445 analyzeTraceLog() 3445 except:
1446createHTML() 3446 doError('No adb binary supplied', True)
3447 if(not os.path.exists(val)):
3448 doError('file doesnt exist: %s' % val, False)
3449 if(not os.access(val, os.X_OK)):
3450 doError('file isnt executable: %s' % val, False)
3451 try:
3452 check = os.popen(val+' version').read().strip()
3453 except:
3454 doError('adb version failed to execute', False)
3455 if(not re.match('Android Debug Bridge .*', check)):
3456 doError('adb version failed to execute', False)
3457 sysvals.adb = val
3458 sysvals.android = True
3459 elif(arg == '-x2'):
3460 if(sysvals.postresumetime > 0):
3461 doError('-x2 is not compatible with -postres', False)
3462 sysvals.execcount = 2
3463 elif(arg == '-x2delay'):
3464 sysvals.x2delay = getArgInt('-x2delay', args, 0, 60000)
3465 elif(arg == '-postres'):
3466 if(sysvals.execcount != 1):
3467 doError('-x2 is not compatible with -postres', False)
3468 sysvals.postresumetime = getArgInt('-postres', args, 0, 3600)
3469 elif(arg == '-f'):
3470 sysvals.usecallgraph = True
3471 elif(arg == '-modes'):
3472 cmd = 'modes'
3473 elif(arg == '-fpdt'):
3474 cmd = 'fpdt'
3475 elif(arg == '-usbtopo'):
3476 cmd = 'usbtopo'
3477 elif(arg == '-usbauto'):
3478 cmd = 'usbauto'
3479 elif(arg == '-status'):
3480 cmd = 'status'
3481 elif(arg == '-verbose'):
3482 sysvals.verbose = True
3483 elif(arg == '-v'):
3484 print("Version %.1f" % sysvals.version)
3485 sys.exit()
3486 elif(arg == '-rtcwake'):
3487 sysvals.rtcwake = True
3488 sysvals.rtcwaketime = getArgInt('-rtcwake', args, 0, 3600)
3489 elif(arg == '-multi'):
3490 multitest['run'] = True
3491 multitest['count'] = getArgInt('-multi n (exec count)', args, 2, 1000000)
3492 multitest['delay'] = getArgInt('-multi d (delay between tests)', args, 0, 3600)
3493 elif(arg == '-dmesg'):
3494 try:
3495 val = args.next()
3496 except:
3497 doError('No dmesg file supplied', True)
3498 sysvals.notestrun = True
3499 sysvals.dmesgfile = val
3500 if(os.path.exists(sysvals.dmesgfile) == False):
3501 doError('%s doesnt exist' % sysvals.dmesgfile, False)
3502 elif(arg == '-ftrace'):
3503 try:
3504 val = args.next()
3505 except:
3506 doError('No ftrace file supplied', True)
3507 sysvals.notestrun = True
3508 sysvals.usecallgraph = True
3509 sysvals.ftracefile = val
3510 if(os.path.exists(sysvals.ftracefile) == False):
3511 doError('%s doesnt exist' % sysvals.ftracefile, False)
3512 elif(arg == '-summary'):
3513 try:
3514 val = args.next()
3515 except:
3516 doError('No directory supplied', True)
3517 cmd = 'summary'
3518 cmdarg = val
3519 sysvals.notestrun = True
3520 if(os.path.isdir(val) == False):
3521 doError('%s isnt accesible' % val, False)
3522 elif(arg == '-filter'):
3523 try:
3524 val = args.next()
3525 except:
3526 doError('No devnames supplied', True)
3527 sysvals.setDeviceFilter(val)
3528 elif(arg == '-h'):
3529 printHelp()
3530 sys.exit()
3531 else:
3532 doError('Invalid argument: '+arg, True)
3533
3534 # just run a utility command and exit
3535 if(cmd != ''):
3536 if(cmd == 'status'):
3537 statusCheck()
3538 elif(cmd == 'fpdt'):
3539 if(sysvals.android):
3540 doError('cannot read FPDT on android device', False)
3541 getFPDT(True)
3542 elif(cmd == 'usbtopo'):
3543 if(sysvals.android):
3544 doError('cannot read USB topology '+\
3545 'on an android device', False)
3546 detectUSB(True)
3547 elif(cmd == 'modes'):
3548 modes = getModes()
3549 print modes
3550 elif(cmd == 'usbauto'):
3551 setUSBDevicesAuto()
3552 elif(cmd == 'summary'):
3553 print("Generating a summary of folder \"%s\"" % cmdarg)
3554 runSummary(cmdarg, True)
3555 sys.exit()
3556
3557 # run test on android device
3558 if(sysvals.android):
3559 if(sysvals.usecallgraph):
3560 doError('ftrace (-f) is not yet supported '+\
3561 'in the android kernel', False)
3562 if(sysvals.notestrun):
3563 doError('cannot analyze test files on the '+\
3564 'android device', False)
3565
3566 # if instructed, re-analyze existing data files
3567 if(sysvals.notestrun):
3568 rerunTest()
3569 sys.exit()
3570
3571 # verify that we can run a test
3572 if(not statusCheck()):
3573 print('Check FAILED, aborting the test run!')
3574 sys.exit()
3575
3576 if multitest['run']:
3577 # run multiple tests in a separte subdirectory
3578 s = 'x%d' % multitest['count']
3579 subdir = datetime.now().strftime('suspend-'+s+'-%m%d%y-%H%M%S')
3580 os.mkdir(subdir)
3581 for i in range(multitest['count']):
3582 if(i != 0):
3583 print('Waiting %d seconds...' % (multitest['delay']))
3584 time.sleep(multitest['delay'])
3585 print('TEST (%d/%d) START' % (i+1, multitest['count']))
3586 runTest(subdir)
3587 print('TEST (%d/%d) COMPLETE' % (i+1, multitest['count']))
3588 runSummary(subdir, False)
3589 else:
3590 # run the test in the current directory
3591 runTest(".")
diff --git a/scripts/basic/.gitignore b/scripts/basic/.gitignore
index a776371a3502..9528ec9e5adc 100644
--- a/scripts/basic/.gitignore
+++ b/scripts/basic/.gitignore
@@ -1 +1,2 @@
1fixdep 1fixdep
2bin2c
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
index 4fcef87bb875..ec10d9345bc2 100644
--- a/scripts/basic/Makefile
+++ b/scripts/basic/Makefile
@@ -9,6 +9,7 @@
9# fixdep: Used to generate dependency information during build process 9# fixdep: Used to generate dependency information during build process
10 10
11hostprogs-y := fixdep 11hostprogs-y := fixdep
12hostprogs-$(CONFIG_BUILD_BIN2C) += bin2c
12always := $(hostprogs-y) 13always := $(hostprogs-y)
13 14
14# fixdep is needed to compile other host programs 15# fixdep is needed to compile other host programs
diff --git a/scripts/bin2c.c b/scripts/basic/bin2c.c
index 96dd2bcbb407..af187e695345 100644
--- a/scripts/bin2c.c
+++ b/scripts/basic/bin2c.c
@@ -11,7 +11,7 @@
11 11
12int main(int argc, char *argv[]) 12int main(int argc, char *argv[])
13{ 13{
14 int ch, total=0; 14 int ch, total = 0;
15 15
16 if (argc > 1) 16 if (argc > 1)
17 printf("const char %s[] %s=\n", 17 printf("const char %s[] %s=\n",
@@ -19,10 +19,9 @@ int main(int argc, char *argv[])
19 19
20 do { 20 do {
21 printf("\t\""); 21 printf("\t\"");
22 while ((ch = getchar()) != EOF) 22 while ((ch = getchar()) != EOF) {
23 {
24 total++; 23 total++;
25 printf("\\x%02x",ch); 24 printf("\\x%02x", ch);
26 if (total % 16 == 0) 25 if (total % 16 == 0)
27 break; 26 break;
28 } 27 }
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
index 549d0ab8c662..23e78dcd12bf 100755
--- a/scripts/bloat-o-meter
+++ b/scripts/bloat-o-meter
@@ -20,6 +20,8 @@ def getsizes(file):
20 if type in "tTdDbBrR": 20 if type in "tTdDbBrR":
21 # strip generated symbols 21 # strip generated symbols
22 if name.startswith("__mod_"): continue 22 if name.startswith("__mod_"): continue
23 if name.startswith("SyS_"): continue
24 if name.startswith("compat_SyS_"): continue
23 if name == "linux_banner": continue 25 if name == "linux_banner": continue
24 # statics and some other optimizations adds random .NUMBER 26 # statics and some other optimizations adds random .NUMBER
25 name = re.sub(r'\.[0-9]+', '', name) 27 name = re.sub(r'\.[0-9]+', '', name)
diff --git a/scripts/bootgraph.pl b/scripts/bootgraph.pl
index 9ca667bcaee9..9ca667bcaee9 100644..100755
--- a/scripts/bootgraph.pl
+++ b/scripts/bootgraph.pl
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 182be0f12407..374abf443636 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -9,7 +9,8 @@ use strict;
9use POSIX; 9use POSIX;
10 10
11my $P = $0; 11my $P = $0;
12$P =~ s@.*/@@g; 12$P =~ s@(.*)/@@g;
13my $D = $1;
13 14
14my $V = '0.32'; 15my $V = '0.32';
15 16
@@ -43,6 +44,8 @@ my $configuration_file = ".checkpatch.conf";
43my $max_line_length = 80; 44my $max_line_length = 80;
44my $ignore_perl_version = 0; 45my $ignore_perl_version = 0;
45my $minimum_perl_version = 5.10.0; 46my $minimum_perl_version = 5.10.0;
47my $min_conf_desc_length = 4;
48my $spelling_file = "$D/spelling.txt";
46 49
47sub help { 50sub help {
48 my ($exitcode) = @_; 51 my ($exitcode) = @_;
@@ -63,6 +66,7 @@ Options:
63 --types TYPE(,TYPE2...) show only these comma separated message types 66 --types TYPE(,TYPE2...) show only these comma separated message types
64 --ignore TYPE(,TYPE2...) ignore various comma separated message types 67 --ignore TYPE(,TYPE2...) ignore various comma separated message types
65 --max-line-length=n set the maximum line length, if exceeded, warn 68 --max-line-length=n set the maximum line length, if exceeded, warn
69 --min-conf-desc-length=n set the min description length, if shorter, warn
66 --show-types show the message "types" in the output 70 --show-types show the message "types" in the output
67 --root=PATH PATH to the kernel tree root 71 --root=PATH PATH to the kernel tree root
68 --no-summary suppress the per-file summary 72 --no-summary suppress the per-file summary
@@ -131,6 +135,7 @@ GetOptions(
131 'types=s' => \@use, 135 'types=s' => \@use,
132 'show-types!' => \$show_types, 136 'show-types!' => \$show_types,
133 'max-line-length=i' => \$max_line_length, 137 'max-line-length=i' => \$max_line_length,
138 'min-conf-desc-length=i' => \$min_conf_desc_length,
134 'root=s' => \$root, 139 'root=s' => \$root,
135 'summary!' => \$summary, 140 'summary!' => \$summary,
136 'mailback!' => \$mailback, 141 'mailback!' => \$mailback,
@@ -309,9 +314,12 @@ our $Operators = qr{
309our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; 314our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x;
310 315
311our $NonptrType; 316our $NonptrType;
317our $NonptrTypeMisordered;
312our $NonptrTypeWithAttr; 318our $NonptrTypeWithAttr;
313our $Type; 319our $Type;
320our $TypeMisordered;
314our $Declare; 321our $Declare;
322our $DeclareMisordered;
315 323
316our $NON_ASCII_UTF8 = qr{ 324our $NON_ASCII_UTF8 = qr{
317 [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte 325 [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
@@ -353,16 +361,36 @@ our $signature_tags = qr{(?xi:
353 Cc: 361 Cc:
354)}; 362)};
355 363
364our @typeListMisordered = (
365 qr{char\s+(?:un)?signed},
366 qr{int\s+(?:(?:un)?signed\s+)?short\s},
367 qr{int\s+short(?:\s+(?:un)?signed)},
368 qr{short\s+int(?:\s+(?:un)?signed)},
369 qr{(?:un)?signed\s+int\s+short},
370 qr{short\s+(?:un)?signed},
371 qr{long\s+int\s+(?:un)?signed},
372 qr{int\s+long\s+(?:un)?signed},
373 qr{long\s+(?:un)?signed\s+int},
374 qr{int\s+(?:un)?signed\s+long},
375 qr{int\s+(?:un)?signed},
376 qr{int\s+long\s+long\s+(?:un)?signed},
377 qr{long\s+long\s+int\s+(?:un)?signed},
378 qr{long\s+long\s+(?:un)?signed\s+int},
379 qr{long\s+long\s+(?:un)?signed},
380 qr{long\s+(?:un)?signed},
381);
382
356our @typeList = ( 383our @typeList = (
357 qr{void}, 384 qr{void},
358 qr{(?:unsigned\s+)?char}, 385 qr{(?:(?:un)?signed\s+)?char},
359 qr{(?:unsigned\s+)?short}, 386 qr{(?:(?:un)?signed\s+)?short\s+int},
360 qr{(?:unsigned\s+)?int}, 387 qr{(?:(?:un)?signed\s+)?short},
361 qr{(?:unsigned\s+)?long}, 388 qr{(?:(?:un)?signed\s+)?int},
362 qr{(?:unsigned\s+)?long\s+int}, 389 qr{(?:(?:un)?signed\s+)?long\s+int},
363 qr{(?:unsigned\s+)?long\s+long}, 390 qr{(?:(?:un)?signed\s+)?long\s+long\s+int},
364 qr{(?:unsigned\s+)?long\s+long\s+int}, 391 qr{(?:(?:un)?signed\s+)?long\s+long},
365 qr{unsigned}, 392 qr{(?:(?:un)?signed\s+)?long},
393 qr{(?:un)?signed},
366 qr{float}, 394 qr{float},
367 qr{double}, 395 qr{double},
368 qr{bool}, 396 qr{bool},
@@ -372,6 +400,7 @@ our @typeList = (
372 qr{${Ident}_t}, 400 qr{${Ident}_t},
373 qr{${Ident}_handler}, 401 qr{${Ident}_handler},
374 qr{${Ident}_handler_fn}, 402 qr{${Ident}_handler_fn},
403 @typeListMisordered,
375); 404);
376our @typeListWithAttr = ( 405our @typeListWithAttr = (
377 @typeList, 406 @typeList,
@@ -399,20 +428,41 @@ foreach my $entry (@mode_permission_funcs) {
399 $mode_perms_search .= $entry->[0]; 428 $mode_perms_search .= $entry->[0];
400} 429}
401 430
402our $declaration_macros = qr{(?x:
403 (?:$Storage\s+)?(?:DECLARE|DEFINE)_[A-Z]+\s*\(|
404 (?:$Storage\s+)?LIST_HEAD\s*\(
405)};
406
407our $allowed_asm_includes = qr{(?x: 431our $allowed_asm_includes = qr{(?x:
408 irq| 432 irq|
409 memory 433 memory|
434 time|
435 reboot
410)}; 436)};
411# memory.h: ARM has a custom one 437# memory.h: ARM has a custom one
412 438
439# Load common spelling mistakes and build regular expression list.
440my $misspellings;
441my @spelling_list;
442my %spelling_fix;
443open(my $spelling, '<', $spelling_file)
444 or die "$P: Can't open $spelling_file for reading: $!\n";
445while (<$spelling>) {
446 my $line = $_;
447
448 $line =~ s/\s*\n?$//g;
449 $line =~ s/^\s*//g;
450
451 next if ($line =~ m/^\s*#/);
452 next if ($line =~ m/^\s*$/);
453
454 my ($suspect, $fix) = split(/\|\|/, $line);
455
456 push(@spelling_list, $suspect);
457 $spelling_fix{$suspect} = $fix;
458}
459close($spelling);
460$misspellings = join("|", @spelling_list);
461
413sub build_types { 462sub build_types {
414 my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)"; 463 my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)";
415 my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)"; 464 my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)";
465 my $Misordered = "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)";
416 my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)"; 466 my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)";
417 $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; 467 $Modifier = qr{(?:$Attribute|$Sparse|$mods)};
418 $NonptrType = qr{ 468 $NonptrType = qr{
@@ -424,6 +474,13 @@ sub build_types {
424 ) 474 )
425 (?:\s+$Modifier|\s+const)* 475 (?:\s+$Modifier|\s+const)*
426 }x; 476 }x;
477 $NonptrTypeMisordered = qr{
478 (?:$Modifier\s+|const\s+)*
479 (?:
480 (?:${Misordered}\b)
481 )
482 (?:\s+$Modifier|\s+const)*
483 }x;
427 $NonptrTypeWithAttr = qr{ 484 $NonptrTypeWithAttr = qr{
428 (?:$Modifier\s+|const\s+)* 485 (?:$Modifier\s+|const\s+)*
429 (?: 486 (?:
@@ -435,10 +492,16 @@ sub build_types {
435 }x; 492 }x;
436 $Type = qr{ 493 $Type = qr{
437 $NonptrType 494 $NonptrType
438 (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*|\[\])+|(?:\s*\[\s*\])+)? 495 (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)?
496 (?:\s+$Inline|\s+$Modifier)*
497 }x;
498 $TypeMisordered = qr{
499 $NonptrTypeMisordered
500 (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)?
439 (?:\s+$Inline|\s+$Modifier)* 501 (?:\s+$Inline|\s+$Modifier)*
440 }x; 502 }x;
441 $Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type}; 503 $Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type};
504 $DeclareMisordered = qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered};
442} 505}
443build_types(); 506build_types();
444 507
@@ -452,6 +515,12 @@ our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/;
452our $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*}; 515our $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*};
453our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant)}; 516our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant)};
454 517
518our $declaration_macros = qr{(?x:
519 (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,2}\s*\(|
520 (?:$Storage\s+)?LIST_HEAD\s*\(|
521 (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\(
522)};
523
455sub deparenthesize { 524sub deparenthesize {
456 my ($string) = @_; 525 my ($string) = @_;
457 return "" if (!defined($string)); 526 return "" if (!defined($string));
@@ -550,11 +619,43 @@ sub seed_camelcase_includes {
550 } 619 }
551} 620}
552 621
622sub git_commit_info {
623 my ($commit, $id, $desc) = @_;
624
625 return ($id, $desc) if ((which("git") eq "") || !(-e ".git"));
626
627 my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`;
628 $output =~ s/^\s*//gm;
629 my @lines = split("\n", $output);
630
631 if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) {
632# Maybe one day convert this block of bash into something that returns
633# all matching commit ids, but it's very slow...
634#
635# echo "checking commits $1..."
636# git rev-list --remotes | grep -i "^$1" |
637# while read line ; do
638# git log --format='%H %s' -1 $line |
639# echo "commit $(cut -c 1-12,41-)"
640# done
641 } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) {
642 } else {
643 $id = substr($lines[0], 0, 12);
644 $desc = substr($lines[0], 41);
645 }
646
647 return ($id, $desc);
648}
649
553$chk_signoff = 0 if ($file); 650$chk_signoff = 0 if ($file);
554 651
555my @rawlines = (); 652my @rawlines = ();
556my @lines = (); 653my @lines = ();
557my @fixed = (); 654my @fixed = ();
655my @fixed_inserted = ();
656my @fixed_deleted = ();
657my $fixlinenr = -1;
658
558my $vname; 659my $vname;
559for my $filename (@ARGV) { 660for my $filename (@ARGV) {
560 my $FILE; 661 my $FILE;
@@ -583,6 +684,9 @@ for my $filename (@ARGV) {
583 @rawlines = (); 684 @rawlines = ();
584 @lines = (); 685 @lines = ();
585 @fixed = (); 686 @fixed = ();
687 @fixed_inserted = ();
688 @fixed_deleted = ();
689 $fixlinenr = -1;
586} 690}
587 691
588exit($exit); 692exit($exit);
@@ -674,6 +778,18 @@ sub format_email {
674 return $formatted_email; 778 return $formatted_email;
675} 779}
676 780
781sub which {
782 my ($bin) = @_;
783
784 foreach my $path (split(/:/, $ENV{PATH})) {
785 if (-e "$path/$bin") {
786 return "$path/$bin";
787 }
788 }
789
790 return "";
791}
792
677sub which_conf { 793sub which_conf {
678 my ($conf) = @_; 794 my ($conf) = @_;
679 795
@@ -1483,6 +1599,90 @@ sub report_dump {
1483 our @report; 1599 our @report;
1484} 1600}
1485 1601
1602sub fixup_current_range {
1603 my ($lineRef, $offset, $length) = @_;
1604
1605 if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) {
1606 my $o = $1;
1607 my $l = $2;
1608 my $no = $o + $offset;
1609 my $nl = $l + $length;
1610 $$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/;
1611 }
1612}
1613
1614sub fix_inserted_deleted_lines {
1615 my ($linesRef, $insertedRef, $deletedRef) = @_;
1616
1617 my $range_last_linenr = 0;
1618 my $delta_offset = 0;
1619
1620 my $old_linenr = 0;
1621 my $new_linenr = 0;
1622
1623 my $next_insert = 0;
1624 my $next_delete = 0;
1625
1626 my @lines = ();
1627
1628 my $inserted = @{$insertedRef}[$next_insert++];
1629 my $deleted = @{$deletedRef}[$next_delete++];
1630
1631 foreach my $old_line (@{$linesRef}) {
1632 my $save_line = 1;
1633 my $line = $old_line; #don't modify the array
1634 if ($line =~ /^(?:\+\+\+\|\-\-\-)\s+\S+/) { #new filename
1635 $delta_offset = 0;
1636 } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk
1637 $range_last_linenr = $new_linenr;
1638 fixup_current_range(\$line, $delta_offset, 0);
1639 }
1640
1641 while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) {
1642 $deleted = @{$deletedRef}[$next_delete++];
1643 $save_line = 0;
1644 fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1);
1645 }
1646
1647 while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) {
1648 push(@lines, ${$inserted}{'LINE'});
1649 $inserted = @{$insertedRef}[$next_insert++];
1650 $new_linenr++;
1651 fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1);
1652 }
1653
1654 if ($save_line) {
1655 push(@lines, $line);
1656 $new_linenr++;
1657 }
1658
1659 $old_linenr++;
1660 }
1661
1662 return @lines;
1663}
1664
1665sub fix_insert_line {
1666 my ($linenr, $line) = @_;
1667
1668 my $inserted = {
1669 LINENR => $linenr,
1670 LINE => $line,
1671 };
1672 push(@fixed_inserted, $inserted);
1673}
1674
1675sub fix_delete_line {
1676 my ($linenr, $line) = @_;
1677
1678 my $deleted = {
1679 LINENR => $linenr,
1680 LINE => $line,
1681 };
1682
1683 push(@fixed_deleted, $deleted);
1684}
1685
1486sub ERROR { 1686sub ERROR {
1487 my ($type, $msg) = @_; 1687 my ($type, $msg) = @_;
1488 1688
@@ -1637,11 +1837,13 @@ sub process {
1637 my $signoff = 0; 1837 my $signoff = 0;
1638 my $is_patch = 0; 1838 my $is_patch = 0;
1639 1839
1640 my $in_header_lines = 1; 1840 my $in_header_lines = $file ? 0 : 1;
1641 my $in_commit_log = 0; #Scanning lines before patch 1841 my $in_commit_log = 0; #Scanning lines before patch
1642 1842 my $reported_maintainer_file = 0;
1643 my $non_utf8_charset = 0; 1843 my $non_utf8_charset = 0;
1644 1844
1845 my $last_blank_line = 0;
1846
1645 our @report = (); 1847 our @report = ();
1646 our $cnt_lines = 0; 1848 our $cnt_lines = 0;
1647 our $cnt_error = 0; 1849 our $cnt_error = 0;
@@ -1759,8 +1961,10 @@ sub process {
1759 1961
1760 $realcnt = 0; 1962 $realcnt = 0;
1761 $linenr = 0; 1963 $linenr = 0;
1964 $fixlinenr = -1;
1762 foreach my $line (@lines) { 1965 foreach my $line (@lines) {
1763 $linenr++; 1966 $linenr++;
1967 $fixlinenr++;
1764 my $sline = $line; #copy of $line 1968 my $sline = $line; #copy of $line
1765 $sline =~ s/$;/ /g; #with comments as spaces 1969 $sline =~ s/$;/ /g; #with comments as spaces
1766 1970
@@ -1891,7 +2095,7 @@ sub process {
1891 if (WARN("BAD_SIGN_OFF", 2095 if (WARN("BAD_SIGN_OFF",
1892 "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) && 2096 "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) &&
1893 $fix) { 2097 $fix) {
1894 $fixed[$linenr - 1] = 2098 $fixed[$fixlinenr] =
1895 "$ucfirst_sign_off $email"; 2099 "$ucfirst_sign_off $email";
1896 } 2100 }
1897 } 2101 }
@@ -1899,7 +2103,7 @@ sub process {
1899 if (WARN("BAD_SIGN_OFF", 2103 if (WARN("BAD_SIGN_OFF",
1900 "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) && 2104 "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) &&
1901 $fix) { 2105 $fix) {
1902 $fixed[$linenr - 1] = 2106 $fixed[$fixlinenr] =
1903 "$ucfirst_sign_off $email"; 2107 "$ucfirst_sign_off $email";
1904 } 2108 }
1905 2109
@@ -1908,7 +2112,7 @@ sub process {
1908 if (WARN("BAD_SIGN_OFF", 2112 if (WARN("BAD_SIGN_OFF",
1909 "Use a single space after $ucfirst_sign_off\n" . $herecurr) && 2113 "Use a single space after $ucfirst_sign_off\n" . $herecurr) &&
1910 $fix) { 2114 $fix) {
1911 $fixed[$linenr - 1] = 2115 $fixed[$fixlinenr] =
1912 "$ucfirst_sign_off $email"; 2116 "$ucfirst_sign_off $email";
1913 } 2117 }
1914 } 2118 }
@@ -1956,6 +2160,34 @@ sub process {
1956 "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr); 2160 "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr);
1957 } 2161 }
1958 2162
2163# Check for improperly formed commit descriptions
2164 if ($in_commit_log &&
2165 $line =~ /\bcommit\s+[0-9a-f]{5,}/i &&
2166 !($line =~ /\b[Cc]ommit [0-9a-f]{12,40} \("/ ||
2167 ($line =~ /\b[Cc]ommit [0-9a-f]{12,40}\s*$/ &&
2168 defined $rawlines[$linenr] &&
2169 $rawlines[$linenr] =~ /^\s*\("/))) {
2170 $line =~ /\b(c)ommit\s+([0-9a-f]{5,})/i;
2171 my $init_char = $1;
2172 my $orig_commit = lc($2);
2173 my $id = '01234567890ab';
2174 my $desc = 'commit description';
2175 ($id, $desc) = git_commit_info($orig_commit, $id, $desc);
2176 ERROR("GIT_COMMIT_ID",
2177 "Please use 12 or more chars for the git commit ID like: '${init_char}ommit $id (\"$desc\")'\n" . $herecurr);
2178 }
2179
2180# Check for added, moved or deleted files
2181 if (!$reported_maintainer_file && !$in_commit_log &&
2182 ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ ||
2183 $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ ||
2184 ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ &&
2185 (defined($1) || defined($2))))) {
2186 $reported_maintainer_file = 1;
2187 WARN("FILE_PATH_CHANGES",
2188 "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
2189 }
2190
1959# Check for wrappage within a valid hunk of the file 2191# Check for wrappage within a valid hunk of the file
1960 if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { 2192 if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
1961 ERROR("CORRUPTED_PATCH", 2193 ERROR("CORRUPTED_PATCH",
@@ -1993,7 +2225,8 @@ sub process {
1993# Check if it's the start of a commit log 2225# Check if it's the start of a commit log
1994# (not a header line and we haven't seen the patch filename) 2226# (not a header line and we haven't seen the patch filename)
1995 if ($in_header_lines && $realfile =~ /^$/ && 2227 if ($in_header_lines && $realfile =~ /^$/ &&
1996 $rawline !~ /^(commit\b|from\b|[\w-]+:).+$/i) { 2228 !($rawline =~ /^\s+\S/ ||
2229 $rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) {
1997 $in_header_lines = 0; 2230 $in_header_lines = 0;
1998 $in_commit_log = 1; 2231 $in_commit_log = 1;
1999 } 2232 }
@@ -2012,6 +2245,23 @@ sub process {
2012 "8-bit UTF-8 used in possible commit log\n" . $herecurr); 2245 "8-bit UTF-8 used in possible commit log\n" . $herecurr);
2013 } 2246 }
2014 2247
2248# Check for various typo / spelling mistakes
2249 if ($in_commit_log || $line =~ /^\+/) {
2250 while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:$|[^a-z@])/gi) {
2251 my $typo = $1;
2252 my $typo_fix = $spelling_fix{lc($typo)};
2253 $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
2254 $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/);
2255 my $msg_type = \&WARN;
2256 $msg_type = \&CHK if ($file);
2257 if (&{$msg_type}("TYPO_SPELLING",
2258 "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) &&
2259 $fix) {
2260 $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/;
2261 }
2262 }
2263 }
2264
2015# ignore non-hunk lines and lines being removed 2265# ignore non-hunk lines and lines being removed
2016 next if (!$hunk_line || $line =~ /^-/); 2266 next if (!$hunk_line || $line =~ /^-/);
2017 2267
@@ -2021,14 +2271,14 @@ sub process {
2021 if (ERROR("DOS_LINE_ENDINGS", 2271 if (ERROR("DOS_LINE_ENDINGS",
2022 "DOS line endings\n" . $herevet) && 2272 "DOS line endings\n" . $herevet) &&
2023 $fix) { 2273 $fix) {
2024 $fixed[$linenr - 1] =~ s/[\s\015]+$//; 2274 $fixed[$fixlinenr] =~ s/[\s\015]+$//;
2025 } 2275 }
2026 } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { 2276 } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
2027 my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 2277 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
2028 if (ERROR("TRAILING_WHITESPACE", 2278 if (ERROR("TRAILING_WHITESPACE",
2029 "trailing whitespace\n" . $herevet) && 2279 "trailing whitespace\n" . $herevet) &&
2030 $fix) { 2280 $fix) {
2031 $fixed[$linenr - 1] =~ s/\s+$//; 2281 $fixed[$fixlinenr] =~ s/\s+$//;
2032 } 2282 }
2033 2283
2034 $rpt_cleaners = 1; 2284 $rpt_cleaners = 1;
@@ -2049,7 +2299,7 @@ sub process {
2049# Only applies when adding the entry originally, after that we do not have 2299# Only applies when adding the entry originally, after that we do not have
2050# sufficient context to determine whether it is indeed long enough. 2300# sufficient context to determine whether it is indeed long enough.
2051 if ($realfile =~ /Kconfig/ && 2301 if ($realfile =~ /Kconfig/ &&
2052 $line =~ /.\s*config\s+/) { 2302 $line =~ /^\+\s*config\s+/) {
2053 my $length = 0; 2303 my $length = 0;
2054 my $cnt = $realcnt; 2304 my $cnt = $realcnt;
2055 my $ln = $linenr + 1; 2305 my $ln = $linenr + 1;
@@ -2062,10 +2312,11 @@ sub process {
2062 $is_end = $lines[$ln - 1] =~ /^\+/; 2312 $is_end = $lines[$ln - 1] =~ /^\+/;
2063 2313
2064 next if ($f =~ /^-/); 2314 next if ($f =~ /^-/);
2315 last if (!$file && $f =~ /^\@\@/);
2065 2316
2066 if ($lines[$ln - 1] =~ /.\s*(?:bool|tristate)\s*\"/) { 2317 if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate)\s*\"/) {
2067 $is_start = 1; 2318 $is_start = 1;
2068 } elsif ($lines[$ln - 1] =~ /.\s*(?:---)?help(?:---)?$/) { 2319 } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) {
2069 $length = -1; 2320 $length = -1;
2070 } 2321 }
2071 2322
@@ -2079,8 +2330,10 @@ sub process {
2079 } 2330 }
2080 $length++; 2331 $length++;
2081 } 2332 }
2082 WARN("CONFIG_DESCRIPTION", 2333 if ($is_start && $is_end && $length < $min_conf_desc_length) {
2083 "please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_start && $is_end && $length < 4); 2334 WARN("CONFIG_DESCRIPTION",
2335 "please write a paragraph that describes the config symbol fully\n" . $herecurr);
2336 }
2084 #print "is_start<$is_start> is_end<$is_end> length<$length>\n"; 2337 #print "is_start<$is_start> is_end<$is_end> length<$length>\n";
2085 } 2338 }
2086 2339
@@ -2137,7 +2390,7 @@ sub process {
2137 } 2390 }
2138 2391
2139# check we are in a valid source file if not then ignore this hunk 2392# check we are in a valid source file if not then ignore this hunk
2140 next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/); 2393 next if ($realfile !~ /\.(h|c|s|S|pl|sh|dtsi|dts)$/);
2141 2394
2142#line length limit 2395#line length limit
2143 if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ && 2396 if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
@@ -2161,12 +2414,18 @@ sub process {
2161 "quoted string split across lines\n" . $hereprev); 2414 "quoted string split across lines\n" . $hereprev);
2162 } 2415 }
2163 2416
2417# check for missing a space in a string concatination
2418 if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) {
2419 WARN('MISSING_SPACE',
2420 "break quoted strings at a space character\n" . $hereprev);
2421 }
2422
2164# check for spaces before a quoted newline 2423# check for spaces before a quoted newline
2165 if ($rawline =~ /^.*\".*\s\\n/) { 2424 if ($rawline =~ /^.*\".*\s\\n/) {
2166 if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", 2425 if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE",
2167 "unnecessary whitespace before a quoted newline\n" . $herecurr) && 2426 "unnecessary whitespace before a quoted newline\n" . $herecurr) &&
2168 $fix) { 2427 $fix) {
2169 $fixed[$linenr - 1] =~ s/^(\+.*\".*)\s+\\n/$1\\n/; 2428 $fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/;
2170 } 2429 }
2171 2430
2172 } 2431 }
@@ -2192,7 +2451,7 @@ sub process {
2192 } 2451 }
2193 2452
2194# check we are in a valid source file C or perl if not then ignore this hunk 2453# check we are in a valid source file C or perl if not then ignore this hunk
2195 next if ($realfile !~ /\.(h|c|pl)$/); 2454 next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/);
2196 2455
2197# at the beginning of a line any tabs must come first and anything 2456# at the beginning of a line any tabs must come first and anything
2198# more than 8 must use tabs. 2457# more than 8 must use tabs.
@@ -2203,7 +2462,7 @@ sub process {
2203 if (ERROR("CODE_INDENT", 2462 if (ERROR("CODE_INDENT",
2204 "code indent should use tabs where possible\n" . $herevet) && 2463 "code indent should use tabs where possible\n" . $herevet) &&
2205 $fix) { 2464 $fix) {
2206 $fixed[$linenr - 1] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; 2465 $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
2207 } 2466 }
2208 } 2467 }
2209 2468
@@ -2213,9 +2472,9 @@ sub process {
2213 if (WARN("SPACE_BEFORE_TAB", 2472 if (WARN("SPACE_BEFORE_TAB",
2214 "please, no space before tabs\n" . $herevet) && 2473 "please, no space before tabs\n" . $herevet) &&
2215 $fix) { 2474 $fix) {
2216 while ($fixed[$linenr - 1] =~ 2475 while ($fixed[$fixlinenr] =~
2217 s/(^\+.*) {8,8}+\t/$1\t\t/) {} 2476 s/(^\+.*) {8,8}\t/$1\t\t/) {}
2218 while ($fixed[$linenr - 1] =~ 2477 while ($fixed[$fixlinenr] =~
2219 s/(^\+.*) +\t/$1\t/) {} 2478 s/(^\+.*) +\t/$1\t/) {}
2220 } 2479 }
2221 } 2480 }
@@ -2249,19 +2508,19 @@ sub process {
2249 if (CHK("PARENTHESIS_ALIGNMENT", 2508 if (CHK("PARENTHESIS_ALIGNMENT",
2250 "Alignment should match open parenthesis\n" . $hereprev) && 2509 "Alignment should match open parenthesis\n" . $hereprev) &&
2251 $fix && $line =~ /^\+/) { 2510 $fix && $line =~ /^\+/) {
2252 $fixed[$linenr - 1] =~ 2511 $fixed[$fixlinenr] =~
2253 s/^\+[ \t]*/\+$goodtabindent/; 2512 s/^\+[ \t]*/\+$goodtabindent/;
2254 } 2513 }
2255 } 2514 }
2256 } 2515 }
2257 } 2516 }
2258 2517
2259 if ($line =~ /^\+.*\*[ \t]*\)[ \t]+(?!$Assignment|$Arithmetic)/) { 2518 if ($line =~ /^\+.*\(\s*$Type\s*\)[ \t]+(?!$Assignment|$Arithmetic|{)/) {
2260 if (CHK("SPACING", 2519 if (CHK("SPACING",
2261 "No space is necessary after a cast\n" . $hereprev) && 2520 "No space is necessary after a cast\n" . $herecurr) &&
2262 $fix) { 2521 $fix) {
2263 $fixed[$linenr - 1] =~ 2522 $fixed[$fixlinenr] =~
2264 s/^(\+.*\*[ \t]*\))[ \t]+/$1/; 2523 s/(\(\s*$Type\s*\))[ \t]+/$1/;
2265 } 2524 }
2266 } 2525 }
2267 2526
@@ -2291,10 +2550,44 @@ sub process {
2291 "networking block comments put the trailing */ on a separate line\n" . $herecurr); 2550 "networking block comments put the trailing */ on a separate line\n" . $herecurr);
2292 } 2551 }
2293 2552
2553# check for missing blank lines after struct/union declarations
2554# with exceptions for various attributes and macros
2555 if ($prevline =~ /^[\+ ]};?\s*$/ &&
2556 $line =~ /^\+/ &&
2557 !($line =~ /^\+\s*$/ ||
2558 $line =~ /^\+\s*EXPORT_SYMBOL/ ||
2559 $line =~ /^\+\s*MODULE_/i ||
2560 $line =~ /^\+\s*\#\s*(?:end|elif|else)/ ||
2561 $line =~ /^\+[a-z_]*init/ ||
2562 $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ ||
2563 $line =~ /^\+\s*DECLARE/ ||
2564 $line =~ /^\+\s*__setup/)) {
2565 if (CHK("LINE_SPACING",
2566 "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) &&
2567 $fix) {
2568 fix_insert_line($fixlinenr, "\+");
2569 }
2570 }
2571
2572# check for multiple consecutive blank lines
2573 if ($prevline =~ /^[\+ ]\s*$/ &&
2574 $line =~ /^\+\s*$/ &&
2575 $last_blank_line != ($linenr - 1)) {
2576 if (CHK("LINE_SPACING",
2577 "Please don't use multiple blank lines\n" . $hereprev) &&
2578 $fix) {
2579 fix_delete_line($fixlinenr, $rawline);
2580 }
2581
2582 $last_blank_line = $linenr;
2583 }
2584
2294# check for missing blank lines after declarations 2585# check for missing blank lines after declarations
2295 if ($sline =~ /^\+\s+\S/ && #Not at char 1 2586 if ($sline =~ /^\+\s+\S/ && #Not at char 1
2296 # actual declarations 2587 # actual declarations
2297 ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || 2588 ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
2589 # function pointer declarations
2590 $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
2298 # foo bar; where foo is some local typedef or #define 2591 # foo bar; where foo is some local typedef or #define
2299 $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || 2592 $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
2300 # known declaration macros 2593 # known declaration macros
@@ -2307,6 +2600,8 @@ sub process {
2307 $prevline =~ /(?:\{\s*|\\)$/) && 2600 $prevline =~ /(?:\{\s*|\\)$/) &&
2308 # looks like a declaration 2601 # looks like a declaration
2309 !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || 2602 !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
2603 # function pointer declarations
2604 $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
2310 # foo bar; where foo is some local typedef or #define 2605 # foo bar; where foo is some local typedef or #define
2311 $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || 2606 $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
2312 # known declaration macros 2607 # known declaration macros
@@ -2321,8 +2616,11 @@ sub process {
2321 $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) && 2616 $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) &&
2322 # indentation of previous and current line are the same 2617 # indentation of previous and current line are the same
2323 (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) { 2618 (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) {
2324 WARN("SPACING", 2619 if (WARN("LINE_SPACING",
2325 "Missing a blank line after declarations\n" . $hereprev); 2620 "Missing a blank line after declarations\n" . $hereprev) &&
2621 $fix) {
2622 fix_insert_line($fixlinenr, "\+");
2623 }
2326 } 2624 }
2327 2625
2328# check for spaces at the beginning of a line. 2626# check for spaces at the beginning of a line.
@@ -2335,13 +2633,37 @@ sub process {
2335 if (WARN("LEADING_SPACE", 2633 if (WARN("LEADING_SPACE",
2336 "please, no spaces at the start of a line\n" . $herevet) && 2634 "please, no spaces at the start of a line\n" . $herevet) &&
2337 $fix) { 2635 $fix) {
2338 $fixed[$linenr - 1] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; 2636 $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
2339 } 2637 }
2340 } 2638 }
2341 2639
2342# check we are in a valid C source file if not then ignore this hunk 2640# check we are in a valid C source file if not then ignore this hunk
2343 next if ($realfile !~ /\.(h|c)$/); 2641 next if ($realfile !~ /\.(h|c)$/);
2344 2642
2643# check indentation of any line with a bare else
2644# (but not if it is a multiple line "if (foo) return bar; else return baz;")
2645# if the previous line is a break or return and is indented 1 tab more...
2646 if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) {
2647 my $tabs = length($1) + 1;
2648 if ($prevline =~ /^\+\t{$tabs,$tabs}break\b/ ||
2649 ($prevline =~ /^\+\t{$tabs,$tabs}return\b/ &&
2650 defined $lines[$linenr] &&
2651 $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) {
2652 WARN("UNNECESSARY_ELSE",
2653 "else is not generally useful after a break or return\n" . $hereprev);
2654 }
2655 }
2656
2657# check indentation of a line with a break;
2658# if the previous line is a goto or return and is indented the same # of tabs
2659 if ($sline =~ /^\+([\t]+)break\s*;\s*$/) {
2660 my $tabs = $1;
2661 if ($prevline =~ /^\+$tabs(?:goto|return)\b/) {
2662 WARN("UNNECESSARY_BREAK",
2663 "break is not useful after a goto or return\n" . $hereprev);
2664 }
2665 }
2666
2345# discourage the addition of CONFIG_EXPERIMENTAL in #if(def). 2667# discourage the addition of CONFIG_EXPERIMENTAL in #if(def).
2346 if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) { 2668 if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) {
2347 WARN("CONFIG_EXPERIMENTAL", 2669 WARN("CONFIG_EXPERIMENTAL",
@@ -2477,7 +2799,7 @@ sub process {
2477 2799
2478# if/while/etc brace do not go on next line, unless defining a do while loop, 2800# if/while/etc brace do not go on next line, unless defining a do while loop,
2479# or if that brace on the next line is for something else 2801# or if that brace on the next line is for something else
2480 if ($line =~ /(.*)\b((?:if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) { 2802 if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) {
2481 my $pre_ctx = "$1$2"; 2803 my $pre_ctx = "$1$2";
2482 2804
2483 my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); 2805 my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
@@ -2504,7 +2826,7 @@ sub process {
2504 #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n"; 2826 #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
2505 #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n"; 2827 #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
2506 2828
2507 if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { 2829 if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
2508 ERROR("OPEN_BRACE", 2830 ERROR("OPEN_BRACE",
2509 "that open brace { should be on the previous line\n" . 2831 "that open brace { should be on the previous line\n" .
2510 "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); 2832 "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
@@ -2523,7 +2845,7 @@ sub process {
2523 } 2845 }
2524 2846
2525# Check relative indent for conditionals and blocks. 2847# Check relative indent for conditionals and blocks.
2526 if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { 2848 if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
2527 ($stat, $cond, $line_nr_next, $remain_next, $off_next) = 2849 ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
2528 ctx_statement_block($linenr, $realcnt, 0) 2850 ctx_statement_block($linenr, $realcnt, 0)
2529 if (!defined $stat); 2851 if (!defined $stat);
@@ -2654,8 +2976,18 @@ sub process {
2654# check for initialisation to aggregates open brace on the next line 2976# check for initialisation to aggregates open brace on the next line
2655 if ($line =~ /^.\s*{/ && 2977 if ($line =~ /^.\s*{/ &&
2656 $prevline =~ /(?:^|[^=])=\s*$/) { 2978 $prevline =~ /(?:^|[^=])=\s*$/) {
2657 ERROR("OPEN_BRACE", 2979 if (ERROR("OPEN_BRACE",
2658 "that open brace { should be on the previous line\n" . $hereprev); 2980 "that open brace { should be on the previous line\n" . $hereprev) &&
2981 $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
2982 fix_delete_line($fixlinenr - 1, $prevrawline);
2983 fix_delete_line($fixlinenr, $rawline);
2984 my $fixedline = $prevrawline;
2985 $fixedline =~ s/\s*=\s*$/ = {/;
2986 fix_insert_line($fixlinenr, $fixedline);
2987 $fixedline = $line;
2988 $fixedline =~ s/^(.\s*){\s*/$1/;
2989 fix_insert_line($fixlinenr, $fixedline);
2990 }
2659 } 2991 }
2660 2992
2661# 2993#
@@ -2680,10 +3012,10 @@ sub process {
2680 if (ERROR("C99_COMMENTS", 3012 if (ERROR("C99_COMMENTS",
2681 "do not use C99 // comments\n" . $herecurr) && 3013 "do not use C99 // comments\n" . $herecurr) &&
2682 $fix) { 3014 $fix) {
2683 my $line = $fixed[$linenr - 1]; 3015 my $line = $fixed[$fixlinenr];
2684 if ($line =~ /\/\/(.*)$/) { 3016 if ($line =~ /\/\/(.*)$/) {
2685 my $comment = trim($1); 3017 my $comment = trim($1);
2686 $fixed[$linenr - 1] =~ s@\/\/(.*)$@/\* $comment \*/@; 3018 $fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@;
2687 } 3019 }
2688 } 3020 }
2689 } 3021 }
@@ -2742,7 +3074,7 @@ sub process {
2742 "do not initialise globals to 0 or NULL\n" . 3074 "do not initialise globals to 0 or NULL\n" .
2743 $herecurr) && 3075 $herecurr) &&
2744 $fix) { 3076 $fix) {
2745 $fixed[$linenr - 1] =~ s/($Type\s*$Ident\s*(?:\s+$Modifier))*\s*=\s*(0|NULL|false)\s*;/$1;/; 3077 $fixed[$fixlinenr] =~ s/($Type\s*$Ident\s*(?:\s+$Modifier))*\s*=\s*(0|NULL|false)\s*;/$1;/;
2746 } 3078 }
2747 } 3079 }
2748# check for static initialisers. 3080# check for static initialisers.
@@ -2751,10 +3083,17 @@ sub process {
2751 "do not initialise statics to 0 or NULL\n" . 3083 "do not initialise statics to 0 or NULL\n" .
2752 $herecurr) && 3084 $herecurr) &&
2753 $fix) { 3085 $fix) {
2754 $fixed[$linenr - 1] =~ s/(\bstatic\s.*?)\s*=\s*(0|NULL|false)\s*;/$1;/; 3086 $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*(0|NULL|false)\s*;/$1;/;
2755 } 3087 }
2756 } 3088 }
2757 3089
3090# check for misordered declarations of char/short/int/long with signed/unsigned
3091 while ($sline =~ m{(\b$TypeMisordered\b)}g) {
3092 my $tmp = trim($1);
3093 WARN("MISORDERED_TYPE",
3094 "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr);
3095 }
3096
2758# check for static const char * arrays. 3097# check for static const char * arrays.
2759 if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) { 3098 if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
2760 WARN("STATIC_CONST_CHAR_ARRAY", 3099 WARN("STATIC_CONST_CHAR_ARRAY",
@@ -2781,7 +3120,7 @@ sub process {
2781 if (ERROR("FUNCTION_WITHOUT_ARGS", 3120 if (ERROR("FUNCTION_WITHOUT_ARGS",
2782 "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) && 3121 "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) &&
2783 $fix) { 3122 $fix) {
2784 $fixed[$linenr - 1] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/; 3123 $fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/;
2785 } 3124 }
2786 } 3125 }
2787 3126
@@ -2790,7 +3129,7 @@ sub process {
2790 if (WARN("DEFINE_PCI_DEVICE_TABLE", 3129 if (WARN("DEFINE_PCI_DEVICE_TABLE",
2791 "Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) && 3130 "Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) &&
2792 $fix) { 3131 $fix) {
2793 $fixed[$linenr - 1] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /; 3132 $fixed[$fixlinenr] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /;
2794 } 3133 }
2795 } 3134 }
2796 3135
@@ -2827,7 +3166,7 @@ sub process {
2827 my $sub_from = $ident; 3166 my $sub_from = $ident;
2828 my $sub_to = $ident; 3167 my $sub_to = $ident;
2829 $sub_to =~ s/\Q$from\E/$to/; 3168 $sub_to =~ s/\Q$from\E/$to/;
2830 $fixed[$linenr - 1] =~ 3169 $fixed[$fixlinenr] =~
2831 s@\Q$sub_from\E@$sub_to@; 3170 s@\Q$sub_from\E@$sub_to@;
2832 } 3171 }
2833 } 3172 }
@@ -2855,7 +3194,7 @@ sub process {
2855 my $sub_from = $match; 3194 my $sub_from = $match;
2856 my $sub_to = $match; 3195 my $sub_to = $match;
2857 $sub_to =~ s/\Q$from\E/$to/; 3196 $sub_to =~ s/\Q$from\E/$to/;
2858 $fixed[$linenr - 1] =~ 3197 $fixed[$fixlinenr] =~
2859 s@\Q$sub_from\E@$sub_to@; 3198 s@\Q$sub_from\E@$sub_to@;
2860 } 3199 }
2861 } 3200 }
@@ -2917,7 +3256,7 @@ sub process {
2917 if (WARN("PREFER_PR_LEVEL", 3256 if (WARN("PREFER_PR_LEVEL",
2918 "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) && 3257 "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) &&
2919 $fix) { 3258 $fix) {
2920 $fixed[$linenr - 1] =~ 3259 $fixed[$fixlinenr] =~
2921 s/\bpr_warning\b/pr_warn/; 3260 s/\bpr_warning\b/pr_warn/;
2922 } 3261 }
2923 } 3262 }
@@ -2933,17 +3272,40 @@ sub process {
2933 3272
2934# function brace can't be on same line, except for #defines of do while, 3273# function brace can't be on same line, except for #defines of do while,
2935# or if closed on same line 3274# or if closed on same line
2936 if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and 3275 if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and
2937 !($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) { 3276 !($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) {
2938 ERROR("OPEN_BRACE", 3277 if (ERROR("OPEN_BRACE",
2939 "open brace '{' following function declarations go on the next line\n" . $herecurr); 3278 "open brace '{' following function declarations go on the next line\n" . $herecurr) &&
3279 $fix) {
3280 fix_delete_line($fixlinenr, $rawline);
3281 my $fixed_line = $rawline;
3282 $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/;
3283 my $line1 = $1;
3284 my $line2 = $2;
3285 fix_insert_line($fixlinenr, ltrim($line1));
3286 fix_insert_line($fixlinenr, "\+{");
3287 if ($line2 !~ /^\s*$/) {
3288 fix_insert_line($fixlinenr, "\+\t" . trim($line2));
3289 }
3290 }
2940 } 3291 }
2941 3292
2942# open braces for enum, union and struct go on the same line. 3293# open braces for enum, union and struct go on the same line.
2943 if ($line =~ /^.\s*{/ && 3294 if ($line =~ /^.\s*{/ &&
2944 $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { 3295 $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) {
2945 ERROR("OPEN_BRACE", 3296 if (ERROR("OPEN_BRACE",
2946 "open brace '{' following $1 go on the same line\n" . $hereprev); 3297 "open brace '{' following $1 go on the same line\n" . $hereprev) &&
3298 $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
3299 fix_delete_line($fixlinenr - 1, $prevrawline);
3300 fix_delete_line($fixlinenr, $rawline);
3301 my $fixedline = rtrim($prevrawline) . " {";
3302 fix_insert_line($fixlinenr, $fixedline);
3303 $fixedline = $rawline;
3304 $fixedline =~ s/^(.\s*){\s*/$1\t/;
3305 if ($fixedline !~ /^\+\s*$/) {
3306 fix_insert_line($fixlinenr, $fixedline);
3307 }
3308 }
2947 } 3309 }
2948 3310
2949# missing space after union, struct or enum definition 3311# missing space after union, struct or enum definition
@@ -2951,7 +3313,7 @@ sub process {
2951 if (WARN("SPACING", 3313 if (WARN("SPACING",
2952 "missing space after $1 definition\n" . $herecurr) && 3314 "missing space after $1 definition\n" . $herecurr) &&
2953 $fix) { 3315 $fix) {
2954 $fixed[$linenr - 1] =~ 3316 $fixed[$fixlinenr] =~
2955 s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/; 3317 s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/;
2956 } 3318 }
2957 } 3319 }
@@ -3021,7 +3383,7 @@ sub process {
3021 } 3383 }
3022 3384
3023 if (show_type("SPACING") && $fix) { 3385 if (show_type("SPACING") && $fix) {
3024 $fixed[$linenr - 1] =~ 3386 $fixed[$fixlinenr] =~
3025 s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex; 3387 s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex;
3026 } 3388 }
3027 } 3389 }
@@ -3038,7 +3400,7 @@ sub process {
3038 if (ERROR("BRACKET_SPACE", 3400 if (ERROR("BRACKET_SPACE",
3039 "space prohibited before open square bracket '['\n" . $herecurr) && 3401 "space prohibited before open square bracket '['\n" . $herecurr) &&
3040 $fix) { 3402 $fix) {
3041 $fixed[$linenr - 1] =~ 3403 $fixed[$fixlinenr] =~
3042 s/^(\+.*?)\s+\[/$1\[/; 3404 s/^(\+.*?)\s+\[/$1\[/;
3043 } 3405 }
3044 } 3406 }
@@ -3073,7 +3435,7 @@ sub process {
3073 if (WARN("SPACING", 3435 if (WARN("SPACING",
3074 "space prohibited between function name and open parenthesis '('\n" . $herecurr) && 3436 "space prohibited between function name and open parenthesis '('\n" . $herecurr) &&
3075 $fix) { 3437 $fix) {
3076 $fixed[$linenr - 1] =~ 3438 $fixed[$fixlinenr] =~
3077 s/\b$name\s+\(/$name\(/; 3439 s/\b$name\s+\(/$name\(/;
3078 } 3440 }
3079 } 3441 }
@@ -3341,8 +3703,8 @@ sub process {
3341 $fixed_line = $fixed_line . $fix_elements[$#elements]; 3703 $fixed_line = $fixed_line . $fix_elements[$#elements];
3342 } 3704 }
3343 3705
3344 if ($fix && $line_fixed && $fixed_line ne $fixed[$linenr - 1]) { 3706 if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) {
3345 $fixed[$linenr - 1] = $fixed_line; 3707 $fixed[$fixlinenr] = $fixed_line;
3346 } 3708 }
3347 3709
3348 3710
@@ -3353,7 +3715,7 @@ sub process {
3353 if (WARN("SPACING", 3715 if (WARN("SPACING",
3354 "space prohibited before semicolon\n" . $herecurr) && 3716 "space prohibited before semicolon\n" . $herecurr) &&
3355 $fix) { 3717 $fix) {
3356 1 while $fixed[$linenr - 1] =~ 3718 1 while $fixed[$fixlinenr] =~
3357 s/^(\+.*\S)\s+;/$1;/; 3719 s/^(\+.*\S)\s+;/$1;/;
3358 } 3720 }
3359 } 3721 }
@@ -3386,7 +3748,7 @@ sub process {
3386 if (ERROR("SPACING", 3748 if (ERROR("SPACING",
3387 "space required before the open brace '{'\n" . $herecurr) && 3749 "space required before the open brace '{'\n" . $herecurr) &&
3388 $fix) { 3750 $fix) {
3389 $fixed[$linenr - 1] =~ s/^(\+.*(?:do|\))){/$1 {/; 3751 $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\))){/$1 {/;
3390 } 3752 }
3391 } 3753 }
3392 3754
@@ -3404,7 +3766,7 @@ sub process {
3404 if (ERROR("SPACING", 3766 if (ERROR("SPACING",
3405 "space required after that close brace '}'\n" . $herecurr) && 3767 "space required after that close brace '}'\n" . $herecurr) &&
3406 $fix) { 3768 $fix) {
3407 $fixed[$linenr - 1] =~ 3769 $fixed[$fixlinenr] =~
3408 s/}((?!(?:,|;|\)))\S)/} $1/; 3770 s/}((?!(?:,|;|\)))\S)/} $1/;
3409 } 3771 }
3410 } 3772 }
@@ -3414,7 +3776,7 @@ sub process {
3414 if (ERROR("SPACING", 3776 if (ERROR("SPACING",
3415 "space prohibited after that open square bracket '['\n" . $herecurr) && 3777 "space prohibited after that open square bracket '['\n" . $herecurr) &&
3416 $fix) { 3778 $fix) {
3417 $fixed[$linenr - 1] =~ 3779 $fixed[$fixlinenr] =~
3418 s/\[\s+/\[/; 3780 s/\[\s+/\[/;
3419 } 3781 }
3420 } 3782 }
@@ -3422,7 +3784,7 @@ sub process {
3422 if (ERROR("SPACING", 3784 if (ERROR("SPACING",
3423 "space prohibited before that close square bracket ']'\n" . $herecurr) && 3785 "space prohibited before that close square bracket ']'\n" . $herecurr) &&
3424 $fix) { 3786 $fix) {
3425 $fixed[$linenr - 1] =~ 3787 $fixed[$fixlinenr] =~
3426 s/\s+\]/\]/; 3788 s/\s+\]/\]/;
3427 } 3789 }
3428 } 3790 }
@@ -3433,7 +3795,7 @@ sub process {
3433 if (ERROR("SPACING", 3795 if (ERROR("SPACING",
3434 "space prohibited after that open parenthesis '('\n" . $herecurr) && 3796 "space prohibited after that open parenthesis '('\n" . $herecurr) &&
3435 $fix) { 3797 $fix) {
3436 $fixed[$linenr - 1] =~ 3798 $fixed[$fixlinenr] =~
3437 s/\(\s+/\(/; 3799 s/\(\s+/\(/;
3438 } 3800 }
3439 } 3801 }
@@ -3443,18 +3805,26 @@ sub process {
3443 if (ERROR("SPACING", 3805 if (ERROR("SPACING",
3444 "space prohibited before that close parenthesis ')'\n" . $herecurr) && 3806 "space prohibited before that close parenthesis ')'\n" . $herecurr) &&
3445 $fix) { 3807 $fix) {
3446 $fixed[$linenr - 1] =~ 3808 $fixed[$fixlinenr] =~
3447 s/\s+\)/\)/; 3809 s/\s+\)/\)/;
3448 } 3810 }
3449 } 3811 }
3450 3812
3813# check unnecessary parentheses around addressof/dereference single $Lvals
3814# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar
3815
3816 while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) {
3817 CHK("UNNECESSARY_PARENTHESES",
3818 "Unnecessary parentheses around $1\n" . $herecurr);
3819 }
3820
3451#goto labels aren't indented, allow a single space however 3821#goto labels aren't indented, allow a single space however
3452 if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and 3822 if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
3453 !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { 3823 !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
3454 if (WARN("INDENTED_LABEL", 3824 if (WARN("INDENTED_LABEL",
3455 "labels should not be indented\n" . $herecurr) && 3825 "labels should not be indented\n" . $herecurr) &&
3456 $fix) { 3826 $fix) {
3457 $fixed[$linenr - 1] =~ 3827 $fixed[$fixlinenr] =~
3458 s/^(.)\s+/$1/; 3828 s/^(.)\s+/$1/;
3459 } 3829 }
3460 } 3830 }
@@ -3516,7 +3886,7 @@ sub process {
3516 if (ERROR("SPACING", 3886 if (ERROR("SPACING",
3517 "space required before the open parenthesis '('\n" . $herecurr) && 3887 "space required before the open parenthesis '('\n" . $herecurr) &&
3518 $fix) { 3888 $fix) {
3519 $fixed[$linenr - 1] =~ 3889 $fixed[$fixlinenr] =~
3520 s/\b(if|while|for|switch)\(/$1 \(/; 3890 s/\b(if|while|for|switch)\(/$1 \(/;
3521 } 3891 }
3522 } 3892 }
@@ -3606,7 +3976,7 @@ sub process {
3606# if should not continue a brace 3976# if should not continue a brace
3607 if ($line =~ /}\s*if\b/) { 3977 if ($line =~ /}\s*if\b/) {
3608 ERROR("TRAILING_STATEMENTS", 3978 ERROR("TRAILING_STATEMENTS",
3609 "trailing statements should be on next line\n" . 3979 "trailing statements should be on next line (or did you mean 'else if'?)\n" .
3610 $herecurr); 3980 $herecurr);
3611 } 3981 }
3612# case and default should not have general statements after them 3982# case and default should not have general statements after them
@@ -3622,14 +3992,26 @@ sub process {
3622 3992
3623 # Check for }<nl>else {, these must be at the same 3993 # Check for }<nl>else {, these must be at the same
3624 # indent level to be relevant to each other. 3994 # indent level to be relevant to each other.
3625 if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and 3995 if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ &&
3626 $previndent == $indent) { 3996 $previndent == $indent) {
3627 ERROR("ELSE_AFTER_BRACE", 3997 if (ERROR("ELSE_AFTER_BRACE",
3628 "else should follow close brace '}'\n" . $hereprev); 3998 "else should follow close brace '}'\n" . $hereprev) &&
3999 $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
4000 fix_delete_line($fixlinenr - 1, $prevrawline);
4001 fix_delete_line($fixlinenr, $rawline);
4002 my $fixedline = $prevrawline;
4003 $fixedline =~ s/}\s*$//;
4004 if ($fixedline !~ /^\+\s*$/) {
4005 fix_insert_line($fixlinenr, $fixedline);
4006 }
4007 $fixedline = $rawline;
4008 $fixedline =~ s/^(.\s*)else/$1} else/;
4009 fix_insert_line($fixlinenr, $fixedline);
4010 }
3629 } 4011 }
3630 4012
3631 if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ and 4013 if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ &&
3632 $previndent == $indent) { 4014 $previndent == $indent) {
3633 my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0); 4015 my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
3634 4016
3635 # Find out what is on the end of the line after the 4017 # Find out what is on the end of the line after the
@@ -3638,8 +4020,18 @@ sub process {
3638 $s =~ s/\n.*//g; 4020 $s =~ s/\n.*//g;
3639 4021
3640 if ($s =~ /^\s*;/) { 4022 if ($s =~ /^\s*;/) {
3641 ERROR("WHILE_AFTER_BRACE", 4023 if (ERROR("WHILE_AFTER_BRACE",
3642 "while should follow close brace '}'\n" . $hereprev); 4024 "while should follow close brace '}'\n" . $hereprev) &&
4025 $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
4026 fix_delete_line($fixlinenr - 1, $prevrawline);
4027 fix_delete_line($fixlinenr, $rawline);
4028 my $fixedline = $prevrawline;
4029 my $trailing = $rawline;
4030 $trailing =~ s/^\+//;
4031 $trailing = trim($trailing);
4032 $fixedline =~ s/}\s*$/} $trailing/;
4033 fix_insert_line($fixlinenr, $fixedline);
4034 }
3643 } 4035 }
3644 } 4036 }
3645 4037
@@ -3653,7 +4045,7 @@ sub process {
3653 "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) && 4045 "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) &&
3654 $fix) { 4046 $fix) {
3655 my $hexval = sprintf("0x%x", oct($var)); 4047 my $hexval = sprintf("0x%x", oct($var));
3656 $fixed[$linenr - 1] =~ 4048 $fixed[$fixlinenr] =~
3657 s/\b$var\b/$hexval/; 4049 s/\b$var\b/$hexval/;
3658 } 4050 }
3659 } 4051 }
@@ -3689,7 +4081,7 @@ sub process {
3689 if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION", 4081 if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION",
3690 "Whitespace after \\ makes next lines useless\n" . $herecurr) && 4082 "Whitespace after \\ makes next lines useless\n" . $herecurr) &&
3691 $fix) { 4083 $fix) {
3692 $fixed[$linenr - 1] =~ s/\s+$//; 4084 $fixed[$fixlinenr] =~ s/\s+$//;
3693 } 4085 }
3694 } 4086 }
3695 4087
@@ -3720,12 +4112,17 @@ sub process {
3720 my $cnt = $realcnt; 4112 my $cnt = $realcnt;
3721 my ($off, $dstat, $dcond, $rest); 4113 my ($off, $dstat, $dcond, $rest);
3722 my $ctx = ''; 4114 my $ctx = '';
4115 my $has_flow_statement = 0;
4116 my $has_arg_concat = 0;
3723 ($dstat, $dcond, $ln, $cnt, $off) = 4117 ($dstat, $dcond, $ln, $cnt, $off) =
3724 ctx_statement_block($linenr, $realcnt, 0); 4118 ctx_statement_block($linenr, $realcnt, 0);
3725 $ctx = $dstat; 4119 $ctx = $dstat;
3726 #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n"; 4120 #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
3727 #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; 4121 #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
3728 4122
4123 $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/);
4124 $has_arg_concat = 1 if ($ctx =~ /\#\#/);
4125
3729 $dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//; 4126 $dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//;
3730 $dstat =~ s/$;//g; 4127 $dstat =~ s/$;//g;
3731 $dstat =~ s/\\\n.//g; 4128 $dstat =~ s/\\\n.//g;
@@ -3762,7 +4159,7 @@ sub process {
3762 $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), 4159 $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(),
3763 $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); 4160 $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo();
3764 $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz 4161 $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz
3765 $dstat !~ /^'X'$/ && # character constants 4162 $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ && # character constants
3766 $dstat !~ /$exceptions/ && 4163 $dstat !~ /$exceptions/ &&
3767 $dstat !~ /^\.$Ident\s*=/ && # .foo = 4164 $dstat !~ /^\.$Ident\s*=/ && # .foo =
3768 $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo 4165 $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo
@@ -3786,8 +4183,21 @@ sub process {
3786 "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx"); 4183 "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx");
3787 } else { 4184 } else {
3788 ERROR("COMPLEX_MACRO", 4185 ERROR("COMPLEX_MACRO",
3789 "Macros with complex values should be enclosed in parenthesis\n" . "$herectx"); 4186 "Macros with complex values should be enclosed in parentheses\n" . "$herectx");
4187 }
4188 }
4189
4190# check for macros with flow control, but without ## concatenation
4191# ## concatenation is commonly a macro that defines a function so ignore those
4192 if ($has_flow_statement && !$has_arg_concat) {
4193 my $herectx = $here . "\n";
4194 my $cnt = statement_rawlines($ctx);
4195
4196 for (my $n = 0; $n < $cnt; $n++) {
4197 $herectx .= raw_line($linenr, $n) . "\n";
3790 } 4198 }
4199 WARN("MACRO_WITH_FLOW_CONTROL",
4200 "Macros with flow control statements should be avoided\n" . "$herectx");
3791 } 4201 }
3792 4202
3793# check for line continuations outside of #defines, preprocessor #, and asm 4203# check for line continuations outside of #defines, preprocessor #, and asm
@@ -3998,6 +4408,12 @@ sub process {
3998 "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr); 4408 "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
3999 } 4409 }
4000 4410
4411# concatenated string without spaces between elements
4412 if ($line =~ /"X+"[A-Z_]+/ || $line =~ /[A-Z_]+"X+"/) {
4413 CHK("CONCATENATED_STRING",
4414 "Concatenated strings should use spaces between elements\n" . $herecurr);
4415 }
4416
4001# warn about #if 0 4417# warn about #if 0
4002 if ($line =~ /^.\s*\#\s*if\s+0\b/) { 4418 if ($line =~ /^.\s*\#\s*if\s+0\b/) {
4003 CHK("REDUNDANT_CODE", 4419 CHK("REDUNDANT_CODE",
@@ -4014,6 +4430,34 @@ sub process {
4014 } 4430 }
4015 } 4431 }
4016 4432
4433# check for unnecessary "Out of Memory" messages
4434 if ($line =~ /^\+.*\b$logFunctions\s*\(/ &&
4435 $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ &&
4436 (defined $1 || defined $3) &&
4437 $linenr > 3) {
4438 my $testval = $2;
4439 my $testline = $lines[$linenr - 3];
4440
4441 my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0);
4442# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n");
4443
4444 if ($c =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|(?:dev_)?alloc_skb)/) {
4445 WARN("OOM_MESSAGE",
4446 "Possible unnecessary 'out of memory' message\n" . $hereprev);
4447 }
4448 }
4449
4450# check for logging functions with KERN_<LEVEL>
4451 if ($line !~ /printk\s*\(/ &&
4452 $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) {
4453 my $level = $1;
4454 if (WARN("UNNECESSARY_KERN_LEVEL",
4455 "Possible unnecessary $level\n" . $herecurr) &&
4456 $fix) {
4457 $fixed[$fixlinenr] =~ s/\s*$level\s*//;
4458 }
4459 }
4460
4017# check for bad placement of section $InitAttribute (e.g.: __initdata) 4461# check for bad placement of section $InitAttribute (e.g.: __initdata)
4018 if ($line =~ /(\b$InitAttribute\b)/) { 4462 if ($line =~ /(\b$InitAttribute\b)/) {
4019 my $attr = $1; 4463 my $attr = $1;
@@ -4027,7 +4471,7 @@ sub process {
4027 WARN("MISPLACED_INIT", 4471 WARN("MISPLACED_INIT",
4028 "$attr should be placed after $var\n" . $herecurr))) && 4472 "$attr should be placed after $var\n" . $herecurr))) &&
4029 $fix) { 4473 $fix) {
4030 $fixed[$linenr - 1] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e; 4474 $fixed[$fixlinenr] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e;
4031 } 4475 }
4032 } 4476 }
4033 } 4477 }
@@ -4041,7 +4485,7 @@ sub process {
4041 if (ERROR("INIT_ATTRIBUTE", 4485 if (ERROR("INIT_ATTRIBUTE",
4042 "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) && 4486 "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) &&
4043 $fix) { 4487 $fix) {
4044 $fixed[$linenr - 1] =~ 4488 $fixed[$fixlinenr] =~
4045 s/$InitAttributeData/${attr_prefix}initconst/; 4489 s/$InitAttributeData/${attr_prefix}initconst/;
4046 } 4490 }
4047 } 4491 }
@@ -4052,12 +4496,12 @@ sub process {
4052 if (ERROR("INIT_ATTRIBUTE", 4496 if (ERROR("INIT_ATTRIBUTE",
4053 "Use of $attr requires a separate use of const\n" . $herecurr) && 4497 "Use of $attr requires a separate use of const\n" . $herecurr) &&
4054 $fix) { 4498 $fix) {
4055 my $lead = $fixed[$linenr - 1] =~ 4499 my $lead = $fixed[$fixlinenr] =~
4056 /(^\+\s*(?:static\s+))/; 4500 /(^\+\s*(?:static\s+))/;
4057 $lead = rtrim($1); 4501 $lead = rtrim($1);
4058 $lead = "$lead " if ($lead !~ /^\+$/); 4502 $lead = "$lead " if ($lead !~ /^\+$/);
4059 $lead = "${lead}const "; 4503 $lead = "${lead}const ";
4060 $fixed[$linenr - 1] =~ s/(^\+\s*(?:static\s+))/$lead/; 4504 $fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/;
4061 } 4505 }
4062 } 4506 }
4063 4507
@@ -4070,7 +4514,7 @@ sub process {
4070 if (WARN("CONSTANT_CONVERSION", 4514 if (WARN("CONSTANT_CONVERSION",
4071 "$constant_func should be $func\n" . $herecurr) && 4515 "$constant_func should be $func\n" . $herecurr) &&
4072 $fix) { 4516 $fix) {
4073 $fixed[$linenr - 1] =~ s/\b$constant_func\b/$func/g; 4517 $fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g;
4074 } 4518 }
4075 } 4519 }
4076 4520
@@ -4120,7 +4564,7 @@ sub process {
4120 if (ERROR("SPACING", 4564 if (ERROR("SPACING",
4121 "exactly one space required after that #$1\n" . $herecurr) && 4565 "exactly one space required after that #$1\n" . $herecurr) &&
4122 $fix) { 4566 $fix) {
4123 $fixed[$linenr - 1] =~ 4567 $fixed[$fixlinenr] =~
4124 s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /; 4568 s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /;
4125 } 4569 }
4126 4570
@@ -4168,7 +4612,7 @@ sub process {
4168 if (WARN("INLINE", 4612 if (WARN("INLINE",
4169 "plain inline is preferred over $1\n" . $herecurr) && 4613 "plain inline is preferred over $1\n" . $herecurr) &&
4170 $fix) { 4614 $fix) {
4171 $fixed[$linenr - 1] =~ s/\b(__inline__|__inline)\b/inline/; 4615 $fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/;
4172 4616
4173 } 4617 }
4174 } 4618 }
@@ -4193,7 +4637,7 @@ sub process {
4193 if (WARN("PREFER_PRINTF", 4637 if (WARN("PREFER_PRINTF",
4194 "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) && 4638 "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) &&
4195 $fix) { 4639 $fix) {
4196 $fixed[$linenr - 1] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex; 4640 $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex;
4197 4641
4198 } 4642 }
4199 } 4643 }
@@ -4204,7 +4648,7 @@ sub process {
4204 if (WARN("PREFER_SCANF", 4648 if (WARN("PREFER_SCANF",
4205 "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) && 4649 "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) &&
4206 $fix) { 4650 $fix) {
4207 $fixed[$linenr - 1] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex; 4651 $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex;
4208 } 4652 }
4209 } 4653 }
4210 4654
@@ -4219,7 +4663,7 @@ sub process {
4219 if (WARN("SIZEOF_PARENTHESIS", 4663 if (WARN("SIZEOF_PARENTHESIS",
4220 "sizeof $1 should be sizeof($1)\n" . $herecurr) && 4664 "sizeof $1 should be sizeof($1)\n" . $herecurr) &&
4221 $fix) { 4665 $fix) {
4222 $fixed[$linenr - 1] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex; 4666 $fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex;
4223 } 4667 }
4224 } 4668 }
4225 4669
@@ -4242,7 +4686,7 @@ sub process {
4242 if (WARN("PREFER_SEQ_PUTS", 4686 if (WARN("PREFER_SEQ_PUTS",
4243 "Prefer seq_puts to seq_printf\n" . $herecurr) && 4687 "Prefer seq_puts to seq_printf\n" . $herecurr) &&
4244 $fix) { 4688 $fix) {
4245 $fixed[$linenr - 1] =~ s/\bseq_printf\b/seq_puts/; 4689 $fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/;
4246 } 4690 }
4247 } 4691 }
4248 } 4692 }
@@ -4271,7 +4715,7 @@ sub process {
4271 if (WARN("PREFER_ETHER_ADDR_COPY", 4715 if (WARN("PREFER_ETHER_ADDR_COPY",
4272 "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . $herecurr) && 4716 "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . $herecurr) &&
4273 $fix) { 4717 $fix) {
4274 $fixed[$linenr - 1] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; 4718 $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;
4275 } 4719 }
4276 } 4720 }
4277 4721
@@ -4359,7 +4803,7 @@ sub process {
4359 if (CHK("AVOID_EXTERNS", 4803 if (CHK("AVOID_EXTERNS",
4360 "extern prototypes should be avoided in .h files\n" . $herecurr) && 4804 "extern prototypes should be avoided in .h files\n" . $herecurr) &&
4361 $fix) { 4805 $fix) {
4362 $fixed[$linenr - 1] =~ s/(.*)\bextern\b\s*(.*)/$1$2/; 4806 $fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/;
4363 } 4807 }
4364 } 4808 }
4365 4809
@@ -4419,23 +4863,24 @@ sub process {
4419 4863
4420# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc 4864# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
4421 if ($^V && $^V ge 5.10.0 && 4865 if ($^V && $^V ge 5.10.0 &&
4422 $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/) { 4866 $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
4423 my $oldfunc = $3; 4867 my $oldfunc = $3;
4424 my $a1 = $4; 4868 my $a1 = $4;
4425 my $a2 = $10; 4869 my $a2 = $10;
4426 my $newfunc = "kmalloc_array"; 4870 my $newfunc = "kmalloc_array";
4427 $newfunc = "kcalloc" if ($oldfunc eq "kzalloc"); 4871 $newfunc = "kcalloc" if ($oldfunc eq "kzalloc");
4428 if ($a1 =~ /^sizeof\s*\S/ || $a2 =~ /^sizeof\s*\S/) { 4872 my $r1 = $a1;
4873 my $r2 = $a2;
4874 if ($a1 =~ /^sizeof\s*\S/) {
4875 $r1 = $a2;
4876 $r2 = $a1;
4877 }
4878 if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ &&
4879 !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) {
4429 if (WARN("ALLOC_WITH_MULTIPLY", 4880 if (WARN("ALLOC_WITH_MULTIPLY",
4430 "Prefer $newfunc over $oldfunc with multiply\n" . $herecurr) && 4881 "Prefer $newfunc over $oldfunc with multiply\n" . $herecurr) &&
4431 $fix) { 4882 $fix) {
4432 my $r1 = $a1; 4883 $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
4433 my $r2 = $a2;
4434 if ($a1 =~ /^sizeof\s*\S/) {
4435 $r1 = $a2;
4436 $r2 = $a1;
4437 }
4438 $fixed[$linenr - 1] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
4439 4884
4440 } 4885 }
4441 } 4886 }
@@ -4459,17 +4904,17 @@ sub process {
4459 if (WARN("ONE_SEMICOLON", 4904 if (WARN("ONE_SEMICOLON",
4460 "Statements terminations use 1 semicolon\n" . $herecurr) && 4905 "Statements terminations use 1 semicolon\n" . $herecurr) &&
4461 $fix) { 4906 $fix) {
4462 $fixed[$linenr - 1] =~ s/(\s*;\s*){2,}$/;/g; 4907 $fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g;
4463 } 4908 }
4464 } 4909 }
4465 4910
4466# check for case / default statements not preceeded by break/fallthrough/switch 4911# check for case / default statements not preceded by break/fallthrough/switch
4467 if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) { 4912 if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) {
4468 my $has_break = 0; 4913 my $has_break = 0;
4469 my $has_statement = 0; 4914 my $has_statement = 0;
4470 my $count = 0; 4915 my $count = 0;
4471 my $prevline = $linenr; 4916 my $prevline = $linenr;
4472 while ($prevline > 1 && $count < 3 && !$has_break) { 4917 while ($prevline > 1 && ($file || $count < 3) && !$has_break) {
4473 $prevline--; 4918 $prevline--;
4474 my $rline = $rawlines[$prevline - 1]; 4919 my $rline = $rawlines[$prevline - 1];
4475 my $fline = $lines[$prevline - 1]; 4920 my $fline = $lines[$prevline - 1];
@@ -4507,7 +4952,7 @@ sub process {
4507 if (WARN("USE_FUNC", 4952 if (WARN("USE_FUNC",
4508 "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) && 4953 "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) &&
4509 $fix) { 4954 $fix) {
4510 $fixed[$linenr - 1] =~ s/\b__FUNCTION__\b/__func__/g; 4955 $fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g;
4511 } 4956 }
4512 } 4957 }
4513 4958
@@ -4750,12 +5195,16 @@ sub process {
4750 hash_show_words(\%use_type, "Used"); 5195 hash_show_words(\%use_type, "Used");
4751 hash_show_words(\%ignore_type, "Ignored"); 5196 hash_show_words(\%ignore_type, "Ignored");
4752 5197
4753 if ($clean == 0 && $fix && "@rawlines" ne "@fixed") { 5198 if ($clean == 0 && $fix &&
5199 ("@rawlines" ne "@fixed" ||
5200 $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) {
4754 my $newfile = $filename; 5201 my $newfile = $filename;
4755 $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace); 5202 $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace);
4756 my $linecount = 0; 5203 my $linecount = 0;
4757 my $f; 5204 my $f;
4758 5205
5206 @fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted);
5207
4759 open($f, '>', $newfile) 5208 open($f, '>', $newfile)
4760 or die "$P: Can't open $newfile for write\n"; 5209 or die "$P: Can't open $newfile for write\n";
4761 foreach my $fixed_line (@fixed) { 5210 foreach my $fixed_line (@fixed) {
@@ -4763,7 +5212,7 @@ sub process {
4763 if ($file) { 5212 if ($file) {
4764 if ($linecount > 3) { 5213 if ($linecount > 3) {
4765 $fixed_line =~ s/^\+//; 5214 $fixed_line =~ s/^\+//;
4766 print $f $fixed_line. "\n"; 5215 print $f $fixed_line . "\n";
4767 } 5216 }
4768 } else { 5217 } else {
4769 print $f $fixed_line . "\n"; 5218 print $f $fixed_line . "\n";
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index d54a114748a6..dd8397894d5c 100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -55,14 +55,12 @@ my (@stack, $re, $dre, $x, $xs, $funcre);
55 #8000008a: 20 1d sub sp,4 55 #8000008a: 20 1d sub sp,4
56 #80000ca8: fa cd 05 b0 sub sp,sp,1456 56 #80000ca8: fa cd 05 b0 sub sp,sp,1456
57 $re = qr/^.*sub.*sp.*,([0-9]{1,8})/o; 57 $re = qr/^.*sub.*sp.*,([0-9]{1,8})/o;
58 } elsif ($arch =~ /^i[3456]86$/) { 58 } elsif ($arch =~ /^x86(_64)?$/ || $arch =~ /^i[3456]86$/) {
59 #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp 59 #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp
60 $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%esp$/o; 60 # or
61 $dre = qr/^.*[as][du][db] (%.*),\%esp$/o; 61 # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp
62 } elsif ($arch eq 'x86_64') { 62 $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%(e|r)sp$/o;
63 # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp 63 $dre = qr/^.*[as][du][db] (%.*),\%(e|r)sp$/o;
64 $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%rsp$/o;
65 $dre = qr/^.*[as][du][db] (\%.*),\%rsp$/o;
66 } elsif ($arch eq 'ia64') { 64 } elsif ($arch eq 'ia64') {
67 #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12 65 #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12
68 $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o; 66 $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o;
diff --git a/scripts/coccinelle/api/alloc/alloc_cast.cocci b/scripts/coccinelle/api/alloc/alloc_cast.cocci
new file mode 100644
index 000000000000..6c308ee19b32
--- /dev/null
+++ b/scripts/coccinelle/api/alloc/alloc_cast.cocci
@@ -0,0 +1,72 @@
1/// Remove casting the values returned by memory allocation functions
2/// like kmalloc, kzalloc, kmem_cache_alloc, kmem_cache_zalloc etc.
3///
4//# This makes an effort to find cases of casting of values returned by
5//# kmalloc, kzalloc, kcalloc, kmem_cache_alloc, kmem_cache_zalloc,
6//# kmem_cache_alloc_node, kmalloc_node and kzalloc_node and removes
7//# the casting as it is not required. The result in the patch case may
8//#need some reformatting.
9//
10// Confidence: High
11// Copyright: 2014, Himangi Saraogi GPLv2.
12// Comments:
13// Options: --no-includes --include-headers
14//
15
16virtual context
17virtual patch
18virtual org
19virtual report
20
21//----------------------------------------------------------
22// For context mode
23//----------------------------------------------------------
24
25@depends on context@
26type T;
27@@
28
29* (T *)
30 \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
31 kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...)
32
33//----------------------------------------------------------
34// For patch mode
35//----------------------------------------------------------
36
37@depends on patch@
38type T;
39@@
40
41- (T *)
42 (\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
43 kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...))
44
45//----------------------------------------------------------
46// For org and report mode
47//----------------------------------------------------------
48
49@r depends on org || report@
50type T;
51position p;
52@@
53
54 (T@p *)\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
55 kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...)
56
57@script:python depends on org@
58p << r.p;
59t << r.T;
60@@
61
62coccilib.org.print_safe_todo(p[0], t)
63
64@script:python depends on report@
65p << r.p;
66t << r.T;
67@@
68
69msg="WARNING: casting value returned by memory allocation function to (%s *) is useless." % (t)
70coccilib.report.print_report(p[0], msg)
71
72
diff --git a/scripts/coccinelle/free/ifnullfree.cocci b/scripts/coccinelle/free/ifnullfree.cocci
new file mode 100644
index 000000000000..a42d70bf88b3
--- /dev/null
+++ b/scripts/coccinelle/free/ifnullfree.cocci
@@ -0,0 +1,53 @@
1/// NULL check before some freeing functions is not needed.
2///
3/// Based on checkpatch warning
4/// "kfree(NULL) is safe this check is probably not required"
5/// and kfreeaddr.cocci by Julia Lawall.
6///
7// Copyright: (C) 2014 Fabian Frederick. GPLv2.
8// Comments: -
9// Options: --no-includes --include-headers
10
11virtual patch
12virtual org
13virtual report
14virtual context
15
16@r2 depends on patch@
17expression E;
18@@
19- if (E)
20(
21- kfree(E);
22+ kfree(E);
23|
24- debugfs_remove(E);
25+ debugfs_remove(E);
26|
27- debugfs_remove_recursive(E);
28+ debugfs_remove_recursive(E);
29|
30- usb_free_urb(E);
31+ usb_free_urb(E);
32)
33
34@r depends on context || report || org @
35expression E;
36position p;
37@@
38
39* if (E)
40* \(kfree@p\|debugfs_remove@p\|debugfs_remove_recursive@p\|usb_free_urb\)(E);
41
42@script:python depends on org@
43p << r.p;
44@@
45
46cocci.print_main("NULL check before that freeing function is not needed", p)
47
48@script:python depends on report@
49p << r.p;
50@@
51
52msg = "WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values."
53coccilib.report.print_report(p[0], msg)
diff --git a/scripts/coccinelle/misc/array_size.cocci b/scripts/coccinelle/misc/array_size.cocci
new file mode 100644
index 000000000000..81e279cd347b
--- /dev/null
+++ b/scripts/coccinelle/misc/array_size.cocci
@@ -0,0 +1,87 @@
1/// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element
2///
3//# This makes an effort to find cases where ARRAY_SIZE can be used such as
4//# where there is a division of sizeof the array by the sizeof its first
5//# element or by any indexed element or the element type. It replaces the
6//# division of the two sizeofs by ARRAY_SIZE.
7//
8// Confidence: High
9// Copyright: (C) 2014 Himangi Saraogi. GPLv2.
10// Comments:
11// Options: --no-includes --include-headers
12
13virtual patch
14virtual context
15virtual org
16virtual report
17
18@i@
19@@
20
21#include <linux/kernel.h>
22
23//----------------------------------------------------------
24// For context mode
25//----------------------------------------------------------
26
27@depends on i&&context@
28type T;
29T[] E;
30@@
31(
32* (sizeof(E)/sizeof(*E))
33|
34* (sizeof(E)/sizeof(E[...]))
35|
36* (sizeof(E)/sizeof(T))
37)
38
39//----------------------------------------------------------
40// For patch mode
41//----------------------------------------------------------
42
43@depends on i&&patch@
44type T;
45T[] E;
46@@
47(
48- (sizeof(E)/sizeof(*E))
49+ ARRAY_SIZE(E)
50|
51- (sizeof(E)/sizeof(E[...]))
52+ ARRAY_SIZE(E)
53|
54- (sizeof(E)/sizeof(T))
55+ ARRAY_SIZE(E)
56)
57
58//----------------------------------------------------------
59// For org and report mode
60//----------------------------------------------------------
61
62@r@
63type T;
64T[] E;
65position p;
66@@
67(
68 (sizeof(E)@p /sizeof(*E))
69|
70 (sizeof(E)@p /sizeof(E[...]))
71|
72 (sizeof(E)@p /sizeof(T))
73)
74
75@script:python depends on i&&org@
76p << r.p;
77@@
78
79coccilib.org.print_todo(p[0], "WARNING should use ARRAY_SIZE")
80
81@script:python depends on i&&report@
82p << r.p;
83@@
84
85msg="WARNING: Use ARRAY_SIZE"
86coccilib.report.print_report(p[0], msg)
87
diff --git a/scripts/coccinelle/misc/badty.cocci b/scripts/coccinelle/misc/badty.cocci
new file mode 100644
index 000000000000..2fc06fc71927
--- /dev/null
+++ b/scripts/coccinelle/misc/badty.cocci
@@ -0,0 +1,76 @@
1/// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element
2///
3//# This makes an effort to find cases where the argument to sizeof is wrong
4//# in memory allocation functions by checking the type of the allocated memory
5//# when it is a double pointer and ensuring the sizeof argument takes a pointer
6//# to the the memory being allocated. There are false positives in cases the
7//# sizeof argument is not used in constructing the return value. The result
8//# may need some reformatting.
9//
10// Confidence: Moderate
11// Copyright: (C) 2014 Himangi Saraogi. GPLv2.
12// Comments:
13// Options:
14
15virtual patch
16virtual context
17virtual org
18virtual report
19
20//----------------------------------------------------------
21// For context mode
22//----------------------------------------------------------
23
24@depends on context disable sizeof_type_expr@
25type T;
26T **x;
27@@
28
29 x =
30 <+...sizeof(
31* T
32 )...+>
33
34//----------------------------------------------------------
35// For patch mode
36//----------------------------------------------------------
37
38@depends on patch disable sizeof_type_expr@
39type T;
40T **x;
41@@
42
43 x =
44 <+...sizeof(
45- T
46+ *x
47 )...+>
48
49//----------------------------------------------------------
50// For org and report mode
51//----------------------------------------------------------
52
53@r disable sizeof_type_expr@
54type T;
55T **x;
56position p;
57@@
58
59 x =
60 <+...sizeof(
61 T@p
62 )...+>
63
64@script:python depends on org@
65p << r.p;
66@@
67
68coccilib.org.print_todo(p[0], "WARNING sizeof argument should be pointer type, not structure type")
69
70@script:python depends on report@
71p << r.p;
72@@
73
74msg="WARNING: Use correct pointer type argument for sizeof"
75coccilib.report.print_report(p[0], msg)
76
diff --git a/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci b/scripts/coccinelle/misc/bugon.cocci
index bd5d08b882ee..556456ca761c 100644
--- a/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci
+++ b/scripts/coccinelle/misc/bugon.cocci
@@ -1,20 +1,17 @@
1/// Use BUG_ON instead of a if condition followed by BUG.
1/// 2///
2/// Casting (void *) value returned by kmalloc is useless 3//# This makes an effort to find cases where BUG() follows an if
3/// as mentioned in Documentation/CodingStyle, Chap 14. 4//# condition on an expression and replaces the if condition and BUG()
4/// 5//# with a BUG_ON having the conditional expression of the if statement
5// Confidence: High 6//# as argument.
6// Copyright: 2009,2010 Nicolas Palix, DIKU. GPLv2.
7// URL: http://coccinelle.lip6.fr/
8// Options: --no-includes --include-headers
9//
10// Keywords: kmalloc, kzalloc, kcalloc
11// Version min: < 2.6.12 kmalloc
12// Version min: < 2.6.12 kcalloc
13// Version min: 2.6.14 kzalloc
14// 7//
8// Confidence: High
9// Copyright: (C) 2014 Himangi Saraogi. GPLv2.
10// Comments:
11// Options: --no-includes, --include-headers
15 12
16virtual context
17virtual patch 13virtual patch
14virtual context
18virtual org 15virtual org
19virtual report 16virtual report
20 17
@@ -23,45 +20,43 @@ virtual report
23//---------------------------------------------------------- 20//----------------------------------------------------------
24 21
25@depends on context@ 22@depends on context@
26type T; 23expression e;
27@@ 24@@
28 25
29* (T *) 26*if (e) BUG();
30 \(kmalloc\|kzalloc\|kcalloc\)(...)
31 27
32//---------------------------------------------------------- 28//----------------------------------------------------------
33// For patch mode 29// For patch mode
34//---------------------------------------------------------- 30//----------------------------------------------------------
35 31
36@depends on patch@ 32@depends on patch@
37type T; 33expression e;
38@@ 34@@
39 35
40- (T *) 36-if (e) BUG();
41 \(kmalloc\|kzalloc\|kcalloc\)(...) 37+BUG_ON(e);
42 38
43//---------------------------------------------------------- 39//----------------------------------------------------------
44// For org and report mode 40// For org and report mode
45//---------------------------------------------------------- 41//----------------------------------------------------------
46 42
47@r depends on org || report@ 43@r@
48type T; 44expression e;
49position p; 45position p;
50@@ 46@@
51 47
52 (T@p *)\(kmalloc\|kzalloc\|kcalloc\)(...) 48 if (e) BUG@p ();
53 49
54@script:python depends on org@ 50@script:python depends on org@
55p << r.p; 51p << r.p;
56t << r.T;
57@@ 52@@
58 53
59coccilib.org.print_safe_todo(p[0], t) 54coccilib.org.print_todo(p[0], "WARNING use BUG_ON")
60 55
61@script:python depends on report@ 56@script:python depends on report@
62p << r.p; 57p << r.p;
63t << r.T;
64@@ 58@@
65 59
66msg="WARNING: casting value returned by k[cmz]alloc to (%s *) is useless." % (t) 60msg="WARNING: Use BUG_ON"
67coccilib.report.print_report(p[0], msg) 61coccilib.report.print_report(p[0], msg)
62
diff --git a/scripts/coccinelle/misc/simple_return.cocci b/scripts/coccinelle/misc/simple_return.cocci
new file mode 100644
index 000000000000..47f7084b6360
--- /dev/null
+++ b/scripts/coccinelle/misc/simple_return.cocci
@@ -0,0 +1,180 @@
1/// Simplify a trivial if-return sequence. Possibly combine with a
2/// preceding function call.
3//
4// Confidence: High
5// Copyright: (C) 2014 Julia Lawall, INRIA/LIP6. GPLv2.
6// Copyright: (C) 2014 Gilles Muller, INRIA/LiP6. GPLv2.
7// URL: http://coccinelle.lip6.fr/
8// Comments:
9// Options: --no-includes --include-headers
10
11virtual patch
12virtual context
13virtual org
14virtual report
15
16@r depends on patch@
17local idexpression e;
18identifier i,f,fn;
19@@
20
21fn(...) { <...
22- e@i =
23+ return
24 f(...);
25-if (i != 0) return i;
26-return 0;
27...> }
28
29@depends on patch@
30identifier r.i;
31type t;
32@@
33
34-t i;
35 ... when != i
36
37@depends on patch@
38expression e;
39@@
40
41-if (e != 0)
42 return e;
43-return 0;
44
45// -----------------------------------------------------------------------
46
47@s1 depends on context || org || report@
48local idexpression e;
49identifier i,f,fn;
50position p,p1,p2;
51@@
52
53fn(...) { <...
54* e@i@p = f(...);
55 if (\(i@p1 != 0\|i@p2 < 0\))
56 return i;
57 return 0;
58...> }
59
60@s2 depends on context || org || report forall@
61identifier s1.i;
62type t;
63position q,s1.p;
64expression e,f;
65@@
66
67* t i@q;
68 ... when != i
69 e@p = f(...);
70
71@s3 depends on context || org || report@
72expression e;
73position p1!=s1.p1;
74position p2!=s1.p2;
75@@
76
77*if (\(e@p1 != 0\|e@p2 < 0\))
78 return e;
79 return 0;
80
81// -----------------------------------------------------------------------
82
83@script:python depends on org@
84p << s1.p;
85p1 << s1.p1;
86q << s2.q;
87@@
88
89cocci.print_main("decl",q)
90cocci.print_secs("use",p)
91cocci.include_match(False)
92
93@script:python depends on org@
94p << s1.p;
95p2 << s1.p2;
96q << s2.q;
97@@
98
99cocci.print_main("decl",q)
100cocci.print_secs("use with questionable test",p)
101cocci.include_match(False)
102
103@script:python depends on org@
104p << s1.p;
105p1 << s1.p1;
106@@
107
108cocci.print_main("use",p)
109
110@script:python depends on org@
111p << s1.p;
112p2 << s1.p2;
113@@
114
115cocci.print_main("use with questionable test",p)
116
117@script:python depends on org@
118p << s3.p1;
119@@
120
121cocci.print_main("test",p)
122
123@script:python depends on org@
124p << s3.p2;
125@@
126
127cocci.print_main("questionable test",p)
128
129// -----------------------------------------------------------------------
130
131@script:python depends on report@
132p << s1.p;
133p1 << s1.p1;
134q << s2.q;
135@@
136
137msg = "WARNING: end returns can be simpified and declaration on line %s can be dropped" % (q[0].line)
138coccilib.report.print_report(p[0],msg)
139cocci.include_match(False)
140
141@script:python depends on report@
142p << s1.p;
143p1 << s1.p1;
144q << s2.q
145;
146@@
147
148msg = "WARNING: end returns may be simpified if negative or 0 value and declaration on line %s can be dropped" % (q[0].line)
149coccilib.report.print_report(p[0],msg)
150cocci.include_match(False)
151
152@script:python depends on report@
153p << s1.p;
154p1 << s1.p1;
155@@
156
157msg = "WARNING: end returns can be simpified"
158coccilib.report.print_report(p[0],msg)
159
160@script:python depends on report@
161p << s1.p;
162p2 << s1.p2;
163@@
164
165msg = "WARNING: end returns can be simpified if negative or 0 value"
166coccilib.report.print_report(p[0],msg)
167
168@script:python depends on report@
169p << s3.p1;
170@@
171
172msg = "WARNING: end returns can be simpified"
173coccilib.report.print_report(p[0],msg)
174
175@script:python depends on report@
176p << s3.p2;
177@@
178
179msg = "WARNING: end returns can be simpified if tested value is negative or 0"
180coccilib.report.print_report(p[0],msg)
diff --git a/scripts/coccinelle/null/badzero.cocci b/scripts/coccinelle/null/badzero.cocci
index d79baf7220e7..5551da2b4fe3 100644
--- a/scripts/coccinelle/null/badzero.cocci
+++ b/scripts/coccinelle/null/badzero.cocci
@@ -10,7 +10,7 @@
10// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2. 10// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
11// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. 11// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
12// URL: http://coccinelle.lip6.fr/ 12// URL: http://coccinelle.lip6.fr/
13// Comments: 13// Comments: Requires Coccinelle version 1.0.0-rc20 or later
14// Options: 14// Options:
15 15
16virtual patch 16virtual patch
@@ -19,6 +19,7 @@ virtual org
19virtual report 19virtual report
20 20
21@initialize:ocaml@ 21@initialize:ocaml@
22@@
22let negtable = Hashtbl.create 101 23let negtable = Hashtbl.create 101
23 24
24@depends on patch@ 25@depends on patch@
diff --git a/scripts/export_report.pl b/scripts/export_report.pl
index 8f79b701de87..8f79b701de87 100644..100755
--- a/scripts/export_report.pl
+++ b/scripts/export_report.pl
diff --git a/scripts/gcc-goto.sh b/scripts/gcc-goto.sh
index c9469d34ecc6..c9469d34ecc6 100644..100755
--- a/scripts/gcc-goto.sh
+++ b/scripts/gcc-goto.sh
diff --git a/scripts/gcc-ld b/scripts/gcc-ld
index cadab9a13ed7..cadab9a13ed7 100644..100755
--- a/scripts/gcc-ld
+++ b/scripts/gcc-ld
diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh
index 7f2126df91f2..7f2126df91f2 100644..100755
--- a/scripts/gcc-version.sh
+++ b/scripts/gcc-version.sh
diff --git a/scripts/gcc-x86_32-has-stack-protector.sh b/scripts/gcc-x86_32-has-stack-protector.sh
index 12dbd0b11ea4..12dbd0b11ea4 100644..100755
--- a/scripts/gcc-x86_32-has-stack-protector.sh
+++ b/scripts/gcc-x86_32-has-stack-protector.sh
diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh
index 973e8c141567..973e8c141567 100644..100755
--- a/scripts/gcc-x86_64-has-stack-protector.sh
+++ b/scripts/gcc-x86_64-has-stack-protector.sh
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index 17fa901418ae..17fa901418ae 100644..100755
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
diff --git a/scripts/headers_check.pl b/scripts/headers_check.pl
index 62320f93e903..62320f93e903 100644..100755
--- a/scripts/headers_check.pl
+++ b/scripts/headers_check.pl
diff --git a/scripts/headers_install.sh b/scripts/headers_install.sh
index 5de5660cb708..fdebd66f8fc1 100644..100755
--- a/scripts/headers_install.sh
+++ b/scripts/headers_install.sh
@@ -1,8 +1,8 @@
1#!/bin/sh 1#!/bin/sh
2 2
3if [ $# -lt 1 ] 3if [ $# -lt 2 ]
4then 4then
5 echo "Usage: headers_install.sh OUTDIR SRCDIR [FILES...] 5 echo "Usage: headers_install.sh OUTDIR SRCDIR [FILES...]"
6 echo 6 echo
7 echo "Prepares kernel header files for use by user space, by removing" 7 echo "Prepares kernel header files for use by user space, by removing"
8 echo "all compiler.h definitions and #includes, removing any" 8 echo "all compiler.h definitions and #includes, removing any"
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index dc7aa45e80ce..c6d33bd15b04 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -84,7 +84,7 @@ static void usage(void)
84 */ 84 */
85static inline int is_arm_mapping_symbol(const char *str) 85static inline int is_arm_mapping_symbol(const char *str)
86{ 86{
87 return str[0] == '$' && strchr("atd", str[1]) 87 return str[0] == '$' && strchr("axtd", str[1])
88 && (str[2] == '\0' || str[2] == '.'); 88 && (str[2] == '\0' || str[2] == '.');
89} 89}
90 90
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 9c4d2412fb72..9645c0739386 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -104,6 +104,23 @@ endif
104%_defconfig: $(obj)/conf 104%_defconfig: $(obj)/conf
105 $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig) 105 $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
106 106
107configfiles=$(wildcard $(srctree)/kernel/configs/$(1).config $(srctree)/arch/$(SRCARCH)/configs/$(1).config)
108
109define mergeconfig
110$(if $(wildcard $(objtree)/.config),, $(error You need an existing .config for this target))
111$(if $(call configfiles,$(1)),, $(error No configuration exists for this target on this architecture))
112$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m -O $(objtree) $(objtree)/.config $(call configfiles,$(1))
113$(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig
114endef
115
116PHONY += kvmconfig
117kvmconfig:
118 $(call mergeconfig,kvm_guest)
119
120PHONY += tinyconfig
121tinyconfig: allnoconfig
122 $(call mergeconfig,tiny)
123
107# Help text used by make help 124# Help text used by make help
108help: 125help:
109 @echo ' config - Update current config utilising a line-oriented program' 126 @echo ' config - Update current config utilising a line-oriented program'
@@ -124,6 +141,8 @@ help:
124 @echo ' randconfig - New config with random answer to all options' 141 @echo ' randconfig - New config with random answer to all options'
125 @echo ' listnewconfig - List new options' 142 @echo ' listnewconfig - List new options'
126 @echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their default value' 143 @echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their default value'
144 @echo ' kvmconfig - Enable additional options for guest kernel support'
145 @echo ' tinyconfig - Configure the tiniest possible kernel'
127 146
128# lxdialog stuff 147# lxdialog stuff
129check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh 148check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
@@ -157,39 +176,10 @@ qconf-cxxobjs := qconf.o
157qconf-objs := zconf.tab.o 176qconf-objs := zconf.tab.o
158gconf-objs := gconf.o zconf.tab.o 177gconf-objs := gconf.o zconf.tab.o
159 178
160hostprogs-y := conf 179hostprogs-y := conf nconf mconf kxgettext qconf gconf
161
162ifeq ($(MAKECMDGOALS),nconfig)
163 hostprogs-y += nconf
164endif
165
166ifeq ($(MAKECMDGOALS),menuconfig)
167 hostprogs-y += mconf
168endif
169
170ifeq ($(MAKECMDGOALS),update-po-config)
171 hostprogs-y += kxgettext
172endif
173
174ifeq ($(MAKECMDGOALS),xconfig)
175 qconf-target := 1
176endif
177ifeq ($(MAKECMDGOALS),gconfig)
178 gconf-target := 1
179endif
180
181
182ifeq ($(qconf-target),1)
183 hostprogs-y += qconf
184endif
185
186ifeq ($(gconf-target),1)
187 hostprogs-y += gconf
188endif
189 180
190clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck 181clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck
191clean-files += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h 182clean-files += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h
192clean-files += mconf qconf gconf nconf
193clean-files += config.pot linux.pot 183clean-files += config.pot linux.pot
194 184
195# Check that we have the required ncurses stuff installed for lxdialog (menuconfig) 185# Check that we have the required ncurses stuff installed for lxdialog (menuconfig)
@@ -220,11 +210,12 @@ HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
220HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) 210HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
221 211
222HOSTLOADLIBES_nconf = $(shell \ 212HOSTLOADLIBES_nconf = $(shell \
223 pkg-config --libs menu panel ncurses 2>/dev/null \ 213 pkg-config --libs menuw panelw ncursesw 2>/dev/null \
214 || pkg-config --libs menu panel ncurses 2>/dev/null \
224 || echo "-lmenu -lpanel -lncurses" ) 215 || echo "-lmenu -lpanel -lncurses" )
225$(obj)/qconf.o: $(obj)/.tmp_qtcheck 216$(obj)/qconf.o: $(obj)/.tmp_qtcheck
226 217
227ifeq ($(qconf-target),1) 218ifeq ($(MAKECMDGOALS),xconfig)
228$(obj)/.tmp_qtcheck: $(src)/Makefile 219$(obj)/.tmp_qtcheck: $(src)/Makefile
229-include $(obj)/.tmp_qtcheck 220-include $(obj)/.tmp_qtcheck
230 221
@@ -281,7 +272,7 @@ endif
281 272
282$(obj)/gconf.o: $(obj)/.tmp_gtkcheck 273$(obj)/gconf.o: $(obj)/.tmp_gtkcheck
283 274
284ifeq ($(gconf-target),1) 275ifeq ($(MAKECMDGOALS),gconfig)
285-include $(obj)/.tmp_gtkcheck 276-include $(obj)/.tmp_gtkcheck
286 277
287# GTK needs some extra effort, too... 278# GTK needs some extra effort, too...
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
index 9d2a4c585ee1..5075ebf2d3b9 100644..100755
--- a/scripts/kconfig/lxdialog/check-lxdialog.sh
+++ b/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -21,7 +21,11 @@ ldflags()
21# Where is ncurses.h? 21# Where is ncurses.h?
22ccflags() 22ccflags()
23{ 23{
24 if [ -f /usr/include/ncursesw/curses.h ]; then 24 if pkg-config --cflags ncursesw 2>/dev/null; then
25 echo '-DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1'
26 elif pkg-config --cflags ncurses 2>/dev/null; then
27 echo '-DCURSES_LOC="<ncurses.h>"'
28 elif [ -f /usr/include/ncursesw/curses.h ]; then
25 echo '-I/usr/include/ncursesw -DCURSES_LOC="<curses.h>"' 29 echo '-I/usr/include/ncursesw -DCURSES_LOC="<curses.h>"'
26 echo ' -DNCURSES_WIDECHAR=1' 30 echo ' -DNCURSES_WIDECHAR=1'
27 elif [ -f /usr/include/ncurses/ncurses.h ]; then 31 elif [ -f /usr/include/ncurses/ncurses.h ]; then
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
index b4343d384926..fcffd5b41fb0 100644
--- a/scripts/kconfig/lxdialog/dialog.h
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -170,7 +170,7 @@ char item_tag(void);
170/* item list manipulation for lxdialog use */ 170/* item list manipulation for lxdialog use */
171#define MAXITEMSTR 200 171#define MAXITEMSTR 200
172struct dialog_item { 172struct dialog_item {
173 char str[MAXITEMSTR]; /* promtp displayed */ 173 char str[MAXITEMSTR]; /* prompt displayed */
174 char tag; 174 char tag;
175 void *data; /* pointer to menu item - used by menubox+checklist */ 175 void *data; /* pointer to menu item - used by menubox+checklist */
176 int selected; /* Set to 1 by dialog_*() function if selected. */ 176 int selected; /* Set to 1 by dialog_*() function if selected. */
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index 9cb8522d8d22..9cb8522d8d22 100644..100755
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 16a07cfa4d34..70bea942b413 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -2085,6 +2085,7 @@ sub dump_function($$) {
2085 $prototype =~ s/^noinline +//; 2085 $prototype =~ s/^noinline +//;
2086 $prototype =~ s/__init +//; 2086 $prototype =~ s/__init +//;
2087 $prototype =~ s/__init_or_module +//; 2087 $prototype =~ s/__init_or_module +//;
2088 $prototype =~ s/__meminit +//;
2088 $prototype =~ s/__must_check +//; 2089 $prototype =~ s/__must_check +//;
2089 $prototype =~ s/__weak +//; 2090 $prototype =~ s/__weak +//;
2090 my $define = $prototype =~ s/^#\s*define\s+//; #ak added 2091 my $define = $prototype =~ s/^#\s*define\s+//; #ak added
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 86a4fe75f453..86a4fe75f453 100644..100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
diff --git a/scripts/markup_oops.pl b/scripts/markup_oops.pl
index c21d16328d3f..c21d16328d3f 100644..100755
--- a/scripts/markup_oops.pl
+++ b/scripts/markup_oops.pl
diff --git a/scripts/mkmakefile b/scripts/mkmakefile
index 84af27bf0f99..84af27bf0f99 100644..100755
--- a/scripts/mkmakefile
+++ b/scripts/mkmakefile
diff --git a/scripts/mksysmap b/scripts/mksysmap
index 7ada35a0f478..7ada35a0f478 100644..100755
--- a/scripts/mksysmap
+++ b/scripts/mksysmap
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 9d9c5b905b35..d439856f8176 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -24,9 +24,9 @@
24#include "../../include/linux/export.h" 24#include "../../include/linux/export.h"
25 25
26/* Are we using CONFIG_MODVERSIONS? */ 26/* Are we using CONFIG_MODVERSIONS? */
27int modversions = 0; 27static int modversions = 0;
28/* Warn about undefined symbols? (do so if we have vmlinux) */ 28/* Warn about undefined symbols? (do so if we have vmlinux) */
29int have_vmlinux = 0; 29static int have_vmlinux = 0;
30/* Is CONFIG_MODULE_SRCVERSION_ALL set? */ 30/* Is CONFIG_MODULE_SRCVERSION_ALL set? */
31static int all_versions = 0; 31static int all_versions = 0;
32/* If we are modposting external module set to 1 */ 32/* If we are modposting external module set to 1 */
@@ -229,7 +229,7 @@ static struct symbol *find_symbol(const char *name)
229 return NULL; 229 return NULL;
230} 230}
231 231
232static struct { 232static const struct {
233 const char *str; 233 const char *str;
234 enum export export; 234 enum export export;
235} export_list[] = { 235} export_list[] = {
@@ -772,32 +772,10 @@ static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr)
772 sechdr->sh_name; 772 sechdr->sh_name;
773} 773}
774 774
775/* if sym is empty or point to a string
776 * like ".[0-9]+" then return 1.
777 * This is the optional prefix added by ld to some sections
778 */
779static int number_prefix(const char *sym)
780{
781 if (*sym++ == '\0')
782 return 1;
783 if (*sym != '.')
784 return 0;
785 do {
786 char c = *sym++;
787 if (c < '0' || c > '9')
788 return 0;
789 } while (*sym);
790 return 1;
791}
792
793/* The pattern is an array of simple patterns. 775/* The pattern is an array of simple patterns.
794 * "foo" will match an exact string equal to "foo" 776 * "foo" will match an exact string equal to "foo"
795 * "*foo" will match a string that ends with "foo" 777 * "*foo" will match a string that ends with "foo"
796 * "foo*" will match a string that begins with "foo" 778 * "foo*" will match a string that begins with "foo"
797 * "foo$" will match a string equal to "foo" or "foo.1"
798 * where the '1' can be any number including several digits.
799 * The $ syntax is for sections where ld append a dot number
800 * to make section name unique.
801 */ 779 */
802static int match(const char *sym, const char * const pat[]) 780static int match(const char *sym, const char * const pat[])
803{ 781{
@@ -816,13 +794,6 @@ static int match(const char *sym, const char * const pat[])
816 if (strncmp(sym, p, strlen(p) - 1) == 0) 794 if (strncmp(sym, p, strlen(p) - 1) == 0)
817 return 1; 795 return 1;
818 } 796 }
819 /* "foo$" */
820 else if (*endp == '$') {
821 if (strncmp(sym, p, strlen(p) - 1) == 0) {
822 if (number_prefix(sym + strlen(p) - 1))
823 return 1;
824 }
825 }
826 /* no wildcards */ 797 /* no wildcards */
827 else { 798 else {
828 if (strcmp(p, sym) == 0) 799 if (strcmp(p, sym) == 0)
@@ -834,7 +805,7 @@ static int match(const char *sym, const char * const pat[])
834} 805}
835 806
836/* sections that we do not want to do full section mismatch check on */ 807/* sections that we do not want to do full section mismatch check on */
837static const char *section_white_list[] = 808static const char *const section_white_list[] =
838{ 809{
839 ".comment*", 810 ".comment*",
840 ".debug*", 811 ".debug*",
@@ -880,20 +851,20 @@ static void check_section(const char *modname, struct elf_info *elf,
880 851
881 852
882#define ALL_INIT_DATA_SECTIONS \ 853#define ALL_INIT_DATA_SECTIONS \
883 ".init.setup$", ".init.rodata$", ".meminit.rodata$", \ 854 ".init.setup", ".init.rodata", ".meminit.rodata", \
884 ".init.data$", ".meminit.data$" 855 ".init.data", ".meminit.data"
885#define ALL_EXIT_DATA_SECTIONS \ 856#define ALL_EXIT_DATA_SECTIONS \
886 ".exit.data$", ".memexit.data$" 857 ".exit.data", ".memexit.data"
887 858
888#define ALL_INIT_TEXT_SECTIONS \ 859#define ALL_INIT_TEXT_SECTIONS \
889 ".init.text$", ".meminit.text$" 860 ".init.text", ".meminit.text"
890#define ALL_EXIT_TEXT_SECTIONS \ 861#define ALL_EXIT_TEXT_SECTIONS \
891 ".exit.text$", ".memexit.text$" 862 ".exit.text", ".memexit.text"
892 863
893#define ALL_PCI_INIT_SECTIONS \ 864#define ALL_PCI_INIT_SECTIONS \
894 ".pci_fixup_early$", ".pci_fixup_header$", ".pci_fixup_final$", \ 865 ".pci_fixup_early", ".pci_fixup_header", ".pci_fixup_final", \
895 ".pci_fixup_enable$", ".pci_fixup_resume$", \ 866 ".pci_fixup_enable", ".pci_fixup_resume", \
896 ".pci_fixup_resume_early$", ".pci_fixup_suspend$" 867 ".pci_fixup_resume_early", ".pci_fixup_suspend"
897 868
898#define ALL_XXXINIT_SECTIONS MEM_INIT_SECTIONS 869#define ALL_XXXINIT_SECTIONS MEM_INIT_SECTIONS
899#define ALL_XXXEXIT_SECTIONS MEM_EXIT_SECTIONS 870#define ALL_XXXEXIT_SECTIONS MEM_EXIT_SECTIONS
@@ -901,8 +872,8 @@ static void check_section(const char *modname, struct elf_info *elf,
901#define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS 872#define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS
902#define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS 873#define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS
903 874
904#define DATA_SECTIONS ".data$", ".data.rel$" 875#define DATA_SECTIONS ".data", ".data.rel"
905#define TEXT_SECTIONS ".text$", ".text.unlikely$" 876#define TEXT_SECTIONS ".text", ".text.unlikely"
906 877
907#define INIT_SECTIONS ".init.*" 878#define INIT_SECTIONS ".init.*"
908#define MEM_INIT_SECTIONS ".meminit.*" 879#define MEM_INIT_SECTIONS ".meminit.*"
@@ -911,17 +882,18 @@ static void check_section(const char *modname, struct elf_info *elf,
911#define MEM_EXIT_SECTIONS ".memexit.*" 882#define MEM_EXIT_SECTIONS ".memexit.*"
912 883
913/* init data sections */ 884/* init data sections */
914static const char *init_data_sections[] = { ALL_INIT_DATA_SECTIONS, NULL }; 885static const char *const init_data_sections[] =
886 { ALL_INIT_DATA_SECTIONS, NULL };
915 887
916/* all init sections */ 888/* all init sections */
917static const char *init_sections[] = { ALL_INIT_SECTIONS, NULL }; 889static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL };
918 890
919/* All init and exit sections (code + data) */ 891/* All init and exit sections (code + data) */
920static const char *init_exit_sections[] = 892static const char *const init_exit_sections[] =
921 {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }; 893 {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL };
922 894
923/* data section */ 895/* data section */
924static const char *data_sections[] = { DATA_SECTIONS, NULL }; 896static const char *const data_sections[] = { DATA_SECTIONS, NULL };
925 897
926 898
927/* symbols in .data that may refer to init/exit sections */ 899/* symbols in .data that may refer to init/exit sections */
@@ -935,8 +907,8 @@ static const char *data_sections[] = { DATA_SECTIONS, NULL };
935 "*_probe_one", \ 907 "*_probe_one", \
936 "*_console" 908 "*_console"
937 909
938static const char *head_sections[] = { ".head.text*", NULL }; 910static const char *const head_sections[] = { ".head.text*", NULL };
939static const char *linker_symbols[] = 911static const char *const linker_symbols[] =
940 { "__init_begin", "_sinittext", "_einittext", NULL }; 912 { "__init_begin", "_sinittext", "_einittext", NULL };
941 913
942enum mismatch { 914enum mismatch {
@@ -958,7 +930,7 @@ struct sectioncheck {
958 const char *symbol_white_list[20]; 930 const char *symbol_white_list[20];
959}; 931};
960 932
961const struct sectioncheck sectioncheck[] = { 933static const struct sectioncheck sectioncheck[] = {
962/* Do not reference init/exit code/data from 934/* Do not reference init/exit code/data from
963 * normal code and data 935 * normal code and data
964 */ 936 */
@@ -1175,7 +1147,7 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
1175 1147
1176static inline int is_arm_mapping_symbol(const char *str) 1148static inline int is_arm_mapping_symbol(const char *str)
1177{ 1149{
1178 return str[0] == '$' && strchr("atd", str[1]) 1150 return str[0] == '$' && strchr("axtd", str[1])
1179 && (str[2] == '\0' || str[2] == '.'); 1151 && (str[2] == '\0' || str[2] == '.');
1180} 1152}
1181 1153
@@ -1703,12 +1675,11 @@ static void check_sec_ref(struct module *mod, const char *modname,
1703 1675
1704static char *remove_dot(char *s) 1676static char *remove_dot(char *s)
1705{ 1677{
1706 char *end; 1678 size_t n = strcspn(s, ".");
1707 int n = strcspn(s, ".");
1708 1679
1709 if (n > 0 && s[n] != 0) { 1680 if (n && s[n]) {
1710 strtoul(s + n + 1, &end, 10); 1681 size_t m = strspn(s + n + 1, "0123456789");
1711 if (end > s + n + 1 && (*end == '.' || *end == 0)) 1682 if (m && (s[n + m] == '.' || s[n + m] == 0))
1712 s[n] = 0; 1683 s[n] = 0;
1713 } 1684 }
1714 return s; 1685 return s;
@@ -2241,7 +2212,7 @@ int main(int argc, char **argv)
2241 err = 0; 2212 err = 0;
2242 2213
2243 for (mod = modules; mod; mod = mod->next) { 2214 for (mod = modules; mod; mod = mod->next) {
2244 char fname[strlen(mod->name) + 10]; 2215 char fname[PATH_MAX];
2245 2216
2246 if (mod->skip) 2217 if (mod->skip)
2247 continue; 2218 continue;
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 35d5a5877d04..59726243c2eb 100644..100755
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -37,7 +37,7 @@ create_package() {
37 s390*) 37 s390*)
38 debarch=s390$(grep -q CONFIG_64BIT=y $KCONFIG_CONFIG && echo x || true) ;; 38 debarch=s390$(grep -q CONFIG_64BIT=y $KCONFIG_CONFIG && echo x || true) ;;
39 ppc*) 39 ppc*)
40 debarch=powerpc ;; 40 debarch=$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo ppc64el || echo powerpc) ;;
41 parisc*) 41 parisc*)
42 debarch=hppa ;; 42 debarch=hppa ;;
43 mips*) 43 mips*)
@@ -64,7 +64,7 @@ create_package() {
64 fi 64 fi
65 65
66 # Create the package 66 # Create the package
67 dpkg-gencontrol -isp $forcearch -Vkernel:debarch="${debarch:-$(dpkg --print-architecture)}" -p$pname -P"$pdir" 67 dpkg-gencontrol $forcearch -Vkernel:debarch="${debarch:-$(dpkg --print-architecture)}" -p$pname -P"$pdir"
68 dpkg --build "$pdir" .. 68 dpkg --build "$pdir" ..
69} 69}
70 70
@@ -152,18 +152,16 @@ if grep -q '^CONFIG_MODULES=y' $KCONFIG_CONFIG ; then
152 rmdir "$tmpdir/lib/modules/$version" 152 rmdir "$tmpdir/lib/modules/$version"
153 fi 153 fi
154 if [ -n "$BUILD_DEBUG" ] ; then 154 if [ -n "$BUILD_DEBUG" ] ; then
155 ( 155 for module in $(find $tmpdir/lib/modules/ -name *.ko -printf '%P\n'); do
156 cd $tmpdir 156 module=lib/modules/$module
157 for module in $(find lib/modules/ -name *.ko); do 157 mkdir -p $(dirname $dbg_dir/usr/lib/debug/$module)
158 mkdir -p $(dirname $dbg_dir/usr/lib/debug/$module) 158 # only keep debug symbols in the debug file
159 # only keep debug symbols in the debug file 159 $OBJCOPY --only-keep-debug $tmpdir/$module $dbg_dir/usr/lib/debug/$module
160 $OBJCOPY --only-keep-debug $module $dbg_dir/usr/lib/debug/$module 160 # strip original module from debug symbols
161 # strip original module from debug symbols 161 $OBJCOPY --strip-debug $tmpdir/$module
162 $OBJCOPY --strip-debug $module 162 # then add a link to those
163 # then add a link to those 163 $OBJCOPY --add-gnu-debuglink=$dbg_dir/usr/lib/debug/$module $tmpdir/$module
164 $OBJCOPY --add-gnu-debuglink=$dbg_dir/usr/lib/debug/$module $module 164 done
165 done
166 )
167 fi 165 fi
168fi 166fi
169 167
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
index e046bff33589..e046bff33589 100644..100755
--- a/scripts/package/buildtar
+++ b/scripts/package/buildtar
diff --git a/scripts/profile2linkerlist.pl b/scripts/profile2linkerlist.pl
index 6943fa7cc95b..6943fa7cc95b 100644..100755
--- a/scripts/profile2linkerlist.pl
+++ b/scripts/profile2linkerlist.pl
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 650ecc83d7d7..001facfa5b74 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -388,10 +388,6 @@ do_file(char const *const fname)
388 "unrecognized ET_REL file: %s\n", fname); 388 "unrecognized ET_REL file: %s\n", fname);
389 fail_file(); 389 fail_file();
390 } 390 }
391 if (w2(ehdr->e_machine) == EM_S390) {
392 reltype = R_390_32;
393 mcount_adjust_32 = -4;
394 }
395 if (w2(ehdr->e_machine) == EM_MIPS) { 391 if (w2(ehdr->e_machine) == EM_MIPS) {
396 reltype = R_MIPS_32; 392 reltype = R_MIPS_32;
397 is_fake_mcount32 = MIPS32_is_fake_mcount; 393 is_fake_mcount32 = MIPS32_is_fake_mcount;
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 397b6b84e8c5..d4b665610d67 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -241,13 +241,6 @@ if ($arch eq "x86_64") {
241 $objcopy .= " -O elf32-i386"; 241 $objcopy .= " -O elf32-i386";
242 $cc .= " -m32"; 242 $cc .= " -m32";
243 243
244} elsif ($arch eq "s390" && $bits == 32) {
245 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_32\\s+_mcount\$";
246 $mcount_adjust = -4;
247 $alignment = 4;
248 $ld .= " -m elf_s390";
249 $cc .= " -m31";
250
251} elsif ($arch eq "s390" && $bits == 64) { 244} elsif ($arch eq "s390" && $bits == 64) {
252 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$"; 245 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$";
253 $mcount_adjust = -8; 246 $mcount_adjust = -8;
diff --git a/scripts/rt-tester/rt-tester.py b/scripts/rt-tester/rt-tester.py
index 6d916c2a45a5..6d916c2a45a5 100644..100755
--- a/scripts/rt-tester/rt-tester.py
+++ b/scripts/rt-tester/rt-tester.py
diff --git a/scripts/selinux/install_policy.sh b/scripts/selinux/install_policy.sh
index f6a0ce71015f..f6a0ce71015f 100644..100755
--- a/scripts/selinux/install_policy.sh
+++ b/scripts/selinux/install_policy.sh
diff --git a/scripts/sortextable.h b/scripts/sortextable.h
index 8fac3fd697a6..ba8700428e21 100644
--- a/scripts/sortextable.h
+++ b/scripts/sortextable.h
@@ -103,7 +103,7 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
103 Elf_Sym *sort_needed_sym; 103 Elf_Sym *sort_needed_sym;
104 Elf_Shdr *sort_needed_sec; 104 Elf_Shdr *sort_needed_sec;
105 Elf_Rel *relocs = NULL; 105 Elf_Rel *relocs = NULL;
106 int relocs_size; 106 int relocs_size = 0;
107 uint32_t *sort_done_location; 107 uint32_t *sort_done_location;
108 const char *secstrtab; 108 const char *secstrtab;
109 const char *strtab; 109 const char *strtab;
diff --git a/scripts/spelling.txt b/scripts/spelling.txt
new file mode 100644
index 000000000000..fc7fd52b5e03
--- /dev/null
+++ b/scripts/spelling.txt
@@ -0,0 +1,1042 @@
1# Originally from Debian's Lintian tool. Various false positives have been
2# removed, and various additions have been made as they've been discovered
3# in the kernel source.
4#
5# License: GPLv2
6#
7# The format of each line is:
8# mistake||correction
9#
10abandonning||abandoning
11abigious||ambiguous
12abitrate||arbitrate
13abov||above
14abreviated||abbreviated
15absense||absence
16absolut||absolute
17absoulte||absolute
18acccess||access
19acceleratoin||acceleration
20accelleration||acceleration
21accesing||accessing
22accesnt||accent
23accessable||accessible
24accesss||access
25accidentaly||accidentally
26accidentually||accidentally
27accoding||according
28accomodate||accommodate
29accomodates||accommodates
30accordign||according
31accoring||according
32accout||account
33accquire||acquire
34accquired||acquired
35acessable||accessible
36acess||access
37achitecture||architecture
38acient||ancient
39acitions||actions
40acitve||active
41acknowldegement||acknowldegement
42acknowledgement||acknowledgment
43ackowledge||acknowledge
44ackowledged||acknowledged
45acording||according
46activete||activate
47acumulating||accumulating
48adapater||adapter
49addional||additional
50additionaly||additionally
51addres||address
52addreses||addresses
53addresss||address
54aditional||additional
55aditionally||additionally
56aditionaly||additionally
57adminstrative||administrative
58adress||address
59adresses||addresses
60adviced||advised
61afecting||affecting
62agaist||against
63albumns||albums
64alegorical||allegorical
65algorith||algorithm
66algorithmical||algorithmically
67algoritm||algorithm
68algoritms||algorithms
69algorrithm||algorithm
70algorritm||algorithm
71allign||align
72allocatrd||allocated
73allocte||allocate
74allpication||application
75alocate||allocate
76alogirhtms||algorithms
77alogrithm||algorithm
78alot||a lot
79alow||allow
80alows||allows
81altough||although
82alue||value
83ambigious||ambiguous
84amoung||among
85amout||amount
86analysator||analyzer
87ang||and
88anniversery||anniversary
89annoucement||announcement
90anomolies||anomalies
91anomoly||anomaly
92anway||anyway
93aplication||application
94appearence||appearance
95applicaion||application
96appliction||application
97applictions||applications
98appplications||applications
99appropiate||appropriate
100appropriatly||appropriately
101approriate||appropriate
102approriately||appropriately
103aquainted||acquainted
104aquired||acquired
105arbitary||arbitrary
106architechture||architecture
107arguement||argument
108arguements||arguments
109aritmetic||arithmetic
110arne't||aren't
111arraival||arrival
112artifical||artificial
113artillary||artillery
114assiged||assigned
115assigment||assignment
116assigments||assignments
117assistent||assistant
118assocation||association
119associcated||associated
120assotiated||associated
121assum||assume
122assumtpion||assumption
123asuming||assuming
124asycronous||asynchronous
125asynchnous||asynchronous
126atomatically||automatically
127atomicly||atomically
128attachement||attachment
129attched||attached
130attemps||attempts
131attruibutes||attributes
132authentification||authentication
133automaticaly||automatically
134automaticly||automatically
135automatize||automate
136automatized||automated
137automatizes||automates
138autonymous||autonomous
139auxilliary||auxiliary
140avaiable||available
141avaible||available
142availabe||available
143availabled||available
144availablity||availability
145availale||available
146availavility||availability
147availble||available
148availiable||available
149avalable||available
150avaliable||available
151aysnc||async
152backgroud||background
153backword||backward
154backwords||backwards
155bahavior||behavior
156bakup||backup
157baloon||balloon
158baloons||balloons
159bandwith||bandwidth
160batery||battery
161beacuse||because
162becasue||because
163becomming||becoming
164becuase||because
165beeing||being
166befor||before
167begining||beginning
168beter||better
169betweeen||between
170bianries||binaries
171bitmast||bitmask
172boardcast||broadcast
173borad||board
174boundry||boundary
175brievely||briefly
176broadcat||broadcast
177cacluated||calculated
178caculation||calculation
179calender||calendar
180calle||called
181calucate||calculate
182calulate||calculate
183cancelation||cancellation
184capabilites||capabilities
185capabitilies||capabilities
186capatibilities||capabilities
187carefuly||carefully
188cariage||carriage
189catagory||category
190challange||challenge
191challanges||challenges
192chanell||channel
193changable||changeable
194channle||channel
195channnel||channel
196charachter||character
197charachters||characters
198charactor||character
199charater||character
200charaters||characters
201charcter||character
202checksuming||checksumming
203childern||children
204childs||children
205chiled||child
206chked||checked
207chnage||change
208chnages||changes
209chnnel||channel
210choosen||chosen
211chouse||chose
212circumvernt||circumvent
213claread||cleared
214clared||cleared
215closeing||closing
216clustred||clustered
217collapsable||collapsible
218colorfull||colorful
219comand||command
220comit||commit
221commerical||commercial
222comming||coming
223comminucation||communication
224commited||committed
225commiting||committing
226committ||commit
227commoditiy||commodity
228compability||compatibility
229compaibility||compatibility
230compatability||compatibility
231compatable||compatible
232compatibiliy||compatibility
233compatibilty||compatibility
234compilant||compliant
235compleatly||completely
236completly||completely
237complient||compliant
238componnents||components
239compres||compress
240compresion||compression
241comression||compression
242comunication||communication
243conbination||combination
244conditionaly||conditionally
245conected||connected
246configuratoin||configuration
247configuraton||configuration
248configuretion||configuration
249conider||consider
250conjuction||conjunction
251connectinos||connections
252connnection||connection
253connnections||connections
254consistancy||consistency
255consistant||consistent
256containes||contains
257containts||contains
258contaisn||contains
259contant||contact
260contence||contents
261continous||continuous
262continously||continuously
263continueing||continuing
264contraints||constraints
265controled||controlled
266controler||controller
267controll||control
268contruction||construction
269contry||country
270convertion||conversion
271convertor||converter
272convienient||convenient
273convinient||convenient
274corected||corrected
275correponding||corresponding
276correponds||corresponds
277correspoding||corresponding
278cotrol||control
279couter||counter
280coutner||counter
281cryptocraphic||cryptographic
282cunter||counter
283curently||currently
284dafault||default
285deafult||default
286deamon||daemon
287decompres||decompress
288decription||description
289defailt||default
290defferred||deferred
291definate||definite
292definately||definitely
293defintion||definition
294defualt||default
295defult||default
296deivce||device
297delared||declared
298delare||declare
299delares||declares
300delaring||declaring
301delemiter||delimiter
302dependancies||dependencies
303dependancy||dependency
304dependant||dependent
305depreacted||deprecated
306depreacte||deprecate
307desactivate||deactivate
308desciptors||descriptors
309descrition||description
310descritptor||descriptor
311desctiptor||descriptor
312desriptor||descriptor
313desriptors||descriptors
314destory||destroy
315destoryed||destroyed
316destorys||destroys
317destroied||destroyed
318detabase||database
319develope||develop
320developement||development
321developped||developed
322developpement||development
323developper||developer
324developpment||development
325deveolpment||development
326devided||divided
327deviece||device
328diable||disable
329dictionnary||dictionary
330diferent||different
331differrence||difference
332difinition||definition
333diplay||display
334direectly||directly
335disapear||disappear
336disapeared||disappeared
337disappared||disappeared
338disconnet||disconnect
339discontinous||discontinuous
340dispertion||dispersion
341dissapears||disappears
342distiction||distinction
343docuentation||documentation
344documantation||documentation
345documentaion||documentation
346documment||document
347dorp||drop
348dosen||doesn
349downlad||download
350downlads||downloads
351druing||during
352dynmaic||dynamic
353easilly||easily
354ecspecially||especially
355edditable||editable
356editting||editing
357efficently||efficiently
358ehther||ether
359eigth||eight
360eletronic||electronic
361enabledi||enabled
362enchanced||enhanced
363encorporating||incorporating
364encrupted||encrypted
365encrypiton||encryption
366endianess||endianness
367enhaced||enhanced
368enlightnment||enlightenment
369enocded||encoded
370enterily||entirely
371enviroiment||environment
372enviroment||environment
373environement||environment
374environent||environment
375eqivalent||equivalent
376equiped||equipped
377equivelant||equivalent
378equivilant||equivalent
379eror||error
380estbalishment||establishment
381etsablishment||establishment
382etsbalishment||establishment
383excecutable||executable
384exceded||exceeded
385excellant||excellent
386existance||existence
387existant||existent
388exixt||exist
389exlcude||exclude
390exlcusive||exclusive
391exmaple||example
392expecially||especially
393explicite||explicit
394explicitely||explicitly
395explict||explicit
396explictly||explicitly
397expresion||expression
398exprimental||experimental
399extened||extended
400extensability||extensibility
401extention||extension
402extracter||extractor
403faild||failed
404faill||fail
405failue||failure
406failuer||failure
407faireness||fairness
408faliure||failure
409familar||familiar
410fatser||faster
411feauture||feature
412feautures||features
413fetaure||feature
414fetaures||features
415fileystem||filesystem
416finanize||finalize
417findn||find
418finilizes||finalizes
419finsih||finish
420flusing||flushing
421folloing||following
422followign||following
423follwing||following
424forseeable||foreseeable
425forse||force
426fortan||fortran
427forwardig||forwarding
428framwork||framework
429frequncy||frequency
430frome||from
431fucntion||function
432fuction||function
433fuctions||functions
434funcion||function
435functionallity||functionality
436functionaly||functionally
437functionnality||functionality
438functonality||functionality
439funtion||function
440funtions||functions
441furthur||further
442futhermore||furthermore
443futrue||future
444gaurenteed||guaranteed
445generiously||generously
446genric||generic
447globel||global
448grabing||grabbing
449grahical||graphical
450grahpical||graphical
451grapic||graphic
452guage||gauge
453guarentee||guarantee
454halfs||halves
455hander||handler
456handfull||handful
457hanled||handled
458harware||hardware
459heirarchically||hierarchically
460helpfull||helpful
461hierachy||hierarchy
462hierarchie||hierarchy
463howver||however
464hsould||should
465hypter||hyper
466identidier||identifier
467imblance||imbalance
468immeadiately||immediately
469immedaite||immediate
470immediatelly||immediately
471immediatly||immediately
472immidiate||immediate
473impelentation||implementation
474impementated||implemented
475implemantation||implementation
476implemenation||implementation
477implementaiton||implementation
478implementated||implemented
479implemention||implementation
480implemetation||implementation
481implemntation||implementation
482implentation||implementation
483implmentation||implementation
484implmenting||implementing
485incomming||incoming
486incompatabilities||incompatibilities
487incompatable||incompatible
488inconsistant||inconsistent
489increas||increase
490incrment||increment
491indendation||indentation
492indended||intended
493independant||independent
494independantly||independently
495independed||independent
496indiate||indicate
497inexpect||inexpected
498infomation||information
499informatiom||information
500informations||information
501informtion||information
502infromation||information
503ingore||ignore
504inital||initial
505initalised||initialized
506initalise||initialize
507initalize||initialize
508initation||initiation
509initators||initiators
510initializiation||initialization
511initialzed||initialized
512initilization||initialization
513initilize||initialize
514inofficial||unofficial
515instal||install
516inteface||interface
517integreated||integrated
518integrety||integrity
519integrey||integrity
520intendet||intended
521intented||intended
522interanl||internal
523interchangable||interchangeable
524interferring||interfering
525interger||integer
526intermittant||intermittent
527internel||internal
528interoprability||interoperability
529interrface||interface
530interrrupt||interrupt
531interrup||interrupt
532interrups||interrupts
533interruptted||interrupted
534interupted||interrupted
535interupt||interrupt
536intial||initial
537intialized||initialized
538intialize||initialize
539intregral||integral
540intrrupt||interrupt
541intuative||intuitive
542invaid||invalid
543invalde||invald
544invalide||invalid
545invididual||individual
546invokation||invocation
547invokations||invocations
548irrelevent||irrelevant
549isssue||issue
550itslef||itself
551jave||java
552jeffies||jiffies
553juse||just
554jus||just
555kown||known
556langage||language
557langauage||language
558langauge||language
559langugage||language
560lauch||launch
561leightweight||lightweight
562lengh||length
563lenght||length
564lenth||length
565lesstiff||lesstif
566libaries||libraries
567libary||library
568librairies||libraries
569libraris||libraries
570licenceing||licencing
571loggging||logging
572loggin||login
573logile||logfile
574loosing||losing
575losted||lost
576machinary||machinery
577maintainance||maintenance
578maintainence||maintenance
579maintan||maintain
580makeing||making
581malplaced||misplaced
582malplace||misplace
583managable||manageable
584managment||management
585mangement||management
586manoeuvering||maneuvering
587mappping||mapping
588mathimatical||mathematical
589mathimatic||mathematic
590mathimatics||mathematics
591maxium||maximum
592mechamism||mechanism
593meetign||meeting
594ment||meant
595mergable||mergeable
596mesage||message
597messags||messages
598messgaes||messages
599messsage||message
600messsages||messages
601microprocesspr||microprocessor
602milliseonds||milliseconds
603minumum||minimum
604miscelleneous||miscellaneous
605misformed||malformed
606mispelled||misspelled
607mispelt||misspelt
608miximum||maximum
609mmnemonic||mnemonic
610mnay||many
611modeled||modelled
612modulues||modules
613monochorome||monochrome
614monochromo||monochrome
615monocrome||monochrome
616mopdule||module
617mroe||more
618mulitplied||multiplied
619multidimensionnal||multidimensional
620multple||multiple
621mumber||number
622muticast||multicast
623mutiple||multiple
624mutli||multi
625nams||names
626navagating||navigating
627nead||need
628neccecary||necessary
629neccesary||necessary
630neccessary||necessary
631necesary||necessary
632negaive||negative
633negoitation||negotiation
634negotation||negotiation
635nerver||never
636nescessary||necessary
637nessessary||necessary
638noticable||noticeable
639notications||notifications
640notifed||notified
641numebr||number
642numner||number
643obtaion||obtain
644occassionally||occasionally
645occationally||occasionally
646occurance||occurrence
647occurances||occurrences
648occured||occurred
649occurence||occurrence
650occure||occurred
651occuring||occurring
652offet||offset
653omitt||omit
654ommiting||omitting
655ommitted||omitted
656onself||oneself
657ony||only
658operatione||operation
659opertaions||operations
660optionnal||optional
661optmizations||optimizations
662orientatied||orientated
663orientied||oriented
664otherise||otherwise
665ouput||output
666overaall||overall
667overhread||overhead
668overlaping||overlapping
669overriden||overridden
670overun||overrun
671pacakge||package
672pachage||package
673packacge||package
674packege||package
675packge||package
676packtes||packets
677pakage||package
678pallette||palette
679paln||plan
680paramameters||parameters
681paramater||parameter
682parametes||parameters
683parametised||parametrised
684paramter||parameter
685paramters||parameters
686particuarly||particularly
687particularily||particularly
688pased||passed
689passin||passing
690pathes||paths
691pecularities||peculiarities
692peformance||performance
693peice||piece
694pendantic||pedantic
695peprocessor||preprocessor
696perfoming||performing
697permissons||permissions
698peroid||period
699persistance||persistence
700persistant||persistent
701platfrom||platform
702plattform||platform
703pleaes||please
704ploting||plotting
705plugable||pluggable
706poinnter||pointer
707poiter||pointer
708posible||possible
709positon||position
710possibilites||possibilities
711powerfull||powerful
712preceeded||preceded
713preceeding||preceding
714preceed||precede
715precendence||precedence
716precission||precision
717prefered||preferred
718prefferably||preferably
719premption||preemption
720prepaired||prepared
721pressre||pressure
722primative||primitive
723princliple||principle
724priorty||priority
725privilaged||privileged
726privilage||privilege
727priviledge||privilege
728priviledges||privileges
729probaly||probably
730procceed||proceed
731proccesors||processors
732procesed||processed
733proces||process
734processessing||processing
735processess||processes
736processpr||processor
737processsed||processed
738processsing||processing
739procteted||protected
740prodecure||procedure
741progams||programs
742progess||progress
743programers||programmers
744programm||program
745programms||programs
746progresss||progress
747promps||prompts
748pronnounced||pronounced
749prononciation||pronunciation
750pronouce||pronounce
751pronunce||pronounce
752propery||property
753propigate||propagate
754propigation||propagation
755propogate||propagate
756prosess||process
757protable||portable
758protcol||protocol
759protecion||protection
760protocoll||protocol
761psudo||pseudo
762psuedo||pseudo
763psychadelic||psychedelic
764pwoer||power
765quering||querying
766raoming||roaming
767reasearcher||researcher
768reasearchers||researchers
769reasearch||research
770recepient||recipient
771receving||receiving
772recieved||received
773recieve||receive
774reciever||receiver
775recieves||receives
776recogniced||recognised
777recognizeable||recognizable
778recommanded||recommended
779recyle||recycle
780redircet||redirect
781redirectrion||redirection
782refcounf||refcount
783refence||reference
784refered||referred
785referenace||reference
786refering||referring
787refernces||references
788refernnce||reference
789refrence||reference
790registerd||registered
791registeresd||registered
792registes||registers
793registraration||registration
794regster||register
795regualar||regular
796reguator||regulator
797regulamentations||regulations
798reigstration||registration
799releated||related
800relevent||relevant
801remoote||remote
802remore||remote
803removeable||removable
804repectively||respectively
805replacable||replaceable
806replacments||replacements
807replys||replies
808reponse||response
809representaion||representation
810reqeust||request
811requiere||require
812requirment||requirement
813requred||required
814requried||required
815requst||request
816reseting||resetting
817resizeable||resizable
818resouces||resources
819resoures||resources
820ressizes||resizes
821ressource||resource
822ressources||resources
823retransmited||retransmitted
824retreived||retrieved
825retreive||retrieve
826retrive||retrieve
827retuned||returned
828reuest||request
829reuqest||request
830reutnred||returned
831rmeoved||removed
832rmeove||remove
833rmeoves||removes
834rountine||routine
835routins||routines
836rquest||request
837runing||running
838runned||ran
839runnning||running
840runtine||runtime
841sacrifying||sacrificing
842safly||safely
843safty||safety
844savable||saveable
845scaned||scanned
846scaning||scanning
847scarch||search
848seach||search
849searchs||searches
850secquence||sequence
851secund||second
852segement||segment
853senarios||scenarios
854sentivite||sensitive
855separatly||separately
856sepcify||specify
857sepc||spec
858seperated||separated
859seperately||separately
860seperate||separate
861seperatly||separately
862seperator||separator
863sepperate||separate
864sequece||sequence
865sequencial||sequential
866serveral||several
867setts||sets
868settting||setting
869shotdown||shutdown
870shoud||should
871shoule||should
872shrinked||shrunk
873siginificantly||significantly
874signabl||signal
875similary||similarly
876similiar||similar
877simlar||similar
878simliar||similar
879simpified||simplified
880singaled||signaled
881singal||signal
882singed||signed
883sleeped||slept
884softwares||software
885speach||speech
886specfic||specific
887speciefied||specified
888specifc||specific
889specifed||specified
890specificatin||specification
891specificaton||specification
892specifing||specifying
893specifiying||specifying
894speficied||specified
895speicify||specify
896speling||spelling
897spinlcok||spinlock
898spinock||spinlock
899splitted||split
900spreaded||spread
901sructure||structure
902stablilization||stabilization
903staically||statically
904staion||station
905standardss||standards
906standartization||standardization
907standart||standard
908staticly||statically
909stoped||stopped
910stoppped||stopped
911straming||streaming
912struc||struct
913structres||structures
914stuct||struct
915sturcture||structure
916subdirectoires||subdirectories
917suble||subtle
918succesfully||successfully
919succesful||successful
920successfull||successful
921sucessfully||successfully
922sucess||success
923superflous||superfluous
924superseeded||superseded
925suplied||supplied
926suported||supported
927suport||support
928suppored||supported
929supportin||supporting
930suppoted||supported
931suppported||supported
932suppport||support
933supress||suppress
934surpresses||suppresses
935susbsystem||subsystem
936suspicously||suspiciously
937swaping||swapping
938switchs||switches
939symetric||symmetric
940synax||syntax
941synchonized||synchronized
942syncronize||synchronize
943syncronizing||synchronizing
944syncronus||synchronous
945syste||system
946sytem||system
947sythesis||synthesis
948taht||that
949targetted||targeted
950targetting||targeting
951teh||the
952temorary||temporary
953temproarily||temporarily
954thier||their
955threds||threads
956threshhold||threshold
957throught||through
958thses||these
959tiggered||triggered
960tipically||typically
961tmis||this
962torerable||tolerable
963tramsmitted||transmitted
964tramsmit||transmit
965tranfer||transfer
966transciever||transceiver
967transferd||transferrd
968transfered||transferred
969transfering||transferring
970transision||transition
971transmittd||transmitted
972transormed||transformed
973trasmission||transmission
974treshold||threshold
975trigerring||triggering
976trun||turn
977ture||true
978tyep||type
979udpate||update
980uesd||used
981unconditionaly||unconditionally
982underun||underrun
983unecessary||unnecessary
984unexecpted||unexpected
985unexpectd||unexpected
986unexpeted||unexpected
987unfortunatelly||unfortunately
988unifiy||unify
989unknonw||unknown
990unknow||unknown
991unkown||unknown
992unneedingly||unnecessarily
993unresgister||unregister
994unsinged||unsigned
995unstabel||unstable
996unsuccessfull||unsuccessful
997unsuported||unsupported
998untill||until
999unuseful||useless
1000upate||update
1001usefule||useful
1002usefull||useful
1003usege||usage
1004usera||users
1005usualy||usually
1006utilites||utilities
1007utillities||utilities
1008utilties||utilities
1009utiltity||utility
1010utitity||utility
1011utitlty||utility
1012vaid||valid
1013vaild||valid
1014valide||valid
1015variantions||variations
1016varient||variant
1017vaule||value
1018verbse||verbose
1019verisons||versions
1020verison||version
1021verson||version
1022vicefersa||vice-versa
1023virtal||virtual
1024virtaul||virtual
1025virtiual||virtual
1026visiters||visitors
1027vitual||virtual
1028wating||waiting
1029whataver||whatever
1030whenver||whenever
1031wheter||whether
1032whe||when
1033wierd||weird
1034wiil||will
1035wirte||write
1036withing||within
1037wnat||want
1038workarould||workaround
1039writeing||writing
1040writting||writing
1041zombe||zombie
1042zomebie||zombie
diff --git a/scripts/tags.sh b/scripts/tags.sh
index e6b011fe1d0d..cdb491d84503 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -168,6 +168,7 @@ exuberant()
168 --extra=+f --c-kinds=+px \ 168 --extra=+f --c-kinds=+px \
169 --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ 169 --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \
170 --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ 170 --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \
171 --regex-c='/^COMPAT_SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/compat_sys_\1/' \
171 --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ 172 --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \
172 --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \ 173 --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \
173 --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \ 174 --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \
@@ -192,10 +193,9 @@ exuberant()
192 --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ 193 --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
193 --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ 194 --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \
194 --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \ 195 --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \
195 --regex-c++='/TESTPCGFLAG\(([^,)]*).*/PageCgroup\1/' \ 196 --regex-c++='/TASK_PFA_TEST\([^,]*,\s*([^)]*)\)/task_\1/' \
196 --regex-c++='/SETPCGFLAG\(([^,)]*).*/SetPageCgroup\1/' \ 197 --regex-c++='/TASK_PFA_SET\([^,]*,\s*([^)]*)\)/task_set_\1/' \
197 --regex-c++='/CLEARPCGFLAG\(([^,)]*).*/ClearPageCgroup\1/' \ 198 --regex-c++='/TASK_PFA_CLEAR\([^,]*,\s*([^)]*)\)/task_clear_\1/'\
198 --regex-c++='/TESTCLEARPCGFLAG\(([^,)]*).*/TestClearPageCgroup\1/' \
199 --regex-c='/PCI_OP_READ\((\w*).*[1-4]\)/pci_bus_read_config_\1/' \ 199 --regex-c='/PCI_OP_READ\((\w*).*[1-4]\)/pci_bus_read_config_\1/' \
200 --regex-c='/PCI_OP_WRITE\((\w*).*[1-4]\)/pci_bus_write_config_\1/' \ 200 --regex-c='/PCI_OP_WRITE\((\w*).*[1-4]\)/pci_bus_write_config_\1/' \
201 --regex-c='/DEFINE_(MUTEX|SEMAPHORE|SPINLOCK)\((\w*)/\2/v/' \ 201 --regex-c='/DEFINE_(MUTEX|SEMAPHORE|SPINLOCK)\((\w*)/\2/v/' \
@@ -231,6 +231,7 @@ emacs()
231 all_target_sources | xargs $1 -a \ 231 all_target_sources | xargs $1 -a \
232 --regex='/^\(ENTRY\|_GLOBAL\)(\([^)]*\)).*/\2/' \ 232 --regex='/^\(ENTRY\|_GLOBAL\)(\([^)]*\)).*/\2/' \
233 --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \ 233 --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \
234 --regex='/^COMPAT_SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/compat_sys_\1/' \
234 --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \ 235 --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \
235 --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \ 236 --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \
236 --regex='/PAGEFLAG(\([^,)]*\).*/Page\1/' \ 237 --regex='/PAGEFLAG(\([^,)]*\).*/Page\1/' \
@@ -254,14 +255,13 @@ emacs()
254 --regex='/__CLEARPAGEFLAG_NOOP(\([^,)]*\).*/__ClearPage\1/' \ 255 --regex='/__CLEARPAGEFLAG_NOOP(\([^,)]*\).*/__ClearPage\1/' \
255 --regex='/TESTCLEARFLAG_FALSE(\([^,)]*\).*/TestClearPage\1/' \ 256 --regex='/TESTCLEARFLAG_FALSE(\([^,)]*\).*/TestClearPage\1/' \
256 --regex='/__TESTCLEARFLAG_FALSE(\([^,)]*\).*/__TestClearPage\1/' \ 257 --regex='/__TESTCLEARFLAG_FALSE(\([^,)]*\).*/__TestClearPage\1/' \
257 --regex='/TESTPCGFLAG\(([^,)]*).*/PageCgroup\1/' \ 258 --regex='/TASK_PFA_TEST\([^,]*,\s*([^)]*)\)/task_\1/' \
258 --regex='/SETPCGFLAG\(([^,)]*).*/SetPageCgroup\1/' \ 259 --regex='/TASK_PFA_SET\([^,]*,\s*([^)]*)\)/task_set_\1/' \
259 --regex='/CLEARPCGFLAG\(([^,)]*).*/ClearPageCgroup\1/' \ 260 --regex='/TASK_PFA_CLEAR\([^,]*,\s*([^)]*)\)/task_clear_\1/' \
260 --regex='/TESTCLEARPCGFLAG\(([^,)]*).*/TestClearPageCgroup\1/' \
261 --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/' \ 261 --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/' \
262 --regex='/PCI_OP_READ(\([a-z]*[a-z]\).*[1-4])/pci_bus_read_config_\1/' \ 262 --regex='/PCI_OP_READ(\([a-z]*[a-z]\).*[1-4])/pci_bus_read_config_\1/' \
263 --regex='/PCI_OP_WRITE(\([a-z]*[a-z]\).*[1-4])/pci_bus_write_config_\1/'\ 263 --regex='/PCI_OP_WRITE(\([a-z]*[a-z]\).*[1-4])/pci_bus_write_config_\1/'\
264 --regex='/DEFINE_HASHTABLE\((\w*)/\1/v/' 264 --regex='/[^#]*DEFINE_HASHTABLE(\([^,)]*\)/\1/'
265 265
266 all_kconfigs | xargs $1 -a \ 266 all_kconfigs | xargs $1 -a \
267 --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' 267 --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'
diff --git a/scripts/tracing/draw_functrace.py b/scripts/tracing/draw_functrace.py
index db40fa04cd51..db40fa04cd51 100644..100755
--- a/scripts/tracing/draw_functrace.py
+++ b/scripts/tracing/draw_functrace.py
diff --git a/scripts/xz_wrap.sh b/scripts/xz_wrap.sh
index 7a2d372f4885..7a2d372f4885 100644..100755
--- a/scripts/xz_wrap.sh
+++ b/scripts/xz_wrap.sh