1#!/usr/bin/perl 2 3# Copyright (c) 2006-2010 by Mauro Carvalho Chehab <mchehab@kernel.org> 4# 5# Licensed under the terms of the GNU GPL License version 2 6 7use strict; 8use File::Find; 9 10my %depend = (); 11my %depend2 = (); 12my %rmlist = (); 13my @nodep; 14my @modlist; 15my @allmodules; 16my %reqmodules; 17my %loaded = (); 18my $i=0; 19 20sub findprog($) 21{ 22 foreach(split(/:/, $ENV{PATH}),qw(/sbin /usr/sbin /usr/local/sbin)) { 23 return "$_/$_[0]" if(-x "$_/$_[0]"); 24 } 25 die "Can't find needed utility '$_[0]'"; 26} 27 28sub parse_dir { 29 my $file = $File::Find::name; 30 my $modinfo = findprog('modinfo'); 31 32 if (!($file =~ /[.]ko$/)) { 33 return; 34 } 35 36 my $module = $file; 37 $module =~ s|.*\/([^/]+)\.ko|\1|; 38 39 open IN, "$modinfo $module.ko|" or die "can't run $modinfo $file"; 40 while (<IN>) { 41 if (m/depends:\s*(.*)/) { 42 my $deps = $1; 43 $deps =~ s/\n//; 44 $deps =~ s/[,]/ /g; 45 $deps = " $deps "; 46 $depend{$module} = $deps; 47 push @allmodules, $module; 48 $i++; 49 } 50 } 51 close IN; 52} 53 54sub parse_loaded { 55 open IN, "/proc/modules"; 56 while (<IN>) { 57 m/^([\w\d_-]+)/; 58 $loaded{$1}=1; 59 } 60 close IN; 61} 62 63sub cleandep() 64{ 65 my $dep; 66 67 while ( my ($k, $v) = each(%depend) ) { 68 my $arg=$v; 69 my $arg2=" "; 70 while (!($arg =~ m/^\s*$/)) { 71 if ($arg =~ m/^ ([^ ]+) /) { 72 my $val=$1; 73 if (exists($depend{$val})) { 74 $arg2="$arg2 $val "; 75 } else { 76 $reqmodules{$val}=1; 77 } 78 } 79 $arg =~ s/^ [^ ]+//; 80 $arg2 =~ s/\s\s+/ /; 81 } 82 $depend2 { $k } = $arg2; 83 } 84 85} 86 87sub rmdep() 88{ 89 my $dep; 90 91 while ($dep=pop @nodep) { 92 while ( my ($k, $v) = each(%depend2) ) { 93 if ($v =~ m/\s($dep)\s/) { 94 $v =~ s/\s${dep}\s/ /; 95 $v =~ s/\s${dep}\s/ /; 96 $v =~ s/\s${dep}\s/ /; 97 $depend2 {$k} = $v; 98 } 99 } 100 } 101} 102 103sub orderdep () 104{ 105 my $old; 106 do { 107 $old=$i; 108 while ( my ($key, $value) = each(%depend2) ) { 109 if ($value =~ m/^\s*$/) { 110 push @nodep, $key; 111 push @modlist, $key; 112 $i=$i-1; 113 delete $depend2 {$key}; 114 } 115 } 116 rmdep(); 117 } until ($old==$i); 118 while ( my ($key, $value) = each(%depend2) ) { 119 printf "ERROR: bad dependencies - $key ($value)\n"; 120 } 121} 122 123sub rmmod(@) 124{ 125 my $rmmod = findprog('rmmod'); 126 my @not; 127 foreach (reverse @_) { 128 s/-/_/g; 129 if (exists ($loaded{$_})) { 130 print "$rmmod $_\n"; 131 unshift @not, $_ if (system "$rmmod $_"); 132 } 133 } 134 return @not; 135} 136 137sub prepare_cmd() 138{ 139 my $ver=qx(uname -r); 140 $ver =~ s/\s+$//; 141 die "Couldn't get kernel version" if (!$ver); 142 143 print "Seeking media drivers at /lib/modules/$ver/kernel/drivers/media/\n"; 144 find(\&parse_dir, "/lib/modules/$ver/kernel/drivers/media/"); 145 print "Seeking media drivers at /lib/modules/$ver/kernel/drivers/staging/media/\n"; 146 find(\&parse_dir, "/lib/modules/$ver/kernel/drivers/staging/media/"); 147 printf "found $i modules\n"; 148 149 cleandep(); 150 orderdep(); 151} 152 153prepare_cmd; 154parse_loaded; 155 156my @notunloaded = rmmod(@modlist); 157@notunloaded = rmmod(@notunloaded) if (@notunloaded); 158if (@notunloaded) { 159 print "Couldn't unload: ", join(' ', @notunloaded), "\n"; 160} 161