]> git.sur5r.net Git - u-boot/commitdiff
checkpatch.pl: update from Linux kernel v4.16
authorHeinrich Schuchardt <xypron.glpk@gmx.de>
Wed, 4 Apr 2018 13:39:20 +0000 (15:39 +0200)
committerTom Rini <trini@konsulko.com>
Tue, 10 Apr 2018 19:19:15 +0000 (15:19 -0400)
Update scripts/checkpatch.pl from upstream.

One of the many corrections is not creating an error for cover-letters.

Reintroduce U-Boot's
5c761ce58666b3a1695697498598f8bf3484a0c7
checkpatch.pl: Add warning for new __packed additions

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
scripts/checkpatch.pl

index e450826c36fddb477a0b26f011f8e5ffacf8c206..373094e59ef011502170513b63ba9da5215ac002 100755 (executable)
@@ -145,7 +145,8 @@ sub list_types {
        close($script);
 
        my @types = ();
-       for ($text =~ /\b(?:(?:CHK|WARN|ERROR)\s*\(\s*"([^"]+)")/g) {
+       # Also catch when type or level is passed through a variable
+       for ($text =~ /(?:(?:\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_type\s*=)\s*"([^"]+)"/g) {
                push (@types, $_);
        }
        @types = sort(uniq(@types));
@@ -392,7 +393,7 @@ our $Binary = qr{(?i)0b[01]+$Int_type?};
 our $Hex       = qr{(?i)0x[0-9a-f]+$Int_type?};
 our $Int       = qr{[0-9]+$Int_type?};
 our $Octal     = qr{0[0-7]+$Int_type?};
-our $String    = qr{(?:\bL)?"[X\t]*"};
+our $String    = qr{"[X\t]*"};
 our $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?};
 our $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?};
 our $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?};
