checkpatch: add a "prefer __aligned" check
[linux-2.6.git] / scripts / checkpatch.pl
index c71a0fa..8f35f0e 100755 (executable)
@@ -1,8 +1,8 @@
 #!/usr/bin/perl -w
-# (c) 2001, Dave Jones. <davej@redhat.com> (the file handling bit)
+# (c) 2001, Dave Jones. (the file handling bit)
 # (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
 # (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
-# (c) 2008, Andy Whitcroft <apw@canonical.com>
+# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
 # Licensed under the terms of the GNU GPL License version 2
 
 use strict;
@@ -10,7 +10,7 @@ use strict;
 my $P = $0;
 $P =~ s@.*/@@g;
 
-my $V = '0.27';
+my $V = '0.31';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -28,6 +28,41 @@ my $mailback = 0;
 my $summary_file = 0;
 my $root;
 my %debug;
+my $help = 0;
+
+sub help {
+       my ($exitcode) = @_;
+
+       print << "EOM";
+Usage: $P [OPTION]... [FILE]...
+Version: $V
+
+Options:
+  -q, --quiet                quiet
+  --no-tree                  run without a kernel tree
+  --no-signoff               do not check for 'Signed-off-by' line
+  --patch                    treat FILE as patchfile (default)
+  --emacs                    emacs compile window format
+  --terse                    one line per report
+  -f, --file                 treat FILE as regular source file
+  --subjective, --strict     enable more subjective tests
+  --root=PATH                PATH to the kernel tree root
+  --no-summary               suppress the per-file summary
+  --mailback                 only produce a report in case of warnings/errors
+  --summary-file             include the filename in summary
+  --debug KEY=[0|1]          turn on/off debugging of KEY, where KEY is one of
+                             'values', 'possible', 'type', and 'attr' (default
+                             is all off)
+  --test-only=WORD           report only warnings/errors containing WORD
+                             literally
+  -h, --help, --version      display this help and exit
+
+When FILE is - read standard input.
+EOM
+
+       exit($exitcode);
+}
+
 GetOptions(
        'q|quiet+'      => \$quiet,
        'tree!'         => \$tree,
@@ -35,7 +70,7 @@ GetOptions(
        'patch!'        => \$chk_patch,
        'emacs!'        => \$emacs,
        'terse!'        => \$terse,
-       'file!'         => \$file,
+       'f|file!'       => \$file,
        'subjective!'   => \$check,
        'strict!'       => \$check,
        'root=s'        => \$root,
@@ -45,22 +80,16 @@ GetOptions(
 
        'debug=s'       => \%debug,
        'test-only=s'   => \$tst_only,
-) or exit;
+       'h|help'        => \$help,
+       'version'       => \$help
+) or help(1);
+
+help(0) if ($help);
 
 my $exit = 0;
 
 if ($#ARGV < 0) {
-       print "usage: $P [options] patchfile\n";
-       print "version: $V\n";
-       print "options: -q               => quiet\n";
-       print "         --no-tree        => run without a kernel tree\n";
-       print "         --terse          => one line per report\n";
-       print "         --emacs          => emacs compile window format\n";
-       print "         --file           => check a source file\n";
-       print "         --strict         => enable more subjective tests\n";
-       print "         --root           => path to the kernel tree root\n";
-       print "         --no-summary     => suppress the per-file summary\n";
-       print "         --summary-file   => include the filename in summary\n";
+       print "$P: no input files\n";
        exit(1);
 }
 
@@ -74,6 +103,8 @@ for my $key (keys %debug) {
        die "$@" if ($@);
 }
 
+my $rpt_cleaners = 0;
+
 if ($terse) {
        $emacs = 1;
        $quiet++;
@@ -101,7 +132,10 @@ if ($tree) {
 
 my $emitted_corrupt = 0;
 
-our $Ident       = qr{[A-Za-z_][A-Za-z\d_]*};
+our $Ident     = qr{
+                       [A-Za-z_][A-Za-z\d_]*
+                       (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)*
+               }x;
 our $Storage   = qr{extern|static|asmlinkage};
 our $Sparse    = qr{
                        __user|
@@ -110,13 +144,32 @@ our $Sparse       = qr{
                        __iomem|
                        __must_check|
                        __init_refok|
-                       __kprobes
+                       __kprobes|
+                       __ref|
+                       __rcu
                }x;
+
+# Notes to $Attribute:
+# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
 our $Attribute = qr{
                        const|
+                       __percpu|
+                       __nocast|
+                       __safe|
+                       __bitwise__|
+                       __packed__|
+                       __packed2__|
+                       __naked|
+                       __maybe_unused|
+                       __always_unused|
+                       __noreturn|
+                       __used|
+                       __cold|
+                       __noclone|
+                       __deprecated|
                        __read_mostly|
                        __kprobes|
-                       __(?:mem|cpu|dev|)(?:initdata|init)|
+                       __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)|
                        ____cacheline_aligned|
                        ____cacheline_aligned_in_smp|
                        ____cacheline_internodealigned_in_smp|
@@ -152,10 +205,28 @@ our $UTF8 = qr {
 }x;
 
 our $typeTypedefs = qr{(?x:
-       (?:__)?(?:u|s|be|le)(?:\d|\d\d)|
+       (?:__)?(?:u|s|be|le)(?:8|16|32|64)|
        atomic_t
 )};
 
+our $logFunctions = qr{(?x:
+       printk|
+       [a-z]+_(emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)|
+       WARN|
+       panic|
+       MODULE_[A-Z_]+
+)};
+
+our $signature_tags = qr{(?xi:
+       Signed-off-by:|
+       Acked-by:|
+       Tested-by:|
+       Reviewed-by:|
+       Reported-by:|
+       To:|
+       Cc:
+)};
+
 our @typeList = (
        qr{void},
        qr{(?:unsigned\s+)?char},
@@ -180,6 +251,12 @@ our @modifierList = (
        qr{fastcall},
 );
 
+our $allowed_asm_includes = qr{(?x:
+       irq|
+       memory
+)};
+# memory.h: ARM has a custom one
+
 sub build_types {
        my $mods = "(?x:  \n" . join("|\n  ", @modifierList) . "\n)";
        my $all = "(?x:  \n" . join("|\n  ", @typeList) . "\n)";
@@ -202,6 +279,20 @@ sub build_types {
 }
 build_types();
 
+our $match_balanced_parentheses = qr/(\((?:[^\(\)]+|(-1))*\))/;
+
+our $Typecast  = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*};
+our $LvalOrFunc        = qr{($Lval)\s*($match_balanced_parentheses{0,1})\s*};
+
+sub deparenthesize {
+       my ($string) = @_;
+       return "" if (!defined($string));
+       $string =~ s@^\s*\(\s*@@g;
+       $string =~ s@\s*\)\s*$@@g;
+       $string =~ s@\s+@ @g;
+       return $string;
+}
+
 $chk_signoff = 0 if ($file);
 
 my @dep_includes = ();
@@ -275,6 +366,76 @@ sub top_of_kernel_tree {
        return 1;
 }
 
+sub parse_email {
+       my ($formatted_email) = @_;
+
+       my $name = "";
+       my $address = "";
+       my $comment = "";
+
+       if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) {
+               $name = $1;
+               $address = $2;
+               $comment = $3 if defined $3;
+       } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) {
+               $address = $1;
+               $comment = $2 if defined $2;
+       } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) {
+               $address = $1;
+               $comment = $2 if defined $2;
+               $formatted_email =~ s/$address.*$//;
+               $name = $formatted_email;
+               $name =~ s/^\s+|\s+$//g;
+               $name =~ s/^\"|\"$//g;
+               # If there's a name left after stripping spaces and
+               # leading quotes, and the address doesn't have both
+               # leading and trailing angle brackets, the address
+               # is invalid. ie:
+               #   "joe smith joe@smith.com" bad
+               #   "joe smith <joe@smith.com" bad
+               if ($name ne "" && $address !~ /^<[^>]+>$/) {
+                       $name = "";
+                       $address = "";
+                       $comment = "";
+               }
+       }
+
+       $name =~ s/^\s+|\s+$//g;
+       $name =~ s/^\"|\"$//g;
+       $address =~ s/^\s+|\s+$//g;
+       $address =~ s/^\<|\>$//g;
+
+       if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
+               $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
+               $name = "\"$name\"";
+       }
+
+       return ($name, $address, $comment);
+}
+
+sub format_email {
+       my ($name, $address) = @_;
+
+       my $formatted_email;
+
+       $name =~ s/^\s+|\s+$//g;
+       $name =~ s/^\"|\"$//g;
+       $address =~ s/^\s+|\s+$//g;
+
+       if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
+               $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
+               $name = "\"$name\"";
+       }
+
+       if ("$name" eq "") {
+               $formatted_email = "$address";
+       } else {
+               $formatted_email = "$name <$address>";
+       }
+
+       return $formatted_email;
+}
+
 sub expand_tabs {
        my ($str) = @_;
 
@@ -355,6 +516,13 @@ sub sanitise_line {
                        $off++;
                        next;
                }
+               if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') {
+                       $sanitise_quote = '//';
+
+                       substr($res, $off, 2, $sanitise_quote);
+                       $off++;
+                       next;
+               }
 
                # A \ in a string means ignore the next character.
                if (($sanitise_quote eq "'" || $sanitise_quote eq '"') &&
@@ -378,6 +546,8 @@ sub sanitise_line {
                #print "c<$c> SQ<$sanitise_quote>\n";
                if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") {
                        substr($res, $off, 1, $;);
+               } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") {
+                       substr($res, $off, 1, $;);
                } elsif ($off != 0 && $sanitise_quote && $c ne "\t") {
                        substr($res, $off, 1, 'X');
                } else {
@@ -385,6 +555,10 @@ sub sanitise_line {
                }
        }
 
