ALSA: pcm: fix delta calculation at boundary wraparound
[safe/jmp/linux-2.6] / scripts / checkpatch.pl
index bd6ac90..a4d7434 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,2009, 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.25';
+my $V = '0.30';
 
 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);
 }
 
@@ -101,7 +130,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 +142,17 @@ our $Sparse       = qr{
                        __iomem|
                        __must_check|
                        __init_refok|
-                       __kprobes
+                       __kprobes|
+                       __ref
                }x;
+
+# Notes to $Attribute:
+# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
 our $Attribute = qr{
                        const|
                        __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 +188,18 @@ 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|
+       pr_(debug|dbg|vdbg|devel|info|warning|err|notice|alert|crit|emerg|cont)|
+       dev_(printk|dbg|vdbg|info|warn|err|notice|alert|crit|emerg|WARN)|
+       WARN|
+       panic
+)};
+
 our @typeList = (
        qr{void},
        qr{(?:unsigned\s+)?char},
@@ -355,6 +399,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 +429,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 +438,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);
@@ -411,13 +468,15 @@ sub ctx_statement_block {
 
        my $type = '';
        my $level = 0;
-       my @stack = ([$type, $level]);
+       my @stack = ();
        my $p;
        my $c;
        my $len = 0;
 
        my $remainder;
        while (1) {
+               @stack = (['', 0]) if ($#stack == -1);
+
                #warn "CSB: blk<$blk> remain<$remain>\n";
                # If we are about to drop off the end, pull in more
                # context.
@@ -952,23 +1011,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;
@@ -977,8 +1038,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 {
@@ -1093,6 +1156,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.
@@ -1185,7 +1249,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+))? \@\@/) {
@@ -1202,6 +1265,7 @@ sub process {
 
                        %suppress_ifbraces = ();
                        %suppress_whiletrailers = ();
+                       %suppress_export = ();
                        next;
 
 # track the line number as we move through the hunk, note that
@@ -1225,6 +1289,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);
@@ -1238,7 +1304,8 @@ sub process {
                        $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");
                        }
 
@@ -1321,17 +1388,34 @@ 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*$/ &&
                    $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 +1427,12 @@ sub process {
                        ERROR("code indent should use tabs where possible\n" . $herevet);
                }
 
+# 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 we are in a valid C source file if not then ignore this hunk
                next if ($realfile !~ /\.(h|c)$/);
 
@@ -1351,14 +1441,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;
 
@@ -1368,6 +1477,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;
@@ -1528,8 +1639,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++;
+                                       }
                                }
                        }
 
@@ -1581,17 +1693,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);
                }
 
@@ -1616,21 +1728,40 @@ 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.*\((.*)\)/)) {
                        my $name = $1;
-                       if ($prevline !~ /(?:
-                               ^.}|
+                       if ($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.
                if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) {
@@ -1655,7 +1786,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.
@@ -1663,14 +1794,14 @@ sub process {
                        # Should not end with a space.
                        $to =~ s/\s+$//;
                        # '*'s should not have spaces between.
-                       while ($to =~ s/(.)\s\*/$1\*/) {
+                       while ($to =~ s/\*\s+\*/\*\*/) {
                        }
 
                        #print "from<$from> to<$to>\n";
                        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.
@@ -1678,13 +1809,13 @@ sub process {
                        # Should not end with a space.
                        $to =~ s/\s+$//;
                        # '*'s should not have spaces between.
-                       while ($to =~ s/(.)\s\*/$1\*/) {
+                       while ($to =~ s/\*\s+\*/\*\*/) {
                        }
                        # 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);
                        }
                }
@@ -1883,7 +2014,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/) {
@@ -2014,7 +2145,11 @@ sub process {
 
                        # Flatten any parentheses
                        $value =~ s/\)\(/\) \(/g;
-                       while ($value !~ /(?:$Ident|-?$Constant)\s*$Compare\s*(?:$Ident|-?$Constant)/ && $value =~ s/\([^\(\)]*\)/1/) {
+                       while ($value =~ s/\[[^\{\}]*\]/1/ ||
+                              $value !~ /(?:$Ident|-?$Constant)\s*
+                                            $Compare\s*
+                                            (?:$Ident|-?$Constant)/x &&
+                              $value =~ s/\([^\(\)]*\)/1/) {
                        }
 
                        if ($value =~ /^(?:$Ident|-?$Constant)$/) {
@@ -2069,8 +2204,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";
                                }
@@ -2102,6 +2239,11 @@ sub process {
                                ERROR("trailing statements should be on next line\n" . $herecurr);
                        }
                }
+# if should not continue a brace
+               if ($line =~ /}\s*if\b/) {
+                       ERROR("trailing statements should be on next line\n" .
+                               $herecurr);
+               }
 # case and default should not have general statements after them
                if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
                    $line !~ /\G(?:
@@ -2230,7 +2372,10 @@ 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 '') {
@@ -2453,6 +2598,11 @@ sub process {
                        WARN("plain inline is preferred over $1\n" . $herecurr);
                }
 
+# check for sizeof(&)
+               if ($line =~ /\bsizeof\s*\(\s*\&/) {
+                       WARN("sizeof(& should be avoided\n" . $herecurr);
+               }
+
 # check for new externs in .c files.
                if ($realfile =~ /\.c$/ && defined $stat &&
                    $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
@@ -2515,10 +2665,48 @@ sub process {
                if ($line =~ /^.\s*__initcall\s*\(/) {
                        WARN("please use device_initcall() instead of __initcall()\n" . $herecurr);
                }
-# check for struct file_operations, ensure they are const.
-               if ($line =~ /\bstruct\s+file_operations\b/ &&
-                   $line !~ /\bconst\b/) {
-                       WARN("struct file_operations should normally be const\n" . $herecurr);
+# 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+($struct_ops)\b/) {
+                       WARN("struct $1 should normally be const\n" .
+                               $herecurr);
                }
 
 # use of NR_CPUS is usually wrong
@@ -2548,7 +2736,7 @@ sub process {
                if ($line =~ /\bin_atomic\s*\(/) {
                        if ($realfile =~ m@^drivers/@) {
                                ERROR("do not use in_atomic in drivers\n" . $herecurr);
-                       } else {
+                       } elsif ($realfile !~ m@^kernel/@) {
                                WARN("use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
                        }
                }