@@ -453,6 +454,7 @@ our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b};
 our $logFunctions = qr{(?x:
        printk(?:_ratelimited|_once|_deferred_once|_deferred|)|
        (?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)|
+       TP_printk|
        WARN(?:_RATELIMIT|_ONCE|)|
        panic|
        MODULE_[A-Z_]+|
@@ -564,6 +566,7 @@ foreach my $entry (@mode_permission_funcs) {
        $mode_perms_search .= '|' if ($mode_perms_search ne "");
        $mode_perms_search .= $entry->[0];
 }
+$mode_perms_search = "(?:${mode_perms_search})";
 
 our $mode_perms_world_writable = qr{
        S_IWUGO         |
@@ -598,6 +601,37 @@ foreach my $entry (keys %mode_permission_string_types) {
        $mode_perms_string_search .= '|' if ($mode_perms_string_search ne "");
        $mode_perms_string_search .= $entry;
 }
+our $single_mode_perms_string_search = "(?:${mode_perms_string_search})";
+our $multi_mode_perms_string_search = qr{
+       ${single_mode_perms_string_search}
+       (?:\s*\|\s*${single_mode_perms_string_search})*
+}x;
+
+sub perms_to_octal {
+       my ($string) = @_;
+
+       return trim($string) if ($string =~ /^\s*0[0-7]{3,3}\s*$/);
+
+       my $val = "";
+       my $oval = "";
+       my $to = 0;
+       my $curpos = 0;
+       my $lastpos = 0;
+       while ($string =~ /\b(($single_mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) {
+               $curpos = pos($string);
+               my $match = $2;
+               my $omatch = $1;
+               last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos));
+               $lastpos = $curpos;
+               $to |= $mode_permission_string_types{$match};
+               $val .= '\s*\|\s*' if ($val ne "");
+               $val .= $match;
+               $oval .= $omatch;
+       }
+       $oval =~ s/^\s*\|\s*//;
+       $oval =~ s/\s*\|\s*$//;
+       return sprintf("%04o", $to);
+}
 
 our $allowed_asm_includes = qr{(?x:
        irq|
@@ -757,7 +791,8 @@ our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)};
 our $declaration_macros = qr{(?x:
        (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(|
        (?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(|
-       (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\(
+       (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\(|
+       (?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(
 )};
 
 sub deparenthesize {
@@ -1041,7 +1076,7 @@ sub parse_email {
        } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) {
                $address = $1;
                $comment = $2 if defined $2;
-               $formatted_email =~ s/$address.*$//;
+               $formatted_email =~ s/\Q$address\E.*$//;
                $name = $formatted_email;
                $name = trim($name);
                $name =~ s/^\"|\"$//g;
@@ -1183,7 +1218,7 @@ sub sanitise_line {
        for ($off = 1; $off < length($line); $off++) {
                $c = substr($line, $off, 1);
 
-               # Comments we are wacking completly including the begin
+               # Comments we are whacking completely including the begin
                # and end, all to $;.
                if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') {
                        $sanitise_quote = '*/';
@@ -1263,6 +1298,7 @@ sub sanitise_line {
 sub get_quoted_string {
        my ($line, $rawline) = @_;
 
+       return "" if (!defined($line) || !defined($rawline));
        return "" if ($line !~ m/($String)/g);
        return substr($rawline, $-[0], $+[0] - $-[0]);
 }
@@ -1610,6 +1646,28 @@ sub raw_line {
        return $line;
 }
 
+sub get_stat_real {
+       my ($linenr, $lc) = @_;
+
+       my $stat_real = raw_line($linenr, 0);
+       for (my $count = $linenr + 1; $count <= $lc; $count++) {
+               $stat_real = $stat_real . "\n" . raw_line($count, 0);
+       }
+
+       return $stat_real;
+}
+
+sub get_stat_here {
+       my ($linenr, $cnt, $here) = @_;
+
+       my $herectx = $here . "\n";
+       for (my $n = 0; $n < $cnt; $n++) {
+               $herectx .= raw_line($linenr, $n) . "\n";
+       }
+
+       return $herectx;
+}
+
 sub cat_vet {
        my ($vet) = @_;
        my ($res, $coded);
@@ -2223,6 +2281,8 @@ sub process {
 
        my $camelcase_file_seeded = 0;
 
+       my $checklicenseline = 1;
+
        sanitise_line_reset();
        my $line;
        foreach my $rawline (@rawlines) {
@@ -2414,6 +2474,7 @@ sub process {
                        } else {
                                $check = $check_orig;
                        }
+                       $checklicenseline = 1;
                        next;
                }
 
@@ -2715,10 +2776,10 @@ sub process {
                                my $typo_fix = $spelling_fix{lc($typo)};
                                $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
                                $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/);
-                               my $msg_type = \&WARN;
-                               $msg_type = \&CHK if ($file);
-                               if (&{$msg_type}("TYPO_SPELLING",
-                                                "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) &&
+                               my $msg_level = \&WARN;
+                               $msg_level = \&CHK if ($file);
+                               if (&{$msg_level}("TYPO_SPELLING",
+                                                 "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) &&
                                    $fix) {
                                        $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/;
                                }
@@ -2753,17 +2814,20 @@ sub process {
                    $rawline =~ /\b59\s+Temple\s+Pl/i ||
                    $rawline =~ /\b51\s+Franklin\s+St/i) {
                        my $herevet = "$here\n" . cat_vet($rawline) . "\n";
-                       my $msg_type = \&ERROR;
-                       $msg_type = \&CHK if ($file);
-                       &{$msg_type}("FSF_MAILING_ADDRESS",
-                                    "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet)
+                       my $msg_level = \&ERROR;
+                       $msg_level = \&CHK if ($file);
+                       &{$msg_level}("FSF_MAILING_ADDRESS",
+                                     "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet)
                }
 
 # 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*config\s+/) {
+                   # 'choice' is usually the last thing on the line (though
+                   # Kconfig supports named choices), so use a word boundary
+                   # (\b) rather than a whitespace character (\s)
+                   $line =~ /^\+\s*(?:config|menuconfig|choice)\b/) {
                        my $length = 0;
                        my $cnt = $realcnt;
                        my $ln = $linenr + 1;
@@ -2778,9 +2842,13 @@ sub process {
                                next if ($f =~ /^-/);
                                last if (!$file && $f =~ /^\@\@/);
 
-                               if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate)\s*\"/) {
+                               if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) {
                                        $is_start = 1;
-                               } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) {
+                               } elsif ($lines[$ln - 1] =~ /^\+\s*(?:help|---help---)\s*$/) {
+                                       if ($lines[$ln - 1] =~ "---help---") {
+                                               WARN("CONFIG_DESCRIPTION",
+                                                    "prefer 'help' over '---help---' for new help texts\n" . $herecurr);
+                                       }
                                        $length = -1;
                                }
 
@@ -2788,7 +2856,13 @@ sub process {
                                $f =~ s/#.*//;
                                $f =~ s/^\s+//;
                                next if ($f =~ /^$/);
-                               if ($f =~ /^\s*config\s/) {
+
+                               # This only checks context lines in the patch
+                               # and so hopefully shouldn't trigger false
+                               # positives, even though some of these are
+                               # common words in help texts
+                               if ($f =~ /^\s*(?:config|menuconfig|choice|endchoice|
+                                                 if|endif|menu|endmenu|source)\b/x) {
                                        $is_end = 1;
                                        last;
                                }
@@ -2864,6 +2938,30 @@ sub process {
                        }
                }
 
+# check for using SPDX license tag at beginning of files
+               if ($realline == $checklicenseline) {
+                       if ($rawline =~ /^[ \+]\s*\#\!\s*\//) {
+                               $checklicenseline = 2;
+                       } elsif ($rawline =~ /^\+/) {
+                               my $comment = "";
+                               if ($realfile =~ /\.(h|s|S)$/) {
+                                       $comment = '/*';
+                               } elsif ($realfile =~ /\.(c|dts|dtsi)$/) {
+                                       $comment = '//';
+                               } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc)$/) {
+                                       $comment = '#';
+                               } elsif ($realfile =~ /\.rst$/) {
+                                       $comment = '..';
+                               }
+
+                               if ($comment !~ /^$/ &&
+                                   $rawline !~ /^\+\Q$comment\E SPDX-License-Identifier: /) {
+                                       WARN("SPDX_LICENSE_TAG",
+                                            "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
+                               }
+                       }
+               }
+
 # check we are in a valid source file if not then ignore this hunk
                next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/);
 
@@ -2873,9 +2971,10 @@ sub process {
 #      logging functions like pr_info that end in a string
 #      lines with a single string
 #      #defines that are a single string
+#      lines with an RFC3986 like URL
 #
 # There are 3 different line length message types:
-# LONG_LINE_COMMENT    a comment starts before but extends beyond $max_linelength
+# LONG_LINE_COMMENT    a comment starts before but extends beyond $max_line_length
 # LONG_LINE_STRING     a string starts before but extends beyond $max_line_length
 # LONG_LINE            all other lines longer than $max_line_length
 #
@@ -2899,8 +2998,13 @@ sub process {
                                 $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) {
                                $msg_type = "";
 
-                       # EFI_GUID is another special case
-                       } elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/) {
+                       # More special cases
+                       } elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/ ||
+                                $line =~ /^\+\s*(?:\w+)?\s*DEFINE_PER_CPU/) {
+                               $msg_type = "";
+
+                       # URL ($rawline is used in case the URL is in a comment)
+                       } elsif ($rawline =~ /^\+.*\b[a-z][\w\.\+\-]*:\/\/\S+/i) {
                                $msg_type = "";
 
                        # Otherwise set the alternate message types
@@ -2929,20 +3033,6 @@ sub process {
                             "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("LO_MACRO",
-                                     "use the LO() macro, not (... & 0xFFFF)\n" . $herevet);
-                       }
-                       if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) {
-                               my $herevet = "$here\n" . cat_vet($line) . "\n";
-                               ERROR("HI_MACRO",
-                                     "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|dtsi|dts)$/);
 
@@ -2980,7 +3070,7 @@ sub process {
 
 # check indentation starts on a tab stop
                if ($^V && $^V ge 5.10.0 &&
-                   $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$))/) {
+                   $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) {
                        my $indent = length($1);
                        if ($indent % 8) {
                                if (WARN("TABSTOP",
@@ -3102,6 +3192,7 @@ sub process {
                      $line =~ /^\+[a-z_]*init/ ||
                      $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ ||
                      $line =~ /^\+\s*DECLARE/ ||
+                     $line =~ /^\+\s*builtin_[\w_]*driver/ ||
                      $line =~ /^\+\s*__setup/)) {
                        if (CHK("LINE_SPACING",
                                "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) &&
@@ -3181,6 +3272,12 @@ sub process {
 # check we are in a valid C source file if not then ignore this hunk
                next if ($realfile !~ /\.(h|c)$/);
 
+# check for unusual line ending [ or (
+               if ($line =~ /^\+.*([\[\(])\s*$/) {
+                       CHK("OPEN_ENDED_LINE",
+                           "Lines should not end with a '$1'\n" . $herecurr);
+               }
+
 # check if this appears to be the start function declaration, save the name
                if ($sline =~ /^\+\{\s*$/ &&
                    $prevline =~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ident)\(/) {
@@ -3222,18 +3319,6 @@ sub process {
                             "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("CSYNC",
-                             "use the CSYNC() macro in asm/blackfin.h\n" . $herevet);
-               }
-               if ($line =~ /__builtin_bfin_ssync/) {
-                       my $herevet = "$here\n" . cat_vet($line) . "\n";
-                       ERROR("SSYNC",
-                             "use the SSYNC() macro in asm/blackfin.h\n" . $herevet);
-               }
-
 # check for old HOTPLUG __dev<foo> section markings
                if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) {
                        WARN("HOTPLUG_SECTION",
@@ -3810,10 +3895,10 @@ sub process {
 
 # avoid BUG() or BUG_ON()
                if ($line =~ /\b(?:BUG|BUG_ON)\b/) {
-                       my $msg_type = \&WARN;
-                       $msg_type = \&CHK if ($file);
-                       &{$msg_type}("AVOID_BUG",
-                                    "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr);
+                       my $msg_level = \&WARN;
+                       $msg_level = \&CHK if ($file);
+                       &{$msg_level}("AVOID_BUG",
+                                     "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr);
                }
 
 # avoid LINUX_VERSION_CODE
@@ -3828,28 +3913,10 @@ sub process {
                             "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 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 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"}) {
-                                               $ok = 1;
-                                       }
-                                       last;
-                               }
-                       }
-                       if ($ok == 0) {
-                               WARN("PRINTK_WITHOUT_KERN_LEVEL",
-                                    "printk() should include KERN_ facility level\n" . $herecurr);
-                       }
+# printk should use KERN_* levels
+               if ($line =~ /\bprintk\s*\(\s*(?!KERN_[A-Z]+\b)/) {
+                       WARN("PRINTK_WITHOUT_KERN_LEVEL",
+                            "printk() should include KERN_<LEVEL> facility level\n" . $herecurr);
                }
 
                if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) {
@@ -3890,10 +3957,12 @@ sub process {
 
 # function brace can't be on same line, except for #defines of do while,
 # or if closed on same line
-               if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and
-                   !($line=~/\#\s*define.*do\s\{/) and !($line=~/}/)) {
+               if ($^V && $^V ge 5.10.0 &&
+                   $sline =~ /$Type\s*$Ident\s*$balanced_parens\s*\{/ &&
+                   $sline !~ /\#\s*define\b.*do\s*\{/ &&
+                   $sline !~ /}/) {
                        if (ERROR("OPEN_BRACE",
-                                 "open brace '{' following function declarations go on the next line\n" . $herecurr) &&
+                                 "open brace '{' following function definitions go on the next line\n" . $herecurr) &&
                            $fix) {
                                fix_delete_line($fixlinenr, $rawline);
                                my $fixed_line = $rawline;
@@ -4339,11 +4408,11 @@ sub process {
 
                                        # messages are ERROR, but ?: are CHK
                                        if ($ok == 0) {
-                                               my $msg_type = \&ERROR;
-                                               $msg_type = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/);
+                                               my $msg_level = \&ERROR;
+                                               $msg_level = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/);
 
-                                               if (&{$msg_type}("SPACING",
-                                                                "spaces required around that '$op' $at\n" . $hereptr)) {
+                                               if (&{$msg_level}("SPACING",
+                                                                 "spaces required around that '$op' $at\n" . $hereptr)) {
                                                        $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
                                                        if (defined $fix_elements[$n + 2]) {
                                                                $fix_elements[$n + 2] =~ s/^\s+//;
@@ -4496,6 +4565,32 @@ sub process {
                        }
                }
 
+# check for unnecessary parentheses around comparisons in if uses
+# when !drivers/staging or command-line uses --strict
+               if (($realfile !~ m@^(?:drivers/staging/)@ || $check_orig) &&
+                   $^V && $^V ge 5.10.0 && defined($stat) &&
+                   $stat =~ /(^.\s*if\s*($balanced_parens))/) {
+                       my $if_stat = $1;
+                       my $test = substr($2, 1, -1);
+                       my $herectx;
+                       while ($test =~ /(?:^|[^\w\&\!\~])+\s*\(\s*([\&\!\~]?\s*$Lval\s*(?:$Compare\s*$FuncArg)?)\s*\)/g) {
+                               my $match = $1;
+                               # avoid parentheses around potential macro args
+                               next if ($match =~ /^\s*\w+\s*$/);
+                               if (!defined($herectx)) {
+                                       $herectx = $here . "\n";
+                                       my $cnt = statement_rawlines($if_stat);
+                                       for (my $n = 0; $n < $cnt; $n++) {
+                                               my $rl = raw_line($linenr, $n);
+                                               $herectx .=  $rl . "\n";
+                                               last if $rl =~ /^[ \+].*\{/;
+                                       }
+                               }
+                               CHK("UNNECESSARY_PARENTHESES",
+                                   "Unnecessary parentheses around '$match'\n" . $herectx);
+                       }
+               }
+
 #goto labels aren't indented, allow a single space however
                if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
                   !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
@@ -4884,12 +4979,8 @@ sub process {
                        #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
 
                        $ctx =~ s/\n*$//;
-                       my $herectx = $here . "\n";
                        my $stmt_cnt = statement_rawlines($ctx);
-
-                       for (my $n = 0; $n < $stmt_cnt; $n++) {
-                               $herectx .= raw_line($linenr, $n) . "\n";
-                       }
+                       my $herectx = get_stat_here($linenr, $stmt_cnt, $here);
 
                        if ($dstat ne '' &&
                            $dstat !~ /^(?:$Ident|-?$Constant),$/ &&                    # 10, // foo(),
@@ -4961,12 +5052,9 @@ sub process {
 # check for macros with flow control, but without ## concatenation
 # ## concatenation is commonly a macro that defines a function so ignore those
                        if ($has_flow_statement && !$has_arg_concat) {
-                               my $herectx = $here . "\n";
                                my $cnt = statement_rawlines($ctx);
+                               my $herectx = get_stat_here($linenr, $cnt, $here);
 
-                               for (my $n = 0; $n < $cnt; $n++) {
-                                       $herectx .= raw_line($linenr, $n) . "\n";
-                               }
                                WARN("MACRO_WITH_FLOW_CONTROL",
                                     "Macros with flow control statements should be avoided\n" . "$herectx");
                        }
@@ -5006,11 +5094,7 @@ sub process {
 
                                $ctx =~ s/\n*$//;
                                my $cnt = statement_rawlines($ctx);
-                               my $herectx = $here . "\n";
-
-                               for (my $n = 0; $n < $cnt; $n++) {
-                                       $herectx .= raw_line($linenr, $n) . "\n";
-                               }
+                               my $herectx = get_stat_here($linenr, $cnt, $here);
 
                                if (($stmts =~ tr/;/;/) == 1 &&
                                    $stmts !~ /^\s*(if|while|for|switch)\b/) {
@@ -5024,11 +5108,7 @@ sub process {
                        } elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) {
                                $ctx =~ s/\n*$//;
                                my $cnt = statement_rawlines($ctx);
-                               my $herectx = $here . "\n";
-
-                               for (my $n = 0; $n < $cnt; $n++) {
-                                       $herectx .= raw_line($linenr, $n) . "\n";
-                               }
+                               my $herectx = get_stat_here($linenr, $cnt, $here);
 
                                WARN("TRAILING_SEMICOLON",
                                     "macros should not use a trailing semicolon\n" . "$herectx");
@@ -5151,12 +5231,8 @@ sub process {
                                }
                        }
                        if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
-                               my $herectx = $here . "\n";
                                my $cnt = statement_rawlines($block);
-
-                               for (my $n = 0; $n < $cnt; $n++) {
-                                       $herectx .= raw_line($linenr, $n) . "\n";
-                               }
+                               my $herectx = get_stat_here($linenr, $cnt, $here);
 
                                WARN("BRACES",
                                     "braces {} are not necessary for single statement blocks\n" . $herectx);
@@ -5254,14 +5330,13 @@ sub process {
                }
 
 # concatenated string without spaces between elements
-               if ($line =~ /$String[A-Z_]/ ||
-                   ($line =~ /([A-Za-z0-9_]+)$String/ && $1 !~ /^L$/)) {
+               if ($line =~ /$String[A-Z_]/ || $line =~ /[A-Za-z0-9_]$String/) {
                        CHK("CONCATENATED_STRING",
                            "Concatenated strings should use spaces between elements\n" . $herecurr);
                }
 
 # uncoalesced string fragments
-               if ($line =~ /$String\s*L?"/) {
+               if ($line =~ /$String\s*"/) {
                        WARN("STRING_FRAGMENTS",
                             "Consecutive strings are generally better as a single string\n" . $herecurr);
                }
@@ -5292,7 +5367,7 @@ sub process {
                }
 
 # check for line continuations in quoted strings with odd counts of "
-               if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) {
+               if ($rawline =~ /\\$/ && $sline =~ tr/"/"/ % 2) {
                        WARN("LINE_CONTINUATIONS",
                             "Avoid line continuations in quoted strings\n" . $herecurr);
                }
@@ -5571,6 +5646,12 @@ sub process {
                        }
                }
 
+# check for smp_read_barrier_depends and read_barrier_depends
+               if (!$file && $line =~ /\b(smp_|)read_barrier_depends\s*\(/) {
+                       WARN("READ_BARRIER_DEPENDS",
+                            "$1read_barrier_depends should only be used in READ_ONCE or DEC Alpha code\n" . $herecurr);
+               }
+
 # check of hardware specific defines
                if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {
                        CHK("ARCH_DEFINES",
@@ -5734,29 +5815,50 @@ sub process {
                        }
                }
 
-               # check for vsprintf extension %p<foo> misuses
+# check for vsprintf extension %p<foo> misuses
                if ($^V && $^V ge 5.10.0 &&
                    defined $stat &&
                    $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s &&
                    $1 !~ /^_*volatile_*$/) {
-                       my $bad_extension = "";
+                       my $specifier;
+                       my $extension;
+                       my $bad_specifier = "";
+                       my $stat_real;
+
                        my $lc = $stat =~ tr@\n@@;
                        $lc = $lc + $linenr;
                        for (my $count = $linenr; $count <= $lc; $count++) {
                                my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));
                                $fmt =~ s/%%//g;
-                               if ($fmt =~ /(\%[\*\d\.]*p(?![\WFfSsBKRraEhMmIiUDdgVCbGNO]).)/) {
-                                       $bad_extension = $1;
-                                       last;
+
+                               while ($fmt =~ /(\%[\*\d\.]*p(\w))/g) {
+                                       $specifier = $1;
+                                       $extension = $2;
+                                       if ($extension !~ /[SsBKRraEhMmIiUDdgVCbGNOx]/) {
+                                               $bad_specifier = $specifier;
+                                               last;
+                                       }
+                                       if ($extension eq "x" && !defined($stat_real)) {
+                                               if (!defined($stat_real)) {
+                                                       $stat_real = get_stat_real($linenr, $lc);
+                                               }
+                                               WARN("VSPRINTF_SPECIFIER_PX",
+                                                    "Using vsprintf specifier '\%px' potentially exposes the kernel memory layout, if you don't really need the address please consider using '\%p'.\n" . "$here\n$stat_real\n");
+                                       }
                                }
-                       }
-                       if ($bad_extension ne "") {
-                               my $stat_real = raw_line($linenr, 0);
-                               for (my $count = $linenr + 1; $count <= $lc; $count++) {
-                                       $stat_real = $stat_real . "\n" . raw_line($count, 0);
+                               if ($bad_specifier ne "") {
+                                       my $stat_real = get_stat_real($linenr, $lc);
+                                       my $ext_type = "Invalid";
+                                       my $use = "";
+                                       if ($bad_specifier =~ /p[Ff]/) {
+                                               $ext_type = "Deprecated";
+                                               $use = " - use %pS instead";
+                                               $use =~ s/pS/ps/ if ($bad_specifier =~ /pf/);
+                                       }
+
+                                       WARN("VSPRINTF_POINTER_EXTENSION",
+                                            "$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n");
                                }
-                               WARN("VSPRINTF_POINTER_EXTENSION",
-                                    "Invalid vsprintf pointer extension '$bad_extension'\n" . "$here\n$stat_real\n");
                        }
                }
 
@@ -5869,10 +5971,7 @@ sub process {
                     $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) {
                        my $lc = $stat =~ tr@\n@@;
                        $lc = $lc + $linenr;
-                       my $stat_real = raw_line($linenr, 0);
-                       for (my $count = $linenr + 1; $count <= $lc; $count++) {
-                               $stat_real = $stat_real . "\n" . raw_line($count, 0);
-                       }
+                       my $stat_real = get_stat_real($linenr, $lc);
                        WARN("NAKED_SSCANF",
                             "unchecked sscanf return value\n" . "$here\n$stat_real\n");
                }
@@ -5883,10 +5982,7 @@ sub process {
                    $line =~ /\bsscanf\b/) {
                        my $lc = $stat =~ tr@\n@@;
                        $lc = $lc + $linenr;
-                       my $stat_real = raw_line($linenr, 0);
-                       for (my $count = $linenr + 1; $count <= $lc; $count++) {
-                               $stat_real = $stat_real . "\n" . raw_line($count, 0);
-                       }
+                       my $stat_real = get_stat_real($linenr, $lc);
                        if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) {
                                my $format = $6;
                                my $count = $format =~ tr@%@%@;
@@ -5940,7 +6036,7 @@ sub process {
 
 # check for function declarations that have arguments without identifier names
                if (defined $stat &&
-                   $stat =~ /^.\s*(?:extern\s+)?$Type\s*$Ident\s*\(\s*([^{]+)\s*\)\s*;/s &&
+                   $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s &&
                    $1 ne "void") {
                        my $args = trim($1);
                        while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) {
@@ -6016,12 +6112,9 @@ sub process {
                        }
                        if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ &&
                            !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) {
-                               my $ctx = '';
-                               my $herectx = $here . "\n";
                                my $cnt = statement_rawlines($stat);
-                               for (my $n = 0; $n < $cnt; $n++) {
-                                       $herectx .= raw_line($linenr, $n) . "\n";
-                               }
+                               my $herectx = get_stat_here($linenr, $cnt, $here);
+
                                if (WARN("ALLOC_WITH_MULTIPLY",
                                         "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
                                    $cnt == 1 &&
@@ -6092,7 +6185,7 @@ sub process {
                                next if ($fline =~ /^.[\s$;]*$/);
                                $has_statement = 1;
                                $count++;
-                               $has_break = 1 if ($fline =~ /\bswitch\b|\b(?:break\s*;[\s$;]*$|return\b|goto\b|continue\b)/);
+                               $has_break = 1 if ($fline =~ /\bswitch\b|\b(?:break\s*;[\s$;]*$|exit\s*\(\b|return\b|goto\b|continue\b)/);
                        }
                        if (!$has_break && $has_statement) {
                                WARN("MISSING_BREAK",
@@ -6104,12 +6197,9 @@ sub process {
                if ($^V && $^V ge 5.10.0 &&
                    defined $stat &&
                    $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) {
-                       my $ctx = '';
-                       my $herectx = $here . "\n";
                        my $cnt = statement_rawlines($stat);
-                       for (my $n = 0; $n < $cnt; $n++) {
-                               $herectx .= raw_line($linenr, $n) . "\n";
-                       }
+                       my $herectx = get_stat_here($linenr, $cnt, $here);
+
                        WARN("DEFAULT_NO_BREAK",
                             "switch default: should use break\n" . $herectx);
                }
@@ -6225,28 +6315,6 @@ sub process {
                        }
                }
 
-# whine about ACCESS_ONCE
-               if ($^V && $^V ge 5.10.0 &&
-                   $line =~ /\bACCESS_ONCE\s*$balanced_parens\s*(=(?!=))?\s*($FuncArg)?/) {
-                       my $par = $1;
-                       my $eq = $2;
-                       my $fun = $3;
-                       $par =~ s/^\(\s*(.*)\s*\)$/$1/;
-                       if (defined($eq)) {
-                               if (WARN("PREFER_WRITE_ONCE",
-                                        "Prefer WRITE_ONCE(<FOO>, <BAR>) over ACCESS_ONCE(<FOO>) = <BAR>\n" . $herecurr) &&
-                                   $fix) {
-                                       $fixed[$fixlinenr] =~ s/\bACCESS_ONCE\s*\(\s*\Q$par\E\s*\)\s*$eq\s*\Q$fun\E/WRITE_ONCE($par, $fun)/;
-                               }
-                       } else {
-                               if (WARN("PREFER_READ_ONCE",
-                                        "Prefer READ_ONCE(<FOO>) over ACCESS_ONCE(<FOO>)\n" . $herecurr) &&
-                                   $fix) {
-                                       $fixed[$fixlinenr] =~ s/\bACCESS_ONCE\s*\(\s*\Q$par\E\s*\)/READ_ONCE($par)/;
-                               }
-                       }
-               }
-
 # check for mutex_trylock_recursive usage
                if ($line =~ /mutex_trylock_recursive/) {
                        ERROR("LOCKING",
@@ -6270,8 +6338,69 @@ sub process {
                             "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
                }
 
+# check for DEVICE_ATTR uses that could be DEVICE_ATTR_<FOO>
+# and whether or not function naming is typical and if
+# DEVICE_ATTR permissions uses are unusual too
+               if ($^V && $^V ge 5.10.0 &&
+                   defined $stat &&
+                   $stat =~ /\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?\s*(\s*(?:${multi_mode_perms_string_search}|0[0-7]{3,3})\s*)\s*\)?\s*,\s*(\w+)\s*,\s*(\w+)\s*\)/) {
+                       my $var = $1;
+                       my $perms = $2;
+                       my $show = $3;
+                       my $store = $4;
+                       my $octal_perms = perms_to_octal($perms);
+                       if ($show =~ /^${var}_show$/ &&
+                           $store =~ /^${var}_store$/ &&
+                           $octal_perms eq "0644") {
+                               if (WARN("DEVICE_ATTR_RW",
+                                        "Use DEVICE_ATTR_RW\n" . $herecurr) &&
+                                   $fix) {
+                                       $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*$store\s*\)/DEVICE_ATTR_RW(${var})/;
+                               }
+                       } elsif ($show =~ /^${var}_show$/ &&
+                                $store =~ /^NULL$/ &&
+                                $octal_perms eq "0444") {
+                               if (WARN("DEVICE_ATTR_RO",
+                                        "Use DEVICE_ATTR_RO\n" . $herecurr) &&
+                                   $fix) {
+                                       $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*NULL\s*\)/DEVICE_ATTR_RO(${var})/;
+                               }
+                       } elsif ($show =~ /^NULL$/ &&
+                                $store =~ /^${var}_store$/ &&
+                                $octal_perms eq "0200") {
+                               if (WARN("DEVICE_ATTR_WO",
+                                        "Use DEVICE_ATTR_WO\n" . $herecurr) &&
+                                   $fix) {
+                                       $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*NULL\s*,\s*$store\s*\)/DEVICE_ATTR_WO(${var})/;
+                               }
+                       } elsif ($octal_perms eq "0644" ||
+                                $octal_perms eq "0444" ||
+                                $octal_perms eq "0200") {
+                               my $newshow = "$show";
+                               $newshow = "${var}_show" if ($show ne "NULL" && $show ne "${var}_show");
+                               my $newstore = $store;
+                               $newstore = "${var}_store" if ($store ne "NULL" && $store ne "${var}_store");
+                               my $rename = "";
+                               if ($show ne $newshow) {
+                                       $rename .= " '$show' to '$newshow'";
+                               }
+                               if ($store ne $newstore) {
+                                       $rename .= " '$store' to '$newstore'";
+                               }
+                               WARN("DEVICE_ATTR_FUNCTIONS",
+                                    "Consider renaming function(s)$rename\n" . $herecurr);
+                       } else {
+                               WARN("DEVICE_ATTR_PERMS",
+                                    "DEVICE_ATTR unusual permissions '$perms' used\n" . $herecurr);
+                       }
+               }
+
 # Mode permission misuses where it seems decimal should be octal
 # This uses a shortcut match to avoid unnecessary uses of a slow foreach loop
+# o Ignore module_param*(...) uses with a decimal 0 permission as that has a
+#   specific definition of not visible in sysfs.
+# o Ignore proc_create*(...) uses with a decimal 0 permission as that means
+#   use the default permissions
                if ($^V && $^V ge 5.10.0 &&
                    defined $stat &&
                    $line =~ /$mode_perms_search/) {
@@ -6281,10 +6410,7 @@ sub process {
 
                                my $lc = $stat =~ tr@\n@@;
                                $lc = $lc + $linenr;
-                               my $stat_real = raw_line($linenr, 0);
-                               for (my $count = $linenr + 1; $count <= $lc; $count++) {
-                                       $stat_real = $stat_real . "\n" . raw_line($count, 0);
-                               }
+                               my $stat_real = get_stat_real($linenr, $lc);
 
                                my $skip_args = "";
                                if ($arg_pos > 1) {
@@ -6295,8 +6421,9 @@ sub process {
                                if ($stat =~ /$test/) {
                                        my $val = $1;
                                        $val = $6 if ($skip_args ne "");
-                                       if (($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
-                                           ($val =~ /^$Octal$/ && length($val) ne 4)) {
+                                       if (!($func =~ /^(?:module_param|proc_create)/ && $val eq "0") &&
+                                           (($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
+                                            ($val =~ /^$Octal$/ && length($val) ne 4))) {
                                                ERROR("NON_OCTAL_PERMISSIONS",
                                                      "Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real);
                                        }
@@ -6309,30 +6436,13 @@ sub process {
                }
 
 # check for uses of S_<PERMS> that could be octal for readability
-               if ($line =~ /\b$mode_perms_string_search\b/) {
-                       my $val = "";
-                       my $oval = "";
-                       my $to = 0;
-                       my $curpos = 0;
-                       my $lastpos = 0;
-                       while ($line =~ /\b(($mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) {
-                               $curpos = pos($line);
-                               my $match = $2;
-                               my $omatch = $1;
-                               last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos));
-                               $lastpos = $curpos;
-                               $to |= $mode_permission_string_types{$match};
-                               $val .= '\s*\|\s*' if ($val ne "");
-                               $val .= $match;
-                               $oval .= $omatch;
-                       }
-                       $oval =~ s/^\s*\|\s*//;
-                       $oval =~ s/\s*\|\s*$//;
-                       my $octal = sprintf("%04o", $to);
+               while ($line =~ m{\b($multi_mode_perms_string_search)\b}g) {
+                       my $oval = $1;
+                       my $octal = perms_to_octal($oval);
                        if (WARN("SYMBOLIC_PERMS",
                                 "Symbolic permissions '$oval' are not preferred. Consider using octal permissions '$octal'.\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$fixlinenr] =~ s/$val/$octal/;
+                               $fixed[$fixlinenr] =~ s/\Q$oval\E/$octal/;
                        }
                }
 
@@ -6373,7 +6483,7 @@ sub process {
                exit(0);
        }
 
-       if (!$is_patch && $file !~ /cover-letter\.patch$/) {
+       if (!$is_patch && $filename !~ /cover-letter\.patch$/) {
                ERROR("NOT_UNIFIED_DIFF",
                      "Does not appear to be a unified-diff format patch\n");
        }