+       if ($sanitise_quote eq '//') {
+               $sanitise_quote = '';
+       }
+
        # The pathname on a #include may be surrounded by '<' and '>'.
        if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) {
                my $clean = 'X' x length($1);
@@ -495,6 +669,9 @@ sub ctx_statement_block {
                        $type = ($level != 0)? '{' : '';
 
                        if ($level == 0) {
+                               if (substr($blk, $off + 1, 1) eq ';') {
+                                       $off++;
+                               }
                                last;
                        }
                }
@@ -609,15 +786,15 @@ sub ctx_block_get {
                $blk .= $rawlines[$line];
 
                # Handle nested #if/#else.
-               if ($rawlines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
+               if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
                        push(@stack, $level);
-               } elsif ($rawlines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
+               } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
                        $level = $stack[$#stack - 1];
-               } elsif ($rawlines[$line] =~ /^.\s*#\s*endif\b/) {
+               } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
                        $level = pop(@stack);
                }
 
-               foreach my $c (split(//, $rawlines[$line])) {
+               foreach my $c (split(//, $lines[$line])) {
                        ##print "C<$c>L<$level><$open$close>O<$off>\n";
                        if ($off > 0) {
                                $off--;
@@ -777,7 +954,12 @@ sub annotate_values {
                                $av_preprocessor = 0;
                        }
 
-               } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\()/) {
+               } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') {
+                       print "CAST($1)\n" if ($dbg_values > 1);
+                       push(@av_paren_type, $type);
+                       $type = 'C';
+
+               } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
                        print "DECLARE($1)\n" if ($dbg_values > 1);
                        $type = 'T';
 
@@ -954,23 +1136,25 @@ sub annotate_values {
 
 sub possible {
        my ($possible, $line) = @_;
-
-       print "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
-       if ($possible !~ /(?:
+       my $notPermitted = qr{(?:
                ^(?:
                        $Modifier|
                        $Storage|
                        $Type|
-                       DEFINE_\S+|
+                       DEFINE_\S+
+               )$|
+               ^(?:
                        goto|
                        return|
                        case|
                        else|
                        asm|__asm__|
                        do
-               )$|
+               )(?:\s|$)|
                ^(?:typedef|struct|enum)\b
-           )/x) {
+           )}x;
+       warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
+       if ($possible !~ $notPermitted) {
                # Check for modifiers.
                $possible =~ s/\s*$Storage\s*//g;
                $possible =~ s/\s*$Sparse\s*//g;
@@ -979,8 +1163,10 @@ sub possible {
                } elsif ($possible =~ /\s/) {
                        $possible =~ s/\s*$Type\s*//g;
                        for my $modifier (split(' ', $possible)) {
-                               warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
-                               push(@modifierList, $modifier);
+                               if ($modifier !~ $notPermitted) {
+                                       warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
+                                       push(@modifierList, $modifier);
+                               }
                        }
 
                } else {
@@ -1095,6 +1281,7 @@ sub process {
        # suppression flags
        my %suppress_ifbraces;
        my %suppress_whiletrailers;
+       my %suppress_export;
 
        # Pre-scan the patch sanitizing the lines.
        # Pre-scan the patch looking for any __setup documentation.
@@ -1187,7 +1374,6 @@ sub process {
                $linenr++;
 
                my $rawline = $rawlines[$linenr - 1];
-               my $hunk_line = ($realcnt != 0);
 
 #extract the line range in the file after the patch is applied
                if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
@@ -1204,6 +1390,7 @@ sub process {
 
                        %suppress_ifbraces = ();
                        %suppress_whiletrailers = ();
+                       %suppress_export = ();
                        next;
 
 # track the line number as we move through the hunk, note that
@@ -1227,6 +1414,8 @@ sub process {
                        $realcnt--;
                }
 
+               my $hunk_line = ($realcnt != 0);
+
 #make up the handle for any error we report on this line
                $prefix = "$filename:$realline: " if ($emacs && $file);
                $prefix = "$filename:$linenr: " if ($emacs && !$file);
@@ -1235,12 +1424,17 @@ sub process {
                $here = "#$realline: " if ($file);
 
                # extract the filename as it passes
-               if ($line=~/^\+\+\+\s+(\S+)/) {
+               if ($line =~ /^diff --git.*?(\S+)$/) {
+                       $realfile = $1;
+                       $realfile =~ s@^([^/]*)/@@;
+
+               } elsif ($line =~ /^\+\+\+\s+(\S+)/) {
                        $realfile = $1;
                        $realfile =~ s@^([^/]*)/@@;
 
                        $p1_prefix = $1;
-                       if ($tree && $p1_prefix ne '' && -e "$root/$p1_prefix") {
+                       if (!$file && $tree && $p1_prefix ne '' &&
+                           -e "$root/$p1_prefix") {
                                WARN("patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
                        }
 
@@ -1258,17 +1452,52 @@ sub process {
 
                $cnt_lines++ if ($realcnt != 0);
 
-#check the patch for a signoff:
+# Check for incorrect file permissions
+               if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
+                       my $permhere = $here . "FILE: $realfile\n";
+                       if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) {
+                               ERROR("do not set execute permissions for source files\n" . $permhere);
+                       }
+               }
+
+# Check the patch for a signoff:
                if ($line =~ /^\s*signed-off-by:/i) {
-                       # This is a signoff, if ugly, so do not double report.
                        $signoff++;
-                       if (!($line =~ /^\s*Signed-off-by:/)) {
-                               WARN("Signed-off-by: is the preferred form\n" .
-                                       $herecurr);
+               }
+
+# Check signature styles
+               if ($line =~ /^(\s*)($signature_tags)(\s*)(.*)/) {
+                       my $space_before = $1;
+                       my $sign_off = $2;
+                       my $space_after = $3;
+                       my $email = $4;
+                       my $ucfirst_sign_off = ucfirst(lc($sign_off));
+
+                       if (defined $space_before && $space_before ne "") {
+                               WARN("Do not use whitespace before $ucfirst_sign_off\n" . $herecurr);
                        }
-                       if ($line =~ /^\s*signed-off-by:\S/i) {
-                               WARN("space required after Signed-off-by:\n" .
-                                       $herecurr);
+                       if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) {
+                               WARN("'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr);
+                       }
+                       if (!defined $space_after || $space_after ne " ") {
+                               WARN("Use a single space after $ucfirst_sign_off\n" . $herecurr);
+                       }
+
+                       my ($email_name, $email_address, $comment) = parse_email($email);
+                       my $suggested_email = format_email(($email_name, $email_address));
+                       if ($suggested_email eq "") {
+                               ERROR("Unrecognized email address: '$email'\n" . $herecurr);
+                       } else {
+                               my $dequoted = $suggested_email;
+                               $dequoted =~ s/^"//;
+                               $dequoted =~ s/" </ </;
+                               # Don't force email to have quotes
+                               # Allow just an angle bracketed address
+                               if ("$dequoted$comment" ne $email &&
+                                   "<$email_address>$comment" ne $email &&
+                                   "$suggested_email$comment" ne $email) {
+                                       WARN("email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr);
+                               }
                        }
                }
 
@@ -1315,6 +1544,38 @@ sub process {
                } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
                        my $herevet = "$here\n" . cat_vet($rawline) . "\n";
                        ERROR("trailing whitespace\n" . $herevet);
+                       $rpt_cleaners = 1;
+               }
+
+# check for Kconfig help text having a real description
+# Only applies when adding the entry originally, after that we do not have
+# sufficient context to determine whether it is indeed long enough.
+               if ($realfile =~ /Kconfig/ &&
+                   $line =~ /\+\s*(?:---)?help(?:---)?$/) {
+                       my $length = 0;
+                       my $cnt = $realcnt;
+                       my $ln = $linenr + 1;
+                       my $f;
+                       my $is_end = 0;
+                       while ($cnt > 0 && defined $lines[$ln - 1]) {
+                               $f = $lines[$ln - 1];
+                               $cnt-- if ($lines[$ln - 1] !~ /^-/);
+                               $is_end = $lines[$ln - 1] =~ /^\+/;
+                               $ln++;
+
+                               next if ($f =~ /^-/);
+                               $f =~ s/^.//;
+                               $f =~ s/#.*//;
+                               $f =~ s/^\s+//;
+                               next if ($f =~ /^$/);
+                               if ($f =~ /^\s*config\s/) {
+                                       $is_end = 1;
+                                       last;
+                               }
+                               $length++;
+                       }
+                       WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4);
+                       #print "is_end<$is_end> length<$length>\n";
                }
 
 # check we are in a valid source file if not then ignore this hunk
@@ -1323,17 +1584,35 @@ sub process {
 #80 column limit
                if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
                    $rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
-                   $line !~ /^\+\s*printk\s*\(\s*(?:KERN_\S+\s*)?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ &&
+                   !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:|,|\)\s*;)\s*$/ ||
+                   $line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) &&
                    $length > 80)
                {
                        WARN("line over 80 characters\n" . $herecurr);
                }
 
+# check for spaces before a quoted newline
+               if ($rawline =~ /^.*\".*\s\\n/) {
+                       WARN("unnecessary whitespace before a quoted newline\n" . $herecurr);
+               }
+
 # check for adding lines without a newline.
                if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
                        WARN("adding a line without newline at end of file\n" . $herecurr);
                }
 
+# Blackfin: use hi/lo macros
+               if ($realfile =~ m@arch/blackfin/.*\.S$@) {
+                       if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) {
+                               my $herevet = "$here\n" . cat_vet($line) . "\n";
+                               ERROR("use the LO() macro, not (... & 0xFFFF)\n" . $herevet);
+                       }
+                       if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) {
+                               my $herevet = "$here\n" . cat_vet($line) . "\n";
+                               ERROR("use the HI() macro, not (... >> 16)\n" . $herevet);
+                       }
+               }
+
 # check we are in a valid source file C or perl if not then ignore this hunk
                next if ($realfile !~ /\.(h|c|pl)$/);
 
@@ -1343,6 +1622,23 @@ sub process {
                    $rawline =~ /^\+\s*        \s*/) {
                        my $herevet = "$here\n" . cat_vet($rawline) . "\n";
                        ERROR("code indent should use tabs where possible\n" . $herevet);
+                       $rpt_cleaners = 1;
+               }
+
+# check for space before tabs.
+               if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
+                       my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+                       WARN("please, no space before tabs\n" . $herevet);
+               }
+
+# check for spaces at the beginning of a line.
+# Exceptions:
+#  1) within comments
+#  2) indented preprocessor commands
+#  3) hanging labels
+               if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/)  {
+                       my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+                       WARN("please, no spaces at the start of a line\n" . $herevet);
                }
 
 # check we are in a valid C source file if not then ignore this hunk
@@ -1353,14 +1649,33 @@ sub process {
                        WARN("CVS style keyword markers, these will _not_ be updated\n". $herecurr);
                }
 
+# Blackfin: don't use __builtin_bfin_[cs]sync
+               if ($line =~ /__builtin_bfin_csync/) {
+                       my $herevet = "$here\n" . cat_vet($line) . "\n";
+                       ERROR("use the CSYNC() macro in asm/blackfin.h\n" . $herevet);
+               }
+               if ($line =~ /__builtin_bfin_ssync/) {
+                       my $herevet = "$here\n" . cat_vet($line) . "\n";
+                       ERROR("use the SSYNC() macro in asm/blackfin.h\n" . $herevet);
+               }
+
 # Check for potential 'bare' types
-               my ($stat, $cond, $line_nr_next, $remain_next, $off_next);
+               my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
+                   $realline_next);
                if ($realcnt && $line =~ /.\s*\S/) {
                        ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
                                ctx_statement_block($linenr, $realcnt, 0);
                        $stat =~ s/\n./\n /g;
                        $cond =~ s/\n./\n /g;
 
+                       # Find the real next line.
+                       $realline_next = $line_nr_next;
+                       if (defined $realline_next &&
+                           (!defined $lines[$realline_next - 1] ||
+                            substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) {
+                               $realline_next++;
+                       }
+
                        my $s = $stat;
                        $s =~ s/{.*$//s;
 
@@ -1370,6 +1685,8 @@ sub process {
                        # Ignore functions being called
                        } elsif ($s =~ /^.\s*$Ident\s*\(/s) {
 
+                       } elsif ($s =~ /^.\s*else\b/s) {
+
                        # declarations always start with types
                        } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) {
                                my $type = $1;
@@ -1457,7 +1774,7 @@ sub process {
 
                        if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
                                ERROR("that open brace { should be on the previous line\n" .
-                                       "$here\n$ctx\n$lines[$ctx_ln - 1]\n");
+                                       "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
                        }
                        if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
                            $ctx =~ /\)\s*\;\s*$/ &&
@@ -1466,7 +1783,7 @@ sub process {
                                my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
                                if ($nindent > $indent) {
                                        WARN("trailing semicolon indicates no statements, indent implies otherwise\n" .
-                                               "$here\n$ctx\n$lines[$ctx_ln - 1]\n");
+                                               "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
                                }
                        }
                }
@@ -1530,8 +1847,9 @@ sub process {
                                    $s =~ /^\s*#\s*?/ ||
                                    $s =~ /^\s*$Ident\s*:/) {
                                        $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0;
-                                       $s =~ s/^.*?\n//;
-                                       $cond_lines++;
+                                       if ($s =~ s/^.*?\n//) {
+                                               $cond_lines++;
+                                       }
                                }
                        }
 
@@ -1583,17 +1901,17 @@ sub process {
                }
 # TEST: allow direct testing of the attribute matcher.
                if ($dbg_attr) {
-                       if ($line =~ /^.\s*$Attribute\s*$/) {
+                       if ($line =~ /^.\s*$Modifier\s*$/) {
                                ERROR("TEST: is attr\n" . $herecurr);
-                       } elsif ($dbg_attr > 1 && $line =~ /^.+($Attribute)/) {
+                       } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) {
                                ERROR("TEST: is not attr ($1 is)\n". $herecurr);
                        }
                        next;
                }
 
 # check for initialisation to aggregates open brace on the next line
-               if ($prevline =~ /$Declare\s*$Ident\s*=\s*$/ &&
-                   $line =~ /^.\s*{/) {
+               if ($line =~ /^.\s*{/ &&
+                   $prevline =~ /(?:^|[^=])=\s*$/) {
                        ERROR("that open brace { should be on the previous line\n" . $hereprev);
                }
 
@@ -1618,25 +1936,53 @@ sub process {
                $line =~ s@//.*@@;
                $opline =~ s@//.*@@;
 
-#EXPORT_SYMBOL should immediately follow its function closing }.
-               if (($line =~ /EXPORT_SYMBOL.*\((.*)\)/) ||
-                   ($line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider
+# the whole statement.
+#print "APW <$lines[$realline_next - 1]>\n";
+               if (defined $realline_next &&
+                   exists $lines[$realline_next - 1] &&
+                   !defined $suppress_export{$realline_next} &&
+                   ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
+                    $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+                       # Handle definitions which produce identifiers with
+                       # a prefix:
+                       #   XXX(foo);
+                       #   EXPORT_SYMBOL(something_foo);
                        my $name = $1;
-                       if ($prevline !~ /(?:
-                               ^.}|
+                       if ($stat =~ /^.([A-Z_]+)\s*\(\s*($Ident)/ &&
+                           $name =~ /^${Ident}_$2/) {
+#print "FOO C name<$name>\n";
+                               $suppress_export{$realline_next} = 1;
+
+                       } elsif ($stat !~ /(?:
+                               \n.}\s*$|
                                ^.DEFINE_$Ident\(\Q$name\E\)|
                                ^.DECLARE_$Ident\(\Q$name\E\)|
                                ^.LIST_HEAD\(\Q$name\E\)|
-                               ^.$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(|
-                               \b\Q$name\E(?:\s+$Attribute)?\s*(?:;|=|\[)
+                               ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(|
+                               \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\()
                            )/x) {
-                               WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
+#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n";
+                               $suppress_export{$realline_next} = 2;
+                       } else {
+                               $suppress_export{$realline_next} = 1;
                        }
                }
+               if (!defined $suppress_export{$linenr} &&
+                   $prevline =~ /^.\s*$/ &&
+                   ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
+                    $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+#print "FOO B <$lines[$linenr - 1]>\n";
+                       $suppress_export{$linenr} = 2;
+               }
+               if (defined $suppress_export{$linenr} &&
+                   $suppress_export{$linenr} == 2) {
+                       WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
+               }
 
-# check for external initialisers.
+# check for global initialisers.
                if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) {
-                       ERROR("do not initialise externals to 0 or NULL\n" .
+                       ERROR("do not initialise globals to 0 or NULL\n" .
                                $herecurr);
                }
 # check for static initialisers.
@@ -1645,6 +1991,23 @@ sub process {
                                $herecurr);
                }
 
+# check for static const char * arrays.
+               if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
+                       WARN("static const char * array should probably be static const char * const\n" .
+                               $herecurr);
+               }
+
+# check for static char foo[] = "bar" declarations.
+               if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
+                       WARN("static char array declaration should probably be static const char\n" .
+                               $herecurr);
+               }
+
+# check for declarations of struct pci_device_id
+               if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) {
+                       WARN("Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr);
+               }
+
 # check for new typedefs, only function parameters and sparse annotations
 # make sense.
                if ($line =~ /\btypedef\s/ &&
@@ -1657,7 +2020,7 @@ sub process {
 
 # * goes on variable not on type
                # (char*[ const])
-               if ($line =~ m{\($NonptrType(\s*\*[\s\*]*(?:$Modifier\s*)*)\)}) {
+               if ($line =~ m{\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\)}) {
                        my ($from, $to) = ($1, $1);
 
                        # Should start with a space.
@@ -1672,7 +2035,7 @@ sub process {
                        if ($from ne $to) {
                                ERROR("\"(foo$from)\" should be \"(foo$to)\"\n" .  $herecurr);
                        }
-               } elsif ($line =~ m{\b$NonptrType(\s*\*[\s\*]*(?:$Modifier\s*)?)($Ident)}) {
+               } elsif ($line =~ m{\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)}) {
                        my ($from, $to, $ident) = ($1, $1, $2);
 
                        # Should start with a space.
@@ -1685,8 +2048,8 @@ sub process {
                        # Modifiers should have spaces.
                        $to =~ s/(\b$Modifier$)/$1 /;
 
-                       #print "from<$from> to<$to>\n";
-                       if ($from ne $to) {
+                       #print "from<$from> to<$to> ident<$ident>\n";
+                       if ($from ne $to && $ident !~ /^$Modifier$/) {
                                ERROR("\"foo${from}bar\" should be \"foo${to}bar\"\n" .  $herecurr);
                        }
                }
@@ -1702,16 +2065,21 @@ sub process {
                        WARN("LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
                }
 
+# check for uses of printk_ratelimit
+               if ($line =~ /\bprintk_ratelimit\s*\(/) {
+                       WARN("Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr);
+               }
+
 # printk should use KERN_* levels.  Note that follow on printk's on the
 # same line do not need a level, so we use the current block context
 # to try and find and validate the current printk.  In summary the current
-# printk includes all preceeding printk's which have no newline on the end.
+# printk includes all preceding printk's which have no newline on the end.
 # we assume the first bad printk is the one to report.
                if ($line =~ /\bprintk\((?!KERN_)\s*"/) {
                        my $ok = 0;
                        for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
                                #print "CHECK<$lines[$ln - 1]\n";
-                               # we have a preceeding printk if it ends
+                               # we have a preceding printk if it ends
                                # with "\n" ignore it, else it is to blame
                                if ($lines[$ln - 1] =~ m{\bprintk\(}) {
                                        if ($rawlines[$ln - 1] !~ m{\\n"}) {
@@ -1738,6 +2106,11 @@ sub process {
                        ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
                }
 
+# missing space after union, struct or enum definition
+               if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
+                   WARN("missing space after $1 definition\n" . $herecurr);
+               }
+
 # check for spacing round square brackets; allowed:
 #  1. with a type on the left -- int [] a;
 #  2. at the beginning of a line for slice initialisers -- [0...10] = 5,
@@ -1798,7 +2171,7 @@ sub process {
                        for (my $n = 0; $n < $#elements; $n += 2) {
                                $off += length($elements[$n]);
 
-                               # Pick up the preceeding and succeeding characters.
+                               # Pick up the preceding and succeeding characters.
                                my $ca = substr($opline, 0, $off);
                                my $cc = '';
                                if (length($opline) >= ($off + length($elements[$n + 1]))) {
@@ -1885,7 +2258,7 @@ sub process {
                                        if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
                                                ERROR("space required before that '$op' $at\n" . $hereptr);
                                        }
-                                       if ($op eq '*' && $cc =~/\s*const\b/) {
+                                       if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
                                                # A unary '*' may be const
 
                                        } elsif ($ctx =~ /.xW/) {
@@ -2015,21 +2388,50 @@ sub process {
                        my $value = $2;
 
                        # Flatten any parentheses
-                       $value =~ s/\)\(/\) \(/g;
+                       $value =~ s/\(/ \(/g;
+                       $value =~ s/\)/\) /g;
                        while ($value =~ s/\[[^\{\}]*\]/1/ ||
                               $value !~ /(?:$Ident|-?$Constant)\s*
                                             $Compare\s*
                                             (?:$Ident|-?$Constant)/x &&
                               $value =~ s/\([^\(\)]*\)/1/) {
                        }
-
-                       if ($value =~ /^(?:$Ident|-?$Constant)$/) {
+#print "value<$value>\n";
+                       if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) {
                                ERROR("return is not a function, parentheses are not required\n" . $herecurr);
 
                        } elsif ($spacing !~ /\s+/) {
                                ERROR("space required before the open parenthesis '('\n" . $herecurr);
                        }
                }
+# Return of what appears to be an errno should normally be -'ve
+               if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
+                       my $name = $1;
+                       if ($name ne 'EOF' && $name ne 'ERROR') {
+                               WARN("return of an errno should typically be -ve (return -$1)\n" . $herecurr);
+                       }
+               }
+
+# typecasts on min/max could be min_t/max_t
+               if ($line =~ /^\+(?:.*?)\b(min|max)\s*\($Typecast{0,1}($LvalOrFunc)\s*,\s*$Typecast{0,1}($LvalOrFunc)\s*\)/) {
+                       if (defined $2 || defined $8) {
+                               my $call = $1;
+                               my $cast1 = deparenthesize($2);
+                               my $arg1 = $3;
+                               my $cast2 = deparenthesize($8);
+                               my $arg2 = $9;
+                               my $cast;
+
+                               if ($cast1 ne "" && $cast2 ne "") {
+                                       $cast = "$cast1 or $cast2";
+                               } elsif ($cast1 ne "") {
+                                       $cast = $cast1;
+                               } else {
+                                       $cast = $cast2;
+                               }
+                               WARN("$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . $herecurr);
+                       }
+               }
 
 # Need a space before open parenthesis after if, while etc
                if ($line=~/\b(if|while|for|switch)\(/) {
@@ -2075,8 +2477,10 @@ sub process {
                                # Find out how long the conditional actually is.
                                my @newlines = ($c =~ /\n/gs);
                                my $cond_lines = 1 + $#newlines;
+                               my $stat_real = '';
 
-                               my $stat_real = raw_line($linenr, $cond_lines);
+                               $stat_real = raw_line($linenr, $cond_lines)
+                                                       . "\n" if ($cond_lines);
                                if (defined($stat_real) && $cond_lines > 1) {
                                        $stat_real = "[...]\n$stat_real";
                                }
@@ -2162,7 +2566,7 @@ sub process {
                        my $checkfile = "include/linux/$file";
                        if (-f "$root/$checkfile" &&
                            $realfile ne $checkfile &&
-                           $1 ne 'irq')
+                           $1 !~ /$allowed_asm_includes/)
                        {
                                if ($realfile =~ m{^arch/}) {
                                        CHK("Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
@@ -2241,10 +2645,13 @@ sub process {
                                DECLARE_PER_CPU|
                                DEFINE_PER_CPU|
                                __typeof__\(|
-                               \.$Ident\s*=\s*
+                               union|
+                               struct|
+                               \.$Ident\s*=\s*|
+                               ^\"|\"$
                        }x;
-                       #print "REST<$rest> dstat<$dstat>\n";
-                       if ($rest ne '') {
+                       #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
+                       if ($rest ne '' && $rest ne ',') {
                                if ($rest !~ /while\s*\(/ &&
                                    $dstat !~ /$exceptions/)
                                {
@@ -2395,11 +2802,6 @@ sub process {
                        WARN("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
                }
 
-# SPIN_LOCK_UNLOCKED & RW_LOCK_UNLOCKED are deprecated
-               if ($line =~ /\b(SPIN_LOCK_UNLOCKED|RW_LOCK_UNLOCKED)/) {
-                       ERROR("Use of $1 is deprecated: see Documentation/spinlocks.txt\n" . $herecurr);
-               }
-
 # warn about #if 0
                if ($line =~ /^.\s*\#\s*if\s+0\b/) {
                        CHK("if this code is redundant consider removing it\n" .
@@ -2421,6 +2823,21 @@ sub process {
                        }
                }
 
+# prefer usleep_range over udelay
+               if ($line =~ /\budelay\s*\(\s*(\w+)\s*\)/) {
+                       # ignore udelay's < 10, however
+                       if (! (($1 =~ /(\d+)/) && ($1 < 10)) ) {
+                               CHK("usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $line);
+                       }
+               }
+
+# warn about unexpectedly long msleep's
+               if ($line =~ /\bmsleep\s*\((\d+)\);/) {
+                       if ($1 < 20) {
+                               WARN("msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $line);
+                       }
+               }
+
 # warn about #ifdefs in C files
 #              if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
 #                      print "#ifdef in C files should be avoided\n";
@@ -2452,6 +2869,11 @@ sub process {
                        CHK("architecture specific defines should be avoided\n" .  $herecurr);
                }
 
+# Check that the storage class is at the beginning of a declaration
+               if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) {
+                       WARN("storage class should be at the beginning of the declaration\n" . $herecurr)
+               }
+
 # check the location of the inline attribute, that it is between
 # storage class and type.
                if ($line =~ /\b$Type\s+$Inline\b/ ||
@@ -2464,6 +2886,26 @@ sub process {
                        WARN("plain inline is preferred over $1\n" . $herecurr);
                }
 
+# Check for __attribute__ packed, prefer __packed
+               if ($line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
+                       WARN("__packed is preferred over __attribute__((packed))\n" . $herecurr);
+               }
+
+# Check for __attribute__ aligned, prefer __aligned
+               if ($line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
+                       WARN("__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
+               }
+
+# check for sizeof(&)
+               if ($line =~ /\bsizeof\s*\(\s*\&/) {
+                       WARN("sizeof(& should be avoided\n" . $herecurr);
+               }
+
+# check for line continuations in quoted strings with odd counts of "
+               if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) {
+                       WARN("Avoid line continuations in quoted strings\n" . $herecurr);
+               }
+
 # check for new externs in .c files.
                if ($realfile =~ /\.c$/ && defined $stat &&
                    $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
@@ -2501,34 +2943,73 @@ sub process {
                }
 
 # check for pointless casting of kmalloc return
-               if ($line =~ /\*\s*\)\s*k[czm]alloc\b/) {
+               if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) {
                        WARN("unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
                }
 
+# check for multiple semicolons
+               if ($line =~ /;\s*;\s*$/) {
+                   WARN("Statements terminations use 1 semicolon\n" . $herecurr);
+               }
+
 # check for gcc specific __FUNCTION__
                if ($line =~ /__FUNCTION__/) {
                        WARN("__func__ should be used instead of gcc specific __FUNCTION__\n"  . $herecurr);
                }
 
-# check for semaphores used as mutexes
-               if ($line =~ /^.\s*(DECLARE_MUTEX|init_MUTEX)\s*\(/) {
-                       WARN("mutexes are preferred for single holder semaphores\n" . $herecurr);
-               }
-# check for semaphores used as mutexes
-               if ($line =~ /^.\s*init_MUTEX_LOCKED\s*\(/) {
+# check for semaphores initialized locked
+               if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
                        WARN("consider using a completion\n" . $herecurr);
+
                }
-# recommend strict_strto* over simple_strto*
+# recommend kstrto* over simple_strto*
                if ($line =~ /\bsimple_(strto.*?)\s*\(/) {
-                       WARN("consider using strict_$1 in preference to simple_$1\n" . $herecurr);
+                       WARN("consider using kstrto* in preference to simple_$1\n" . $herecurr);
                }
 # check for __initcall(), use device_initcall() explicitly please
                if ($line =~ /^.\s*__initcall\s*\(/) {
                        WARN("please use device_initcall() instead of __initcall()\n" . $herecurr);
                }
-# check for struct file_operations, ensure they are const.
+# check for various ops structs, ensure they are const.
+               my $struct_ops = qr{acpi_dock_ops|
+                               address_space_operations|
+                               backlight_ops|
+                               block_device_operations|
+                               dentry_operations|
+                               dev_pm_ops|
+                               dma_map_ops|
+                               extent_io_ops|
+                               file_lock_operations|
+                               file_operations|
+                               hv_ops|
+                               ide_dma_ops|
+                               intel_dvo_dev_ops|
+                               item_operations|
+                               iwl_ops|
+                               kgdb_arch|
+                               kgdb_io|
+                               kset_uevent_ops|
+                               lock_manager_operations|
+                               microcode_ops|
+                               mtrr_ops|
+                               neigh_ops|
+                               nlmsvc_binding|
+                               pci_raw_ops|
+                               pipe_buf_operations|
+                               platform_hibernation_ops|
+                               platform_suspend_ops|
+                               proto_ops|
+                               rpc_pipe_ops|
+                               seq_operations|
+                               snd_ac97_build_ops|
+                               soc_pcmcia_socket_ops|
+                               stacktrace_ops|
+                               sysfs_ops|
+                               tty_operations|
+                               usb_mon_operations|
+                               wd_ops}x;
                if ($line !~ /\bconst\b/ &&
-                   $line =~ /\bstruct\s+(file_operations|seq_operations)\b/) {
+                   $line =~ /\bstruct\s+($struct_ops)\b/) {
                        WARN("struct $1 should normally be const\n" .
                                $herecurr);
                }
@@ -2564,6 +3045,26 @@ sub process {
                                WARN("use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
                        }
                }
+
+# check for lockdep_set_novalidate_class
+               if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
+                   $line =~ /__lockdep_no_validate__\s*\)/ ) {
+                       if ($realfile !~ m@^kernel/lockdep@ &&
+                           $realfile !~ m@^include/linux/lockdep@ &&
+                           $realfile !~ m@^drivers/base/core@) {
+                               ERROR("lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
+                       }
+               }
+
+               if ($line =~ /debugfs_create_file.*S_IWUGO/ ||
+                   $line =~ /DEVICE_ATTR.*S_IWUGO/ ) {
+                       WARN("Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
+               }
+
+               # Check for memset with swapped arguments
+               if ($line =~ /memset.*\,(\ |)(0x|)0(\ |0|)\);/) {
+                       ERROR("memset size is 3rd argument, not the second.\n" . $herecurr);
+               }
        }
 
        # If we have no input at all, then there is nothing to report on
@@ -2600,6 +3101,16 @@ sub process {
                print "\n" if ($quiet == 0);
        }
 
+       if ($quiet == 0) {
+               # If there were whitespace errors which cleanpatch can fix
+               # then suggest that.
+               if ($rpt_cleaners) {
+                       print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
+                       print "      scripts/cleanfile\n\n";
+                       $rpt_cleaners = 0;
+               }
+       }
+
        if ($clean == 1 && $quiet == 0) {
                print "$vname has no obvious style problems and is ready for submission.\n"
        }